changeset 342:516b817415ba

HgIgnore: regex patterns to match part of the filename do not work
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 18 Nov 2011 05:10:33 +0100
parents 75c452fdd76a
children 58016b1b8554
files src/org/tmatesoft/hg/repo/HgIgnore.java test/org/tmatesoft/hg/test/TestIgnore.java
diffstat 2 files changed, 36 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgIgnore.java	Thu Nov 17 07:04:58 2011 +0100
+++ b/src/org/tmatesoft/hg/repo/HgIgnore.java	Fri Nov 18 05:10:33 2011 +0100
@@ -90,6 +90,10 @@
 					// hence no special  treatment of Windows path
 					// however, own attempts make me think '\' on Windows are not treated as escapes
 					line = glob2regex(line);
+				} else {
+					assert "regexp".equals(syntax);
+					// regular expression patterns need not match start of the line unless demanded explicitly 
+					line = line.charAt(0) == '^' ? line : ".*" + line;
 				}
 				try {
 					result.add(Pattern.compile(line)); // case-sensitive
@@ -119,6 +123,7 @@
 		assert line.length() > 0;
 		StringBuilder sb = new StringBuilder(line.length() + 10);
 		int start = 0, end = line.length() - 1;
+		sb.append("(?:|.*/)"); // glob patterns shall match file in any directory
 
 		int inCurly = 0;
 		for (int i = start; i <= end; i++) {
@@ -163,17 +168,18 @@
 	 * @return <code>true</code> if matches repository configuration of ignored files.
 	 */
 	public boolean isIgnored(Path path) {
-		boolean isDeep = path.toString().indexOf('/') != -1;
+		String ps = path.toString();
 		for (Pattern p : entries) {
-			if (p.matcher(path).matches()) {
+			int x = ps.indexOf('/'); // reset for each pattern
+			if (p.matcher(ps).find()) {
 				return true;
 			}
-			if (isDeep) {
-				for (String segment : path.segments()) {
-					if (p.matcher(segment).matches()) {
-						return true;
-					}
+			while (x != -1 && x+1 != ps.length() /*skip very last segment not to check complete string twice*/) {
+				String fragment = ps.substring(0, x);
+				if (p.matcher(fragment).matches()) {
+					return true;
 				}
+				x = ps.indexOf('/', x+1);
 			}
 		}
 		return false;
--- a/test/org/tmatesoft/hg/test/TestIgnore.java	Thu Nov 17 07:04:58 2011 +0100
+++ b/test/org/tmatesoft/hg/test/TestIgnore.java	Fri Nov 18 05:10:33 2011 +0100
@@ -41,7 +41,7 @@
 		TestIgnore test = new TestIgnore();
 		test.testGlobWithAlternatives();
 		test.testComplexFileParse();
-		test.testSegmentsMatch();
+		test.testSegmentsGlobMatch();
 		test.testWildcardsDoNotMatchDirectorySeparator();
 		test.errorCollector.verify();
 	}
@@ -74,7 +74,7 @@
 	}
 
 	@Test
-	public void testSegmentsMatch() throws Exception {
+	public void testSegmentsGlobMatch() throws Exception {
 		String s = "syntax:glob\nbin\n.*\nTEST-*.xml";
 		HgIgnore hgIgnore = HgInternals.newHgIgnore(new StringReader(s));
 		Path[] toCheck = new Path[] {
@@ -89,7 +89,27 @@
 			errorCollector.assertTrue(p.toString(), hgIgnore.isIgnored(p));
 		}
 	}
-	
+
+	@Test
+	public void testSegmentsRegexMatch() throws Exception {
+		// regex patterns that don't start with explicit ^ are allowed to match anywhere in the string
+		String s = "syntax:regex\n/\\.git\n^abc\n";
+		HgIgnore hgIgnore = HgInternals.newHgIgnore(new StringReader(s));
+		Path p = Path.create(".git/aa");
+		errorCollector.assertTrue(p.toString(), !hgIgnore.isIgnored(p));
+		p = Path.create("dir/.git/bb");
+		errorCollector.assertTrue(p.toString(), hgIgnore.isIgnored(p));
+		p = Path.create("dir/abc/aa");
+		errorCollector.assertTrue(p.toString(), !hgIgnore.isIgnored(p));
+		p = Path.create("abc/bb");
+		errorCollector.assertTrue(p.toString(), hgIgnore.isIgnored(p));
+		// Mercurial (in fact, likely pyton's regex match() function) treats
+		// regex patterns as having .* at the end (unless there's explicit $). 
+		// IOW, matches to the beginning of the string, not to the whole string  
+		p = Path.create("abcde/fg"); 
+		errorCollector.assertTrue(p.toString(), hgIgnore.isIgnored(p));
+	}
+
 	@Test
 	public void testWildcardsDoNotMatchDirectorySeparator() throws Exception {
 		String s = "syntax:glob\na?b\nc*d";