]> git.ipfire.org Git - thirdparty/git.git/commitdiff
dir.c: literal match with wildcard in pathspec should still glob
authorK Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Sat, 3 May 2025 06:07:36 +0000 (11:37 +0530)
committerJunio C Hamano <gitster@pobox.com>
Mon, 5 May 2025 14:49:08 +0000 (07:49 -0700)
When a path with wildcard characters, e.g. 'f*o', exists in the
working tree, "git add -- 'f*o'" stops after happily finding
that there is 'f*o' and adding it to the index, without
realizing there may be other paths, e.g. 'foooo', that may match
the given pathspec.

This is because dir.c:do_match_pathspec() disables further
matches with pathspec when it finds an exact match.

Reported-by: piotrsiupa <piotrsiupa@gmail.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
dir.c
t/meson.build
t/t6137-pathspec-wildcards-literal.sh [new file with mode: 0755]

diff --git a/dir.c b/dir.c
index cbd82be6c91637890538995d6f1220e2d3935806..85cc08f4fc1a4dd013ebbeddc7794d2a44b103df 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -519,7 +519,8 @@ static int do_match_pathspec(struct index_state *istate,
                    ( exclude && !(ps->items[i].magic & PATHSPEC_EXCLUDE)))
                        continue;
 
-               if (seen && seen[i] == MATCHED_EXACTLY)
+               if (seen && seen[i] == MATCHED_EXACTLY &&
+                   ps->items[i].nowildcard_len == ps->items[i].len)
                        continue;
                /*
                 * Make exclude patterns optional and never report
index a59da26be3f4716493447242de931c94a81a1a10..78095fca9f079164693a7d7a9179c975dc2083ed 100644 (file)
@@ -787,6 +787,7 @@ integration_tests = [
   't6134-pathspec-in-submodule.sh',
   't6135-pathspec-with-attrs.sh',
   't6136-pathspec-in-bare.sh',
+  't6137-pathspec-wildcards-literal.sh',
   't6200-fmt-merge-msg.sh',
   't6300-for-each-ref.sh',
   't6301-for-each-ref-errors.sh',
diff --git a/t/t6137-pathspec-wildcards-literal.sh b/t/t6137-pathspec-wildcards-literal.sh
new file mode 100755 (executable)
index 0000000..20abad5
--- /dev/null
@@ -0,0 +1,429 @@
+#!/bin/sh
+test_description='test wildcards and literals with git add/commit (subshell style)'
+
+. ./test-lib.sh
+
+test_have_prereq FUNNYNAMES || {
+       skip_all='skipping: needs FUNNYNAMES (non-Windows only)'
+       test_done
+}
+
+prepare_test_files () {
+       for f in "*" "**" "?" "[abc]" "a" "f*" "f**" "f?z" "foo*bar" "hello?world" "hello_world"
+       do
+               >"$f" || return
+       done
+}
+
+test_expect_success 'add wildcard *' '
+       git init test-asterisk &&
+       (
+               cd test-asterisk &&
+               prepare_test_files &&
+               git add "*" &&
+               cat >expect <<-EOF &&
+               *
+               **
+               ?
+               [abc]
+               a
+               f*
+               f**
+               f?z
+               foo*bar
+               hello?world
+               hello_world
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add literal \*' '
+       git init test-asterisk-literal &&
+       (
+               cd test-asterisk-literal &&
+               prepare_test_files &&
+               git add "\*" &&
+               cat >expect <<-EOF &&
+               *
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard **' '
+       git init test-dstar &&
+       (
+               cd test-dstar &&
+               prepare_test_files &&
+               git add "**" &&
+               cat >expect <<-EOF &&
+               *
+               **
+               ?
+               [abc]
+               a
+               f*
+               f**
+               f?z
+               foo*bar
+               hello?world
+               hello_world
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard ?' '
+       git init test-qmark &&
+       (
+               cd test-qmark &&
+               prepare_test_files &&
+               git add "?" &&
+               cat >expect <<-\EOF | sort &&
+               *
+               ?
+               a
+               EOF
+               git ls-files | sort >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard [abc]' '
+       git init test-brackets &&
+       (
+               cd test-brackets &&
+               prepare_test_files &&
+               git add "[abc]" &&
+               cat >expect <<-\EOF | sort &&
+               [abc]
+               a
+               EOF
+               git ls-files | sort >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard f*' '
+       git init test-f-wild &&
+       (
+               cd test-f-wild &&
+               prepare_test_files &&
+               git add "f*" &&
+               cat >expect <<-\EOF | sort &&
+               f*
+               f**
+               f?z
+               foo*bar
+               EOF
+               git ls-files | sort >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add literal f\*' '
+       git init test-f-lit &&
+       (
+               cd test-f-lit &&
+               prepare_test_files &&
+               git add "f\*" &&
+               cat >expect <<-\EOF &&
+               f*
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard f**' '
+       git init test-fdstar &&
+       (
+               cd test-fdstar &&
+               prepare_test_files &&
+               git add "f**" &&
+               cat >expect <<-\EOF | sort &&
+               f*
+               f**
+               f?z
+               foo*bar
+               EOF
+               git ls-files | sort >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add literal f\*\*' '
+       git init test-fdstar-lit &&
+       (
+               cd test-fdstar-lit &&
+               prepare_test_files &&
+               git add "f\*\*" &&
+               cat >expect <<-\EOF &&
+               f**
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard f?z' '
+       git init test-fqz &&
+       (
+               cd test-fqz &&
+               prepare_test_files &&
+               git add "f?z" &&
+               cat >expect <<-\EOF &&
+               f?z
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add literal \? literal' '
+       git init test-q-lit &&
+       (
+               cd test-q-lit &&
+               prepare_test_files &&
+               git add "\?" &&
+               cat >expect <<-\EOF &&
+               ?
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard foo*bar' '
+       git init test-foobar &&
+       (
+               cd test-foobar &&
+               prepare_test_files &&
+               git add "foo*bar" &&
+               cat >expect <<-\EOF &&
+               foo*bar
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add wildcard hello?world' '
+       git init test-hellowild &&
+       (
+               cd test-hellowild &&
+               prepare_test_files &&
+               git add "hello?world" &&
+               cat >expect <<-\EOF &&
+               hello?world
+               hello_world
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add literal hello\?world' '
+       git init test-hellolit &&
+       (
+               cd test-hellolit &&
+               prepare_test_files &&
+               git add "hello\?world" &&
+               cat >expect <<-\EOF &&
+               hello?world
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'add literal [abc]' '
+       git init test-brackets-lit &&
+       (
+               cd test-brackets-lit &&
+               prepare_test_files &&
+               git add "\[abc\]" &&
+               cat >expect <<-\EOF &&
+               [abc]
+               EOF
+               git ls-files >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: wildcard *' '
+       git init test-c-asterisk &&
+       (
+               cd test-c-asterisk &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c1" -- "*" &&
+               cat >expect <<-EOF &&
+               *
+               **
+               ?
+               [abc]
+               a
+               f*
+               f**
+               f?z
+               foo*bar
+               hello?world
+               hello_world
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: literal *' '
+       git init test-c-asterisk-lit &&
+       (
+               cd test-c-asterisk-lit &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c2" -- "\*" &&
+               cat >expect <<-EOF &&
+               *
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: wildcard f*' '
+       git init test-c-fwild &&
+       (
+               cd test-c-fwild &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c3" -- "f*" &&
+               cat >expect <<-EOF &&
+               f*
+               f**
+               f?z
+               foo*bar
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: literal f\*' '
+       git init test-c-flit &&
+       (
+               cd test-c-flit &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c4" -- "f\*" &&
+               cat >expect <<-EOF &&
+               f*
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: wildcard pathspec limits commit' '
+       git init test-c-pathlimit &&
+       (
+               cd test-c-pathlimit &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c5" -- "f**" &&
+               cat >expect <<-EOF &&
+               f*
+               f**
+               f?z
+               foo*bar
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: literal f\*\*' '
+       git init test-c-fdstar-lit &&
+       (
+               cd test-c-fdstar-lit &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c6" -- "f\*\*" &&
+               cat >expect <<-EOF &&
+               f**
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: wildcard ?' '
+       git init test-c-qwild &&
+       (
+               cd test-c-qwild &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c7" -- "?" &&
+               cat >expect <<-EOF &&
+               *
+               ?
+               a
+               EOF
+               git ls-tree -r --name-only HEAD | sort >actual &&
+               sort expect >expect.sorted &&
+               test_cmp expect.sorted actual
+       )
+'
+
+test_expect_success 'commit: literal \?' '
+       git init test-c-qlit &&
+       (
+               cd test-c-qlit &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c8" -- "\?" &&
+               cat >expect <<-EOF &&
+               ?
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_expect_success 'commit: wildcard hello?world' '
+       git init test-c-hellowild &&
+       (
+               cd test-c-hellowild &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c9" -- "hello?world"  &&
+               cat >expect <<-EOF &&
+               hello?world
+               hello_world
+               EOF
+               git ls-tree -r --name-only HEAD | sort >actual &&
+               sort expect >expect.sorted &&
+               test_cmp expect.sorted actual
+       )
+'
+
+test_expect_success 'commit: literal hello\?world' '
+       git init test-c-hellolit &&
+       (
+               cd test-c-hellolit &&
+               prepare_test_files &&
+               git add . &&
+               git commit -m "c10" -- "hello\?world" &&
+               cat >expect <<-EOF &&
+               hello?world
+               EOF
+               git ls-tree -r --name-only HEAD >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_done