On a subtree, a PathSuffixFilter must return -1 ("indeterminate"), not 0 ("include"), otherwise negation goes wrong: an indeterminate result (-1) is passed on, but a decision (0/1) is inverted. As a result a negated PathSuffixFilter would skip all folders. Bug: 574253 Change-Id: I27fe785c0d772392a5b5efe0a7b1c9cafcb6e566 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>changes/26/182126/2
/* | /* | ||||
* Copyright (C) 2010, 2020 Google Inc. and others | |||||
* Copyright (C) 2010, 2021 Google Inc. and others | |||||
* | * | ||||
* This program and the accompanying materials are made available under the | * This program and the accompanying materials are made available under the | ||||
* terms of the Eclipse Distribution License v. 1.0 which is available at | * terms of the Eclipse Distribution License v. 1.0 which is available at | ||||
import java.io.BufferedOutputStream; | import java.io.BufferedOutputStream; | ||||
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.File; | import java.io.File; | ||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import org.eclipse.jgit.api.Git; | import org.eclipse.jgit.api.Git; | ||||
import org.eclipse.jgit.api.Status; | import org.eclipse.jgit.api.Status; | ||||
import org.eclipse.jgit.patch.HunkHeader; | import org.eclipse.jgit.patch.HunkHeader; | ||||
import org.eclipse.jgit.revwalk.RevCommit; | import org.eclipse.jgit.revwalk.RevCommit; | ||||
import org.eclipse.jgit.storage.file.FileBasedConfig; | import org.eclipse.jgit.storage.file.FileBasedConfig; | ||||
import org.eclipse.jgit.treewalk.CanonicalTreeParser; | |||||
import org.eclipse.jgit.treewalk.FileTreeIterator; | import org.eclipse.jgit.treewalk.FileTreeIterator; | ||||
import org.eclipse.jgit.treewalk.filter.OrTreeFilter; | |||||
import org.eclipse.jgit.treewalk.filter.PathFilter; | import org.eclipse.jgit.treewalk.filter.PathFilter; | ||||
import org.eclipse.jgit.treewalk.filter.PathSuffixFilter; | |||||
import org.eclipse.jgit.treewalk.filter.TreeFilter; | |||||
import org.eclipse.jgit.util.FileUtils; | import org.eclipse.jgit.util.FileUtils; | ||||
import org.eclipse.jgit.util.RawParseUtils; | import org.eclipse.jgit.util.RawParseUtils; | ||||
import org.eclipse.jgit.util.io.DisabledOutputStream; | import org.eclipse.jgit.util.io.DisabledOutputStream; | ||||
} | } | ||||
} | } | ||||
@Test | |||||
public void testFilter() throws Exception { | |||||
RevCommit parent; | |||||
RevCommit head; | |||||
try (Git git = new Git(db)) { | |||||
writeTrashFile("foo.txt", "foo\n"); | |||||
writeTrashFile("src/some.txt", "some\n"); | |||||
writeTrashFile("src/image.png", "image\n"); | |||||
writeTrashFile("src/test.pdf", "test\n"); | |||||
writeTrashFile("src/xyz.txt", "xyz\n"); | |||||
git.add().addFilepattern(".").call(); | |||||
parent = git.commit().setMessage("initial").call(); | |||||
writeTrashFile("foo.txt", "FOO\n"); | |||||
writeTrashFile("src/some.txt", "SOME\n"); | |||||
writeTrashFile("src/image.png", "IMAGE\n"); | |||||
writeTrashFile("src/test.pdf", "TEST\n"); | |||||
writeTrashFile("src/xyz.txt", "XYZ\n"); | |||||
git.add().addFilepattern(".").call(); | |||||
head = git.commit().setMessage("second").call(); | |||||
} | |||||
try (ByteArrayOutputStream os = new ByteArrayOutputStream(); | |||||
DiffFormatter dfmt = new DiffFormatter(os)) { | |||||
dfmt.setRepository(db); | |||||
List<TreeFilter> skip = new ArrayList<>(); | |||||
skip.add(PathSuffixFilter.create(".png")); | |||||
skip.add(PathSuffixFilter.create(".pdf")); | |||||
dfmt.setPathFilter(OrTreeFilter.create(skip).negate()); | |||||
dfmt.format( | |||||
new CanonicalTreeParser(null, db.newObjectReader(), | |||||
parent.getTree()), | |||||
new CanonicalTreeParser(null, db.newObjectReader(), | |||||
head.getTree())); | |||||
dfmt.flush(); | |||||
String actual = os.toString("UTF-8"); | |||||
String expected = "diff --git a/foo.txt b/foo.txt\n" | |||||
+ "index 257cc56..b7d6715 100644\n" | |||||
+ "--- a/foo.txt\n" | |||||
+ "+++ b/foo.txt\n" | |||||
+ "@@ -1 +1 @@\n" | |||||
+ "-foo\n" | |||||
+ "+FOO\n" | |||||
+ "diff --git a/src/some.txt b/src/some.txt\n" | |||||
+ "index 363ef61..76cea5f 100644\n" | |||||
+ "--- a/src/some.txt\n" | |||||
+ "+++ b/src/some.txt\n" | |||||
+ "@@ -1 +1 @@\n" | |||||
+ "-some\n" | |||||
+ "+SOME\n" | |||||
+ "diff --git a/src/xyz.txt b/src/xyz.txt\n" | |||||
+ "index cd470e6..d4e3ab0 100644\n" | |||||
+ "--- a/src/xyz.txt\n" | |||||
+ "+++ b/src/xyz.txt\n" | |||||
+ "@@ -1 +1 @@\n" | |||||
+ "-xyz\n" | |||||
+ "+XYZ\n"; | |||||
assertEquals(expected, actual); | |||||
} | |||||
} | |||||
@Test | @Test | ||||
public void testTrackedFileInIgnoredFolderChanged() | public void testTrackedFileInIgnoredFolderChanged() | ||||
throws Exception { | throws Exception { |
/* | /* | ||||
* Copyright (C) 2009, 2013 Google Inc. and others | |||||
* Copyright (C) 2009, 2021 Google Inc. and others | |||||
* | * | ||||
* This program and the accompanying materials are made available under the | * This program and the accompanying materials are made available under the | ||||
* terms of the Eclipse Distribution License v. 1.0 which is available at | * terms of the Eclipse Distribution License v. 1.0 which is available at | ||||
@Test | @Test | ||||
public void testRecursiveFiltering() throws IOException { | public void testRecursiveFiltering() throws IOException { | ||||
ObjectId treeId = createTree("a.sth", "a.txt", "sub/b.sth", "sub/b.txt"); | |||||
ObjectId treeId = createTree("a.sth", "a.txt", "sub/b.sth", "sub/b.txt", | |||||
"t.sth", "t.txt"); | |||||
List<String> paths = getMatchingPaths(".txt", treeId, true); | List<String> paths = getMatchingPaths(".txt", treeId, true); | ||||
List<String> expected = Arrays.asList("a.txt", "sub/b.txt"); | |||||
List<String> expected = Arrays.asList("a.txt", "sub/b.txt", "t.txt"); | |||||
assertEquals(expected, paths); | assertEquals(expected, paths); | ||||
} | } | ||||
assertEquals(Arrays.asList("abc", "c"), getMatchingPaths("c", treeId)); | assertEquals(Arrays.asList("abc", "c"), getMatchingPaths("c", treeId)); | ||||
} | } | ||||
@Test | |||||
public void testNegated() throws IOException { | |||||
ObjectId treeId = createTree("a.sth", "a.txt", "sub/b.sth", | |||||
"sub/b.txt", "t.sth", "t.txt"); | |||||
List<String> paths = getMatchingPaths(".txt", treeId, true, true); | |||||
List<String> expected = Arrays.asList("a.sth", "sub/b.sth", "t.sth"); | |||||
assertEquals(expected, paths); | |||||
} | |||||
private ObjectId createTree(String... paths) throws IOException { | private ObjectId createTree(String... paths) throws IOException { | ||||
final ObjectInserter odi = db.newObjectInserter(); | final ObjectInserter odi = db.newObjectInserter(); | ||||
final DirCache dc = db.readDirCache(); | final DirCache dc = db.readDirCache(); | ||||
private List<String> getMatchingPaths(String suffixFilter, | private List<String> getMatchingPaths(String suffixFilter, | ||||
final ObjectId treeId, boolean recursiveWalk) throws IOException { | final ObjectId treeId, boolean recursiveWalk) throws IOException { | ||||
return getMatchingPaths(suffixFilter, treeId, recursiveWalk, false); | |||||
} | |||||
private List<String> getMatchingPaths(String suffixFilter, | |||||
final ObjectId treeId, boolean recursiveWalk, boolean negated) | |||||
throws IOException { | |||||
try (TreeWalk tw = new TreeWalk(db)) { | try (TreeWalk tw = new TreeWalk(db)) { | ||||
tw.setFilter(PathSuffixFilter.create(suffixFilter)); | |||||
TreeFilter filter = PathSuffixFilter.create(suffixFilter); | |||||
if (negated) { | |||||
filter = filter.negate(); | |||||
} | |||||
tw.setFilter(filter); | |||||
tw.setRecursive(recursiveWalk); | tw.setRecursive(recursiveWalk); | ||||
tw.addTree(treeId); | tw.addTree(treeId); | ||||
/* | /* | ||||
* Copyright (C) 2009, Google Inc. and others | |||||
* Copyright (C) 2009, 2021 Google Inc. and others | |||||
* | * | ||||
* This program and the accompanying materials are made available under the | * This program and the accompanying materials are made available under the | ||||
* terms of the Eclipse Distribution License v. 1.0 which is available at | * terms of the Eclipse Distribution License v. 1.0 which is available at | ||||
} | } | ||||
@Override | |||||
public int matchFilter(TreeWalk walker) throws MissingObjectException, | |||||
IncorrectObjectTypeException, IOException { | |||||
if (walker.isSubtree()) { | |||||
return -1; | |||||
} | |||||
return super.matchFilter(walker); | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | @Override | ||||
public boolean shouldBeRecursive() { | public boolean shouldBeRecursive() { |