diff options
author | Matthias Sohn <matthias.sohn@sap.com> | 2023-08-30 16:43:08 +0200 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2023-08-30 16:43:08 +0200 |
commit | 2e2e58d59f1546a791983e2b28adb99c71a93a34 (patch) | |
tree | e271bafe57718add342e23d552bdf0d710e7a807 /org.eclipse.jgit.test | |
parent | abe155ea94af563110326a44d538fdb4f0af8bba (diff) | |
parent | 2be8bf2b37177256e5183f26b7ccd13e104daf5f (diff) | |
download | jgit-2e2e58d59f1546a791983e2b28adb99c71a93a34.tar.gz jgit-2e2e58d59f1546a791983e2b28adb99c71a93a34.zip |
Merge branch 'master' into stable-6.7
* master:
Remove the cbi-snapshots Maven repository
Update Orbit to orbit-aggregation/release/4.29.0
Add target platform for Eclipse 2023-09 (4.29)
Use release p2 repo for Eclipse 2023-06 (4.28)
Update tycho to 4.0.2
Update jmh to 1.37
Update bouncycastle to 1.76
Fix some tests in ConfigTest
Handle global git config $XDG_CONFIG_HOME/git/config
IO: use JDK convenience methods
org.eclipse.jgit.junit.ssh/.settings/.api_filters: fix unclosed tags
ReadChangedPathFilter: fix Non-externalized string literal warning
Introduce core.packedIndexGitUseStrongRefs config key
DfsReader: Make PackLoadListener interface visible to subclasses
DfsGarbageCollector: provide commit graph stats
DfsGarbageCollector: put only GC commits into the commit graph
DfsReader: Expose when indices are loaded
Change-Id: Idd78a0a1bc3cd3db5edb475e235c13354d9087a9
Diffstat (limited to 'org.eclipse.jgit.test')
7 files changed, 562 insertions, 40 deletions
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index d4d84bcd90..3ae2d6b5dc 100644 --- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF @@ -7,6 +7,8 @@ Bundle-Version: 6.7.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %Bundle-Vendor Bundle-RequiredExecutionEnvironment: JavaSE-11 +Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)", + org.hamcrest.library;bundle-version="[1.3.0,2.0.0)" Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", net.bytebuddy.agent;version="[1.9.0,2.0.0)", net.bytebuddy.dynamic.loading;version="[1.9.0,2.0.0)", @@ -75,8 +77,6 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", org.eclipse.jgit.util;version="[6.7.0,6.8.0)", org.eclipse.jgit.util.io;version="[6.7.0,6.8.0)", org.eclipse.jgit.util.sha1;version="[6.7.0,6.8.0)", - org.hamcrest;version="[1.1.0,3.0.0)", - org.hamcrest.collection;version="[1.1.0,3.0.0)", org.junit;version="[4.13,5.0.0)", org.junit.experimental.theories;version="[4.13,5.0.0)", org.junit.function;version="[4.13.0,5.0.0)", 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 405e12677e..05360dc052 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 @@ -20,6 +20,7 @@ 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.reftable.RefCursor; import org.eclipse.jgit.internal.storage.reftable.ReftableConfig; @@ -979,7 +980,7 @@ public class DfsGarbageCollectorTest { } @Test - public void produceCommitGraphAllRefsIncludedFromDisk() throws Exception { + public void produceCommitGraphOnlyHeadsAndTags() throws Exception { String tag = "refs/tags/tag1"; String head = "refs/heads/head1"; String nonHead = "refs/something/nonHead"; @@ -1001,19 +1002,20 @@ public class DfsGarbageCollectorTest { CommitGraph cg = gcPack.getCommitGraph(reader); assertNotNull(cg); - assertTrue("all commits in commit graph", cg.getCommitCnt() == 3); + assertTrue("Only heads and tags reachable commits in commit graph", + cg.getCommitCnt() == 2); // GC packed assertTrue("tag referenced commit is in graph", cg.findGraphPosition(rootCommitTagged) != -1); assertTrue("head referenced commit is in graph", cg.findGraphPosition(headTip) != -1); - // GC_REST packed - assertTrue("nonHead referenced commit is in graph", - cg.findGraphPosition(nonHeadTip) != -1); + // GC_REST not in commit graph + assertEquals("nonHead referenced commit is NOT in graph", + -1, cg.findGraphPosition(nonHeadTip)); } @Test - public void produceCommitGraphAllRefsIncludedFromCache() throws Exception { + public void produceCommitGraphOnlyHeadsAndTagsIncludedFromCache() throws Exception { String tag = "refs/tags/tag1"; String head = "refs/heads/head1"; String nonHead = "refs/something/nonHead"; @@ -1043,15 +1045,16 @@ public class DfsGarbageCollectorTest { assertTrue("commit graph read time is recorded", reader.stats.readCommitGraphMicros > 0); - assertTrue("all commits in commit graph", cachedCG.getCommitCnt() == 3); + assertTrue("Only heads and tags reachable commits in commit graph", + cachedCG.getCommitCnt() == 2); // GC packed assertTrue("tag referenced commit is in graph", cachedCG.findGraphPosition(rootCommitTagged) != -1); assertTrue("head referenced commit is in graph", cachedCG.findGraphPosition(headTip) != -1); - // GC_REST packed - assertTrue("nonHead referenced commit is in graph", - cachedCG.findGraphPosition(nonHeadTip) != -1); + // GC_REST not in commit graph + assertEquals("nonHead referenced commit is not in graph", + -1, cachedCG.findGraphPosition(nonHeadTip)); } @Test @@ -1102,6 +1105,22 @@ public class DfsGarbageCollectorTest { } @Test + public void produceCommitGraphAndBloomFilter() throws Exception { + String head = "refs/heads/head1"; + + git.branch(head).commit().message("0").noParents().create(); + + gcWithCommitGraphAndBloomFilter(); + + assertEquals(1, odb.getPacks().length); + DfsPackFile pack = odb.getPacks()[0]; + DfsPackDescription desc = pack.getPackDescription(); + CommitGraphWriter.Stats stats = desc.getCommitGraphStats(); + assertNotNull(stats); + assertEquals(1, stats.getChangedPathFiltersComputed()); + } + + @Test public void objectSizeIdx_reachableBlob_bigEnough_indexed() throws Exception { String master = "refs/heads/master"; RevCommit root = git.branch(master).commit().message("root").noParents() @@ -1175,6 +1194,13 @@ public class DfsGarbageCollectorTest { run(gc); } + private void gcWithCommitGraphAndBloomFilter() throws IOException { + DfsGarbageCollector gc = new DfsGarbageCollector(repo); + gc.setWriteCommitGraph(true); + gc.setWriteBloomFilter(true); + run(gc); + } + private void gcWithObjectSizeIndex(int threshold) throws IOException { DfsGarbageCollector gc = new DfsGarbageCollector(repo); gc.getPackConfig().setMinBytesForObjSizeIndex(threshold); 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 298812d6ed..82fc56347e 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 @@ -18,8 +18,12 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import java.util.zip.Deflater; +import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource; +import org.eclipse.jgit.internal.storage.dfs.DfsReader.PackLoadListener; import org.eclipse.jgit.internal.storage.pack.PackExt; import org.eclipse.jgit.internal.storage.pack.PackOutputStream; import org.eclipse.jgit.internal.storage.pack.PackWriter; @@ -130,6 +134,93 @@ public class DfsPackFileTest { assertFalse(pack.hasObjectSizeIndex(reader)); } + private static class TestPackLoadListener implements PackLoadListener { + final Map<PackExt, Integer> indexLoadCount = new HashMap<>(); + + int blockLoadCount; + + @Override + public void onIndexLoad(String packName, PackSource src, PackExt ext, + long size, Object loadedIdx) { + indexLoadCount.merge(ext, 1, Integer::sum); + } + + @Override + public void onBlockLoad(String packName, PackSource src, PackExt ext, long position, + DfsBlockData dfsBlockData) { + blockLoadCount += 1; + } + } + + @Test + public void testIndexLoadCallback_indexNotInCache() throws IOException { + bypassCache = false; + clearCache = true; + setObjectSizeIndexMinBytes(-1); + setupPack(512, 800); + + TestPackLoadListener tal = new TestPackLoadListener(); + DfsReader reader = db.getObjectDatabase().newReader(); + reader.addPackLoadListener(tal); + DfsPackFile pack = db.getObjectDatabase().getPacks()[0]; + pack.getPackIndex(reader); + + assertEquals(1, tal.indexLoadCount.get(PackExt.INDEX).intValue()); + } + + @Test + public void testIndexLoadCallback_indexInCache() throws IOException { + bypassCache = false; + clearCache = false; + setObjectSizeIndexMinBytes(-1); + setupPack(512, 800); + + TestPackLoadListener tal = new TestPackLoadListener(); + DfsReader reader = db.getObjectDatabase().newReader(); + reader.addPackLoadListener(tal); + DfsPackFile pack = db.getObjectDatabase().getPacks()[0]; + pack.getPackIndex(reader); + pack.getPackIndex(reader); + pack.getPackIndex(reader); + + assertEquals(1, tal.indexLoadCount.get(PackExt.INDEX).intValue()); + } + + @Test + public void testIndexLoadCallback_multipleReads() throws IOException { + bypassCache = false; + clearCache = true; + setObjectSizeIndexMinBytes(-1); + setupPack(512, 800); + + TestPackLoadListener tal = new TestPackLoadListener(); + DfsReader reader = db.getObjectDatabase().newReader(); + reader.addPackLoadListener(tal); + DfsPackFile pack = db.getObjectDatabase().getPacks()[0]; + pack.getPackIndex(reader); + pack.getPackIndex(reader); + pack.getPackIndex(reader); + + assertEquals(1, tal.indexLoadCount.get(PackExt.INDEX).intValue()); + } + + + @Test + public void testBlockLoadCallback_loadInCache() throws IOException { + bypassCache = false; + clearCache = true; + setObjectSizeIndexMinBytes(-1); + setupPack(512, 800); + + TestPackLoadListener tal = new TestPackLoadListener(); + DfsReader reader = db.getObjectDatabase().newReader(); + reader.addPackLoadListener(tal); + DfsPackFile pack = db.getObjectDatabase().getPacks()[0]; + ObjectId anObject = pack.getPackIndex(reader).getObjectId(0); + pack.get(reader, anObject).getBytes(); + assertEquals(2, tal.blockLoadCount); + } + private ObjectId setupPack(int bs, int ps) throws IOException { DfsBlockCacheConfig cfg = new DfsBlockCacheConfig().setBlockSize(bs) .setBlockLimit(bs * 100).setStreamRatio(bypassCache ? 0F : 1F); 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 4dd7ba494f..8fc9a0adf9 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 @@ -11,15 +11,20 @@ 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.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource; +import org.eclipse.jgit.internal.storage.dfs.DfsReader.PackLoadListener; +import org.eclipse.jgit.internal.storage.pack.PackExt; import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.TestRng; -import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; import org.junit.Before; @@ -40,31 +45,31 @@ public class DfsReaderTest { ObjectId obj = insertBlobWithSize(200); try (DfsReader ctx = db.getObjectDatabase().newReader()) { assertFalse("limit < threshold < obj", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 50)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 50)); assertEquals(1, ctx.stats.isNotLargerThanCallCount); assertEquals(1, ctx.stats.objectSizeIndexHit); assertEquals(0, ctx.stats.objectSizeIndexMiss); assertFalse("limit = threshold < obj", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 100)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 100)); assertEquals(2, ctx.stats.isNotLargerThanCallCount); assertEquals(2, ctx.stats.objectSizeIndexHit); assertEquals(0, ctx.stats.objectSizeIndexMiss); assertFalse("threshold < limit < obj", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 150)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 150)); assertEquals(3, ctx.stats.isNotLargerThanCallCount); assertEquals(3, ctx.stats.objectSizeIndexHit); assertEquals(0, ctx.stats.objectSizeIndexMiss); assertTrue("threshold < limit = obj", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 200)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 200)); assertEquals(4, ctx.stats.isNotLargerThanCallCount); assertEquals(4, ctx.stats.objectSizeIndexHit); assertEquals(0, ctx.stats.objectSizeIndexMiss); assertTrue("threshold < obj < limit", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 250)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 250)); assertEquals(5, ctx.stats.isNotLargerThanCallCount); assertEquals(5, ctx.stats.objectSizeIndexHit); assertEquals(0, ctx.stats.objectSizeIndexMiss); @@ -80,31 +85,31 @@ public class DfsReaderTest { ObjectId obj = insertBlobWithSize(50); try (DfsReader ctx = db.getObjectDatabase().newReader()) { assertFalse("limit < obj < threshold", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 10)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 10)); assertEquals(1, ctx.stats.isNotLargerThanCallCount); assertEquals(0, ctx.stats.objectSizeIndexHit); assertEquals(1, ctx.stats.objectSizeIndexMiss); assertTrue("limit = obj < threshold", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 50)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 50)); assertEquals(2, ctx.stats.isNotLargerThanCallCount); assertEquals(0, ctx.stats.objectSizeIndexHit); assertEquals(2, ctx.stats.objectSizeIndexMiss); assertTrue("obj < limit < threshold", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 80)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 80)); assertEquals(3, ctx.stats.isNotLargerThanCallCount); assertEquals(0, ctx.stats.objectSizeIndexHit); assertEquals(3, ctx.stats.objectSizeIndexMiss); assertTrue("obj < limit = threshold", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 100)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 100)); assertEquals(4, ctx.stats.isNotLargerThanCallCount); assertEquals(0, ctx.stats.objectSizeIndexHit); assertEquals(4, ctx.stats.objectSizeIndexMiss); assertTrue("obj < threshold < limit", - ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 120)); + ctx.isNotLargerThan(obj, OBJ_BLOB, 120)); assertEquals(5, ctx.stats.isNotLargerThanCallCount); assertEquals(0, ctx.stats.objectSizeIndexHit); assertEquals(5, ctx.stats.objectSizeIndexMiss); @@ -116,11 +121,11 @@ public class DfsReaderTest { setObjectSizeIndexMinBytes(100); ObjectId obj = insertBlobWithSize(10); try (DfsReader ctx = db.getObjectDatabase().newReader()) { - assertFalse(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 0)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 10)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 40)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 50)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 100)); + assertFalse(ctx.isNotLargerThan(obj, OBJ_BLOB, 0)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 10)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 40)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 50)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 100)); assertEquals(5, ctx.stats.isNotLargerThanCallCount); assertEquals(5, ctx.stats.objectSizeIndexMiss); @@ -133,11 +138,11 @@ public class DfsReaderTest { setObjectSizeIndexMinBytes(-1); ObjectId obj = insertBlobWithSize(10); try (DfsReader ctx = db.getObjectDatabase().newReader()) { - assertFalse(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 0)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 10)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 40)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 50)); - assertTrue(ctx.isNotLargerThan(obj, Constants.OBJ_BLOB, 100)); + assertFalse(ctx.isNotLargerThan(obj, OBJ_BLOB, 0)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 10)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 40)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 50)); + assertTrue(ctx.isNotLargerThan(obj, OBJ_BLOB, 100)); assertEquals(5, ctx.stats.isNotLargerThanCallCount); assertEquals(0, ctx.stats.objectSizeIndexMiss); @@ -145,12 +150,103 @@ public class DfsReaderTest { } } + @Test + public void packLoadListener_noInvocations() throws IOException { + insertBlobWithSize(100); + try (DfsReader ctx = db.getObjectDatabase().newReader()) { + CounterPackLoadListener listener = new CounterPackLoadListener(); + ctx.addPackLoadListener(listener); + assertEquals(null, listener.callsPerExt.get(PackExt.INDEX)); + } + } + + @Test + public void packLoadListener_has_openIdx() throws IOException { + ObjectId obj = insertBlobWithSize(100); + try (DfsReader ctx = db.getObjectDatabase().newReader()) { + CounterPackLoadListener listener = new CounterPackLoadListener(); + ctx.addPackLoadListener(listener); + boolean has = ctx.has(obj); + assertTrue(has); + 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)); + } + } + + @Test + public void packLoadListener_has_openMultipleIndices() throws IOException { + setObjectSizeIndexMinBytes(100); + insertBlobWithSize(200); + insertBlobWithSize(230); + insertBlobWithSize(100); + try (DfsReader ctx = db.getObjectDatabase().newReader()) { + CounterPackLoadListener listener = new CounterPackLoadListener(); + ctx.addPackLoadListener(listener); + 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)); + } + } + + + @Test + public void packLoadListener_has_repeatedCalls_openMultipleIndices() throws IOException { + // Two objects NOT in the repo + ObjectId oid = ObjectId.fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f129"); + ObjectId oid2 = ObjectId.fromString("aa48de2aa61d9dffa8a05439dc115fe82f10f130"); + + setObjectSizeIndexMinBytes(100); + insertBlobWithSize(200); + insertBlobWithSize(230); + insertBlobWithSize(100); + CounterPackLoadListener listener = new CounterPackLoadListener(); + try (DfsReader ctx = db.getObjectDatabase().newReader()) { + ctx.addPackLoadListener(listener); + boolean has = ctx.has(oid); + ctx.has(oid); + ctx.has(oid2); + assertFalse(has); + // The 3 indices were loaded only once each + assertEquals(Integer.valueOf(3), listener.callsPerExt.get(PackExt.INDEX)); + } + } + + private static class CounterPackLoadListener implements PackLoadListener { + final Map<PackExt, Integer> callsPerExt = new HashMap<>(); + + @Override + public void onIndexLoad(String packName, PackSource src, PackExt ext, long size, + Object loadedIdx) { + callsPerExt.merge(ext, 1, Integer::sum); + } + + @Override + public void onBlockLoad(String packName, PackSource src, PackExt ext, + long size, DfsBlockData dfsBlockData) { + } + } + private ObjectId insertBlobWithSize(int size) throws IOException { TestRng testRng = new TestRng(JGitTestUtil.getName()); ObjectId oid; try (ObjectInserter ins = db.newObjectInserter()) { - oid = ins.insert(Constants.OBJ_BLOB, + oid = ins.insert(OBJ_BLOB, testRng.nextBytes(size)); ins.flush(); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackTest.java index a3596541fe..e1509456e5 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackTest.java @@ -261,7 +261,7 @@ public class PackTest extends LocalDiskRepositoryTestCase { new PackIndexWriterV1(f).write(list, footer); } - Pack pack = new Pack(packName, null); + Pack pack = new Pack(repo.getConfig(), packName, null); try { pack.get(wc, b); fail("expected LargeObjectException.ExceedsByteArrayLimit"); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java index 8f9d105319..36cf77bb01 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java @@ -1482,7 +1482,9 @@ public class ConfigTest { File workTree = tmp.newFolder("dummy-worktree"); File tempFile = tmp.newFile("testCommitTemplate-"); - Repository repo = FileRepositoryBuilder.create(workTree); + Repository repo = FileRepositoryBuilder + .create(new File(workTree, ".git")); + repo.create(); String templateContent = "content of the template"; JGitTestUtil.write(tempFile, templateContent); String expectedTemplatePath = tempFile.getPath(); @@ -1532,7 +1534,9 @@ public class ConfigTest { throws ConfigInvalidException, IOException { Config config = new Config(null); File workTree = tmp.newFolder("dummy-worktree"); - Repository repo = FileRepositoryBuilder.create(workTree); + Repository repo = FileRepositoryBuilder + .create(new File(workTree, ".git")); + repo.create(); File tempFile = tmp.newFile("testCommitTemplate-"); String templateContent = "content of the template"; JGitTestUtil.write(tempFile, templateContent); @@ -1554,7 +1558,9 @@ public class ConfigTest { Config config = new Config(null); File workTree = tmp.newFolder("dummy-worktree"); File tempFile = tmp.newFile("testCommitTemplate-"); - Repository repo = FileRepositoryBuilder.create(workTree); + Repository repo = FileRepositoryBuilder + .create(new File(workTree, ".git")); + repo.create(); String templateContent = "content of the template"; JGitTestUtil.write(tempFile, templateContent); config = parse("[i18n]\n\tcommitEncoding = invalidEcoding\n" @@ -1569,7 +1575,9 @@ public class ConfigTest { Config config = new Config(null); File workTree = tmp.newFolder("dummy-worktree"); File tempFile = tmp.newFile("testCommitTemplate-"); - Repository repo = FileRepositoryBuilder.create(workTree); + Repository repo = FileRepositoryBuilder + .create(new File(workTree, ".git")); + repo.create(); String templateContent = "content of the template"; JGitTestUtil.write(tempFile, templateContent); // commit message encoding diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UserConfigFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UserConfigFileTest.java new file mode 100644 index 0000000000..7d212d540f --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/UserConfigFileTest.java @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2023, Thomas Wolf <twolf@apache.org> 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.storage.file; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.nio.file.Files; +import java.nio.file.Path; + +import org.eclipse.jgit.util.FS; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class UserConfigFileTest { + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + @Test + public void testParentOnlyLoad() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + } + + @Test + public void testLoadBoth() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Files.writeString(user, "[user]\n\temail = a.u.thor@example.com"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + } + + @Test + public void testOverwriteChild() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Files.writeString(user, "[user]\n\temail = a.u.thor@example.com"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + config.setString("user", null, "name", "A U Thor"); + assertEquals("A U Thor", config.getString("user", null, "name")); + config.save(); + UserConfigFile config2 = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config2.load(); + assertEquals("A U Thor", config2.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + FileBasedConfig cfg = new FileBasedConfig(null, xdg.toFile(), + FS.DETECTED); + cfg.load(); + assertEquals("Archibald Ulysses Thor", + cfg.getString("user", null, "name")); + assertNull(cfg.getString("user", null, "email")); + } + + @Test + public void testUnset() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Files.writeString(user, "[user]\n\temail = a.u.thor@example.com"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + config.setString("user", null, "name", "A U Thor"); + assertEquals("A U Thor", config.getString("user", null, "name")); + config.unset("user", null, "name"); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + config.save(); + UserConfigFile config2 = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config2.load(); + assertEquals("Archibald Ulysses Thor", + config2.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + FileBasedConfig cfg = new FileBasedConfig(null, user.toFile(), + FS.DETECTED); + cfg.load(); + assertNull(cfg.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + cfg.getString("user", null, "email")); + } + + @Test + public void testUnsetSection() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Files.writeString(user, "[user]\n\temail = a.u.thor@example.com"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + config.unsetSection("user", null); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + config.save(); + assertTrue(Files.readString(user).strip().isEmpty()); + } + + @Test + public void testNoChild() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertNull(config.getString("user", null, "email")); + config.setString("user", null, "email", "a.u.thor@example.com"); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + config.save(); + assertFalse(Files.exists(user)); + UserConfigFile config2 = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config2.load(); + assertEquals("Archibald Ulysses Thor", + config2.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config2.getString("user", null, "email")); + } + + @Test + public void testNoFiles() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertNull(config.getString("user", null, "name")); + assertNull(config.getString("user", null, "email")); + config.setString("user", null, "name", "Archibald Ulysses Thor"); + config.setString("user", null, "email", "a.u.thor@example.com"); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + config.save(); + assertTrue(Files.exists(user)); + assertFalse(Files.exists(xdg)); + UserConfigFile config2 = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config2.load(); + assertEquals("Archibald Ulysses Thor", + config2.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config2.getString("user", null, "email")); + } + + @Test + public void testSetInXdg() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + config.setString("user", null, "email", "a.u.thor@example.com"); + config.save(); + assertFalse(Files.exists(user)); + FileBasedConfig cfg = new FileBasedConfig(null, xdg.toFile(), + FS.DETECTED); + cfg.load(); + assertEquals("Archibald Ulysses Thor", + cfg.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + cfg.getString("user", null, "email")); + } + + @Test + public void testUserConfigCreated() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Thread.sleep(3000); // Avoid racily clean isOutdated() below. + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + Files.writeString(user, + "[user]\n\temail = a.u.thor@example.com\n\tname = A U Thor"); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertTrue(config.isOutdated()); + config.load(); + assertEquals("A U Thor", config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + } + + @Test + public void testUserConfigDeleted() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Files.writeString(user, + "[user]\n\temail = a.u.thor@example.com\n\tname = A U Thor"); + Thread.sleep(3000); // Avoid racily clean isOutdated() below. + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("A U Thor", config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + Files.delete(user); + assertEquals("A U Thor", config.getString("user", null, "name")); + assertEquals("a.u.thor@example.com", + config.getString("user", null, "email")); + assertTrue(config.isOutdated()); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertNull(config.getString("user", null, "email")); + } + + @Test + public void testXdgConfigDeleted() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Thread.sleep(3000); // Avoid racily clean isOutdated() below. + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + Files.delete(xdg); + assertEquals("Archibald Ulysses Thor", + config.getString("user", null, "name")); + assertTrue(config.isOutdated()); + config.load(); + assertNull(config.getString("user", null, "name")); + } + + @Test + public void testXdgConfigDeletedUserConfigExists() throws Exception { + Path xdg = tmp.getRoot().toPath().resolve("xdg.cfg"); + Files.writeString(xdg, "[user]\n\tname = Archibald Ulysses Thor"); + Path user = tmp.getRoot().toPath().resolve("user.cfg"); + Files.writeString(user, + "[user]\n\temail = a.u.thor@example.com\n\tname = A U Thor"); + Thread.sleep(3000); // Avoid racily clean isOutdated() below. + UserConfigFile config = new UserConfigFile(null, user.toFile(), + xdg.toFile(), FS.DETECTED); + config.load(); + assertEquals("A U Thor", config.getString("user", null, "name")); + Files.delete(xdg); + assertTrue(config.isOutdated()); + config.load(); + assertEquals("A U Thor", config.getString("user", null, "name")); + } + +} |