diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java index de7279358..50d831031 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java @@ -111,6 +111,26 @@ public class PackWriterTest extends SampleDataRepositoryTestCase { private FileRepository dst; + private RevBlob contentA; + + private RevBlob contentB; + + private RevBlob contentC; + + private RevBlob contentD; + + private RevBlob contentE; + + private RevCommit c1; + + private RevCommit c2; + + private RevCommit c3; + + private RevCommit c4; + + private RevCommit c5; + @Before public void setUp() throws Exception { super.setUp(); @@ -517,16 +537,16 @@ public void testExclude() throws Exception { TestRepository testRepo = new TestRepository( repo); BranchBuilder bb = testRepo.branch("refs/heads/master"); - RevBlob contentA = testRepo.blob("A"); - RevCommit c1 = bb.commit().add("f", contentA).create(); + contentA = testRepo.blob("A"); + c1 = bb.commit().add("f", contentA).create(); testRepo.getRevWalk().parseHeaders(c1); PackIndex pf1 = writePack(repo, wants(c1), EMPTY_ID_SET); assertContent( pf1, Arrays.asList(c1.getId(), c1.getTree().getId(), contentA.getId())); - RevBlob contentB = testRepo.blob("B"); - RevCommit c2 = bb.commit().add("f", contentB).create(); + contentB = testRepo.blob("B"); + c2 = bb.commit().add("f", contentB).create(); testRepo.getRevWalk().parseHeaders(c2); PackIndex pf2 = writePack(repo, wants(c2), Sets.of((ObjectIdSet) pf1)); assertContent( @@ -547,24 +567,7 @@ private static void assertContent(PackIndex pi, List expected) { @Test public void testShallowIsMinimal() throws Exception { - FileRepository repo = createBareRepository(); - TestRepository r = new TestRepository(repo); - BranchBuilder bb = r.branch("refs/heads/master"); - RevBlob contentA = r.blob("A"); - RevBlob contentB = r.blob("B"); - RevBlob contentC = r.blob("C"); - RevBlob contentD = r.blob("D"); - RevBlob contentE = r.blob("E"); - RevCommit c1 = bb.commit().add("a", contentA).create(); - RevCommit c2 = bb.commit().add("b", contentB).create(); - RevCommit c3 = bb.commit().add("c", contentC).create(); - RevCommit c4 = bb.commit().add("d", contentD).create(); - RevCommit c5 = bb.commit().add("e", contentE).create(); - r.getRevWalk().parseHeaders(c1); - r.getRevWalk().parseHeaders(c2); - r.getRevWalk().parseHeaders(c3); - r.getRevWalk().parseHeaders(c4); - r.getRevWalk().parseHeaders(c5); + FileRepository repo = setupRepoForShallowFetch(); PackIndex idx = writeShallowPack(repo, 1, wants(c2), NONE, NONE); assertContent(idx, @@ -580,6 +583,56 @@ public void testShallowIsMinimal() throws Exception { contentD.getId(), contentE.getId())); } + @Test + public void testShallowFetchShallowParent() throws Exception { + FileRepository repo = setupRepoForShallowFetch(); + + PackIndex idx = writeShallowPack(repo, 1, wants(c5), NONE, NONE); + assertContent(idx, + Arrays.asList(c4.getId(), c5.getId(), c4.getTree().getId(), + c5.getTree().getId(), contentA.getId(), + contentB.getId(), contentC.getId(), contentD.getId(), + contentE.getId())); + + idx = writeShallowPack(repo, 1, wants(c3), haves(c4, c5), shallows(c4)); + assertContent(idx, Arrays.asList(c2.getId(), c3.getId(), + c2.getTree().getId(), c3.getTree().getId())); + } + + @Test + public void testShallowFetchShallowAncestor() throws Exception { + FileRepository repo = setupRepoForShallowFetch(); + + PackIndex idx = writeShallowPack(repo, 1, wants(c5), NONE, NONE); + assertContent(idx, + Arrays.asList(c4.getId(), c5.getId(), c4.getTree().getId(), + c5.getTree().getId(), contentA.getId(), + contentB.getId(), contentC.getId(), contentD.getId(), + contentE.getId())); + + idx = writeShallowPack(repo, 1, wants(c2), haves(c4, c5), shallows(c4)); + assertContent(idx, Arrays.asList(c1.getId(), c2.getId(), + c1.getTree().getId(), c2.getTree().getId())); + } + + private FileRepository setupRepoForShallowFetch() throws Exception { + FileRepository repo = createBareRepository(); + TestRepository r = new TestRepository(repo); + BranchBuilder bb = r.branch("refs/heads/master"); + contentA = r.blob("A"); + contentB = r.blob("B"); + contentC = r.blob("C"); + contentD = r.blob("D"); + contentE = r.blob("E"); + c1 = bb.commit().add("a", contentA).create(); + c2 = bb.commit().add("b", contentB).create(); + c3 = bb.commit().add("c", contentC).create(); + c4 = bb.commit().add("d", contentD).create(); + c5 = bb.commit().add("e", contentE).create(); + r.getRevWalk().parseHeaders(c5); // fully initialize the tip RevCommit + return repo; + } + private static PackIndex writePack(FileRepository repo, Set want, Set excludeObjects) throws IOException { diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index 5dcadd385..681b6ac9f 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -557,6 +557,7 @@ sequenceTooLargeForDiffAlgorithm=Sequence too large for difference algorithm. serviceNotEnabledNoName=Service not enabled serviceNotPermitted={0} not permitted shallowCommitsAlreadyInitialized=Shallow commits have already been initialized +shallowPacksRequireDepthWalk=Shallow packs require a DepthWalk shortCompressedStreamAt=Short compressed stream at {0} shortReadOfBlock=Short read of block. shortReadOfOptionalDIRCExtensionExpectedAnotherBytes=Short read of optional DIRC extension {0}; expected another {1} bytes within the section. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index fc54fd80a..127596fe3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -616,6 +616,7 @@ public static JGitText get() { /***/ public String serviceNotEnabledNoName; /***/ public String serviceNotPermitted; /***/ public String shallowCommitsAlreadyInitialized; + /***/ public String shallowPacksRequireDepthWalk; /***/ public String shortCompressedStreamAt; /***/ public String shortReadOfBlock; /***/ public String shortReadOfOptionalDIRCExtensionExpectedAnotherBytes; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index 4c0fc47f6..106308f4a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -752,7 +752,8 @@ public void preparePack(ProgressMonitor countingMonitor, if (countingMonitor == null) countingMonitor = NullProgressMonitor.INSTANCE; if (shallowPack && !(walk instanceof DepthWalk.ObjectWalk)) - walk = new DepthWalk.ObjectWalk(reader, depth); + throw new IllegalArgumentException( + JGitText.get().shallowPacksRequireDepthWalk); findObjectsToPack(countingMonitor, walk, interestingObjects, uninterestingObjects); } @@ -1654,7 +1655,7 @@ private void findObjectsToPack(@NonNull ProgressMonitor countingMonitor, List wantTags = new ArrayList(want.size()); // Retrieve the RevWalk's versions of "want" and "have" objects to - // maintain any flags previously set in the RevWalk. + // maintain any state previously set in the RevWalk. AsyncRevObjectQueue q = walker.parseAny(all, true); try { for (;;) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthWalk.java index 89d05dba5..914b8a8d1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthWalk.java @@ -149,6 +149,14 @@ public RevFlag getUnshallowFlag() { public RevFlag getReinterestingFlag() { return REINTERESTING; } + + @Override + public ObjectWalk toObjectWalkWithSameObjects() { + ObjectWalk ow = new ObjectWalk(reader, depth); + ow.objects = objects; + ow.freeFlags = freeFlags; + return ow; + } } /** Subclass of ObjectWalk that performs depth filtering. */