[RFC PATCH 5/6] unpack-trees: teach check_ok_to_remove() precious
- From
Mirko Faina <mroik@delayed.space>
- Date
- Oct 8, 2026, 12:07 UTC
- Message-ID
- <ae61067e7b835a6dd65f9047a19bb93f3f82f746.1791460418.git.mroik@delayed.space>
- In-Reply-To
- <cover.1791460418.git.mroik@delayed.space>
"git switch" and "git checkout" only clobber local changes when these paths are marked as excluded. With the introduction of precious files we want to make sure that the underlying machinery understands the difference between a trashable and a precious file (which are both excluded/ignored).
Teach check_ok_to_remove() to only target trashable files for clobbering instead of targeting excluded files.
Signed-off-by: Mirko Faina <mroik@delayed.space> --- This is missing some tests for clobbering, but I wasn't sure where to place them.
dir.c | 19 ++++++++++++++++++- dir.h | 4 ++++ unpack-trees.c | 7 ++++--- 3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/dir.c b/dir.c index 9aba1716a6..ffc1818533 100644 --- a/dir.c +++ b/dir.c @@ -1861,7 +1861,24 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir, /* * Loads the exclude lists for the directory containing pathname, then - * scans all exclude lists to determine whether pathname is excluded. + * scans all exclude lists to determine whether pathname is trashable. + * Returns 1 if true, otherwise 0. + */ +int is_trashable(struct dir_struct *dir, struct index_state *istate, + const char *pathname, int *dtype_p) +{ + struct path_pattern *pattern = + last_matching_pattern(dir, istate, pathname, dtype_p); + if (pattern) + return pattern->flags & + (PATTERN_FLAG_NEGATIVE | PATTERN_FLAG_PRECIOUS) ? 0 : 1; + return 0; +} + +/* + * Loads the exclude lists for the directory containing pathname, then + * scans all exclude lists to determine whether pathname is excluded (both + * trashable and precious). * Returns 1 if true, otherwise 0. */ int is_excluded(struct dir_struct *dir, struct index_state *istate, diff --git a/dir.h b/dir.h index a6977149b8..5424036e4e 100644 --- a/dir.h +++ b/dir.h @@ -442,6 +442,10 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir, struct index_state *istate, const char *name, int *dtype); +int is_trashable(struct dir_struct *dir, + struct index_state *istate, + const char *name, int *dtype); + int is_excluded(struct dir_struct *dir, struct index_state *istate, const char *name, int *dtype); diff --git a/unpack-trees.c b/unpack-trees.c index 1802809ad3..632fefd260 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -2434,11 +2434,12 @@ static int check_ok_to_remove(const char *name, int len, int dtype, if (repo_ignore_case(the_repository) && icase_exists(o, name, len, st)) return 0; + /* Check if trashable */ if (o->internal.dir && - is_excluded(o->internal.dir, o->src_index, name, &dtype)) + is_trashable(o->internal.dir, o->src_index, name, &dtype)) /* - * ce->name is explicitly excluded, so it is Ok to - * overwrite it. + * ce->name is explicitly marked as trashable, + * so it is Ok to overwrite it. */ return 0; if (S_ISDIR(st->st_mode)) {
-- 2.56.0