summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAssaf Gordon <assafgordon@gmail.com>2014-12-05 05:20:27 (GMT)
committerAssaf Gordon <assafgordon@gmail.com>2014-12-05 05:20:27 (GMT)
commite5dfba141ee7e889198c4486c2851103f348b39b (patch)
tree7ba7ee5077968af951feaa5604ad992a54d7ff45
parent7362c6947b782f3c965b3bf82b2c84d12440ba96 (diff)
downloadagnostic-e5dfba141ee7e889198c4486c2851103f348b39b.zip
agnostic-e5dfba141ee7e889198c4486c2851103f348b39b.tar.gz
agnostic-e5dfba141ee7e889198c4486c2851103f348b39b.tar.bz2
path-utils: fnmatch: fix longest-suffix bug
-rw-r--r--src/node_modules/utils/path_utils.js45
-rw-r--r--src/tests/fnmatch_tester.js14
2 files changed, 43 insertions, 16 deletions
diff --git a/src/node_modules/utils/path_utils.js b/src/node_modules/utils/path_utils.js
index 92dd27e..23f9cd1 100644
--- a/src/node_modules/utils/path_utils.js
+++ b/src/node_modules/utils/path_utils.js
@@ -268,23 +268,50 @@ function __fnmatch_exec(pattern,string,
if (anchor_start)
fix_pattern = '^' + fix_pattern;
+
+/* A Hack to force the RegExp engine to match non-greedy AND the end (left side)
+ of the string. Since matching always starts from the beginning (right) of
+ the string, if we don't give en RegExp engine an additional '.*' to greedly
+ match the beginning, it won't match non-greedily our pattern.
+
+ Compare:
+
+ # The result is greedy, despite using '?'
+ $ echo helloooooowold | perl -lne 'm/(o.*?$)/ && print $1'
+ oooooowold
+
+ # Now it's non-greedy, because the first '.*' consumed most of the text.
+ $ echo helloooooowold | perl -lne 'm/.*(o.*?$)/ && print $1'
+ old
+*/
+ if (anchor_end && !greedy)
+ fix_pattern = '.*(' + fix_pattern +')';
if (anchor_end)
fix_pattern += '$';
var re = new RegExp( fix_pattern );
var r = re.exec(string);
- if ( r === null )
- return null;
- var pos = r.index;
- var len = r[0].length;
- var str = r[0];
+ if (0) {
+ console.log("string = '" + string + "'");
+ console.log("pattern = '" + pattern + "'");
+ console.log("fix_pattern = '" + fix_pattern + "'");
+ console.log("match = ", JSON.stringify(r,undefined,2));
+ }
+ if ( r === null )
+ return null;
-console.log("string = '" + string + "'");
-console.log("pattern = '" + pattern + "'");
-console.log("fix_pattern = '" + fix_pattern + "'");
-console.log("match = ", r);
+ var pos = r.index;
+ var len = r[0].length;
+ var str = r[0];
+ /* See hack note above. If it's suffix+non-greedy, the regex
+ had a groupping, so use index 1 instead of 0 */
+ if (anchor_end && !greedy){
+ len = r[1].length;
+ str = r[1];
+ pos = string.length - len;
+ }
return { "pos": pos, "len" : len, "str": str } ;
}
diff --git a/src/tests/fnmatch_tester.js b/src/tests/fnmatch_tester.js
index 2aab360..32da9da 100644
--- a/src/tests/fnmatch_tester.js
+++ b/src/tests/fnmatch_tester.js
@@ -69,16 +69,17 @@ var fnmatch_match_tests = [
["m12", "abcdeee", "b*e", "$", "bcdeee"],
["m13", "abcdeee", "b*e", "?", "bcde"],
-/* Will be used in shell expansion, such as:
+/* Simple example of greedy vs non-greedy suffix matching */
+["m14", "helloooooowold", "o*", "$", "oooooowold"],
+["m15", "helloooooowold", "o*", "$?", "old"],
+/*Real-world example of greedy vs non-greedy suffix matching.
+ Will be used in shell expansion, such as:
FILE=/tmp/foo/bar/agnostic.tar.gz.gpg.sig"
echo ${FILE%.*sig} # non-greedy (shortest match), removes '.sig'
echo ${FILE%%.*sig} # greedy (longest match), removes all extensions
*/
-["m14", "agnostic.tar.gz.gpg.sig", ".*sig", "$", ".tar.gz.gpg.sig"],
-
-/* TODO: FIX THIS
-["m15", "agnostic.tar.gz.gpg.sig", ".*sig", "$?", ".sig"],
-*/
+["m16", "agnostic.tar.gz.gpg.sig", ".*sig", "$", ".tar.gz.gpg.sig"],
+["m17", "agnostic.tar.gz.gpg.sig", ".*sig", "$?", ".sig"],
];
@@ -103,7 +104,6 @@ fnmatch_match_tests.forEach(function(test){
} else {
/* If the expected result is a string, check the returned matched string,
(implied: string 'expect' should ALWAYS match) */
-console.log( "result = " + JSON.stringify(result));
assert ( result ) ;
result = input.substr ( result.pos, result.len ) ;
}