diff options
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.java | 158 |
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()); |