@matheusbsbs / matheus-bagliano / commits / 39e21c6ef5
Fork 0

verify_filename(): handle backslashes in "wildcards are pathspecs" rule

Commit 28fcc0b71a (pathspec: avoid the need of "--" when wildcard is used, 2015-05-02) allowed: git rev-parse '*.c' without the double-dash. But the rule it uses to check for wildcards actually looks for any glob special. This is overly liberal, as it means that a pattern that doesn't actually do any wildcard matching, like "a\b", will be considered a pathspec. If you do have such a file on disk, that's presumably what you wanted. But if you don't, the results are confusing: rather than say "there's no such path a\b", we'll quietly accept it as a pathspec which very likely matches nothing (or at least not what you intended). Likewise, looking for path "a\*b" doesn't expand the search at all; it would only find a single entry, "a*b". This commit switches the rule to trigger only when glob metacharacters would expand the search, meaning both of those cases will now report an error (you can still disambiguate using "--", of course; we're just tightening the DWIM heuristic). Note that we didn't test the original feature in 28fcc0b71a at all. So this patch not only tests for these corner cases, but also adds a regression test for the existing behavior. Reported-by: David Burström <davidburstrom@spotify.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jan 24, 2020 at 19:00 UTC 39e21c6ef5221a1dcb8a241f60d7e91d59bd6627
2 files changed +34 -3
setup.c
+20 -3
@@ -197,9 +197,26 @@ static void NORETURN die_verify_filename(struct repository *r,
197 */
198 static int looks_like_pathspec(const char *arg)
199 {
200 - /* anything with a wildcard character */
201 - if (!no_wildcard(arg))
202 - return 1;
200 + const char *p;
201 + int escaped = 0;
202 +
203 + /*
204 + * Wildcard characters imply the user is looking to match pathspecs
205 + * that aren't in the filesystem. Note that this doesn't include
206 + * backslash even though it's a glob special; by itself it doesn't
207 + * cause any increase in the match. Likewise ignore backslash-escaped
208 + * wildcard characters.
209 + */
210 + for (p = arg; *p; p++) {
211 + if (escaped) {
212 + escaped = 0;
213 + } else if (is_glob_special(*p)) {
214 + if (*p == '\\')
215 + escaped = 1;
216 + else
217 + return 1;
218 + }
219 + }
220
221 /* long-form pathspec magic */
222 if (starts_with(arg, ":("))
t/t1506-rev-parse-diagnosis.sh
+14
@@ -222,4 +222,18 @@ test_expect_success 'reject Nth ancestor if N is too high' '
222 test_must_fail git rev-parse HEAD~100000000000000000000000000000000
223 '
224
225 +test_expect_success 'pathspecs with wildcards are not ambiguous' '
226 + echo "*.c" >expect &&
227 + git rev-parse "*.c" >actual &&
228 + test_cmp expect actual
229 +'
230 +
231 +test_expect_success 'backslash does not trigger wildcard rule' '
232 + test_must_fail git rev-parse "foo\\bar"
233 +'
234 +
235 +test_expect_success 'escaped char does not trigger wildcard rule' '
236 + test_must_fail git rev-parse "foo\\*bar"
237 +'
238 +
239 test_done