From 4bc539a8141e8099587536620bdc555c2c4cb01e Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Fri, 11 Aug 2017 21:16:54 +0200 Subject: [PATCH] Use relative paths for attribute rule matching Attribute rules must match against the entry path relative to the attribute node containing the rule. The global entry path is to be used only for the init and the global node (and of course the root node). Bug: 520677 Change-Id: I80389a2dc272a72312729ccd5358d7c75e1ea20a Signed-off-by: Thomas Wolf --- .../attributes/AttributesHandlerTest.java | 27 +++++++++++++++++++ .../jgit/attributes/AttributesHandler.java | 14 +++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java index ca456b3c8..50d020c57 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java @@ -254,6 +254,33 @@ public void testCyclicMacros() throws Exception { endWalk(); } + @Test + public void testRelativePaths() throws Exception { + setupRepo("sub/ global", "sub/** init", + "sub/** top_sub\n*.txt top", + "sub/** subsub\nsub/ subsub2\n*.txt foo"); + // The last two sub/** and sub/ rules are in sub/.gitattributes. They + // must not apply to any of the files here. They would match for a + // further subdirectory sub/sub. + walk = beginWalk(); + assertIteration(F, ".gitattributes"); + assertIteration(D, "sub", attrs("global")); + assertIteration(F, "sub/.gitattributes", attrs("init top_sub global")); + assertIteration(F, "sub/a.txt", attrs("init foo top top_sub global")); + endWalk(); + // All right, let's see that they *do* apply in sub/sub: + writeTrashFile("sub/sub/b.txt", "b"); + walk = beginWalk(); + assertIteration(F, ".gitattributes"); + assertIteration(D, "sub", attrs("global")); + assertIteration(F, "sub/.gitattributes", attrs("init top_sub global")); + assertIteration(F, "sub/a.txt", attrs("init foo top top_sub global")); + assertIteration(D, "sub/sub", attrs("init subsub2 top_sub global")); + assertIteration(F, "sub/sub/b.txt", + attrs("init foo subsub2 subsub top top_sub global")); + endWalk(); + } + private static Collection attrs(String s) { return new AttributesRule("*", s).getAttributes(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java index 3bf4179e7..8d928e374 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesHandler.java @@ -144,7 +144,8 @@ public Attributes getAttributes() throws IOException { mergeInfoAttributes(entryPath, isDirectory, attributes); // Gets the attributes located on the current entry path - mergePerDirectoryEntryAttributes(entryPath, isDirectory, + mergePerDirectoryEntryAttributes(entryPath, entryPath.lastIndexOf('/'), + isDirectory, treeWalk.getTree(WorkingTreeIterator.class), treeWalk.getTree(DirCacheIterator.class), treeWalk.getTree(CanonicalTreeParser.class), @@ -206,6 +207,8 @@ private void mergeInfoAttributes(String entryPath, boolean isDirectory, * the path to test. The path must be relative to this attribute * node's own repository path, and in repository path format * (uses '/' and not '\'). + * @param nameRoot + * index of the '/' preceeding the current level, or -1 if none * @param isDirectory * true if the target item is a directory. * @param workingTreeIterator @@ -217,7 +220,7 @@ private void mergeInfoAttributes(String entryPath, boolean isDirectory, * @throws IOException */ private void mergePerDirectoryEntryAttributes(String entryPath, - boolean isDirectory, + int nameRoot, boolean isDirectory, @Nullable WorkingTreeIterator workingTreeIterator, @Nullable DirCacheIterator dirCacheIterator, @Nullable CanonicalTreeParser otherTree, Attributes result) @@ -228,9 +231,12 @@ private void mergePerDirectoryEntryAttributes(String entryPath, AttributesNode attributesNode = attributesNode( treeWalk, workingTreeIterator, dirCacheIterator, otherTree); if (attributesNode != null) { - mergeAttributes(attributesNode, entryPath, isDirectory, result); + mergeAttributes(attributesNode, + entryPath.substring(nameRoot + 1), isDirectory, + result); } - mergePerDirectoryEntryAttributes(entryPath, isDirectory, + mergePerDirectoryEntryAttributes(entryPath, + entryPath.lastIndexOf('/', nameRoot - 1), isDirectory, parentOf(workingTreeIterator), parentOf(dirCacheIterator), parentOf(otherTree), result); }