Skip to content

iterator: keep pathlist entries that can match a later path - #7393

Open
yerseg wants to merge 1 commit into
libgit2:mainfrom
yerseg:fix-iterator-pathlist-walk
Open

yerseg wants to merge 1 commit into
libgit2:mainfrom
yerseg:fix-iterator-pathlist-walk

Conversation

@yerseg

@yerseg yerseg commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #7391.

iterator_pathlist_next_is advanced pathlist_walk_idx whenever any pathlist entry sorted before the current path. That could skip the first entry even though it could still match a later path. For example, with the pathlist foo, foo-bar/b, the path foo-bar/c made it skip foo, and foo/y was never returned.

With this change the index only advances when the entry that sorts before the path is the one the index points to. I added tests for the tree and index iterators and for checkout. They all fail without the fix, the checkout one because foo/y gets deleted.

This can also change the staged-changes check in git_merge, which uses a pathlist of the staged paths. With a staged deletion of foo and a merge that adds foo/child, the merge was refused, except when other staged paths like foo-bar/b made the iterator drop foo. Now it's refused in both cases.

The tree and index iterators walk the sorted pathlist alongside the
sorted entries, and `pathlist_walk_idx` points to the first pathlist
entry that can still match.  When a pathlist entry sorts before the
current path, the walk increments this index even if that entry is not
the first one.  This drops the first entry, although it can match a
later path.

For example, with the pathlist "foo" and "foo-bar/b", the path
"foo-bar/c" moves the index past "foo", so "foo/y" is not returned.
A diff misses "foo/y", status reports "foo/" as untracked, and a
checkout of these paths does not update "foo/y", or removes it with
GIT_CHECKOUT_FORCE.

Increment the index only when the entry that sorts before the path is
the first one.
@yerseg
yerseg force-pushed the fix-iterator-pathlist-walk branch from 4ef56b7 to f76b520 Compare September 30, 2026 10:21

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Paths matching a pathlist entry are skipped by diff, status and checkout (DISABLE_PATHSPEC_MATCH)

1 participant