git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, lucasseikioshiro@gmail.com, peff@peff.net,
	piotrsiupa@gmail.com, sandals@crustytoothpaste.net,
	jayatheerthkulkarni2005@gmail.com
Subject: [PATCH v2] Dir: Fix and test wildcard pathspec handling
Date: Tue, 22 Apr 2025 21:35:47 +0530	[thread overview]
Message-ID: <20250422160547.577524-1-jayatheerthkulkarni2005@gmail.com> (raw)

Ensure wildcards expand, even with literal file match.
Fixes 'git add f*' skipping files like 'foo' if 'f*' exists.
Use 'f\*' to add the literal.
Tests added for add and commit where dir.c logic applies.
Skips windows specific test.

reported-by: piotrsiupa <piotrsiupa@gmail.com>
Mentored-by: Jeff King <peff@peff.net>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
 dir.c                                 |   3 +-
 t/meson.build                         |   1 +
 t/t6137-pathspec-wildcards-literal.sh | 282 ++++++++++++++++++++++++++
 3 files changed, 285 insertions(+), 1 deletion(-)
 create mode 100755 t/t6137-pathspec-wildcards-literal.sh

diff --git a/dir.c b/dir.c
index 28b0e03feb..9405fee83a 100644
--- 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
diff --git a/t/meson.build b/t/meson.build
index bfb744e886..61285852e9 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -788,6 +788,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
index 0000000000..abf837bf6c
--- /dev/null
+++ b/t/t6137-pathspec-wildcards-literal.sh
@@ -0,0 +1,282 @@
+#!/bin/sh
+
+test_description='test wildcards and literals with various git commands'
+
+. ./test-lib.sh
+
+test_have_prereq FUNNYNAMES || {
+    skip_all='skipping: needs FUNNYNAMES (non-Windows only)'
+    test_done
+}
+
+reset_git_repo () {
+    rm -rf .git &&
+    git init &&
+    rm -rf "actual_files" "expected_files"
+}
+
+end_test_properly() {
+    cd .. &&
+    rm -rf "testdir"
+}
+
+
+test_expect_success 'setup' '
+    mkdir testdir &&
+    cd testdir &&
+    touch "*" "?" "[abc]" "f*" "f?z" "a" &&
+    touch "**" "foo*bar" "hello?world" "f**" "hello_world" &&
+    git init
+'
+
+test_expect_success 'check * wildcard in git add' '
+    git init &&
+    git add "*" &&
+    cat >expected_files <<EOF &&
+*
+**
+?
+[abc]
+a
+f*
+f**
+f?z
+foo*bar
+hello?world
+hello_world
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check \* literal in git add' '
+    reset_git_repo &&
+    git add "\*" &&
+    cat >expected_files <<EOF &&
+*
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check f* wildcard in git add' '
+    reset_git_repo &&
+    git add "f*" &&
+    cat >expected_files <<EOF &&
+f*
+f**
+f?z
+foo*bar
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check f\* literal in git add' '
+    reset_git_repo &&
+    git add "f\*" &&
+    cat >expected_files <<EOF &&
+f*
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check f** wildcard in git add' '
+    reset_git_repo &&
+    git add "f**" &&
+    cat >expected_files <<EOF &&
+f*
+f**
+f?z
+foo*bar
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check f\*\* literal in git add' '
+    reset_git_repo &&
+    git add "f\*\*" &&
+    cat >expected_files <<EOF &&
+f**
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check ? wildcard in git add' '
+    reset_git_repo &&
+    git add "?" &&
+    cat >expected_files <<EOF &&
+*
+?
+a
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check \? literal in git add' '
+    reset_git_repo &&
+    git add "\?" &&
+    cat >expected_files <<EOF &&
+?
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check hello?world wildcard in git add' '
+    reset_git_repo &&
+    git add "hello?world" &&
+    cat >expected_files <<EOF &&
+hello?world
+hello_world
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'check hello\?world literal in git add' '
+    reset_git_repo &&
+    git add "hello\?world" &&
+    cat >expected_files <<EOF &&
+hello?world
+EOF
+    git ls-files >actual_files &&
+    test_cmp expected_files actual_files
+'
+
+test_expect_success 'commit: wildcard *' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "*" &&
+    cat >expected_files <<-\EOF &&
+*
+**
+?
+[abc]
+a
+f*
+f**
+f?z
+foo*bar
+hello?world
+hello_world
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'commit: literal *' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "\*" &&
+    cat >expected_files <<-\EOF &&
+*
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'commit: wildcard f*' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "f*" &&
+    cat >expected_files <<-\EOF &&
+f*
+f**
+f?z
+foo*bar
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'commit: literal f\*' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "f\*" &&
+    cat >expected_files <<-\EOF &&
+f*
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'commit: wildcard pathspec limits commit' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "f**" &&
+    cat >expected_files <<-\EOF &&
+f*
+f**
+f?z
+foo*bar
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'commit: literal f\*\*' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "f\*\*" &&
+    cat >expected_files <<-\EOF &&
+f**
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'commit: wildcard ?' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "?" &&
+    cat >expected_files <<-\EOF &&
+*
+?
+a
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'commit: literal \?' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "\?" &&
+    cat >expected_files <<-\EOF &&
+?
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'check hello?world wildcard in git commit' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "hello?world" &&
+    cat >expected_files <<-\EOF &&
+hello?world
+hello_world
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+test_expect_success 'check hello\?world literal in git commit' '
+    reset_git_repo &&
+    git add . &&
+    git commit --allow-empty -m "Test" -- "hello\?world" &&
+    cat >expected_files <<-\EOF &&
+hello?world
+EOF
+    git ls-tree -r --name-only HEAD > actual_files &&
+    test_cmp expected_files actual_files 
+'
+
+end_test_properly
+
+test_done
-- 
2.49.0.223.ga3111b2db4.dirty


             reply	other threads:[~2025-04-22 16:05 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-22 16:05 K Jayatheerth [this message]
2025-04-22 18:53 ` [PATCH v2] Dir: Fix and test wildcard pathspec handling Junio C Hamano
2025-05-03  6:07   ` [PATCH] dir.c: literal match with wildcard in pathspec should still glob K Jayatheerth
2025-05-03  6:24     ` JAYATHEERTH K
2025-05-05 14:41       ` Junio C Hamano
2025-05-05 15:02         ` K Jayatheerth
2025-05-05 15:03         ` JAYATHEERTH K

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250422160547.577524-1-jayatheerthkulkarni2005@gmail.com \
    --to=jayatheerthkulkarni2005@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=lucasseikioshiro@gmail.com \
    --cc=peff@peff.net \
    --cc=piotrsiupa@gmail.com \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).