diff options
author | Jonathan Nieder <jrn@google.com> | 2015-12-14 19:57:24 -0800 |
---|---|---|
committer | Jonathan Nieder <jrn@google.com> | 2015-12-15 15:22:10 -0800 |
commit | 75a0dcac1883414f5f99eec37ffa9cb305940718 (patch) | |
tree | 7faf6a05c1851c365638a12cb3dd89d20d2605d0 /org.eclipse.jgit.test/tst/org/eclipse/jgit | |
parent | 29dfbd22b7250d1a7779ba4fe00323fd167e35fc (diff) | |
download | jgit-75a0dcac1883414f5f99eec37ffa9cb305940718.tar.gz jgit-75a0dcac1883414f5f99eec37ffa9cb305940718.zip |
Do not let PathFilter.create("a/b") match 'a' unless 'a' is a subtree
PathFilter and PathFilterGroup form JGit's implementation of git's
path-limiting feature in commands like log and diff. To save time
when traversing trees, a path specification
foo/bar/baz
tells the tree walker not to traverse unrelated trees like qux/. It
does that by returning false from include when the tree walker is
visiting qux and true when it is visiting foo.
Unfortunately that test was implemented to be slightly over-eager: it
doesn't only return true when asked whether to visit a subtree "foo"
but when asked about a plain file "foo" as well. As a result, diffs
and logs restricted to some-file/non-existing-suffix unexpectedly
match against some-file:
$ jgit log -- LICENSE/no-such-file
commit 629fd0d594d242eab26161b0dac34f7576fd4d3d
Author: Shawn O. Pearce <spearce@spearce.org>
Date: Fri Jul 02 14:52:49 2010 -0700
Clean up LICENSE file
[...]
Fix it by checking against the entry's mode.
Gitiles +log has the same bug and benefits from the same fix.
Callers know not to worry about what subtrees are included in the tree
walk because shouldBeRecursive() returns true in this case, so this
behavior change should be safe. This also better matches the behavior
of C git:
$ empty=$(git mktree </dev/null)
$ git diff-tree --abbrev $empty HEAD -- LICENSE/no-such-file
$ git diff-tree --abbrev $empty HEAD -- tools/no-such-file
:000000 040000 0000000... b62648d... A tools
Bug: 484266
Change-Id: Ib4d53bddd8413a9548622c7b25b338d287d8889d
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse/jgit')
-rw-r--r-- | org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java | 43 |
1 files changed, 37 insertions, 6 deletions
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 2968067238..5edc1924f2 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 @@ -132,12 +132,22 @@ public class PathFilterGroupTest { @Test public void testKeyIsPrefixOfFilter() throws MissingObjectException, IncorrectObjectTypeException, IOException { - assertMatches(Sets.of("b/c"), fakeWalk("b")); - assertMatches(Sets.of("c/d/e", "c/d/f"), fakeWalk("c/d")); - assertMatches(Sets.of("c/d/e", "c/d/f"), fakeWalk("c")); - assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"), fakeWalk("d/e/f")); - assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"), fakeWalk("d/e")); - assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"), fakeWalk("d")); + assertMatches(Sets.of("b/c"), fakeWalkAtSubtree("b")); + assertMatches(Sets.of("c/d/e", "c/d/f"), fakeWalkAtSubtree("c/d")); + assertMatches(Sets.of("c/d/e", "c/d/f"), fakeWalkAtSubtree("c")); + assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"), + fakeWalkAtSubtree("d/e/f")); + assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"), + fakeWalkAtSubtree("d/e")); + assertMatches(Sets.of("d/e/f/g", "d/e/f/g.x"), fakeWalkAtSubtree("d")); + + assertNoMatches(fakeWalk("b")); + assertNoMatches(fakeWalk("c/d")); + assertNoMatches(fakeWalk("c")); + assertNoMatches(fakeWalk("d/e/f")); + assertNoMatches(fakeWalk("d/e")); + assertNoMatches(fakeWalk("d")); + } @Test @@ -263,4 +273,25 @@ public class PathFilterGroupTest { return ret; } + TreeWalk fakeWalkAtSubtree(final String path) throws IOException { + DirCache dc = DirCache.newInCore(); + DirCacheEditor dce = dc.editor(); + dce.add(new DirCacheEditor.PathEdit(path + "/README") { + public void apply(DirCacheEntry ent) { + ent.setFileMode(FileMode.REGULAR_FILE); + } + }); + dce.finish(); + + TreeWalk ret = new TreeWalk((ObjectReader) null); + ret.addTree(new DirCacheIterator(dc)); + ret.next(); + while (!path.equals(ret.getPathString())) { + if (ret.isSubtree()) { + ret.enterSubtree(); + } + ret.next(); + } + return ret; + } } |