[RFC PATCH 4/6] dir.c: teach add_pattern() reject precious pattern
- From
Mirko Faina <mroik@delayed.space>
- Date
- Oct 8, 2026, 12:07 UTC
- Message-ID
- <b4e2d50f6f5da34a9720d23f487f0db41d2bf3ee.1791460418.git.mroik@delayed.space>
- In-Reply-To
- <cover.1791460418.git.mroik@delayed.space>
There are some places where we want to disallow precious files patterns altogether. This is the case with $GIT_DIR/info/sparse-checkout.
Teach add_pattern() a flag to indicate if we want it to reject precious files patterns. If that's the case it fails the same way it would when we encounter a pattern that starts with '!$', with a warning.
Signed-off-by: Mirko Faina <mroik@delayed.space> --- builtin/clean.c | 4 ++-- builtin/ls-files.c | 2 +- builtin/sparse-checkout.c | 15 +++++++++------ dir.c | 20 +++++++++++++++----- dir.h | 5 +++-- t/helper/test-path-walk.c | 2 +- t/t1091-sparse-checkout-builtin.sh | 8 ++++++++ 7 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c index 1d5e7e5366..73408da5c2 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -707,7 +707,7 @@ static int filter_by_patterns_cmd(void) item = &ignore_list.items[i]; if (!*item->string) continue; - add_pattern(item->string, "", 0, pl, -(i+1)); + add_pattern(item->string, "", 0, pl, -(i+1), 0); } changed = 0; @@ -1018,7 +1018,7 @@ int cmd_clean(int argc, pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option"); for (i = 0; i < exclude_list.nr; i++) - add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1)); + add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1), 0); parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD, diff --git a/builtin/ls-files.c b/builtin/ls-files.c index b044520f9e..d1cc7e92f4 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -685,7 +685,7 @@ int cmd_ls_files(int argc, ls_files_usage, 0); pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option"); for (i = 0; i < exclude_list.nr; i++) { - add_pattern(exclude_list.items[i].string, "", 0, pl, --exclude_args); + add_pattern(exclude_list.items[i].string, "", 0, pl, --exclude_args, 0); } if (format && (show_stage || show_others || show_killed || diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 83981e2b1e..615007148e 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -455,6 +455,8 @@ static struct sparse_checkout_init_opts { int sparse_index; } init_opts; +#define PATTERN_DISALLOW_PRECIOUS (1<<1) + static int sparse_checkout_init(int argc, const char **argv, const char *prefix, struct repository *repo) { @@ -487,7 +489,8 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix, memset(&pl, 0, sizeof(pl)); sparse_filename = get_sparse_checkout_filename(); - res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL, 0); + res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL, + PATTERN_DISALLOW_PRECIOUS); /* If we already have a sparse-checkout file, use it. */ if (res >= 0) { @@ -515,8 +518,8 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix, free(sparse_filename); - add_pattern("/*", empty_base, 0, &pl, 0); - add_pattern("!/*/", empty_base, 0, &pl, 0); + add_pattern("/*", empty_base, 0, &pl, 0, 0); + add_pattern("!/*/", empty_base, 0, &pl, 0, 0); pl.use_cone_patterns = init_opts.cone_mode; return write_patterns_and_update(repo, &pl); @@ -618,12 +621,12 @@ static void add_patterns_from_input(struct pattern_list *pl, struct strbuf line = STRBUF_INIT; while (!strbuf_getline(&line, file)) - add_pattern(line.buf, empty_base, 0, pl, 0); + add_pattern(line.buf, empty_base, 0, pl, 0, 0); strbuf_release(&line); } else { for (i = 0; i < argc; i++) - add_pattern(argv[i], empty_base, 0, pl, 0); + add_pattern(argv[i], empty_base, 0, pl, 0, 0); } } } @@ -1079,7 +1082,7 @@ static int sparse_checkout_disable(int argc, const char **argv, pl.use_cone_patterns = 0; cfg->apply_sparse_checkout = 1; - add_pattern("/*", empty_base, 0, &pl, 0); + add_pattern("/*", empty_base, 0, &pl, 0, 0); prepare_repo_settings(the_repository); repo->settings.sparse_index = 0; diff --git a/dir.c b/dir.c index c6f1bed429..9aba1716a6 100644 --- a/dir.c +++ b/dir.c @@ -993,7 +993,8 @@ int hashmap_contains_parent(struct hashmap *map, * which are negated precious-files. */ void add_pattern(const char *string, const char *base, - int baselen, struct pattern_list *pl, int srcpos) + int baselen, struct pattern_list *pl, int srcpos, + int disable_precious) { struct path_pattern *pattern; int patternlen; @@ -1004,6 +1005,12 @@ void add_pattern(const char *string, const char *base, warning(_("pattern '%s' is problematic, skipping"), string); return; } + + if (disable_precious && (flags & PATTERN_FLAG_PRECIOUS)) { + warning(_("'$%s' precious-files pattern not allowed here, skipping"), + string); + return; + } FLEX_ALLOC_MEM(pattern, pattern, string, patternlen); pattern->patternlen = patternlen; pattern->nowildcardlen = nowildcardlen; @@ -1162,6 +1169,7 @@ static void invalidate_directory(struct untracked_cache *uc, /* Flags for add_patterns() */ #define PATTERN_NOFOLLOW (1<<0) +#define PATTERN_DISALLOW_PRECIOUS (1<<1) /* * Given a file with name "fname", read it (either from disk, or from @@ -1244,14 +1252,15 @@ static int add_patterns(const char *fname, const char *base, int baselen, return -1; } - add_patterns_from_buffer(buf, size, base, baselen, pl); + add_patterns_from_buffer(buf, size, base, baselen, pl, + flags & PATTERN_DISALLOW_PRECIOUS); free(buf); return 0; } int add_patterns_from_buffer(char *buf, size_t size, const char *base, int baselen, - struct pattern_list *pl) + struct pattern_list *pl, int disable_precious) { char *orig = buf; int i, lineno = 1; @@ -1270,7 +1279,8 @@ int add_patterns_from_buffer(char *buf, size_t size, if (entry != buf + i && entry[0] != '#') { buf[i - (i && buf[i-1] == '\r')] = 0; trim_trailing_spaces(entry); - add_pattern(entry, base, baselen, pl, lineno); + add_pattern(entry, base, baselen, pl, lineno, + disable_precious); } lineno++; entry = buf + i + 1; @@ -1307,7 +1317,7 @@ int add_patterns_from_blob_to_list( return -1; } - add_patterns_from_buffer(buf, size, base, baselen, pl); + add_patterns_from_buffer(buf, size, base, baselen, pl, 0); free(buf); return 0; } diff --git a/dir.h b/dir.h index 5cda2cdba7..a6977149b8 100644 --- a/dir.h +++ b/dir.h @@ -464,10 +464,11 @@ int add_patterns_from_blob_to_list(struct object_id *oid, struct pattern_list *pl); int add_patterns_from_buffer(char *buf, size_t size, const char *base, int baselen, - struct pattern_list *pl); + struct pattern_list *pl, int disable_precious); int parse_path_pattern(const char **string, int *patternlen, enum pattern_flags *flags, int *nowildcardlen); void add_pattern(const char *string, const char *base, - int baselen, struct pattern_list *pl, int srcpos); + int baselen, struct pattern_list *pl, int srcpos, + int disable_precious); void clear_pattern_list(struct pattern_list *pl); void dir_clear(struct dir_struct *dir); diff --git a/t/helper/test-path-walk.c b/t/helper/test-path-walk.c index 4233badb58..fefe885ec6 100644 --- a/t/helper/test-path-walk.c +++ b/t/helper/test-path-walk.c @@ -124,7 +124,7 @@ int cmd__path_walk(int argc, const char **argv) info.pl->use_cone_patterns = 1; strbuf_fread(&in, 2048, stdin); - add_patterns_from_buffer(in.buf, in.len, "", 0, info.pl); + add_patterns_from_buffer(in.buf, in.len, "", 0, info.pl, 0); strbuf_release(&in); } diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index 74b1761e0c..caae112037 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -252,6 +252,14 @@ test_expect_success 'sparse-checkout disable' ' check_files repo a deep folder1 folder2 ' +test_expect_success 'skip precious-file pattern in $GIT_DIR/info/sparse-checkout' " + test_when_finished rm actual .git/info/sparse-checkout && + test_when_finished git sparse-checkout disable && + echo \"$/ciao\" > .git/info/sparse-checkout && + git sparse-checkout init >actual 2>&1 && + test_grep \"warning: '$/ciao' precious-files pattern not allowed here, skipping\" actual +" + test_expect_success 'sparse-index enabled and disabled' ' git -C repo sparse-checkout init --cone --sparse-index && test_cmp_config -C repo true index.sparse &&
-- 2.56.0