fish_git_prompt: skip rename/copy source paths in status parsing

When git status --porcelain -z reports renames or copies, it outputs
the source filename as a separate NUL-delimited field after the status
line. This extra entry was counted as an additional change, inflating
staged/dirty counts when the source filename started with [ACDMRTU].

Filter split results to entries matching a valid two-char status code
prefix, which excludes the bare source filenames.

Fixes #11296

Part of #12754
This commit is contained in:
June Kim
2026-05-12 21:12:21 -07:00
committed by Johannes Altmanninger
parent f69f074f66
commit f86c9af455

View File

@@ -298,7 +298,10 @@ function fish_git_prompt --description "Prompt function for Git"
test "$untracked" = true; and set opt -unormal
# Don't use `--ignored=no`; it was introduced in Git 2.16, from January 2018
# Ignored files are omitted by default
set -l stat (command git -c core.fsmonitor= status --porcelain -z $opt | string split0)
# Renames and copies in porcelain -z output have an extra NUL-delimited
# field for the source path. Filter to entries starting with a valid
# two-char status code followed by a space to skip those bare paths.
set -l stat (command git -c core.fsmonitor= status --porcelain -z $opt | string split0 | string match -r '^[ MADRCU?!]{2} .*')
set dirtystate (string match -qr '^.[ACDMRTU]' -- $stat; and echo 1)
if test -n "$sha"
@@ -421,7 +424,10 @@ function __fish_git_prompt_informative_status
# Use git status --porcelain.
# The v2 format is better, but we don't actually care in this case.
set -l stats (string sub -l 2 (git -c core.fsmonitor= status --porcelain -z $untr | string split0))
# Renames and copies in porcelain -z output have an extra NUL-delimited
# field for the source path. Filter to entries starting with a valid
# two-char status code followed by a space to skip those bare paths.
set -l stats (string sub -l 2 (git -c core.fsmonitor= status --porcelain -z $untr | string split0 | string match -r '^[ MADRCU?!]{2} .*'))
set -l invalidstate (string match -r '^UU' $stats | count)
set -l stagedstate (string match -r '^[ACDMRT].' $stats | count)
set -l dirtystate (string match -r '^.[ACDMRT]' $stats | count)