All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: "René Scharfe" <l.s.r@web.de>
Cc: git@vger.kernel.org, 81625@debbugs.gnu.org,
	"Lester Longley" <lester@ieee.org>,
	"Sean Whitton" <spwhitton@spwhitton.name>,
	"Elijah Newren" <newren@gmail.com>,
	"Martin Ågren" <martin.agren@gmail.com>
Subject: Re: [PATCH] dir: skip excluded directory with nested repo on prefix match
Date: Mon, 21 Sep 2026 21:57:43 -0700	[thread overview]
Message-ID: <xmqqjyodj320.fsf@gitster.g> (raw)
In-Reply-To: <be53c379-b0e1-4242-8504-e96c2c49d294@web.de> ("René Scharfe"'s message of "Fri, 18 Sep 2026 13:04:06 +0200")

René Scharfe <l.s.r@web.de> writes:

> +static int dir_match(struct index_state *istate,
> +		     const struct pathspec *pathspec,
> +		     const char *dirname, int len)
> +{
> +	return match_pathspec_with_flags(istate, pathspec, dirname, len,
> +					 0 /* prefix */,
> +					 NULL /* seen */,
> +					 DO_MATCH_LEADING_PATHSPEC);
> +}

OK, this is a good helper to extract and reuse.

> @@ -1996,11 +2006,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
>  	 * for matching patterns.
>  	 */
>  	if (pathspec && !excluded) {
> -		matches_how = match_pathspec_with_flags(istate, pathspec,
> -							dirname, len,
> -							0 /* prefix */,
> -							NULL /* seen */,
> -							DO_MATCH_LEADING_PATHSPEC);
> +		matches_how = dir_match(istate, pathspec, dirname, len);
>  		if (!matches_how)
>  			return path_none;
>  	}

So, this hunk shows that the treat_directory() function is prepared
to be passed a NULL in pathspec.  We make sure we do not trigger
match_pathspec_with_flags() when pathspec is NULL, and this should
extends to dir_match() now.  This is a very sensible conditional, as
match_pathspec_with_flags() calls do_match_pathspec() as the first
thing, which begins with GUARD_PATHSPEC() macro that unconditionally
dereferences the pathspec.

> @@ -2034,8 +2040,13 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
>  		strbuf_release(&sb);
>  
>  		if (nested_repo) {
> -			if ((dir->flags & DIR_SKIP_NESTED_GIT) ||
> -				(matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC))
> +			if (dir->flags & DIR_SKIP_NESTED_GIT)
> +				return path_none;
> +			if (!matches_how)
> +				matches_how = dir_match(istate, pathspec,
> +							dirname, len);
> +			if (!matches_how ||
> +			    matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC)
>  				return path_none;

Here, we do not know if we have pathspec==NULL.  Shouldn't "make
sure we have a result from dir_match() and return path_none as
appropriate" be done only when pathspec != NULL or something like
that, since dir_match() will crash if pathspec is NULL?

Taking all together, something along the following line squashed
into your patch, perhaps?  The newly added test is not essential; it
merely is to demonstrate why an extra conditional I added below
would help avoid segfaulting.

 dir.c                      | 15 +++++++++------
 t/t7061-wtstatus-ignore.sh | 25 +++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git c/dir.c w/dir.c
index 6bda650891..8e858c26d1 100644
--- c/dir.c
+++ w/dir.c
@@ -2042,12 +2042,15 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
 		if (nested_repo) {
 			if (dir->flags & DIR_SKIP_NESTED_GIT)
 				return path_none;
-			if (!matches_how)
-				matches_how = dir_match(istate, pathspec,
-							dirname, len);
-			if (!matches_how ||
-			    matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC)
-				return path_none;
+
+			if (pathspec) {
+				if (!matches_how)
+					matches_how = dir_match(istate, pathspec,
+								dirname, len);
+				if (!matches_how ||
+				    matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC)
+					return path_none;
+			}
 			return excluded ? path_excluded : path_untracked;
 		}
 	}
diff --git c/t/t7061-wtstatus-ignore.sh w/t/t7061-wtstatus-ignore.sh
index 182933471f..6bc680312e 100755
--- c/t/t7061-wtstatus-ignore.sh
+++ w/t/t7061-wtstatus-ignore.sh
@@ -340,6 +340,31 @@ test_expect_success 'status ignores submodule in excluded directory' '
 	test_cmp expected actual
 '
 
+test_expect_success 'replace directory with untracked nested repo' '
+	test_create_repo checkout-nested &&
+	(
+		cd checkout-nested &&
+		test_commit base &&
+
+		# Branch with tracked file "dir"
+		git checkout -b branch-file &&
+		echo "tracked file" >dir &&
+		git add dir &&
+		git commit -m "add file dir" &&
+
+		# Switch back to base
+		git checkout -b branch-nested base &&
+
+		# Create an untracked directory containing a nested git repo
+		mkdir -p dir/nested &&
+		git init dir/nested &&
+
+		# Attempting checkout invokes verify_clean_subdirectory()
+		# with pathspec=NULL
+		test_must_fail git checkout branch-file
+	)
+'
+
 test_expect_success 'status omits excluded directory with submodule on prefix match' '
 	git status --porcelain --ignored -u tracke >actual &&
 	test_must_be_empty actual

  reply	other threads:[~2026-09-22  4:57 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14 13:31 [BUG] 'git status --ignored' <pathspec> matches partial names Sean Whitton
2026-09-15 15:54 ` René Scharfe
2026-09-18 11:04 ` [PATCH] dir: skip excluded directory with nested repo on prefix match René Scharfe
2026-09-22  4:57   ` Junio C Hamano [this message]
2026-09-26 10:51     ` René Scharfe
2026-09-26 10:48   ` [PATCH v2] " René Scharfe

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=xmqqjyodj320.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=81625@debbugs.gnu.org \
    --cc=git@vger.kernel.org \
    --cc=l.s.r@web.de \
    --cc=lester@ieee.org \
    --cc=martin.agren@gmail.com \
    --cc=newren@gmail.com \
    --cc=spwhitton@spwhitton.name \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.