From b0174a089ce886d02c8d7fb80d63f0e50329bec3 Mon Sep 17 00:00:00 2001 From: Shawn Pearce Date: Tue, 28 Jan 2014 16:29:15 -0800 Subject: [PATCH] Fix serving fetch of existing shallow client 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 --- .../src/org/eclipse/jgit/revwalk/RevWalk.java | 12 ++++++++++++ .../src/org/eclipse/jgit/transport/UploadPack.java | 6 ++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java index ca5f4fe61..32d4aac75 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java @@ -1308,6 +1308,18 @@ void carryFlagsImpl(final RevCommit c) { 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 ids) { + for (ObjectId id : ids) + lookupCommit(id).parents = RevCommit.NO_PARENTS; + } + void initializeShallowCommits() throws IOException { if (shallowCommitsInitialized) throw new IllegalStateException( 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 0cc6946b1..b007f2b51 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -684,6 +684,8 @@ else if (requestValidator instanceof AnyRequestValidator) if (depth != 0) processShallow(); + if (!clientShallowCommits.isEmpty()) + walk.assumeShallow(clientShallowCommits); sendPack = negotiate(); } catch (PackProtocolException err) { reportErrorDuringNegotiate(err.getMessage()); @@ -756,7 +758,7 @@ private void processShallow() throws IOException { // 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 @@ private void sendPack(final boolean sideband) throws IOException { 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));