aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2024-04-26 21:51:27 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2024-04-26 23:46:29 +0200
commitc8844571b3a483e3cc5f77d18b4e972ad5fe2c5e (patch)
treee49ae068069a99fd2d3586eb194d5f95d6dfe2eb /org.eclipse.jgit.test
parent265550e63719c47ac9fc59fce107914acf0f8522 (diff)
parent567315af548017cc58eadb91bba493b74c391009 (diff)
downloadjgit-c8844571b3a483e3cc5f77d18b4e972ad5fe2c5e.tar.gz
jgit-c8844571b3a483e3cc5f77d18b4e972ad5fe2c5e.zip
Merge branch 'master' into next
* master: ResolveMerger: Fix the issue with binary modify-modify conflicts Explain why RacyGitTests may be flaky in some environments PackBitmapIndexBuilder.StoredEntry: add getter for objectId PackBitmapIndex: clarify naming of getObject inputs Revert "[releng] Bump Bouncy Castle to 1.78" [releng] Bump Bouncy Castle to 1.78 MergeAlgorithm: Fix diff3 conflict hunk computation [gpg] Remove obsolete import-package [gpg] Correct finding public keys from pubring.gpg [gpg] Fix reading ed25519 GPG keys PackBitmapIndexBuilder: make StoredEntry constructor public PackBitmapIndexBuilder: allow repeated call of getCompressedBitmaps() DfsPackFile: Make the loader classes used to construct bitmaps public. DfsPackFile: make public the constructor with bitmap loader PackWriter: writeBitmapIndex takes bitmap index writer Add more tests on rewriting parents in a RevWalk PackBitmapIndex: convert from class to interface Cache refreshed loose ref dirs in SnapshottingRefDirectory DfsGarbageCollectorTest: add test for bitmap index creation PackBitmapIndex: hide packChecksum behind getter TreeRevFilter: correct changedPathFilter usage for multi-paths inclusion PathFilterGroup: implement getPathsBestEffort() CleanupService: preload JgitText if not running in OSGi DfsPackFile: get commitGraph.readChangePaths from repo config CommitGraphLoader: receive readChangedPaths as parameter Add pull request template discouraging usage of pull requests Update CONTRIBUTING.md to point to GitHub issues FS_POSIX.runInShell(): on MacOS use a login shell [ssh] Implement the "Ciphers" SSH config ShutdownHook: run on bundle deactivation if in OSGi [diffmergetool] Fix running command on Cygwin [releng] Bump japicmp base version to 6.9.0.202403050737-r DfsBlockCache: move cache table specific implementations to a new class Prepare 6.10.0-SNAPSHOT builds Prepare 6.9.1-SNAPSHOT builds JGit v6.9.0.202403050737-r JGit v6.9.0.202403050045-r Prepare 6.9.0-SNAPSHOT builds Introduce core.trustLooseRefStat config JGit v6.9.0.202402281855-rc1 Update SECURITY.md DfsObjDatabase: Let object database instantiate DfsPackFiles DfsPackFile: Abstract the bitmap loading to support other backends Remove unused API problem filters Support public key in IdentityFile Revert "StartGenerator: Fix parent rewrite with non-default RevFilter" Prepare 6.9.0-SNAPSHOT builds JGit v6.9.0.202402211805-m3 DfsReader#getObjectSize: use size index if possible Change-Id: Ibdde5be8c5c2b3938aeaa4f278020cadcaad36a3
Diffstat (limited to 'org.eclipse.jgit.test')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/merge/MergeGitAttributeTest.java9
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java104
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java71
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java117
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java16
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java13
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java186
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java30
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterTest.java131
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterWithRewriteParentsTest.java112
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java27
11 files changed, 657 insertions, 159 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/merge/MergeGitAttributeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/merge/MergeGitAttributeTest.java
index 795029188d..6b23de3320 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/merge/MergeGitAttributeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/merge/MergeGitAttributeTest.java
@@ -10,7 +10,6 @@
package org.eclipse.jgit.attributes.merge;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -42,7 +41,6 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
-import org.junit.Ignore;
import org.junit.Test;
public class MergeGitAttributeTest extends RepositoryTestCase {
@@ -268,12 +266,7 @@ public class MergeGitAttributeTest extends RepositoryTestCase {
}
}
- /*
- * This test is commented because JGit add conflict markers in binary files.
- * cf. https://www.eclipse.org/forums/index.php/t/1086511/
- */
@Test
- @Ignore
public void mergeBinaryFile_NoAttr_Conflict() throws IllegalStateException,
IOException, NoHeadException, ConcurrentRefUpdateException,
CheckoutConflictException, InvalidMergeHeadsException,
@@ -433,7 +426,7 @@ public class MergeGitAttributeTest extends RepositoryTestCase {
try (FileInputStream mergeResultFile = new FileInputStream(
db.getWorkTree().toPath().resolve(ENABLED_CHECKED_GIF)
.toFile())) {
- assertFalse(contentEquals(
+ assertTrue(contentEquals(
getClass().getResourceAsStream(ENABLED_CHECKED_GIF),
mergeResultFile));
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
index 05360dc052..e193de9764 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
@@ -18,10 +18,11 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
-
import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
import org.eclipse.jgit.internal.storage.commitgraph.CommitGraphWriter;
import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
import org.eclipse.jgit.internal.storage.reftable.RefCursor;
import org.eclipse.jgit.internal.storage.reftable.ReftableConfig;
import org.eclipse.jgit.internal.storage.reftable.ReftableReader;
@@ -30,6 +31,8 @@ import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
@@ -1121,6 +1124,40 @@ public class DfsGarbageCollectorTest {
}
@Test
+ public void testReadChangedPathConfigAsFalse() throws Exception {
+ String head = "refs/heads/head1";
+ git.branch(head).commit().message("0").noParents().create();
+ gcWithCommitGraphAndBloomFilter();
+
+ Config repoConfig = odb.getRepository().getConfig();
+ repoConfig.setBoolean(ConfigConstants.CONFIG_COMMIT_GRAPH_SECTION, null,
+ ConfigConstants.CONFIG_KEY_READ_CHANGED_PATHS, false);
+
+ DfsPackFile gcPack = odb.getPacks()[0];
+ try (DfsReader reader = odb.newReader()) {
+ CommitGraph cg = gcPack.getCommitGraph(reader);
+ assertNull(cg.getChangedPathFilter(0));
+ }
+ }
+
+ @Test
+ public void testReadChangedPathConfigAsTrue() throws Exception {
+ String head = "refs/heads/head1";
+ git.branch(head).commit().message("0").noParents().create();
+ gcWithCommitGraphAndBloomFilter();
+
+ Config repoConfig = odb.getRepository().getConfig();
+ repoConfig.setBoolean(ConfigConstants.CONFIG_COMMIT_GRAPH_SECTION, null,
+ ConfigConstants.CONFIG_KEY_READ_CHANGED_PATHS, true);
+
+ DfsPackFile gcPack = odb.getPacks()[0];
+ try (DfsReader reader = odb.newReader()) {
+ CommitGraph cg = gcPack.getCommitGraph(reader);
+ assertNotNull(cg.getChangedPathFilter(0));
+ }
+ }
+
+ @Test
public void objectSizeIdx_reachableBlob_bigEnough_indexed() throws Exception {
String master = "refs/heads/master";
RevCommit root = git.branch(master).commit().message("root").noParents()
@@ -1178,6 +1215,71 @@ public class DfsGarbageCollectorTest {
assertFalse(gcRestPack.hasObjectSizeIndex(reader));
}
+ @Test
+ public void bitmapIndexWrittenDuringGc() throws Exception {
+ int numBranches = 2;
+ int commitsPerBranch = 50;
+
+ RevCommit commit0 = commit().message("0").create();
+ git.update("branch0", commit0);
+ RevCommit branch1 = commitChain(commit0, commitsPerBranch);
+ git.update("branch1", branch1);
+ RevCommit branch2 = commitChain(commit0, commitsPerBranch);
+ git.update("branch2", branch2);
+
+ int contiguousCommitCount = 5;
+ int recentCommitSpan = 2;
+ int recentCommitCount = 10;
+ int distantCommitSpan = 5;
+
+ PackConfig packConfig = new PackConfig();
+ packConfig.setBitmapContiguousCommitCount(contiguousCommitCount);
+ packConfig.setBitmapRecentCommitSpan(recentCommitSpan);
+ packConfig.setBitmapRecentCommitCount(recentCommitCount);
+ packConfig.setBitmapDistantCommitSpan(distantCommitSpan);
+
+ DfsGarbageCollector gc = new DfsGarbageCollector(repo);
+ gc.setPackConfig(packConfig);
+ run(gc);
+
+ DfsPackFile pack = odb.getPacks()[0];
+ PackBitmapIndex bitmapIndex = pack.getBitmapIndex(odb.newReader());
+ assertTrue("pack file has bitmap index extension",
+ pack.getPackDescription().hasFileExt(PackExt.BITMAP_INDEX));
+
+ int recentCommitsPerBranch = (recentCommitCount - contiguousCommitCount
+ - 1) / recentCommitSpan;
+ assertEquals("expected recent commits", 2, recentCommitsPerBranch);
+
+ int distantCommitsPerBranch = (commitsPerBranch - 1 - recentCommitCount)
+ / distantCommitSpan;
+ assertEquals("expected distant commits", 7, distantCommitsPerBranch);
+
+ int branchBitmapsCount = contiguousCommitCount
+ + numBranches
+ * (recentCommitsPerBranch
+ + distantCommitsPerBranch);
+ assertEquals("expected bitmaps count", 23, branchBitmapsCount);
+ assertEquals("bitmap index has expected number of bitmaps",
+ branchBitmapsCount,
+ bitmapIndex.getBitmapCount());
+
+ // The count is just a function of whether any bitmaps happen to
+ // compress efficiently against the others in the index. We expect for
+ // this test that this there will be at least one like this, but the
+ // actual count is situation-specific
+ assertTrue("bitmap index has xor-compressed bitmaps",
+ bitmapIndex.getXorBitmapCount() > 0);
+ }
+
+ private RevCommit commitChain(RevCommit parent, int length)
+ throws Exception {
+ for (int i = 0; i < length; i++) {
+ parent = commit().message("" + i).parent(parent).create();
+ }
+ return parent;
+ }
+
private static DfsPackFile findFirstBySource(DfsPackFile[] packs, PackSource source) {
return Arrays.stream(packs)
.filter(p -> p.getPackDescription().getPackSource() == source)
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
index 77e5b7cb14..d21e51f276 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
@@ -10,10 +10,14 @@
package org.eclipse.jgit.internal.storage.dfs;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_COMMIT_GRAPH_SECTION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_READ_CHANGED_PATHS;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_PACK_SECTION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
@@ -22,16 +26,22 @@ import java.util.HashMap;
import java.util.Map;
import java.util.zip.Deflater;
+import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
import org.eclipse.jgit.internal.storage.dfs.DfsReader.PackLoadListener;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
import org.eclipse.jgit.internal.storage.pack.PackExt;
import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
import org.eclipse.jgit.internal.storage.pack.PackWriter;
import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.junit.TestRng;
+import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.ReceiveCommand;
import org.junit.Before;
import org.junit.Test;
@@ -123,6 +133,41 @@ public class DfsPackFileTest {
}
@Test
+ public void testGetBitmapIndex() throws IOException {
+ bypassCache = false;
+ clearCache = true;
+ ObjectId objectId = setupPack(512, 800);
+
+ // Add a ref for GC
+ BatchRefUpdate batchRefUpdate = db.getRefDatabase().newBatchUpdate();
+ batchRefUpdate.addCommand(new ReceiveCommand(ObjectId.zeroId(),
+ objectId, "refs/heads/master"));
+ try (RevWalk rw = new RevWalk(db)) {
+ batchRefUpdate.execute(rw, NullProgressMonitor.INSTANCE);
+ }
+ DfsGarbageCollector gc = new DfsGarbageCollector(db);
+ gc.pack(NullProgressMonitor.INSTANCE);
+
+ DfsReader reader = db.getObjectDatabase().newReader();
+ PackBitmapIndex bitmapIndex = db.getObjectDatabase().getPacks()[0]
+ .getBitmapIndex(reader);
+ assertNotNull(bitmapIndex);
+ assertEquals(1, bitmapIndex.getObjectCount());
+ }
+
+ @Test
+ public void testGetBitmapIndex_noBitmaps() throws IOException {
+ bypassCache = false;
+ clearCache = true;
+ setupPack(512, 800);
+
+ DfsReader reader = db.getObjectDatabase().newReader();
+ PackBitmapIndex bitmapIndex = db.getObjectDatabase().getPacks()[0]
+ .getBitmapIndex(reader);
+ assertNull(bitmapIndex);
+ }
+
+ @Test
public void testLoadObjectSizeIndex_noIndex() throws IOException {
bypassCache = false;
clearCache = true;
@@ -222,6 +267,27 @@ public class DfsPackFileTest {
assertEquals(2, tal.blockLoadCount);
}
+ @Test
+ public void testExistenceOfBloomFilterAlongWithCommitGraph()
+ throws Exception {
+ try (TestRepository<InMemoryRepository> repository = new TestRepository<>(
+ db)) {
+ repository.branch("/refs/heads/main").commit().add("blob1", "blob1")
+ .create();
+ }
+ setReadChangedPaths(true);
+ DfsGarbageCollector gc = new DfsGarbageCollector(db);
+ gc.setWriteCommitGraph(true).setWriteBloomFilter(true)
+ .pack(NullProgressMonitor.INSTANCE);
+
+ DfsReader reader = db.getObjectDatabase().newReader();
+ CommitGraph cg = db.getObjectDatabase().getPacks()[0]
+ .getCommitGraph(reader);
+ assertNotNull(cg);
+ assertEquals(1, cg.getCommitCnt());
+ assertNotNull(cg.getChangedPathFilter(0));
+ }
+
private ObjectId setupPack(int bs, int ps) throws IOException {
DfsBlockCacheConfig cfg = new DfsBlockCacheConfig().setBlockSize(bs)
.setBlockLimit(bs * 100).setStreamRatio(bypassCache ? 0F : 1F);
@@ -257,4 +323,9 @@ public class DfsPackFileTest {
db.getConfig().setInt(CONFIG_PACK_SECTION, null,
CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX, threshold);
}
+
+ private void setReadChangedPaths(boolean enable) {
+ db.getConfig().setBoolean(CONFIG_COMMIT_GRAPH_SECTION, null,
+ CONFIG_KEY_READ_CHANGED_PATHS, enable);
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java
index eb8ceecd81..254184ee80 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsReaderTest.java
@@ -12,6 +12,7 @@ package org.eclipse.jgit.internal.storage.dfs;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_PACK_SECTION;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -39,8 +40,56 @@ public class DfsReaderTest {
}
@Test
- public void isNotLargerThan_objAboveThreshold()
- throws IOException {
+ public void getObjectSize_noIndex_blob() throws IOException {
+ ObjectId obj = insertBlobWithSize(100);
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ long size = ctx.getObjectSize(obj, OBJ_BLOB);
+ assertEquals(100, size);
+ }
+ }
+
+ @Test
+ public void getObjectSize_noIndex_commit() throws IOException {
+ ObjectId obj = insertObjectWithSize(OBJ_COMMIT, 110);
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ long size = ctx.getObjectSize(obj, OBJ_COMMIT);
+ assertEquals(110, size);
+ }
+ }
+
+ @Test
+ public void getObjectSize_index_indexedBlob() throws IOException {
+ setObjectSizeIndexMinBytes(100);
+ ObjectId obj = insertBlobWithSize(200);
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ long size = ctx.getObjectSize(obj, OBJ_BLOB);
+ assertEquals(200, size);
+ }
+ }
+
+ @Test
+ public void getObjectSize_index_nonIndexedBlob() throws IOException {
+ setObjectSizeIndexMinBytes(100);
+ ObjectId obj = insertBlobWithSize(50);
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ long size = ctx.getObjectSize(obj, OBJ_BLOB);
+ assertEquals(50, size);
+ }
+ }
+
+ @Test
+ public void getObjectSize_index_commit() throws IOException {
+ setObjectSizeIndexMinBytes(100);
+ insertBlobWithSize(110);
+ ObjectId obj = insertObjectWithSize(OBJ_COMMIT, 120);
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ long size = ctx.getObjectSize(obj, OBJ_COMMIT);
+ assertEquals(120, size);
+ }
+ }
+
+ @Test
+ public void isNotLargerThan_objAboveThreshold() throws IOException {
setObjectSizeIndexMinBytes(100);
ObjectId obj = insertBlobWithSize(200);
try (DfsReader ctx = db.getObjectDatabase().newReader()) {
@@ -76,10 +125,8 @@ public class DfsReaderTest {
}
}
-
@Test
- public void isNotLargerThan_objBelowThreshold()
- throws IOException {
+ public void isNotLargerThan_objBelowThreshold() throws IOException {
setObjectSizeIndexMinBytes(100);
insertBlobWithSize(1000); // index not empty
ObjectId obj = insertBlobWithSize(50);
@@ -168,22 +215,26 @@ public class DfsReaderTest {
ctx.addPackLoadListener(listener);
boolean has = ctx.has(obj);
assertTrue(has);
- assertEquals(Integer.valueOf(1), listener.callsPerExt.get(PackExt.INDEX));
+ assertEquals(Integer.valueOf(1),
+ listener.callsPerExt.get(PackExt.INDEX));
}
}
@Test
- public void packLoadListener_notLargerThan_openMultipleIndices() throws IOException {
- setObjectSizeIndexMinBytes(100);
- ObjectId obj = insertBlobWithSize(200);
- try (DfsReader ctx = db.getObjectDatabase().newReader()) {
- CounterPackLoadListener listener = new CounterPackLoadListener();
- ctx.addPackLoadListener(listener);
- boolean notLargerThan = ctx.isNotLargerThan(obj, OBJ_BLOB, 1000);
- assertTrue(notLargerThan);
- assertEquals(Integer.valueOf(1), listener.callsPerExt.get(PackExt.INDEX));
- assertEquals(Integer.valueOf(1), listener.callsPerExt.get(PackExt.OBJECT_SIZE_INDEX));
- }
+ public void packLoadListener_notLargerThan_openMultipleIndices()
+ throws IOException {
+ setObjectSizeIndexMinBytes(100);
+ ObjectId obj = insertBlobWithSize(200);
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ CounterPackLoadListener listener = new CounterPackLoadListener();
+ ctx.addPackLoadListener(listener);
+ boolean notLargerThan = ctx.isNotLargerThan(obj, OBJ_BLOB, 1000);
+ assertTrue(notLargerThan);
+ assertEquals(Integer.valueOf(1),
+ listener.callsPerExt.get(PackExt.INDEX));
+ assertEquals(Integer.valueOf(1),
+ listener.callsPerExt.get(PackExt.OBJECT_SIZE_INDEX));
+ }
}
@Test
@@ -195,20 +246,24 @@ public class DfsReaderTest {
try (DfsReader ctx = db.getObjectDatabase().newReader()) {
CounterPackLoadListener listener = new CounterPackLoadListener();
ctx.addPackLoadListener(listener);
- ObjectId oid = ObjectId.fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f129");
+ ObjectId oid = ObjectId
+ .fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f129");
boolean has = ctx.has(oid);
assertFalse(has);
// Open 3 indices trying to find the pack
- assertEquals(Integer.valueOf(3), listener.callsPerExt.get(PackExt.INDEX));
+ assertEquals(Integer.valueOf(3),
+ listener.callsPerExt.get(PackExt.INDEX));
}
}
-
@Test
- public void packLoadListener_has_repeatedCalls_openMultipleIndices() throws IOException {
+ public void packLoadListener_has_repeatedCalls_openMultipleIndices()
+ throws IOException {
// Two objects NOT in the repo
- ObjectId oid = ObjectId.fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f129");
- ObjectId oid2 = ObjectId.fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f130");
+ ObjectId oid = ObjectId
+ .fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f129");
+ ObjectId oid2 = ObjectId
+ .fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f130");
setObjectSizeIndexMinBytes(100);
insertBlobWithSize(200);
@@ -222,7 +277,8 @@ public class DfsReaderTest {
ctx.has(oid2);
assertFalse(has);
// The 3 indices were loaded only once each
- assertEquals(Integer.valueOf(3), listener.callsPerExt.get(PackExt.INDEX));
+ assertEquals(Integer.valueOf(3),
+ listener.callsPerExt.get(PackExt.INDEX));
}
}
@@ -231,8 +287,8 @@ public class DfsReaderTest {
@SuppressWarnings("boxing")
@Override
- public void onIndexLoad(String packName, PackSource src, PackExt ext, long size,
- Object loadedIdx) {
+ public void onIndexLoad(String packName, PackSource src, PackExt ext,
+ long size, Object loadedIdx) {
callsPerExt.merge(ext, 1, Integer::sum);
}
@@ -243,13 +299,16 @@ public class DfsReaderTest {
}
}
- private ObjectId insertBlobWithSize(int size)
+ private ObjectId insertBlobWithSize(int size) throws IOException {
+ return insertObjectWithSize(OBJ_BLOB, size);
+ }
+
+ private ObjectId insertObjectWithSize(int object_type, int size)
throws IOException {
TestRng testRng = new TestRng(JGitTestUtil.getName());
ObjectId oid;
try (ObjectInserter ins = db.newObjectInserter()) {
- oid = ins.insert(OBJ_BLOB,
- testRng.nextBytes(size));
+ oid = ins.insert(object_type, testRng.nextBytes(size));
ins.flush();
}
return oid;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
index b1d80c5c30..f25e5d10ff 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
@@ -30,6 +30,22 @@ import org.junit.Test;
public class RacyGitTests extends RepositoryTestCase {
+ /**
+ * This test is inherently flaky in nature since using clocks in a computer
+ * to determine file modifications in a filesystem from Java is difficult
+ * and depends on many factors and we can't test all combinations
+ *
+ * If this test fails on your computer, don't worry but let us know if you
+ * are willing to provide details which may help to further improve handling
+ * of the racy git problem in JGit.
+ *
+ * Despite not being completely reproducible this test is still useful to
+ * detect regressions when running this test repeatedly on the same
+ * OS/filesystem/Java version (which we do on the CI used to build JGit).
+ *
+ * @see "https://git-scm.com/docs/racy-git"
+ * @see "https://www.youtube.com/watch?v=m44cAozuLNI"
+ */
@Test
public void testRacyGitDetection() throws Exception {
// Reset to force creation of index file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java
index 680a2d5d72..7a8a93e977 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java
@@ -162,6 +162,19 @@ public class MergeAlgorithmTest {
merge("abz}z}z123q", "Abz}z123Q", "abz}z123q", true));
}
+ @Test
+ public void testInsertionAfterDeletion() throws IOException {
+ assertEquals(t("a<=bc>d"), merge("abd", "ad", "abcd", false));
+ assertEquals(t("a<|b=bc>d"),
+ merge("abd", "ad", "abcd", true));
+ }
+
+ @Test
+ public void testInsertionBeforeDeletion() throws IOException {
+ assertEquals(t("a<=cb>d"), merge("abd", "ad", "acbd", false));
+ assertEquals(t("a<|b=cb>d"), merge("abd", "ad", "acbd", true));
+ }
+
/**
* Test a conflicting region at the very start of the text.
*
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
index 022e8cd55e..3f99fe2b26 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java
@@ -22,9 +22,12 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.nio.file.Files;
import java.time.Instant;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeResult;
@@ -51,6 +54,7 @@ import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ObjectStream;
+import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -1789,6 +1793,188 @@ public class MergerTest extends RepositoryTestCase {
}
+ /**
+ * File is binary in ours, theirs and base with different content in each of
+ * them. Content of the file should not change after the merge conflict as
+ * no conflict markers are added to the binary files
+ */
+ @Theory
+ public void oursBinaryTheirsBinaryBaseBinary(MergeStrategy strategy)
+ throws Exception {
+ Git git = Git.wrap(db);
+ String binaryFile = "file";
+
+ writeTrashFile(binaryFile, "\u0000\u0001");
+ git.add().addFilepattern(binaryFile).call();
+ RevCommit parent = git.commit().setMessage("BASE COMMIT").call();
+ String fileHashInBase = getFileHashInWorkTree(git, binaryFile);
+
+ writeTrashFile(binaryFile, "\u0001\u0002");
+ git.add().addFilepattern(binaryFile).call();
+ RevCommit child1 = git.commit().setMessage("THEIRS COMMIT").call();
+ String fileHashInChild1 = getFileHashInWorkTree(git, binaryFile);
+
+ git.checkout().setCreateBranch(true).setStartPoint(parent)
+ .setName("side").call();
+
+ writeTrashFile(binaryFile, "\u0002\u0000");
+ git.add().addFilepattern(binaryFile).call();
+ git.commit().setMessage("OURS COMMIT").call();
+ String fileHashInChild2 = getFileHashInWorkTree(git, binaryFile);
+
+ MergeResult mergeResult = git.merge().setStrategy(strategy)
+ .include(child1).call();
+
+ // check if the merge caused a conflict
+ assertTrue(mergeResult.getConflicts() != null
+ && !mergeResult.getConflicts().isEmpty());
+ String fileHashInChild2AfterMerge = getFileHashInWorkTree(git,
+ binaryFile);
+
+ // check if the file content changed during a conflicting merge
+ assertEquals(fileHashInChild2AfterMerge, fileHashInChild2);
+
+ Set<String> hashesInIndexFile = new HashSet<>();
+ DirCache indexContent = git.getRepository().readDirCache();
+ for (int i = 0; i < indexContent.getEntryCount(); ++i) {
+ DirCacheEntry indexEntry = indexContent.getEntry(i);
+ if (binaryFile.equals(indexEntry.getPathString())) {
+ hashesInIndexFile.add(indexEntry.getObjectId().name());
+ }
+ }
+
+ // check if all the three stages are added to index file
+ assertTrue(hashesInIndexFile.contains(fileHashInBase));
+ assertTrue(hashesInIndexFile.contains(fileHashInChild1));
+ assertTrue(hashesInIndexFile.contains(fileHashInChild2));
+ }
+
+ /**
+ * File is text in ours and theirs with different content but binary in
+ * base. Even in this case, file will be treated as a binary and no conflict
+ * markers are added to it
+ */
+ @Theory
+ public void oursAndTheirsDifferentTextBaseBinary(MergeStrategy strategy)
+ throws Exception {
+ Git git = Git.wrap(db);
+ String binaryFile = "file";
+
+ writeTrashFile(binaryFile, "\u0000\u0001");
+ git.add().addFilepattern(binaryFile).call();
+ RevCommit parent = git.commit().setMessage("BASE COMMIT").call();
+ String fileHashInBase = getFileHashInWorkTree(git, binaryFile);
+
+ writeTrashFile(binaryFile, "TEXT1");
+ git.add().addFilepattern(binaryFile).call();
+ RevCommit child1 = git.commit().setMessage("THEIRS COMMIT").call();
+ String fileHashInChild1 = getFileHashInWorkTree(git, binaryFile);
+
+ git.checkout().setCreateBranch(true).setStartPoint(parent)
+ .setName("side").call();
+
+ writeTrashFile(binaryFile, "TEXT2");
+ git.add().addFilepattern(binaryFile).call();
+ git.commit().setMessage("OURS COMMIT").call();
+ String fileHashInChild2 = getFileHashInWorkTree(git, binaryFile);
+
+ MergeResult mergeResult = git.merge().setStrategy(strategy)
+ .include(child1).call();
+
+ assertTrue(mergeResult.getConflicts() != null
+ && !mergeResult.getConflicts().isEmpty());
+ String fileHashInChild2AfterMerge = getFileHashInWorkTree(git,
+ binaryFile);
+
+ assertEquals(fileHashInChild2AfterMerge, fileHashInChild2);
+
+ Set<String> hashesInIndexFile = new HashSet<>();
+ DirCache indexContent = git.getRepository().readDirCache();
+ for (int i = 0; i < indexContent.getEntryCount(); ++i) {
+ DirCacheEntry indexEntry = indexContent.getEntry(i);
+ if (binaryFile.equals(indexEntry.getPathString())) {
+ hashesInIndexFile.add(indexEntry.getObjectId().name());
+ }
+ }
+
+ assertTrue(hashesInIndexFile.contains(fileHashInBase));
+ assertTrue(hashesInIndexFile.contains(fileHashInChild1));
+ assertTrue(hashesInIndexFile.contains(fileHashInChild2));
+ }
+
+ /**
+ * Tests the scenario where a file is expected to be treated as binary
+ * according to Git attributes
+ */
+ @Theory
+ public void fileInBinaryInAttribute(MergeStrategy strategy)
+ throws Exception {
+ Git git = Git.wrap(db);
+ String binaryFile = "file.bin";
+
+ writeTrashFile(".gitattributes", binaryFile + " binary");
+ git.add().addFilepattern(".gitattributes").call();
+ git.commit().setMessage("ADDING GITATTRIBUTES").call();
+
+ writeTrashFile(binaryFile, "\u0000\u0001");
+ git.add().addFilepattern(binaryFile).call();
+ RevCommit parent = git.commit().setMessage("BASE COMMIT").call();
+ String fileHashInBase = getFileHashInWorkTree(git, binaryFile);
+
+ writeTrashFile(binaryFile, "\u0001\u0002");
+ git.add().addFilepattern(binaryFile).call();
+ RevCommit child1 = git.commit().setMessage("THEIRS COMMIT").call();
+ String fileHashInChild1 = getFileHashInWorkTree(git, binaryFile);
+
+ git.checkout().setCreateBranch(true).setStartPoint(parent)
+ .setName("side").call();
+
+ writeTrashFile(binaryFile, "\u0002\u0000");
+ git.add().addFilepattern(binaryFile).call();
+ git.commit().setMessage("OURS COMMIT").call();
+ String fileHashInChild2 = getFileHashInWorkTree(git, binaryFile);
+
+ MergeResult mergeResult = git.merge().setStrategy(strategy)
+ .include(child1).call();
+
+ // check if the merge caused a conflict
+ assertTrue(mergeResult.getConflicts() != null
+ && !mergeResult.getConflicts().isEmpty());
+ String fileHashInChild2AfterMerge = getFileHashInWorkTree(git,
+ binaryFile);
+
+ // check if the file content changed during a conflicting merge
+ assertEquals(fileHashInChild2AfterMerge, fileHashInChild2);
+
+ Set<String> hashesInIndexFile = new HashSet<>();
+ DirCache indexContent = git.getRepository().readDirCache();
+ for (int i = 0; i < indexContent.getEntryCount(); ++i) {
+ DirCacheEntry indexEntry = indexContent.getEntry(i);
+ if (binaryFile.equals(indexEntry.getPathString())) {
+ hashesInIndexFile.add(indexEntry.getObjectId().name());
+ }
+ }
+
+ // check if all the three stages are added to index file
+ assertTrue(hashesInIndexFile.contains(fileHashInBase));
+ assertTrue(hashesInIndexFile.contains(fileHashInChild1));
+ assertTrue(hashesInIndexFile.contains(fileHashInChild2));
+ }
+
+ private String getFileHashInWorkTree(Git git, String filePath)
+ throws IOException {
+ Repository repository = git.getRepository();
+ ObjectInserter objectInserter = repository.newObjectInserter();
+
+ File conflictingFile = new File(repository.getWorkTree(), filePath);
+ byte[] fileContent = Files.readAllBytes(conflictingFile.toPath());
+ ObjectId blobId = objectInserter.insert(Constants.OBJ_BLOB,
+ fileContent);
+ objectInserter.flush();
+
+ return blobId.name();
+ }
+
private void writeSubmodule(String path, ObjectId commit)
throws IOException, ConfigInvalidException {
addSubmoduleToIndex(path, commit);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java
index 8215a795b2..c2f8f10631 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java
@@ -38,6 +38,7 @@ import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.junit.Test;
@@ -197,6 +198,35 @@ public class RevWalkCommitGraphTest extends RevWalkTestCase {
}
@Test
+ public void testChangedPathFilterWithMultiPaths() throws Exception {
+ RevCommit c1 = commitFile("file1", "1", "master");
+ RevCommit c2 = commitFile("file1", "2", "master");
+ RevCommit c3 = commitFile("file2", "3", "master");
+ RevCommit c4 = commitFile("file3", "4", "master");
+
+ enableAndWriteCommitGraph();
+
+ TreeRevFilter trf = new TreeRevFilter(rw,
+ PathFilterGroup.createFromStrings(List.of("file1", "file2")));
+ rw.markStart(rw.lookupCommit(c4));
+ rw.setRevFilter(trf);
+ assertEquals(c3, rw.next());
+ assertEquals(c2, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // c2 and c3 has either file1 or file2, c1 did not use ChangedPathFilter
+ // since it has no parent
+ assertEquals(2, trf.getChangedPathFilterTruePositive());
+
+ // No false positives
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // c4 does not match either file1 or file2
+ assertEquals(1, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
public void testChangedPathFilterWithFollowFilter() throws Exception {
RevCommit c0 = commit(tree());
RevCommit c1 = commit(tree(file("file", blob("contents"))), c0);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterTest.java
index f67a623ff6..ddbb19cb8f 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterTest.java
@@ -20,23 +20,58 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.junit.Test;
public class TreeRevFilterTest extends RevWalkTestCase {
- private RevFilter treeRevFilter() {
+ @Test
+ public void testStringOfPearls_FilePath1_treeRevFilter()
+ throws Exception {
+ RevCommit a = commit(tree(file("d/f", blob("a"))));
+ RevCommit b = commit(tree(file("d/f", blob("a"))), a);
+ RevCommit c = commit(tree(file("d/f", blob("b"))), b);
+
+ rw.setRevFilter(new TreeRevFilter(rw, TreeFilter.ANY_DIFF));
+ markStart(c);
+
+ assertCommit(c, rw.next());
+ assertEquals(1, c.getParentCount());
+ assertCommit(b, c.getParent(0));
+
+ assertCommit(a, rw.next()); // b was skipped
+ assertEquals(0, a.getParentCount());
+ assertNull(rw.next());
+ }
+ @Test
+ public void testStringOfPearls_FilePath1_noRewriteParents()
+ throws Exception {
+ RevCommit a = commit(tree(file("d/f", blob("a"))));
+ RevCommit b = commit(tree(file("d/f", blob("a"))), a);
+ RevCommit c = commit(tree(file("d/f", blob("b"))), b);
+
rw.setRewriteParents(false);
- return new TreeRevFilter(rw, TreeFilter.ANY_DIFF);
+ rw.setTreeFilter(TreeFilter.ANY_DIFF);
+ markStart(c);
+
+ assertCommit(c, rw.next());
+ assertEquals(1, c.getParentCount());
+ assertCommit(b, c.getParent(0));
+
+ assertCommit(a, rw.next()); // b was skipped
+ assertEquals(0, a.getParentCount());
+ assertNull(rw.next());
}
@Test
- public void testStringOfPearls_FilePath1()
+ public void testStringOfPearls_FilePath1_RewriteParents()
throws Exception {
RevCommit a = commit(tree(file("d/f", blob("a"))));
RevCommit b = commit(tree(file("d/f", blob("a"))), a);
RevCommit c = commit(tree(file("d/f", blob("b"))), b);
- rw.setRevFilter(treeRevFilter());
+
+ rw.setRevFilter(new TreeRevFilter(rw, TreeFilter.ANY_DIFF));
+ rw.setTreeFilter(TreeFilter.ANY_DIFF);
markStart(c);
assertCommit(c, rw.next());
assertEquals(1, c.getParentCount());
- assertCommit(b, c.getParent(0));
+ assertCommit(a, c.getParent(0));
assertCommit(a, rw.next()); // b was skipped
assertEquals(0, a.getParentCount());
@@ -49,7 +84,49 @@ public class TreeRevFilterTest extends RevWalkTestCase {
RevCommit b = commit(tree(file("d/f", blob("a"))), a);
RevCommit c = commit(tree(file("d/f", blob("b"))), b);
RevCommit d = commit(tree(file("d/f", blob("b"))), c);
- rw.setRevFilter(treeRevFilter());
+ rw.setRevFilter(new TreeRevFilter(rw, TreeFilter.ANY_DIFF));
+ markStart(d);
+
+ // d was skipped
+ assertCommit(c, rw.next());
+ assertEquals(1, c.getParentCount());
+ assertCommit(b, c.getParent(0));
+
+ // b was skipped
+ assertCommit(a, rw.next());
+ assertEquals(0, a.getParentCount());
+ assertNull(rw.next());
+ }
+
+ @Test
+ public void testStringOfPearls_FilePath2_RewriteParents() throws Exception {
+ RevCommit a = commit(tree(file("d/f", blob("a"))));
+ RevCommit b = commit(tree(file("d/f", blob("a"))), a);
+ RevCommit c = commit(tree(file("d/f", blob("b"))), b);
+ RevCommit d = commit(tree(file("d/f", blob("b"))), c);
+ rw.setTreeFilter(TreeFilter.ANY_DIFF);
+ markStart(d);
+
+ // d was skipped
+ assertCommit(c, rw.next());
+ assertEquals(1, c.getParentCount());
+ assertCommit(a, c.getParent(0));
+
+ // b was skipped
+ assertCommit(a, rw.next());
+ assertEquals(0, a.getParentCount());
+ assertNull(rw.next());
+ }
+
+ @Test
+ public void testStringOfPearls_FilePath2_RewriteParents_False() throws Exception {
+ RevCommit a = commit(tree(file("d/f", blob("a"))));
+ RevCommit b = commit(tree(file("d/f", blob("a"))), a);
+ RevCommit c = commit(tree(file("d/f", blob("b"))), b);
+ RevCommit d = commit(tree(file("d/f", blob("b"))), c);
+ rw.setRewriteParents(false);
+ rw.setRevFilter(new TreeRevFilter(rw, TreeFilter.ANY_DIFF));
+ rw.setTreeFilter(TreeFilter.ANY_DIFF);
markStart(d);
// d was skipped
@@ -69,7 +146,7 @@ public class TreeRevFilterTest extends RevWalkTestCase {
RevCommit b = commit(tree(file("d/f", blob("a"))), a);
RevCommit c = commit(tree(file("d/f", blob("b"))), b);
RevCommit d = commit(tree(file("d/f", blob("b"))), c);
- rw.setRevFilter(treeRevFilter());
+ rw.setRevFilter(new TreeRevFilter(rw, TreeFilter.ANY_DIFF));
markStart(d);
// d was skipped
@@ -94,7 +171,9 @@ public class TreeRevFilterTest extends RevWalkTestCase {
RevCommit g = commit(tree(file("d/f", blob("b"))), f);
RevCommit h = commit(tree(file("d/f", blob("b"))), g);
RevCommit i = commit(tree(file("d/f", blob("c"))), h);
- rw.setRevFilter(treeRevFilter());
+
+ // Doesn't rewrite parents since no TreeFilter is set
+ rw.setRevFilter(new TreeRevFilter(rw, TreeFilter.ANY_DIFF));
markStart(i);
assertCommit(i, rw.next());
@@ -113,8 +192,39 @@ public class TreeRevFilterTest extends RevWalkTestCase {
}
@Test
+ public void testStringOfPearls_FilePath3_RewriteParents() throws Exception {
+ RevCommit a = commit(tree(file("d/f", blob("a"))));
+ RevCommit b = commit(tree(file("d/f", blob("a"))), a);
+ RevCommit c = commit(tree(file("d/f", blob("b"))), b);
+ RevCommit d = commit(tree(file("d/f", blob("b"))), c);
+ RevCommit e = commit(tree(file("d/f", blob("b"))), d);
+ RevCommit f = commit(tree(file("d/f", blob("b"))), e);
+ RevCommit g = commit(tree(file("d/f", blob("b"))), f);
+ RevCommit h = commit(tree(file("d/f", blob("b"))), g);
+ RevCommit i = commit(tree(file("d/f", blob("c"))), h);
+
+ rw.setRevFilter(new TreeRevFilter(rw, TreeFilter.ANY_DIFF));
+ rw.setTreeFilter(TreeFilter.ANY_DIFF);
+ markStart(i);
+
+ assertCommit(i, rw.next());
+ assertEquals(1, i.getParentCount());
+ assertCommit(c, i.getParent(0));
+
+ // h..d was skipped
+ assertCommit(c, rw.next());
+ assertEquals(1, c.getParentCount());
+ assertCommit(a, c.getParent(0));
+
+ // b was skipped
+ assertCommit(a, rw.next());
+ assertEquals(0, a.getParentCount());
+ assertNull(rw.next());
+ }
+
+ @Test
public void testPathFilterOrOtherFilter() throws Exception {
- RevFilter pathFilter = treeRevFilter();
+ RevFilter pathFilter = new TreeRevFilter(rw, TreeFilter.ANY_DIFF);
RevFilter skipFilter = SkipRevFilter.create(1);
RevFilter orFilter = OrRevFilter.create(skipFilter, pathFilter);
@@ -126,6 +236,9 @@ public class TreeRevFilterTest extends RevWalkTestCase {
rw.setRevFilter(pathFilter);
markStart(c);
assertCommit(c, rw.next());
+ assertEquals(1, c.getParentCount());
+ assertCommit(b, c.getParent(0));
+
assertCommit(a, rw.next());
// Skip filter matches b, a.
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterWithRewriteParentsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterWithRewriteParentsTest.java
deleted file mode 100644
index 100f2e4164..0000000000
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/TreeRevFilterWithRewriteParentsTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2023, Google LLC and others
- *
- * 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 org.eclipse.jgit.revwalk.filter.RevFilter;
-import org.eclipse.jgit.treewalk.filter.TreeFilter;
-import org.junit.Test;
-
-public class TreeRevFilterWithRewriteParentsTest extends RevWalkTestCase {
- private RevFilter treeRevFilter() {
- rw.setRewriteParents(true);
- return new TreeRevFilter(rw, TreeFilter.ANY_DIFF);
- }
-
- @Test
- public void testStringOfPearls_FilePath1()
- throws Exception {
- RevCommit a = commit(tree(file("d/f", blob("a"))));
- RevCommit b = commit(tree(file("d/f", blob("a"))), a);
- RevCommit c = commit(tree(file("d/f", blob("b"))), b);
- rw.setRevFilter(treeRevFilter());
- markStart(c);
-
- assertCommit(c, rw.next());
- assertEquals(1, c.getParentCount());
- assertCommit(a, c.getParent(0));
-
- assertCommit(a, rw.next()); // b was skipped
- assertEquals(0, a.getParentCount());
- assertNull(rw.next());
- }
-
- @Test
- public void testStringOfPearls_FilePath2() throws Exception {
- RevCommit a = commit(tree(file("d/f", blob("a"))));
- RevCommit b = commit(tree(file("d/f", blob("a"))), a);
- RevCommit c = commit(tree(file("d/f", blob("b"))), b);
- RevCommit d = commit(tree(file("d/f", blob("b"))), c);
- rw.setRevFilter(treeRevFilter());
- markStart(d);
-
- // d was skipped
- assertCommit(c, rw.next());
- assertEquals(1, c.getParentCount());
- assertCommit(a, c.getParent(0));
-
- // b was skipped
- assertCommit(a, rw.next());
- assertEquals(0, a.getParentCount());
- assertNull(rw.next());
- }
-
- @Test
- public void testStringOfPearls_DirPath2() throws Exception {
- RevCommit a = commit(tree(file("d/f", blob("a"))));
- RevCommit b = commit(tree(file("d/f", blob("a"))), a);
- RevCommit c = commit(tree(file("d/f", blob("b"))), b);
- RevCommit d = commit(tree(file("d/f", blob("b"))), c);
- rw.setRevFilter(treeRevFilter());
- markStart(d);
-
- // d was skipped
- assertCommit(c, rw.next());
- assertEquals(1, c.getParentCount());
- assertCommit(a, c.getParent(0));
-
- // b was skipped
- assertCommit(a, rw.next());
- assertEquals(0, a.getParentCount());
- assertNull(rw.next());
- }
-
- @Test
- public void testStringOfPearls_FilePath3() throws Exception {
- RevCommit a = commit(tree(file("d/f", blob("a"))));
- RevCommit b = commit(tree(file("d/f", blob("a"))), a);
- RevCommit c = commit(tree(file("d/f", blob("b"))), b);
- RevCommit d = commit(tree(file("d/f", blob("b"))), c);
- RevCommit e = commit(tree(file("d/f", blob("b"))), d);
- RevCommit f = commit(tree(file("d/f", blob("b"))), e);
- RevCommit g = commit(tree(file("d/f", blob("b"))), f);
- RevCommit h = commit(tree(file("d/f", blob("b"))), g);
- RevCommit i = commit(tree(file("d/f", blob("c"))), h);
- rw.setRevFilter(treeRevFilter());
- markStart(i);
-
- assertCommit(i, rw.next());
- assertEquals(1, i.getParentCount());
- assertCommit(c, i.getParent(0));
-
- // h..d was skipped
- assertCommit(c, rw.next());
- assertEquals(1, c.getParentCount());
- assertCommit(a, c.getParent(0));
-
- // b was skipped
- assertCommit(a, rw.next());
- assertEquals(0, a.getParentCount());
- assertNull(rw.next());
- }
-}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java
index 32bd40312f..1bb4939c85 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java
@@ -11,6 +11,7 @@
package org.eclipse.jgit.treewalk.filter;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -21,7 +22,9 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEditor;
@@ -30,6 +33,7 @@ import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.StopWalkException;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Sets;
@@ -143,6 +147,29 @@ public class PathFilterGroupTest {
}
@Test
+ public void testGetPathsBestEffort() {
+ String[] paths = { "path1", "path2", "path3" };
+ Set<byte[]> expected = Arrays.stream(paths).map(Constants::encode)
+ .collect(Collectors.toSet());
+ TreeFilter pathFilterGroup = PathFilterGroup.createFromStrings(paths);
+ Optional<Set<byte[]>> bestEffortPaths = pathFilterGroup
+ .getPathsBestEffort();
+ assertTrue(bestEffortPaths.isPresent());
+ Set<byte[]> actual = bestEffortPaths.get();
+ assertEquals(expected.size(), actual.size());
+ for (byte[] actualPath : actual) {
+ boolean findMatch = false;
+ for (byte[] expectedPath : expected) {
+ if (Arrays.equals(actualPath, expectedPath)) {
+ findMatch = true;
+ break;
+ }
+ }
+ assertTrue(findMatch);
+ }
+ }
+
+ @Test
public void testStopWalk() throws MissingObjectException,
IncorrectObjectTypeException, IOException {
// Obvious