aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java158
1 files changed, 73 insertions, 85 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
index f245eae39f..41ab8acf05 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -30,11 +30,11 @@ import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_MULTI_ACK_D
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_DONE;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SESSION_ID;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SHALLOW;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
-import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SESSION_ID;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WAIT_FOR_DONE;
import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_ACK;
@@ -80,7 +80,6 @@ import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.pack.CachedPackUriProvider;
import org.eclipse.jgit.internal.storage.pack.PackWriter;
-import org.eclipse.jgit.internal.transport.parser.FirstWant;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
@@ -118,13 +117,13 @@ public class UploadPack implements Closeable {
/** Policy the server uses to validate client requests */
public enum RequestPolicy {
/** Client may only ask for objects the server advertised a reference for. */
- ADVERTISED,
+ ADVERTISED(0x08),
/**
* Client may ask for any commit reachable from a reference advertised by
* the server.
*/
- REACHABLE_COMMIT,
+ REACHABLE_COMMIT(0x02),
/**
* Client may ask for objects that are the tip of any reference, even if not
@@ -134,18 +133,36 @@ public class UploadPack implements Closeable {
*
* @since 3.1
*/
- TIP,
+ TIP(0x01),
/**
* Client may ask for any commit reachable from any reference, even if that
- * reference wasn't advertised.
+ * reference wasn't advertised, implies REACHABLE_COMMIT and TIP.
*
* @since 3.1
*/
- REACHABLE_COMMIT_TIP,
+ REACHABLE_COMMIT_TIP(0x03),
+
+ /** Client may ask for any SHA-1 in the repository, implies REACHABLE_COMMIT_TIP. */
+ ANY(0x07);
+
+ private final int bitmask;
- /** Client may ask for any SHA-1 in the repository. */
- ANY;
+ RequestPolicy(int bitmask) {
+ this.bitmask = bitmask;
+ }
+
+ /**
+ * Check if the current policy implies another, based on its bitmask.
+ *
+ * @param implied
+ * the implied policy based on its bitmask.
+ * @return true if the policy is implied.
+ * @since 6.10.1
+ */
+ public boolean implies(RequestPolicy implied) {
+ return (bitmask & implied.bitmask) != 0;
+ }
}
/**
@@ -172,44 +189,6 @@ public class UploadPack implements Closeable {
throws PackProtocolException, IOException;
}
- /**
- * Data in the first line of a want-list, the line itself plus options.
- *
- * @deprecated Use {@link FirstWant} instead
- */
- @Deprecated
- public static class FirstLine {
-
- private final FirstWant firstWant;
-
- /**
- * @param line
- * line from the client.
- */
- public FirstLine(String line) {
- try {
- firstWant = FirstWant.fromLine(line);
- } catch (PackProtocolException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- /** @return non-capabilities part of the line. */
- public String getLine() {
- return firstWant.getLine();
- }
-
- /** @return capabilities parsed from the line. */
- public Set<String> getOptions() {
- if (firstWant.getAgent() != null) {
- Set<String> caps = new HashSet<>(firstWant.getCapabilities());
- caps.add(OPTION_AGENT + '=' + firstWant.getAgent());
- return caps;
- }
- return firstWant.getCapabilities();
- }
- }
-
/*
* {@link java.util.function.Consumer} doesn't allow throwing checked
* exceptions. Define our own to propagate IOExceptions.
@@ -732,8 +711,11 @@ public class UploadPack implements Closeable {
}
/**
- * @param p provider of URIs corresponding to cached packs (to support
- * the packfile URIs feature)
+ * Set provider of cached pack URIs
+ *
+ * @param p
+ * provider of URIs corresponding to cached packs (to support the
+ * packfile URIs feature)
* @since 5.5
*/
public void setCachedPackUriProvider(@Nullable CachedPackUriProvider p) {
@@ -771,9 +753,13 @@ public class UploadPack implements Closeable {
* its own error handling mechanism.
*
* @param input
+ * input stream
* @param output
+ * output stream
* @param messages
+ * stream for messages
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void upload(InputStream input, OutputStream output,
@Nullable OutputStream messages) throws IOException {
@@ -1175,6 +1161,11 @@ public class UploadPack implements Closeable {
}
private void fetchV2(PacketLineOut pckOut) throws IOException {
+ ProtocolV2Parser parser = new ProtocolV2Parser(transferConfig);
+ FetchV2Request req = parser.parseFetchRequest(pckIn);
+ currentRequest = req;
+ Map<String, ObjectId> wantedRefs = wantedRefs(req);
+
// Depending on the requestValidator, #processHaveLines may
// require that advertised be set. Set it only in the required
// circumstances (to avoid a full ref lookup in the case that
@@ -1184,15 +1175,25 @@ public class UploadPack implements Closeable {
requestValidator instanceof AnyRequestValidator) {
advertised = Collections.emptySet();
} else {
- advertised = refIdSet(getAdvertisedOrDefaultRefs().values());
+ if (req.wantIds.isEmpty()) {
+ // Only refs-in-wants in request. These ref-in-wants where used as
+ // filters already in the ls-refs, there is no need to use a full
+ // advertisement now in fetch. This improves performance and also
+ // accuracy: when the ref db prioritize and truncates the returned
+ // refs (e.g. Gerrit hides too old refs), applying a filter can
+ // return different results than a plain listing.
+ advertised = refIdSet(getFilteredRefs(wantedRefs.keySet()).values());
+ } else {
+ // At least one SHA1 in wants, so we need to take the full
+ // advertisement as base for a reachability check.
+ advertised = refIdSet(getAdvertisedOrDefaultRefs().values());
+ }
}
PackStatistics.Accumulator accumulator = new PackStatistics.Accumulator();
Instant negotiateStart = Instant.now();
+ accumulator.advertised = advertised.size();
- ProtocolV2Parser parser = new ProtocolV2Parser(transferConfig);
- FetchV2Request req = parser.parseFetchRequest(pckIn);
- currentRequest = req;
rawOut.stopBuffering();
protocolV2Hook.onFetch(req);
@@ -1205,10 +1206,10 @@ public class UploadPack implements Closeable {
// copying data back to class fields
List<ObjectId> deepenNots = parseDeepenNots(req.getDeepenNots());
- Map<String, ObjectId> wantedRefs = wantedRefs(req);
// TODO(ifrade): Avoid mutating the parsed request.
req.getWantIds().addAll(wantedRefs.values());
wantIds = req.getWantIds();
+ accumulator.wants = wantIds.size();
boolean sectionSent = false;
boolean mayHaveShallow = req.getDepth() != 0
@@ -1393,6 +1394,7 @@ public class UploadPack implements Closeable {
if (transferConfig.isAdvertiseObjectInfo()) {
caps.add(COMMAND_OBJECT_INFO);
}
+ caps.add(OPTION_AGENT + "=" + UserAgent.get());
return caps;
}
@@ -1599,13 +1601,9 @@ public class UploadPack implements Closeable {
if (!biDirectionalPipe)
adv.advertiseCapability(OPTION_NO_DONE);
RequestPolicy policy = getRequestPolicy();
- if (policy == RequestPolicy.TIP
- || policy == RequestPolicy.REACHABLE_COMMIT_TIP
- || policy == null)
+ if (policy == null || policy.implies(RequestPolicy.TIP))
adv.advertiseCapability(OPTION_ALLOW_TIP_SHA1_IN_WANT);
- if (policy == RequestPolicy.REACHABLE_COMMIT
- || policy == RequestPolicy.REACHABLE_COMMIT_TIP
- || policy == null)
+ if (policy == null || policy.implies(RequestPolicy.REACHABLE_COMMIT))
adv.advertiseCapability(OPTION_ALLOW_REACHABLE_SHA1_IN_WANT);
adv.advertiseCapability(OPTION_AGENT, UserAgent.get());
if (transferConfig.isAllowFilter()) {
@@ -1663,18 +1661,6 @@ public class UploadPack implements Closeable {
}
/**
- * Deprecated synonym for {@code getFilterSpec().getBlobLimit()}.
- *
- * @return filter blob limit requested by the client, or -1 if no limit
- * @since 5.3
- * @deprecated Use {@link #getFilterSpec()} instead
- */
- @Deprecated
- public final long getFilterBlobLimit() {
- return getFilterSpec().getBlobLimit();
- }
-
- /**
* Returns the filter spec for the current request. Valid only after
* calling recvWants(). This may be a no-op filter spec, but it won't be
* null.
@@ -1766,7 +1752,6 @@ public class UploadPack implements Closeable {
&& line.length() == PACKET_HAVE.length() + 40) {
peerHas.add(ObjectId
.fromString(line.substring(PACKET_HAVE.length())));
- accumulator.haves++;
} else if (line.equals(PACKET_DONE)) {
last = processHaveLines(peerHas, last, pckOut, accumulator, Option.NONE);
@@ -1798,6 +1783,7 @@ public class UploadPack implements Closeable {
parseWants(accumulator);
if (peerHas.isEmpty())
return last;
+ accumulator.haves += peerHas.size();
sentReady = false;
int haveCnt = 0;
@@ -1966,10 +1952,9 @@ public class UploadPack implements Closeable {
@Override
public void checkWants(UploadPack up, List<ObjectId> wants)
throws PackProtocolException, IOException {
- if (!up.isBiDirectionalPipe())
+ if (!up.isBiDirectionalPipe() || !wants.isEmpty()) {
new ReachableCommitRequestValidator().checkWants(up, wants);
- else if (!wants.isEmpty())
- throw new WantNotValidException(wants.iterator().next());
+ }
}
}
@@ -2241,7 +2226,7 @@ public class UploadPack implements Closeable {
walk.resetRetain(SAVE);
walk.markStart((RevCommit) want);
if (oldestTime != 0)
- walk.setRevFilter(CommitTimeRevFilter.after(oldestTime * 1000L));
+ walk.setRevFilter(CommitTimeRevFilter.after(Instant.ofEpochSecond(oldestTime)));
for (;;) {
final RevCommit c = walk.next();
if (c == null)
@@ -2264,7 +2249,8 @@ public class UploadPack implements Closeable {
* request in process
* @param allTags
* refs to search for annotated tags to include in the pack if
- * the {@link #OPTION_INCLUDE_TAG} capability was requested.
+ * the {@link GitProtocolConstants#OPTION_INCLUDE_TAG} capability
+ * was requested.
* @param unshallowCommits
* shallow commits on the client that are now becoming unshallow
* @param deepenNots
@@ -2325,7 +2311,8 @@ public class UploadPack implements Closeable {
* where to write statistics about the content of the pack.
* @param allTags
* refs to search for annotated tags to include in the pack if
- * the {@link #OPTION_INCLUDE_TAG} capability was requested.
+ * the {@link GitProtocolConstants#OPTION_INCLUDE_TAG} capability
+ * was requested.
* @param unshallowCommits
* shallow commits on the client that are now becoming unshallow
* @param deepenNots
@@ -2345,11 +2332,6 @@ public class UploadPack implements Closeable {
}
msgOut.flush();
- // Advertised objects and refs are not used from here on and can be
- // cleared.
- advertised = null;
- refs = null;
-
PackConfig cfg = packConfig;
if (cfg == null)
cfg = new PackConfig(db);
@@ -2391,13 +2373,19 @@ public class UploadPack implements Closeable {
pw.setTagTargets(tagTargets);
}
+ // Advertised objects and refs are not used from here on and can be
+ // cleared.
+ advertised = null;
+ refs = null;
+
RevWalk rw = walk;
if (req.getDepth() > 0 || req.getDeepenSince() != 0 || !deepenNots.isEmpty()) {
int walkDepth = req.getDepth() == 0 ? Integer.MAX_VALUE
: req.getDepth() - 1;
pw.setShallowPack(req.getDepth(), unshallowCommits);
- // Ownership is transferred below
+ // dw borrows the reader from walk which is closed by #close
+ @SuppressWarnings("resource")
DepthWalk.RevWalk dw = new DepthWalk.RevWalk(
walk.getObjectReader(), walkDepth);
dw.setDeepenSince(req.getDeepenSince());