Fix matching ignores and attributes pattern of form a/b/**.

Fix patch matching for patterns of form a/b/** : this should not match
paths like a/b but still match a/b/ and a/b/c.

Change-Id: Iacbf496a43f01312e7d9052f29c3f9c33807c85d
Signed-off-by: Dmitry Pavlenko <pavlenko@tmatesoft.com>
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java
index ec2370e..f0d3c36 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java
@@ -166,6 +166,25 @@
 		assertAttribute("file.type3", node, asSet(A_UNSET_ATTR, B_SET_ATTR));
 	}
 
+	@Test
+	public void testDoubleAsteriskAtEnd() throws IOException {
+		String attributeFileContent = "dir/** \tA -B\tC=value";
+
+		is = new ByteArrayInputStream(attributeFileContent.getBytes());
+		AttributesNode node = new AttributesNode();
+		node.parse(is);
+		assertAttribute("dir", node,
+				asSet(new Attribute[]{}));
+		assertAttribute("dir/", node,
+				asSet(new Attribute[]{}));
+		assertAttribute("dir/file.type1", node,
+				asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR));
+		assertAttribute("dir/sub/", node,
+				asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR));
+		assertAttribute("dir/sub/file.type1", node,
+				asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR));
+	}
+
 	private void assertAttribute(String path, AttributesNode node,
 			Attributes attrs) throws IOException {
 		Attributes attributes = new Attributes();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java
index 1863b80..bcc8f7e 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java
@@ -391,7 +391,6 @@
 		assertMatched("/**/a/b", "c/d/a/b");
 		assertMatched("/**/**/a/b", "c/d/a/b");
 
-		assertMatched("a/b/**", "a/b");
 		assertMatched("a/b/**", "a/b/c");
 		assertMatched("a/b/**", "a/b/c/d/");
 		assertMatched("a/b/**/**", "a/b/c/d");
@@ -415,6 +414,12 @@
 
 	@Test
 	public void testWildmatchDoNotMatch() {
+		assertNotMatched("a/**", "a/");
+		assertNotMatched("a/b/**", "a/b/");
+		assertNotMatched("a/**", "a");
+		assertNotMatched("a/b/**", "a/b");
+		assertNotMatched("a/b/**/", "a/b");
+		assertNotMatched("a/b/**/**", "a/b");
 		assertNotMatched("**/a/b", "a/c/b");
 		assertNotMatched("!/**/*.zip", "c/a/b.zip");
 		assertNotMatched("!**/*.zip", "c/a/b.zip");
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java
index 65224ea..ce9ad80 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java
@@ -227,29 +227,30 @@
 			int left = right;
 			right = path.indexOf(slash, right);
 			if (right == -1) {
-				if (left < endExcl)
+				if (left < endExcl) {
 					match = matches(matcher, path, left, endExcl,
 							assumeDirectory);
+				} else {
+					// a/** should not match a/ or a
+					match = match && matchers.get(matcher) != WILD;
+				}
 				if (match) {
-					if (matcher == matchers.size() - 2
-							&& matchers.get(matcher + 1) == WILD)
-						// ** can match *nothing*: a/b/** match also a/b
-						return true;
 					if (matcher < matchers.size() - 1
 							&& matchers.get(matcher) == WILD) {
 						// ** can match *nothing*: a/**/b match also a/b
 						matcher++;
 						match = matches(matcher, path, left, endExcl,
 								assumeDirectory);
-					} else if (dirOnly && !assumeDirectory)
+					} else if (dirOnly && !assumeDirectory) {
 						// Directory expectations not met
 						return false;
+					}
 				}
 				return match && matcher + 1 == matchers.size();
 			}
-			if (right - left > 0)
+			if (right - left > 0) {
 				match = matches(matcher, path, left, right, assumeDirectory);
-			else {
+			} else {
 				// path starts with slash???
 				right++;
 				continue;
@@ -261,12 +262,14 @@
 					right = left - 1;
 				}
 				matcher++;
-				if (matcher == matchers.size())
+				if (matcher == matchers.size()) {
 					return true;
-			} else if (lastWildmatch != -1)
+				}
+			} else if (lastWildmatch != -1) {
 				matcher = lastWildmatch + 1;
-			else
+			} else {
 				return false;
+			}
 			right++;
 		}
 	}