diff options
4 files changed, 143 insertions, 135 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java index a960b4a4b5..5d28a4d9f2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java @@ -42,6 +42,9 @@ */ package org.eclipse.jgit.transport; +import static java.util.Objects.requireNonNull; + +import java.util.List; import java.util.Set; import org.eclipse.jgit.annotations.NonNull; @@ -62,6 +65,10 @@ abstract class FetchRequest { final Set<String> clientCapabilities; + final int deepenSince; + + final List<String> deepenNotRefs; + /** * Initialize the common fields of a fetch request. * @@ -75,20 +82,24 @@ abstract class FetchRequest { * to exclude blobs on certain conditions * @param clientCapabilities * capabilities sent in the request + * @param deepenNotRefs + * Requests that the shallow clone/fetch should be cut at these + * specific revisions instead of a depth. + * @param deepenSince + * Requests that the shallow clone/fetch should be cut at a + * specific time, instead of depth */ - FetchRequest(Set<ObjectId> wantIds, int depth, - Set<ObjectId> clientShallowCommits, long filterBlobLimit, - Set<String> clientCapabilities) { - if (wantIds == null || clientShallowCommits == null - || clientCapabilities == null) { - throw new NullPointerException(); - } - - this.wantIds = wantIds; + FetchRequest(@NonNull Set<ObjectId> wantIds, int depth, + @NonNull Set<ObjectId> clientShallowCommits, long filterBlobLimit, + @NonNull Set<String> clientCapabilities, int deepenSince, + @NonNull List<String> deepenNotRefs) { + this.wantIds = requireNonNull(wantIds); this.depth = depth; - this.clientShallowCommits = clientShallowCommits; + this.clientShallowCommits = requireNonNull(clientShallowCommits); this.filterBlobLimit = filterBlobLimit; - this.clientCapabilities = clientCapabilities; + this.clientCapabilities = requireNonNull(clientCapabilities); + this.deepenSince = deepenSince; + this.deepenNotRefs = requireNonNull(deepenNotRefs); } /** @@ -141,4 +152,23 @@ abstract class FetchRequest { Set<String> getClientCapabilities() { return clientCapabilities; } + + /** + * The value in a "deepen-since" line in the request, indicating the + * timestamp where to stop fetching/cloning. + * + * @return timestamp in seconds since the epoch, where to stop the shallow + * fetch/clone. Defaults to 0 if not set in the request. + */ + int getDeepenSince() { + return deepenSince; + } + + /** + * @return refs received in "deepen-not" lines. + */ + @NonNull + List<String> getDeepenNotRefs() { + return deepenNotRefs; + } }
\ No newline at end of file diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java index a40c734718..bb358c886f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java @@ -43,9 +43,11 @@ package org.eclipse.jgit.transport; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Set; +import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.lib.ObjectId; /** @@ -53,24 +55,24 @@ import org.eclipse.jgit.lib.ObjectId; */ final class FetchV0Request extends FetchRequest { - FetchV0Request(Set<ObjectId> wantIds, int depth, - Set<ObjectId> clientShallowCommits, long filterBlobLimit, - Set<String> clientCapabilities) { + FetchV0Request(@NonNull Set<ObjectId> wantIds, int depth, + @NonNull Set<ObjectId> clientShallowCommits, long filterBlobLimit, + @NonNull Set<String> clientCapabilities) { super(wantIds, depth, clientShallowCommits, filterBlobLimit, - clientCapabilities); + clientCapabilities, 0, Collections.emptyList()); } static final class Builder { int depth; - Set<ObjectId> wantIds = new HashSet<>(); + final Set<ObjectId> wantIds = new HashSet<>(); - Set<ObjectId> clientShallowCommits = new HashSet<>(); + final Set<ObjectId> clientShallowCommits = new HashSet<>(); long filterBlobLimit = -1; - Set<String> clientCaps = new HashSet<>(); + final Set<String> clientCaps = new HashSet<>(); /** * @param objectId diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java index 7d84b19a4e..cd3906ea61 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java @@ -42,6 +42,8 @@ */ package org.eclipse.jgit.transport; +import static java.util.Objects.requireNonNull; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -65,22 +67,19 @@ public final class FetchV2Request extends FetchRequest { private final TreeMap<String, ObjectId> wantedRefs; - private final int deepenSince; - - private final List<String> deepenNotRefs; - private final boolean doneReceived; - private FetchV2Request(List<ObjectId> peerHas, - TreeMap<String, ObjectId> wantedRefs, Set<ObjectId> wantIds, - Set<ObjectId> clientShallowCommits, int deepenSince, - List<String> deepenNotRefs, int depth, long filterBlobLimit, - boolean doneReceived, Set<String> clientCapabilities) { - super(wantIds, depth, clientShallowCommits, filterBlobLimit, clientCapabilities); - this.peerHas = peerHas; - this.wantedRefs = wantedRefs; - this.deepenSince = deepenSince; - this.deepenNotRefs = deepenNotRefs; + FetchV2Request(@NonNull List<ObjectId> peerHas, + @NonNull TreeMap<String, ObjectId> wantedRefs, + @NonNull Set<ObjectId> wantIds, + @NonNull Set<ObjectId> clientShallowCommits, int deepenSince, + @NonNull List<String> deepenNotRefs, int depth, + long filterBlobLimit, + boolean doneReceived, @NonNull Set<String> clientCapabilities) { + super(wantIds, depth, clientShallowCommits, filterBlobLimit, + clientCapabilities, deepenSince, deepenNotRefs); + this.peerHas = requireNonNull(peerHas); + this.wantedRefs = requireNonNull(wantedRefs); this.doneReceived = doneReceived; } @@ -101,25 +100,6 @@ public final class FetchV2Request extends FetchRequest { } /** - * The value in a "deepen-since" line in the request, indicating the - * timestamp where to stop fetching/cloning. - * - * @return timestamp in seconds since the epoch, where to stop the shallow - * fetch/clone. Defaults to 0 if not set in the request. - */ - int getDeepenSince() { - return deepenSince; - } - - /** - * @return refs received in "deepen-not" lines. - */ - @NonNull - List<String> getDeepenNotRefs() { - return deepenNotRefs; - } - - /** * @return true if the request had a "done" line */ boolean wasDoneReceived() { @@ -131,20 +111,19 @@ public final class FetchV2Request extends FetchRequest { return new Builder(); } - /** A builder for {@link FetchV2Request}. */ static final class Builder { - List<ObjectId> peerHas = new ArrayList<>(); + final List<ObjectId> peerHas = new ArrayList<>(); - TreeMap<String, ObjectId> wantedRefs = new TreeMap<>(); + final TreeMap<String, ObjectId> wantedRefs = new TreeMap<>(); - Set<ObjectId> wantIds = new HashSet<>(); + final Set<ObjectId> wantIds = new HashSet<>(); - Set<ObjectId> clientShallowCommits = new HashSet<>(); + final Set<ObjectId> clientShallowCommits = new HashSet<>(); - List<String> deepenNotRefs = new ArrayList<>(); + final List<String> deepenNotRefs = new ArrayList<>(); - Set<String> clientCapabilities = new HashSet<>(); + final Set<String> clientCapabilities = new HashSet<>(); int depth; 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 a385339336..10df55ad48 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -299,25 +299,6 @@ public class UploadPack { /** Objects on both sides, these don't have to be sent. */ private final Set<RevObject> commonBase = new HashSet<>(); - /** Shallow commits the client already has. */ - private Set<ObjectId> clientShallowCommits = new HashSet<>(); - - /** Desired depth from the client on a shallow request. */ - private int depth; - - /** - * Commit time of the newest objects the client has asked us using - * --shallow-since not to send. Cannot be nonzero if depth is nonzero. - */ - private int shallowSince; - - /** - * (Possibly short) ref names, ancestors of which the client has asked us - * not to send using --shallow-exclude. Cannot be non-empty if depth is - * nonzero. - */ - private List<String> deepenNotRefs = new ArrayList<>(); - /** Commit time of the oldest common commit, in seconds. */ private int oldestTime; @@ -351,7 +332,14 @@ public class UploadPack { private PackStatistics statistics; - private long filterBlobLimit = -1; + /** + * Request this instance is handling. + * + * We need to keep a reference to it for {@link PreUploadHook pre upload + * hooks}. They receive a reference this instance and invoke methods like + * getDepth() to get information about the request. + */ + private FetchRequest currentRequest; /** * Create a new pack upload for an open repository. @@ -810,6 +798,7 @@ public class UploadPack { // writing a response. Buffer the response until then. PackStatistics.Accumulator accumulator = new PackStatistics.Accumulator(); List<ObjectId> unshallowCommits = new ArrayList<>(); + FetchRequest req; try { if (biDirectionalPipe) sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut)); @@ -822,13 +811,11 @@ public class UploadPack { accumulator.advertised = advertised.size(); ProtocolV0Parser parser = new ProtocolV0Parser(transferConfig); - FetchV0Request req = parser.recvWants(pckIn); + req = parser.recvWants(pckIn); + currentRequest = req; wantIds = req.getWantIds(); - clientShallowCommits = req.getClientShallowCommits(); - filterBlobLimit = req.getFilterBlobLimit(); options = req.getClientCapabilities(); - depth = req.getDepth(); if (req.getWantIds().isEmpty()) { preUploadHook.onBeginNegotiateRound(this, req.getWantIds(), 0); @@ -846,10 +833,12 @@ public class UploadPack { else multiAck = MultiAck.OFF; - if (!clientShallowCommits.isEmpty()) - verifyClientShallow(clientShallowCommits); - if (depth != 0 || shallowSince != 0) { - computeShallowsAndUnshallows(wantIds, shallow -> { + if (!req.getClientShallowCommits().isEmpty()) { + verifyClientShallow(req.getClientShallowCommits()); + } + + if (req.getDepth() != 0 || req.getDeepenSince() != 0) { + computeShallowsAndUnshallows(req, shallow -> { pckOut.writeString("shallow " + shallow.name() + '\n'); //$NON-NLS-1$ }, unshallow -> { pckOut.writeString("unshallow " + unshallow.name() + '\n'); //$NON-NLS-1$ @@ -857,9 +846,10 @@ public class UploadPack { }); pckOut.end(); } - if (!clientShallowCommits.isEmpty()) - walk.assumeShallow(clientShallowCommits); - sendPack = negotiate(accumulator); + + if (!req.getClientShallowCommits().isEmpty()) + walk.assumeShallow(req.getClientShallowCommits()); + sendPack = negotiate(req, accumulator); accumulator.timeNegotiating += System.currentTimeMillis() - negotiateStart; @@ -909,7 +899,8 @@ public class UploadPack { } if (sendPack) { - sendPack(accumulator, refs == null ? null : refs.values(), unshallowCommits); + sendPack(accumulator, req, refs == null ? null : refs.values(), + unshallowCommits); } } @@ -958,6 +949,7 @@ public class UploadPack { ProtocolV2Parser parser = new ProtocolV2Parser(transferConfig); FetchV2Request req = parser.parseFetchRequest(pckIn, db.getRefDatabase()); + currentRequest = req; rawOut.stopBuffering(); protocolV2Hook.onFetch(req); @@ -966,11 +958,6 @@ public class UploadPack { // copying data back to class fields options = req.getClientCapabilities(); wantIds = req.getWantIds(); - clientShallowCommits = req.getClientShallowCommits(); - depth = req.getDepth(); - shallowSince = req.getDeepenSince(); - filterBlobLimit = req.getFilterBlobLimit(); - deepenNotRefs = req.getDeepenNotRefs(); boolean sectionSent = false; boolean mayHaveShallow = req.getDepth() != 0 @@ -983,7 +970,7 @@ public class UploadPack { verifyClientShallow(req.getClientShallowCommits()); } if (mayHaveShallow) { - computeShallowsAndUnshallows(req.getWantIds(), + computeShallowsAndUnshallows(req, shallowCommit -> shallowCommits.add(shallowCommit), unshallowCommit -> unshallowCommits.add(unshallowCommit)); } @@ -1041,6 +1028,7 @@ public class UploadPack { pckOut.writeDelim(); pckOut.writeString("packfile\n"); //$NON-NLS-1$ sendPack(new PackStatistics.Accumulator(), + req, req.getClientCapabilities().contains(OPTION_INCLUDE_TAG) ? db.getRefDatabase().getRefsByPrefix(R_TAGS) : null, @@ -1146,24 +1134,26 @@ public class UploadPack { * Determines what object ids must be marked as shallow or unshallow for the * client. */ - private void computeShallowsAndUnshallows(Iterable<ObjectId> wants, + private void computeShallowsAndUnshallows(FetchRequest req, IOConsumer<ObjectId> shallowFunc, IOConsumer<ObjectId> unshallowFunc) throws IOException { - if (options.contains(OPTION_DEEPEN_RELATIVE) || !deepenNotRefs.isEmpty()) { + if (req.getClientCapabilities().contains(OPTION_DEEPEN_RELATIVE) + || !req.getDeepenNotRefs().isEmpty()) { // TODO(jonathantanmy): Implement deepen-relative // and deepen-not. throw new UnsupportedOperationException(); } - int walkDepth = depth == 0 ? Integer.MAX_VALUE : depth - 1; + int walkDepth = req.getDepth() == 0 ? Integer.MAX_VALUE + : req.getDepth() - 1; try (DepthWalk.RevWalk depthWalk = new DepthWalk.RevWalk( walk.getObjectReader(), walkDepth)) { - depthWalk.setDeepenSince(shallowSince); + depthWalk.setDeepenSince(req.getDeepenSince()); // Find all the commits which will be shallow - for (ObjectId o : wants) { + for (ObjectId o : req.getWantIds()) { try { depthWalk.markRoot(depthWalk.parseCommit(o)); } catch (IncorrectObjectTypeException notCommit) { @@ -1179,13 +1169,13 @@ public class UploadPack { // Commits at the boundary which aren't already shallow in // the client need to be marked as such - if (isBoundary && !clientShallowCommits.contains(c)) { + if (isBoundary && !req.getClientShallowCommits().contains(c)) { shallowFunc.accept(c.copy()); } // Commits not on the boundary which are shallow in the client // need to become unshallowed - if (!isBoundary && clientShallowCommits.remove(c)) { + if (!isBoundary && req.getClientShallowCommits().remove(c)) { unshallowFunc.accept(c.copy()); } } @@ -1357,9 +1347,9 @@ public class UploadPack { * @since 4.0 */ public int getDepth() { - if (options == null) + if (currentRequest == null) throw new RequestNotYetReadException(); - return depth; + return currentRequest.getDepth(); } /** @@ -1381,7 +1371,8 @@ public class UploadPack { return UserAgent.getAgent(options, userAgent); } - private boolean negotiate(PackStatistics.Accumulator accumulator) + private boolean negotiate(FetchRequest req, + PackStatistics.Accumulator accumulator) throws IOException { okToGiveUp = Boolean.FALSE; @@ -1397,7 +1388,7 @@ public class UploadPack { // disconnected, and will try another request with actual want/have. // Don't report the EOF here, its a bug in the protocol that the client // just disconnects without sending an END. - if (!biDirectionalPipe && depth > 0) + if (!biDirectionalPipe && req.getDepth() > 0) return false; throw eof; } @@ -1778,25 +1769,26 @@ public class UploadPack { * Send the requested objects to the client. * * @param accumulator - * where to write statistics about the content of the pack. + * where to write statistics about the content of the pack. + * @param req + * 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. + * refs to search for annotated tags to include in the pack if + * the {@link #OPTION_INCLUDE_TAG} capability was requested. * @param unshallowCommits - * shallow commits on the client that are now becoming - * unshallow + * shallow commits on the client that are now becoming unshallow * @throws IOException - * if an error occured while generating or writing the pack. + * if an error occured while generating or writing the pack. */ private void sendPack(PackStatistics.Accumulator accumulator, + FetchRequest req, @Nullable Collection<Ref> allTags, List<ObjectId> unshallowCommits) throws IOException { final boolean sideband = options.contains(OPTION_SIDE_BAND) || options.contains(OPTION_SIDE_BAND_64K); if (sideband) { try { - sendPack(true, accumulator, allTags, unshallowCommits); + sendPack(true, req, accumulator, allTags, unshallowCommits); } catch (ServiceMayNotContinueException noPack) { // This was already reported on (below). throw noPack; @@ -1817,7 +1809,7 @@ public class UploadPack { throw err; } } else { - sendPack(false, accumulator, allTags, unshallowCommits); + sendPack(false, req, accumulator, allTags, unshallowCommits); } } @@ -1841,21 +1833,22 @@ public class UploadPack { * Send the requested objects to the client. * * @param sideband - * whether to wrap the pack in side-band pkt-lines, - * interleaved with progress messages and errors. + * whether to wrap the pack in side-band pkt-lines, interleaved + * with progress messages and errors. + * @param req + * request being processed * @param accumulator - * where to write statistics about the content of the pack. + * 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. + * refs to search for annotated tags to include in the pack if + * the {@link #OPTION_INCLUDE_TAG} capability was requested. * @param unshallowCommits - * shallow commits on the client that are now becoming - * unshallow + * shallow commits on the client that are now becoming unshallow * @throws IOException - * if an error occured while generating or writing the pack. + * if an error occured while generating or writing the pack. */ private void sendPack(final boolean sideband, + FetchRequest req, PackStatistics.Accumulator accumulator, @Nullable Collection<Ref> allTags, List<ObjectId> unshallowCommits) throws IOException { @@ -1905,14 +1898,16 @@ public class UploadPack { accumulator); try { pw.setIndexDisabled(true); - if (filterBlobLimit >= 0) { - pw.setFilterBlobLimit(filterBlobLimit); + if (req.getFilterBlobLimit() >= 0) { + pw.setFilterBlobLimit(req.getFilterBlobLimit()); pw.setUseCachedPacks(false); } else { pw.setUseCachedPacks(true); } - pw.setUseBitmaps(depth == 0 && clientShallowCommits.isEmpty()); - pw.setClientShallowCommits(clientShallowCommits); + pw.setUseBitmaps( + req.getDepth() == 0 + && req.getClientShallowCommits().isEmpty()); + pw.setClientShallowCommits(req.getClientShallowCommits()); pw.setReuseDeltaCommits(true); pw.setDeltaBaseAsOffset(options.contains(OPTION_OFS_DELTA)); pw.setThin(options.contains(OPTION_THIN_PACK)); @@ -1934,16 +1929,18 @@ public class UploadPack { } RevWalk rw = walk; - if (depth > 0 || shallowSince != 0) { - int walkDepth = depth == 0 ? Integer.MAX_VALUE : depth - 1; - pw.setShallowPack(depth, unshallowCommits); + if (req.getDepth() > 0 || req.getDeepenSince() != 0) { + int walkDepth = req.getDepth() == 0 ? Integer.MAX_VALUE + : req.getDepth() - 1; + pw.setShallowPack(req.getDepth(), unshallowCommits); rw = new DepthWalk.RevWalk(walk.getObjectReader(), walkDepth); - ((DepthWalk.RevWalk) rw).setDeepenSince(shallowSince); - rw.assumeShallow(clientShallowCommits); + ((DepthWalk.RevWalk) rw).setDeepenSince(req.getDeepenSince()); + rw.assumeShallow(req.getClientShallowCommits()); } if (wantAll.isEmpty()) { - pw.preparePack(pm, wantIds, commonBase, clientShallowCommits); + pw.preparePack(pm, wantIds, commonBase, + req.getClientShallowCommits()); } else { walk.reset(); |