Adds FilteredRevCommit that can overwrites its parents in the DAG.
Change-Id: I1ea63a3b56074099688fc45d6a22943a8ae3c2ae
This commit is contained in:
parent
ab3799be37
commit
6297491e8a
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (C) 2022, Google LLC.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
package org.eclipse.jgit.revwalk;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
|
||||
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
|
||||
import org.eclipse.jgit.junit.TestRepository;
|
||||
import org.eclipse.jgit.lib.AnyObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FilteredRevCommitTest {
|
||||
private TestRepository<InMemoryRepository> tr;
|
||||
|
||||
private RevWalk rw;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
tr = new TestRepository<>(
|
||||
new InMemoryRepository(new DfsRepositoryDescription("test")));
|
||||
rw = tr.getRevWalk();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseHeaders_noParent() throws Exception {
|
||||
RevCommit root = tr.commit().add("todelete", "to be deleted").create();
|
||||
RevCommit orig = tr.commit().parent(root).rm("todelete")
|
||||
.add("foo", "foo contents").add("bar", "bar contents")
|
||||
.add("dir/baz", "baz contents").create();
|
||||
FilteredRevCommit filteredRevCommit = new FilteredRevCommit(orig);
|
||||
filteredRevCommit.parseHeaders(rw);
|
||||
tr.branch("master").update(filteredRevCommit);
|
||||
assertEquals("foo contents", blobAsString(filteredRevCommit, "foo"));
|
||||
assertEquals("bar contents", blobAsString(filteredRevCommit, "bar"));
|
||||
assertEquals("baz contents",
|
||||
blobAsString(filteredRevCommit, "dir/baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParents() throws Exception {
|
||||
RevCommit commit1 = tr.commit().add("foo", "foo contents\n").create();
|
||||
RevCommit commit2 = tr.commit().parent(commit1)
|
||||
.message("original message").add("bar", "bar contents")
|
||||
.create();
|
||||
RevCommit commit3 = tr.commit().parent(commit2).message("commit3")
|
||||
.add("foo", "foo contents\n new line\n").create();
|
||||
|
||||
FilteredRevCommit filteredCommitHead = new FilteredRevCommit(commit3,
|
||||
commit1);
|
||||
|
||||
assertEquals(commit1, Arrays.stream(filteredCommitHead.getParents())
|
||||
.findFirst().get());
|
||||
assertEquals("commit3", filteredCommitHead.getFullMessage());
|
||||
assertEquals("foo contents\n new line\n",
|
||||
blobAsString(filteredCommitHead, "foo"));
|
||||
assertEquals(filteredCommitHead.getTree(), commit3.getTree());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlag() throws Exception {
|
||||
RevCommit root = tr.commit().add("todelete", "to be deleted").create();
|
||||
RevCommit orig = tr.commit().parent(root).rm("todelete")
|
||||
.add("foo", "foo contents").add("bar", "bar contents")
|
||||
.add("dir/baz", "baz contents").create();
|
||||
|
||||
FilteredRevCommit filteredRevCommit = new FilteredRevCommit(orig, root);
|
||||
assertEquals(RevObject.PARSED, orig.flags);
|
||||
assertEquals(RevObject.PARSED, filteredRevCommit.flags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommitState() throws Exception {
|
||||
RevCommit root = tr.commit().add("todelete", "to be deleted").create();
|
||||
RevCommit orig = tr.commit().parent(root).rm("todelete")
|
||||
.add("foo", "foo contents").add("bar", "bar contents")
|
||||
.add("dir/baz", "baz contents").create();
|
||||
|
||||
FilteredRevCommit filteredRevCommit = new FilteredRevCommit(orig, root);
|
||||
assertEquals(filteredRevCommit.getParentCount(), 1);
|
||||
assertSame(filteredRevCommit.getRawBuffer(), orig.getRawBuffer());
|
||||
assertSame(filteredRevCommit.getTree(), orig.getTree());
|
||||
assertEquals(filteredRevCommit.getFullMessage(), orig.getFullMessage());
|
||||
assertEquals(filteredRevCommit.commitTime, orig.commitTime);
|
||||
assertSame(filteredRevCommit.parents, RevCommit.NO_PARENTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCommit_withParents_parsesRealParents()
|
||||
throws Exception {
|
||||
RevCommit commit1 = tr.commit().add("foo", "foo contents\n").create();
|
||||
RevCommit commit2 = tr.commit().parent(commit1)
|
||||
.message("original message").add("bar", "bar contents")
|
||||
.create();
|
||||
RevCommit commit3 = tr.commit().parent(commit2).message("commit3")
|
||||
.add("foo", "foo contents\n new line\n").create();
|
||||
|
||||
FilteredRevCommit filteredCommitHead = new FilteredRevCommit(commit3,
|
||||
commit1);
|
||||
|
||||
RevCommit parsedCommit = rw.parseCommit(filteredCommitHead.getId());
|
||||
assertEquals(filteredCommitHead.getId(), commit3.getId());
|
||||
// This is an intended behavior as revWalk#parseCommit doesn't parse
|
||||
// through the overridden parents rather uses the real parents.
|
||||
assertNotEquals(
|
||||
Arrays.stream(parsedCommit.getParents()).findFirst().get(),
|
||||
Arrays.stream(filteredCommitHead.getParents()).findFirst()
|
||||
.get());
|
||||
}
|
||||
|
||||
private String blobAsString(AnyObjectId treeish, String path)
|
||||
throws Exception {
|
||||
RevObject obj = tr.get(rw.parseTree(treeish), path);
|
||||
assertSame(RevBlob.class, obj.getClass());
|
||||
ObjectLoader loader = rw.getObjectReader().open(obj);
|
||||
return new String(loader.getCachedBytes(), UTF_8);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (C) 2022, Google LLC.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
package org.eclipse.jgit.revwalk;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import org.eclipse.jgit.internal.storage.file.FileRepository;
|
||||
import org.eclipse.jgit.junit.TestRepository;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FilteredRevWalkTest extends RevWalkTestCase {
|
||||
private TestRepository<FileRepository> repository;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
repository = new TestRepository<>(db);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWalk() throws Exception {
|
||||
writeTrashFile("a.txt", "content");
|
||||
repository.git().add().addFilepattern("a.txt").call();
|
||||
RevCommit c1 = repository.git().commit().setMessage("first commit")
|
||||
.call();
|
||||
|
||||
writeTrashFile("b.txt", "new file added");
|
||||
repository.git().add().addFilepattern("b.txt").call();
|
||||
repository.git().commit().setMessage("second commit").call();
|
||||
|
||||
writeTrashFile("a.txt", "content added");
|
||||
repository.git().add().addFilepattern("a.txt").call();
|
||||
RevCommit c3 = repository.git().commit().setMessage("third commit")
|
||||
.call();
|
||||
|
||||
RevWalk revWalk = repository.getRevWalk();
|
||||
FilteredRevCommit filteredRevCommit = new FilteredRevCommit(c3, c1);
|
||||
|
||||
revWalk.markStart(filteredRevCommit);
|
||||
assertEquals(c3, revWalk.next());
|
||||
assertEquals(c1, revWalk.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseBody() throws Exception {
|
||||
writeTrashFile("a.txt", "content");
|
||||
repository.git().add().addFilepattern("a.txt").call();
|
||||
RevCommit c1 = repository.git().commit().setMessage("first commit")
|
||||
.call();
|
||||
|
||||
writeTrashFile("b.txt", "new file added");
|
||||
repository.git().add().addFilepattern("b.txt").call();
|
||||
repository.git().commit().setMessage("second commit").call();
|
||||
|
||||
writeTrashFile("a.txt", "content added");
|
||||
repository.git().add().addFilepattern("a.txt").call();
|
||||
RevCommit c3 = repository.git().commit().setMessage("third commit")
|
||||
.call();
|
||||
|
||||
FilteredRevCommit filteredRevCommit = new FilteredRevCommit(c3, c1);
|
||||
filteredRevCommit.disposeBody();
|
||||
|
||||
RevWalk revWalk = repository.getRevWalk();
|
||||
|
||||
revWalk.parseBody(filteredRevCommit);
|
||||
assertEquals(filteredRevCommit.getFullMessage(), c3.getFullMessage());
|
||||
assertEquals(filteredRevCommit.getShortMessage(), c3.getShortMessage());
|
||||
assertEquals(filteredRevCommit.commitTime, c3.commitTime);
|
||||
assertSame(filteredRevCommit.getTree(), c3.getTree());
|
||||
assertSame(filteredRevCommit.parents, RevCommit.NO_PARENTS);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the uninteresting flag is carried over correctly. Every commit
|
||||
* should have the uninteresting flag resulting in a RevWalk returning no
|
||||
* commit.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testRevWalkCarryUninteresting() throws Exception {
|
||||
writeTrashFile("a.txt", "content");
|
||||
repository.git().add().addFilepattern("a.txt").call();
|
||||
RevCommit c1 = repository.git().commit().setMessage("first commit")
|
||||
.call();
|
||||
|
||||
writeTrashFile("b.txt", "new file added");
|
||||
repository.git().add().addFilepattern("b.txt").call();
|
||||
RevCommit c2 = repository.git().commit().setMessage("second commit")
|
||||
.call();
|
||||
|
||||
writeTrashFile("a.txt", "content added");
|
||||
repository.git().add().addFilepattern("a.txt").call();
|
||||
RevCommit c3 = repository.git().commit().setMessage("third commit")
|
||||
.call();
|
||||
|
||||
RevWalk revWalk = repository.getRevWalk();
|
||||
FilteredRevCommit filteredCommit1 = new FilteredRevCommit(c1);
|
||||
FilteredRevCommit filteredCommit2 = new FilteredRevCommit(c2,
|
||||
filteredCommit1);
|
||||
FilteredRevCommit filteredCommit3 = new FilteredRevCommit(c3,
|
||||
filteredCommit2);
|
||||
|
||||
revWalk.markStart(filteredCommit2);
|
||||
markUninteresting(filteredCommit3);
|
||||
assertNull("Found an unexpected commit", rw.next());
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
|
||||
|
@ -423,9 +424,41 @@ public void testWithTopoSortAndTreeFilter() throws Exception {
|
|||
rw.sort(RevSort.TOPO, true);
|
||||
rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
|
||||
markStart(d);
|
||||
assertCommit(d, rw.next());
|
||||
assertCommit(c, rw.next());
|
||||
assertCommit(b, rw.next());
|
||||
|
||||
assertEquals(d, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(b, rw.next());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithTopoSortAndTreeFilter_shouldUseFilteredRevCommits()
|
||||
throws Exception {
|
||||
RevCommit a = commit();
|
||||
RevCommit b = commit(tree(file("0", blob("b"))), a);
|
||||
RevCommit c = commit(tree(file("0", blob("c"))), b, a);
|
||||
RevCommit d = commit(tree(file("0", blob("d"))), c);
|
||||
|
||||
rw.reset();
|
||||
rw.setFirstParent(true);
|
||||
rw.sort(RevSort.TOPO, true);
|
||||
rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
|
||||
markStart(d);
|
||||
|
||||
RevCommit x = rw.next();
|
||||
assertTrue(x instanceof FilteredRevCommit);
|
||||
assertEquals(1, x.getParentCount());
|
||||
assertEquals(c, x.getParent(0));
|
||||
|
||||
RevCommit y = rw.next();
|
||||
assertTrue(y instanceof FilteredRevCommit);
|
||||
assertEquals(1, y.getParentCount());
|
||||
assertEquals(b, y.getParent(0));
|
||||
|
||||
RevCommit z = rw.next();
|
||||
assertTrue(z instanceof FilteredRevCommit);
|
||||
assertEquals(0, z.getParentCount());
|
||||
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
|
@ -441,8 +474,8 @@ public void testWithTopoSortAndTreeFilter2() throws Exception {
|
|||
rw.sort(RevSort.TOPO, true);
|
||||
rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
|
||||
markStart(d);
|
||||
assertCommit(d, rw.next());
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(d, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
|
@ -458,9 +491,9 @@ public void testWithTopoNonIntermixSortAndTreeFilter() throws Exception {
|
|||
rw.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER, true);
|
||||
rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
|
||||
markStart(d);
|
||||
assertCommit(d, rw.next());
|
||||
assertCommit(c, rw.next());
|
||||
assertCommit(b, rw.next());
|
||||
assertEquals(d, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(b, rw.next());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
|
@ -476,8 +509,8 @@ public void testWithTopoNonIntermixSortAndTreeFilter2() throws Exception {
|
|||
rw.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER, true);
|
||||
rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
|
||||
markStart(d);
|
||||
assertCommit(d, rw.next());
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(d, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
package org.eclipse.jgit.revwalk;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -55,7 +56,7 @@ public void testNoRename() throws Exception {
|
|||
final RevCommit a = commit(tree(file("0", blob("0"))));
|
||||
follow("0");
|
||||
markStart(a);
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertNull(rw.next());
|
||||
|
||||
assertNoRenames();
|
||||
|
@ -72,8 +73,8 @@ public void testSingleRename() throws Exception {
|
|||
|
||||
follow("b");
|
||||
markStart(renameCommit);
|
||||
assertCommit(renameCommit, rw.next());
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(renameCommit, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertNull(rw.next());
|
||||
|
||||
assertRenames("a->b");
|
||||
|
@ -101,10 +102,10 @@ public void testMultiRename() throws Exception {
|
|||
|
||||
follow("a");
|
||||
markStart(renameCommit3);
|
||||
assertCommit(renameCommit3, rw.next());
|
||||
assertCommit(renameCommit2, rw.next());
|
||||
assertCommit(renameCommit1, rw.next());
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(renameCommit3, rw.next());
|
||||
assertEquals(renameCommit2, rw.next());
|
||||
assertEquals(renameCommit1, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertNull(rw.next());
|
||||
|
||||
assertRenames("c->a", "b->c", "a->b");
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.jgit.revwalk;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -23,8 +24,8 @@
|
|||
|
||||
public class RevWalkPathFilter1Test extends RevWalkTestCase {
|
||||
protected void filter(String path) {
|
||||
rw.setTreeFilter(AndTreeFilter.create(PathFilterGroup
|
||||
.createFromStrings(Collections.singleton(path)),
|
||||
rw.setTreeFilter(AndTreeFilter.create(
|
||||
PathFilterGroup.createFromStrings(Collections.singleton(path)),
|
||||
TreeFilter.ANY_DIFF));
|
||||
}
|
||||
|
||||
|
@ -49,7 +50,7 @@ public void testSimple1() throws Exception {
|
|||
final RevCommit a = commit(tree(file("0", blob("0"))));
|
||||
filter("0");
|
||||
markStart(a);
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
|
@ -72,10 +73,10 @@ public void testEdits_MatchAll() throws Exception {
|
|||
final RevCommit d = commit(tree(file("0", blob("d"))), c);
|
||||
filter("0");
|
||||
markStart(d);
|
||||
assertCommit(d, rw.next());
|
||||
assertCommit(c, rw.next());
|
||||
assertCommit(b, rw.next());
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(d, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(b, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
|
@ -87,11 +88,11 @@ public void testStringOfPearls_FilePath1() throws Exception {
|
|||
filter("d/f");
|
||||
markStart(c);
|
||||
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(1, c.getParentCount());
|
||||
assertCommit(a, c.getParent(0)); // b was skipped
|
||||
assertEquals(a, c.getParent(0)); // b was skipped
|
||||
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertEquals(0, a.getParentCount());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
@ -106,11 +107,11 @@ public void testStringOfPearls_FilePath1_NoParentRewriting()
|
|||
markStart(c);
|
||||
rw.setRewriteParents(false);
|
||||
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(1, c.getParentCount());
|
||||
assertCommit(b, c.getParent(0));
|
||||
assertEquals(b, c.getParent(0));
|
||||
|
||||
assertCommit(a, rw.next()); // b was skipped
|
||||
assertEquals(a, rw.next()); // b was skipped
|
||||
assertEquals(0, a.getParentCount());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
@ -125,18 +126,18 @@ public void testStringOfPearls_FilePath2() throws Exception {
|
|||
markStart(d);
|
||||
|
||||
// d was skipped
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(1, c.getParentCount());
|
||||
assertCommit(a, c.getParent(0)); // b was skipped
|
||||
assertEquals(a, c.getParent(0)); // b was skipped
|
||||
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertEquals(0, a.getParentCount());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringOfPearls_FilePath2_NoParentRewriting()
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
final RevCommit a = commit(tree(file("d/f", blob("a"))));
|
||||
final RevCommit b = commit(tree(file("d/f", blob("a"))), a);
|
||||
final RevCommit c = commit(tree(file("d/f", blob("b"))), b);
|
||||
|
@ -146,12 +147,12 @@ public void testStringOfPearls_FilePath2_NoParentRewriting()
|
|||
rw.setRewriteParents(false);
|
||||
|
||||
// d was skipped
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(1, c.getParentCount());
|
||||
assertCommit(b, c.getParent(0));
|
||||
assertEquals(b, c.getParent(0));
|
||||
|
||||
// b was skipped
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertEquals(0, a.getParentCount());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
@ -166,11 +167,11 @@ public void testStringOfPearls_DirPath2() throws Exception {
|
|||
markStart(d);
|
||||
|
||||
// d was skipped
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(1, c.getParentCount());
|
||||
assertCommit(a, c.getParent(0)); // b was skipped
|
||||
assertEquals(a, c.getParent(0)); // b was skipped
|
||||
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertEquals(0, a.getParentCount());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
@ -211,15 +212,15 @@ public void testStringOfPearls_FilePath3() throws Exception {
|
|||
filter("d/f");
|
||||
markStart(i);
|
||||
|
||||
assertCommit(i, rw.next());
|
||||
assertEquals(i, rw.next());
|
||||
assertEquals(1, i.getParentCount());
|
||||
assertCommit(c, i.getParent(0)); // h..d was skipped
|
||||
assertEquals(c, i.getParent(0)); // h..d was skipped
|
||||
|
||||
assertCommit(c, rw.next());
|
||||
assertEquals(c, rw.next());
|
||||
assertEquals(1, c.getParentCount());
|
||||
assertCommit(a, c.getParent(0)); // b was skipped
|
||||
assertEquals(a, c.getParent(0)); // b was skipped
|
||||
|
||||
assertCommit(a, rw.next());
|
||||
assertEquals(a, rw.next());
|
||||
assertEquals(0, a.getParentCount());
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
@ -273,4 +274,49 @@ public void testStopWhenPathDisappears() throws Exception {
|
|||
assertCommit(b, rw.next());
|
||||
assertCommit(a, rw.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommitHeaders_rewrittenParents() throws Exception {
|
||||
final RevCommit a = commit(tree(file("d/f", blob("a"))));
|
||||
final RevCommit b = commit(tree(file("d/f", blob("a"))), a);
|
||||
final RevCommit c = commit(tree(file("d/f", blob("b"))), b);
|
||||
filter("d/f");
|
||||
markStart(c);
|
||||
|
||||
RevCommit cBar = rw.next();
|
||||
assertNotNull(cBar.getShortMessage());
|
||||
assertEquals(cBar.getCommitTime(), c.getCommitTime());
|
||||
|
||||
RevCommit aBar = rw.next();
|
||||
assertNotNull(aBar.getShortMessage());
|
||||
assertEquals(aBar.getCommitTime(), a.getCommitTime());
|
||||
|
||||
assertNull(rw.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlags_rewrittenParents() throws Exception {
|
||||
final RevCommit a = commit(tree(file("d/f", blob("a"))));
|
||||
final RevCommit b = commit(tree(file("d/f", blob("a"))), a);
|
||||
final RevCommit c = commit(tree(file("d/f", blob("b"))), b);
|
||||
|
||||
final RevFlag flag1 = rw.newFlag("flag1");
|
||||
final RevFlag flag2 = rw.newFlag("flag2");
|
||||
|
||||
a.add(flag1);
|
||||
c.add(flag2);
|
||||
|
||||
filter("d/f");
|
||||
markStart(c);
|
||||
|
||||
RevCommit cBar = rw.next();
|
||||
assertEquals(cBar.flags & RevObject.PARSED, 1);
|
||||
assertEquals(cBar.flags & flag2.mask, flag2.mask);
|
||||
|
||||
RevCommit aBar = rw.next();
|
||||
assertEquals(aBar.flags & RevObject.PARSED, 1);
|
||||
assertEquals(aBar.flags & flag1.mask, flag1.mask);
|
||||
|
||||
assertNull(rw.next());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2022, Google LLC.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
package org.eclipse.jgit.revwalk;
|
||||
|
||||
/**
|
||||
* A filtered commit reference that overrides its parent in the DAG.
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
public class FilteredRevCommit extends RevCommit {
|
||||
private RevCommit[] overriddenParents;
|
||||
|
||||
/**
|
||||
* Create a new commit reference wrapping an underlying commit reference.
|
||||
*
|
||||
* @param commit
|
||||
* commit that is being wrapped
|
||||
*/
|
||||
public FilteredRevCommit(RevCommit commit) {
|
||||
this(commit, NO_PARENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new commit reference wrapping an underlying commit reference.
|
||||
*
|
||||
* @param commit
|
||||
* commit that is being wrapped
|
||||
* @param parents
|
||||
* overridden parents for the commit
|
||||
*/
|
||||
public FilteredRevCommit(RevCommit commit, RevCommit... parents) {
|
||||
super(commit);
|
||||
this.overriddenParents = parents;
|
||||
this.parents = NO_PARENTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update parents on the commit
|
||||
*
|
||||
* @param overriddenParents
|
||||
* parents to be overwritten
|
||||
*/
|
||||
public void setParents(RevCommit... overriddenParents) {
|
||||
this.overriddenParents = overriddenParents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of parent commits listed in this commit.
|
||||
*
|
||||
* @return number of parents; always a positive value but can be 0 if it has
|
||||
* no parents.
|
||||
*/
|
||||
@Override
|
||||
public int getParentCount() {
|
||||
return overriddenParents.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nth parent from this commit's parent list.
|
||||
*
|
||||
* @param nth
|
||||
* parent index to obtain. Must be in the range 0 through
|
||||
* {@link #getParentCount()}-1.
|
||||
* @return the specified parent.
|
||||
* @throws java.lang.ArrayIndexOutOfBoundsException
|
||||
* an invalid parent index was specified.
|
||||
*/
|
||||
@Override
|
||||
public RevCommit getParent(int nth) {
|
||||
return overriddenParents[nth];
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain an array of all parents (<b>NOTE - THIS IS NOT A COPY</b>).
|
||||
*
|
||||
* <p>
|
||||
* This method is exposed only to provide very fast, efficient access to
|
||||
* this commit's parent list. Applications relying on this list should be
|
||||
* very careful to ensure they do not modify its contents during their use
|
||||
* of it.
|
||||
*
|
||||
* @return the array of parents.
|
||||
*/
|
||||
@Override
|
||||
public RevCommit[] getParents() {
|
||||
return overriddenParents;
|
||||
}
|
||||
}
|
|
@ -109,7 +109,7 @@ public static RevCommit parse(RevWalk rw, byte[] raw) throws IOException {
|
|||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
protected RevCommit[] parents;
|
||||
RevCommit[] parents;
|
||||
|
||||
int commitTime; // An int here for performance, overflows in 2038
|
||||
|
||||
|
@ -127,6 +127,22 @@ protected RevCommit(AnyObjectId id) {
|
|||
super(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new commit reference.
|
||||
*
|
||||
* @param orig
|
||||
* commit to be copied from.
|
||||
*/
|
||||
RevCommit(RevCommit orig) {
|
||||
super(orig.getId());
|
||||
this.buffer = orig.buffer;
|
||||
this.commitTime = orig.commitTime;
|
||||
this.flags = orig.flags;
|
||||
this.parents = orig.parents;
|
||||
this.tree = orig.tree;
|
||||
this.inDegree = orig.inDegree;
|
||||
}
|
||||
|
||||
@Override
|
||||
void parseHeaders(RevWalk walk) throws MissingObjectException,
|
||||
IncorrectObjectTypeException, IOException {
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
package org.eclipse.jgit.revwalk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
|
@ -38,10 +40,13 @@ class RewriteGenerator extends Generator {
|
|||
|
||||
private final FIFORevQueue pending;
|
||||
|
||||
private final Map<RevCommit, FilteredRevCommit> transformedCommits;
|
||||
|
||||
RewriteGenerator(Generator s) {
|
||||
super(s.firstParent);
|
||||
source = s;
|
||||
pending = new FIFORevQueue(s.firstParent);
|
||||
transformedCommits = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,10 +63,10 @@ int outputType() {
|
|||
@Override
|
||||
RevCommit next() throws MissingObjectException,
|
||||
IncorrectObjectTypeException, IOException {
|
||||
RevCommit c = pending.next();
|
||||
FilteredRevCommit c = (FilteredRevCommit) pending.next();
|
||||
|
||||
if (c == null) {
|
||||
c = source.next();
|
||||
c = transform(source.next());
|
||||
if (c == null) {
|
||||
// We are done: Both the source generator and our internal list
|
||||
// are completely exhausted.
|
||||
|
@ -79,9 +84,9 @@ RevCommit next() throws MissingObjectException,
|
|||
final RevCommit newp = rewrite(oldp);
|
||||
if (firstParent) {
|
||||
if (newp == null) {
|
||||
c.parents = RevCommit.NO_PARENTS;
|
||||
c.setParents(RevCommit.NO_PARENTS);
|
||||
} else {
|
||||
c.parents = new RevCommit[] { newp };
|
||||
c.setParents(newp);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
@ -91,7 +96,7 @@ RevCommit next() throws MissingObjectException,
|
|||
}
|
||||
}
|
||||
if (rewrote) {
|
||||
c.parents = cleanup(pList);
|
||||
c.setParents(cleanup(pList));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
@ -111,7 +116,7 @@ private void applyFilterToParents(RevCommit c)
|
|||
for (RevCommit parent : c.getParents()) {
|
||||
while ((parent.flags & RevWalk.TREE_REV_FILTER_APPLIED) == 0) {
|
||||
|
||||
RevCommit n = source.next();
|
||||
FilteredRevCommit n = transform(source.next());
|
||||
|
||||
if (n != null) {
|
||||
pending.add(n);
|
||||
|
@ -130,6 +135,8 @@ private RevCommit rewrite(RevCommit p) throws MissingObjectException,
|
|||
IncorrectObjectTypeException, IOException {
|
||||
for (;;) {
|
||||
|
||||
p = transform(p);
|
||||
|
||||
if (p.getParentCount() > 1) {
|
||||
// This parent is a merge, so keep it.
|
||||
//
|
||||
|
@ -158,11 +165,27 @@ private RevCommit rewrite(RevCommit p) throws MissingObjectException,
|
|||
}
|
||||
|
||||
applyFilterToParents(p.getParent(0));
|
||||
p = p.getParent(0);
|
||||
p = transform(p.getParent(0));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private FilteredRevCommit transform(RevCommit c) {
|
||||
if (c == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (c instanceof FilteredRevCommit) {
|
||||
return (FilteredRevCommit) c;
|
||||
}
|
||||
|
||||
if (!transformedCommits.containsKey(c)) {
|
||||
transformedCommits.put(c, new FilteredRevCommit(c, c.getParents()));
|
||||
}
|
||||
|
||||
return transformedCommits.get(c);
|
||||
}
|
||||
|
||||
private RevCommit[] cleanup(RevCommit[] oldList) {
|
||||
// Remove any duplicate parents caused due to rewrites (e.g. a merge
|
||||
// with two sides that both simplified back into the merge base).
|
||||
|
|
Loading…
Reference in New Issue