aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java36
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java30
-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/treewalk/filter/PathFilterGroupTest.java27
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java28
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/util/CleanupService.java33
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/util/ShutdownHook.java34
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ByteArraySet.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathFilterGroup.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java2
12 files changed, 228 insertions, 27 deletions
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 1bff27e26a..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
@@ -31,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;
@@ -1122,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()
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 44694acc8d..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,7 +10,9 @@
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;
@@ -24,6 +26,7 @@ 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;
@@ -31,6 +34,7 @@ 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;
@@ -263,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);
@@ -298,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/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/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
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java
index 42b1d235bf..2e534d580f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java
@@ -52,10 +52,12 @@ import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
import org.eclipse.jgit.internal.storage.pack.StoredObjectRepresentation;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.LongList;
/**
@@ -1283,11 +1285,16 @@ public final class DfsPackFile extends BlockBasedFile {
DfsStreamKey cgkey) throws IOException {
ctx.stats.readCommitGraph++;
long start = System.nanoTime();
+ StoredConfig repoConfig = ctx.db.getRepository().getConfig();
+ boolean readChangedPathFilters = repoConfig.getBoolean(
+ ConfigConstants.CONFIG_COMMIT_GRAPH_SECTION,
+ ConfigConstants.CONFIG_KEY_READ_CHANGED_PATHS, false);
try (ReadableChannel rc = ctx.db.openFile(desc, COMMIT_GRAPH)) {
long size;
CommitGraph cg;
try {
- cg = CommitGraphLoader.read(alignTo8kBlocks(rc));
+ cg = CommitGraphLoader.read(alignTo8kBlocks(rc),
+ readChangedPathFilters);
} finally {
size = rc.position();
ctx.stats.readCommitGraphBytes += size;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java
index 46607f60d9..1dc5776e06 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java
@@ -16,15 +16,21 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.revwalk.RevWalk;
+import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Snapshotting write-through cache of a {@link RefDirectory}.
* <p>
* This is intended to be short-term write-through snapshot based cache used in
- * a request scope to avoid re-reading packed-refs on each read. A future
- * improvement could also snapshot loose refs.
+ * a request scope to avoid re-reading packed-refs on each read and to avoid
+ * refreshing paths to a loose ref that has already been refreshed.
* <p>
* Only use this class when concurrent writes from other requests (not using the
* same instance of SnapshottingRefDirectory) generally need not be visible to
@@ -34,6 +40,7 @@ import java.util.List;
*/
class SnapshottingRefDirectory extends RefDirectory {
final RefDirectory refDb;
+ private final Set<File> refreshedLooseRefDirs = ConcurrentHashMap.newKeySet();
private volatile boolean isValid;
@@ -67,6 +74,22 @@ class SnapshottingRefDirectory extends RefDirectory {
}
@Override
+ void refreshPathToLooseRef(Path refPath) {
+ for (int i = 1; i < refPath.getNameCount(); i++) {
+ File dir = fileFor(refPath.subpath(0, i).toString());
+ if (!refreshedLooseRefDirs.contains(dir)) {
+ try (InputStream stream = Files.newInputStream(dir.toPath())) {
+ // open the dir to refresh attributes (on some NFS clients)
+ } catch (IOException e) {
+ break; // loose ref may not exist
+ } finally {
+ refreshedLooseRefDirs.add(dir);
+ }
+ }
+ }
+ }
+
+ @Override
void delete(RefDirectoryUpdate update) throws IOException {
refreshSnapshot();
super.delete(update);
@@ -107,6 +130,7 @@ class SnapshottingRefDirectory extends RefDirectory {
}
synchronized void invalidateSnapshot() {
+ refreshedLooseRefDirs.clear();
isValid = false;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/CleanupService.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/CleanupService.java
index 76e09307ab..29ed7564d3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/CleanupService.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/CleanupService.java
@@ -9,6 +9,10 @@
*/
package org.eclipse.jgit.internal.util;
+import org.eclipse.jgit.internal.JGitText;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* A class that is registered as an OSGi service via the manifest. If JGit runs
* in OSGi, OSGi will instantiate a singleton as soon as the bundle is activated
@@ -23,12 +27,17 @@ package org.eclipse.jgit.internal.util;
*/
public final class CleanupService {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(CleanupService.class);
+
private static final Object LOCK = new Object();
private static CleanupService INSTANCE;
private final boolean isOsgi;
+ private JGitText jgitText;
+
private Runnable cleanup;
/**
@@ -74,8 +83,24 @@ public final class CleanupService {
if (isOsgi) {
cleanup = cleanUp;
} else {
+ // Ensure the JGitText class is loaded. Depending on the framework
+ // JGit runs in, it may not be possible anymore to load classes when
+ // the hook runs. For instance when run in a maven plug-in: the
+ // Plexus class world that loaded JGit may already have been
+ // disposed by the time the JVM shutdown hook runs when the whole
+ // maven build terminates.
+ jgitText = JGitText.get();
+ assert jgitText != null;
try {
- Runtime.getRuntime().addShutdownHook(new Thread(cleanUp));
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ try {
+ cleanUp.run();
+ // Don't catch exceptions; let the JVM do the problem
+ // reporting.
+ } finally {
+ jgitText = null;
+ }
+ }));
} catch (IllegalStateException e) {
// Ignore -- the JVM is already shutting down.
}
@@ -86,7 +111,11 @@ public final class CleanupService {
if (isOsgi && cleanup != null) {
Runnable r = cleanup;
cleanup = null;
- r.run();
+ try {
+ r.run();
+ } catch (RuntimeException e) {
+ LOG.error(JGitText.get().shutdownCleanupFailed, e);
+ }
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/ShutdownHook.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/ShutdownHook.java
index 5ba33dbbff..f6b4723489 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/ShutdownHook.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/util/ShutdownHook.java
@@ -15,9 +15,9 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jgit.internal.JGitText;
import org.slf4j.Logger;
@@ -66,25 +66,27 @@ public enum ShutdownHook {
private final Set<Listener> listeners = ConcurrentHashMap.newKeySet();
- private volatile boolean shutdownInProgress;
+ private final AtomicBoolean shutdownInProgress = new AtomicBoolean();
private ShutdownHook() {
CleanupService.getInstance().register(this::cleanup);
}
private void cleanup() {
- shutdownInProgress = true;
- ExecutorService runner = Executors.newWorkStealingPool();
- try {
- runner.submit(() -> {
- this.doCleanup();
- return null;
- }).get(30L, TimeUnit.SECONDS);
- } catch (RejectedExecutionException | InterruptedException
- | ExecutionException | TimeoutException e) {
- LOG.error(JGitText.get().shutdownCleanupFailed, e);
+ if (!shutdownInProgress.getAndSet(true)) {
+ ExecutorService runner = Executors.newWorkStealingPool();
+ try {
+ runner.submit(() -> {
+ this.doCleanup();
+ return null;
+ }).get(30L, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException
+ | TimeoutException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } finally {
+ runner.shutdownNow();
+ }
}
- runner.shutdownNow();
}
private void doCleanup() {
@@ -112,7 +114,7 @@ public enum ShutdownHook {
* @return {@code true} if this object has been registered
*/
public boolean register(Listener l) {
- if (shutdownInProgress) {
+ if (shutdownInProgress.get()) {
return listeners.contains(l);
}
LOG.debug("register {} with shutdown hook", l); //$NON-NLS-1$
@@ -131,7 +133,7 @@ public enum ShutdownHook {
* @return {@code true} if this object is no longer registered
*/
public boolean unregister(Listener l) {
- if (shutdownInProgress) {
+ if (shutdownInProgress.get()) {
return !listeners.contains(l);
}
LOG.debug("unregister {} from shutdown hook", l); //$NON-NLS-1$
@@ -145,6 +147,6 @@ public enum ShutdownHook {
* @return {@code true} if a JGit shutdown is in progress
*/
public boolean isShutdownInProgress() {
- return shutdownInProgress;
+ return shutdownInProgress.get();
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
index 43571a6868..99943b78e6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
@@ -139,11 +139,8 @@ public class TreeRevFilter extends RevFilter {
.getPathsBestEffort();
if (paths.isPresent()) {
changedPathFilterUsed = true;
- for (byte[] path : paths.get()) {
- if (!cpf.maybeContains(path)) {
- mustCalculateChgs = false;
- break;
- }
+ if (paths.get().stream().noneMatch(cpf::maybeContains)) {
+ mustCalculateChgs = false;
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ByteArraySet.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ByteArraySet.java
index c94160144e..bcf79a285d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ByteArraySet.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ByteArraySet.java
@@ -15,6 +15,10 @@ package org.eclipse.jgit.treewalk.filter;
import org.eclipse.jgit.util.RawParseUtils;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
/**
* Specialized set for byte arrays, interpreted as strings for use in
* {@link PathFilterGroup.Group}. Most methods assume the hash is already know
@@ -291,4 +295,8 @@ class ByteArraySet {
return ret;
}
+ Set<byte[]> toSet() {
+ return Arrays.stream(toArray()).collect(Collectors.toSet());
+ }
+
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathFilterGroup.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathFilterGroup.java
index 59855572f2..4c0604ad56 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathFilterGroup.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/PathFilterGroup.java
@@ -12,6 +12,8 @@
package org.eclipse.jgit.treewalk.filter;
import java.util.Collection;
+import java.util.Optional;
+import java.util.Set;
import org.eclipse.jgit.errors.StopWalkException;
import org.eclipse.jgit.internal.JGitText;
@@ -232,6 +234,15 @@ public class PathFilterGroup {
}
@Override
+ public Optional<Set<byte[]>> getPathsBestEffort() {
+ Set<byte[]> result = fullpaths.toSet();
+ if (result.isEmpty()) {
+ return Optional.empty();
+ }
+ return Optional.of(result);
+ }
+
+ @Override
public TreeFilter clone() {
return this;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java
index 22d430bc27..a9066dc8f8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java
@@ -210,7 +210,7 @@ public abstract class TreeFilter {
public abstract boolean shouldBeRecursive();
/**
- * If this filter checks that a specific set of paths have all been
+ * If this filter checks that at least one of the paths in a set has been
* modified, returns that set of paths to be checked against a changed path
* filter. Otherwise, returns empty.
*