]> source.dussan.org Git - jgit.git/commitdiff
Fix serving fetch of existing shallow client 27/21227/2
authorShawn Pearce <spearce@spearce.org>
Wed, 29 Jan 2014 00:29:15 +0000 (16:29 -0800)
committerShawn Pearce <spearce@spearce.org>
Wed, 29 Jan 2014 01:29:00 +0000 (17:29 -0800)
In certain cases a JGit server updating an existing shallow client
selected a common ancestor that was behind the shallow edge of
the client. This allowed the server to assume the client had some
objects it did not have and allowed creation of pack deltas the
client could never inflate.

Any commit the client has advertised as shallow must be treated
by UploadPack server as though it has no parents. With no parents
the walker cannot visit graph history the client does not have,
and PackWriter cannot consider delta base candidates the client
is lacking.

Change-Id: I4922b9354df9f490966a586fb693762e897345a2

org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java

index ca5f4fe6167fd9ad2a56c7b2dedd77fc9b5d68f8..32d4aac75d06940e6d8698f47f3ac348aa728055 100644 (file)
@@ -1308,6 +1308,18 @@ public class RevWalk implements Iterable<RevCommit> {
                        RevCommit.carryFlags(c, carry);
        }
 
+       /**
+        * Assume additional commits are shallow (have no parents).
+        *
+        * @param ids
+        *            commits that should be treated as shallow commits, in addition
+        *            to any commits already known to be shallow by the repository.
+        */
+       public void assumeShallow(Collection<? extends ObjectId> ids) {
+               for (ObjectId id : ids)
+                       lookupCommit(id).parents = RevCommit.NO_PARENTS;
+       }
+
        void initializeShallowCommits() throws IOException {
                if (shallowCommitsInitialized)
                        throw new IllegalStateException(
index 0cc6946b12e70df0a528598ab2c367989a65ef6c..b007f2b513e00d508c2076aaaba4b90b4aab44b7 100644 (file)
@@ -684,6 +684,8 @@ public class UploadPack {
 
                        if (depth != 0)
                                processShallow();
+                       if (!clientShallowCommits.isEmpty())
+                               walk.assumeShallow(clientShallowCommits);
                        sendPack = negotiate();
                } catch (PackProtocolException err) {
                        reportErrorDuringNegotiate(err.getMessage());
@@ -756,7 +758,7 @@ public class UploadPack {
 
                        // Commits not on the boundary which are shallow in the client
                        // need to become unshallowed
-                       if (c.getDepth() < depth && clientShallowCommits.contains(c)) {
+                       if (c.getDepth() < depth && clientShallowCommits.remove(c)) {
                                unshallowCommits.add(c.copy());
                                pckOut.writeString("unshallow " + c.name()); //$NON-NLS-1$
                        }
@@ -1350,7 +1352,7 @@ public class UploadPack {
                try {
                        pw.setIndexDisabled(true);
                        pw.setUseCachedPacks(true);
-                       pw.setUseBitmaps(true);
+                       pw.setUseBitmaps(depth == 0 && clientShallowCommits.isEmpty());
                        pw.setReuseDeltaCommits(true);
                        pw.setDeltaBaseAsOffset(options.contains(OPTION_OFS_DELTA));
                        pw.setThin(options.contains(OPTION_THIN_PACK));