From 4e9569834936a8c0df8c9afdc0334f1b96b20914 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Date: Thu, 8 Apr 2021 17:41:22 -0300 Subject: add: include magic part of pathspec on --refresh error When `git add --refresh ` doesn't find any matches for the given pathspec, it prints an error message using the `match` field of the `struct pathspec_item`. However, this field doesn't contain the magic part of the pathspec. Instead, let's use the `original` field. Signed-off-by: Matheus Tavares Signed-off-by: Junio C Hamano --- builtin/add.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/add.c b/builtin/add.c index ea762a41e3..24ed7e25f3 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -187,7 +187,7 @@ static void refresh(int verbose, const struct pathspec *pathspec) for (i = 0; i < pathspec->nr; i++) { if (!seen[i]) die(_("pathspec '%s' did not match any files"), - pathspec->items[i].match); + pathspec->items[i].original); } free(seen); } -- cgit v1.2.3 From d73dbafc2c25eb45090d6aa9d56fc21b40c78083 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Date: Thu, 8 Apr 2021 17:41:24 -0300 Subject: add: make --chmod and --renormalize honor sparse checkouts Signed-off-by: Matheus Tavares Signed-off-by: Junio C Hamano --- builtin/add.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'builtin') diff --git a/builtin/add.c b/builtin/add.c index 24ed7e25f3..5fec21a792 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -46,6 +46,9 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) struct cache_entry *ce = active_cache[i]; int err; + if (ce_skip_worktree(ce)) + continue; + if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL)) continue; @@ -144,6 +147,8 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags) for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; + if (ce_skip_worktree(ce)) + continue; if (ce_stage(ce)) continue; /* do not touch unmerged paths */ if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode)) -- cgit v1.2.3 From 719630eb4826ff7f36bc060533dbccc3c96d151c Mon Sep 17 00:00:00 2001 From: Matheus Tavares Date: Thu, 8 Apr 2021 17:41:25 -0300 Subject: pathspec: allow to ignore SKIP_WORKTREE entries on index matching Add a new enum parameter to `add_pathspec_matches_against_index()` and `find_pathspecs_matching_against_index()`, allowing callers to specify whether these function should attempt to match SKIP_WORKTREE entries or not. This will be used in a future patch to make `git add` display a warning when it is asked to update SKIP_WORKTREE entries. Signed-off-by: Matheus Tavares Signed-off-by: Junio C Hamano --- builtin/add.c | 6 ++++-- builtin/check-ignore.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'builtin') diff --git a/builtin/add.c b/builtin/add.c index 5fec21a792..050cb8af30 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -177,7 +177,8 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, *dst++ = entry; } dir->nr = dst - dir->entries; - add_pathspec_matches_against_index(pathspec, &the_index, seen); + add_pathspec_matches_against_index(pathspec, &the_index, seen, + PS_HEED_SKIP_WORKTREE); return seen; } @@ -578,7 +579,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) int i; if (!seen) - seen = find_pathspecs_matching_against_index(&pathspec, &the_index); + seen = find_pathspecs_matching_against_index(&pathspec, + &the_index, PS_HEED_SKIP_WORKTREE); /* * file_exists() assumes exact match diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index 3c652748d5..0f4480a11b 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -100,7 +100,8 @@ static int check_ignore(struct dir_struct *dir, * should not be ignored, in order to be consistent with * 'git status', 'git add' etc. */ - seen = find_pathspecs_matching_against_index(&pathspec, &the_index); + seen = find_pathspecs_matching_against_index(&pathspec, &the_index, + PS_HEED_SKIP_WORKTREE); for (i = 0; i < pathspec.nr; i++) { full_path = pathspec.items[i].match; pattern = NULL; -- cgit v1.2.3 From a20f70478ffcc66d30936920ebcc35ebfc12a7c7 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Date: Thu, 8 Apr 2021 17:41:27 -0300 Subject: add: warn when asked to update SKIP_WORKTREE entries `git add` already refrains from updating SKIP_WORKTREE entries, but it silently exits with zero code when it is asked to do so. Instead, let's warn the user and display a hint on how to update these entries. Note that we only warn the user whey they give a pathspec item that matches no eligible path for updating, but it does match one or more SKIP_WORKTREE entries. A warning was chosen over erroring out right away to reproduce the same behavior `add` already exhibits with ignored files. This also allow users to continue their workflow without having to invoke `add` again with only the eligible paths (as those will have already been added). Signed-off-by: Matheus Tavares Signed-off-by: Junio C Hamano --- builtin/add.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 14 deletions(-) (limited to 'builtin') diff --git a/builtin/add.c b/builtin/add.c index 050cb8af30..6980311aaa 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -178,24 +178,43 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, } dir->nr = dst - dir->entries; add_pathspec_matches_against_index(pathspec, &the_index, seen, - PS_HEED_SKIP_WORKTREE); + PS_IGNORE_SKIP_WORKTREE); return seen; } -static void refresh(int verbose, const struct pathspec *pathspec) +static int refresh(int verbose, const struct pathspec *pathspec) { char *seen; - int i; + int i, ret = 0; + char *skip_worktree_seen = NULL; + struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP; + int flags = REFRESH_IGNORE_SKIP_WORKTREE | + (verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET); seen = xcalloc(pathspec->nr, 1); - refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET, - pathspec, seen, _("Unstaged changes after refreshing the index:")); + refresh_index(&the_index, flags, pathspec, seen, + _("Unstaged changes after refreshing the index:")); for (i = 0; i < pathspec->nr; i++) { - if (!seen[i]) - die(_("pathspec '%s' did not match any files"), - pathspec->items[i].original); + if (!seen[i]) { + if (matches_skip_worktree(pathspec, i, &skip_worktree_seen)) { + string_list_append(&only_match_skip_worktree, + pathspec->items[i].original); + } else { + die(_("pathspec '%s' did not match any files"), + pathspec->items[i].original); + } + } + } + + if (only_match_skip_worktree.nr) { + advise_on_updating_sparse_paths(&only_match_skip_worktree); + ret = 1; } + free(seen); + free(skip_worktree_seen); + string_list_clear(&only_match_skip_worktree, 0); + return ret; } int run_add_interactive(const char *revision, const char *patch_mode, @@ -571,16 +590,18 @@ int cmd_add(int argc, const char **argv, const char *prefix) } if (refresh_only) { - refresh(verbose, &pathspec); + exit_status |= refresh(verbose, &pathspec); goto finish; } if (pathspec.nr) { int i; + char *skip_worktree_seen = NULL; + struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP; if (!seen) seen = find_pathspecs_matching_against_index(&pathspec, - &the_index, PS_HEED_SKIP_WORKTREE); + &the_index, PS_IGNORE_SKIP_WORKTREE); /* * file_exists() assumes exact match @@ -594,12 +615,24 @@ int cmd_add(int argc, const char **argv, const char *prefix) for (i = 0; i < pathspec.nr; i++) { const char *path = pathspec.items[i].match; + if (pathspec.items[i].magic & PATHSPEC_EXCLUDE) continue; - if (!seen[i] && path[0] && - ((pathspec.items[i].magic & - (PATHSPEC_GLOB | PATHSPEC_ICASE)) || - !file_exists(path))) { + if (seen[i]) + continue; + + if (matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) { + string_list_append(&only_match_skip_worktree, + pathspec.items[i].original); + continue; + } + + /* Don't complain at 'git add .' on empty repo */ + if (!path[0]) + continue; + + if ((pathspec.items[i].magic & (PATHSPEC_GLOB | PATHSPEC_ICASE)) || + !file_exists(path)) { if (ignore_missing) { int dtype = DT_UNKNOWN; if (is_excluded(&dir, &the_index, path, &dtype)) @@ -610,7 +643,16 @@ int cmd_add(int argc, const char **argv, const char *prefix) pathspec.items[i].original); } } + + + if (only_match_skip_worktree.nr) { + advise_on_updating_sparse_paths(&only_match_skip_worktree); + exit_status = 1; + } + free(seen); + free(skip_worktree_seen); + string_list_clear(&only_match_skip_worktree, 0); } plug_bulk_checkin(); -- cgit v1.2.3 From d5f4b8260f623d6fdef36d5eaa8a0c2350390472 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Date: Thu, 8 Apr 2021 17:41:28 -0300 Subject: rm: honor sparse checkout patterns `git add` refrains from adding or updating index entries that are outside the current sparse checkout, but `git rm` doesn't follow the same restriction. This is somewhat counter-intuitive and inconsistent. So make `rm` honor the sparsity rules and advise on how to remove SKIP_WORKTREE entries just like `add` does. Also add some tests for the new behavior. Suggested-by: Elijah Newren Signed-off-by: Matheus Tavares Signed-off-by: Junio C Hamano --- builtin/rm.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'builtin') diff --git a/builtin/rm.c b/builtin/rm.c index 4858631e0f..d23a3b2164 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -5,6 +5,7 @@ */ #define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" +#include "advice.h" #include "config.h" #include "lockfile.h" #include "dir.h" @@ -254,7 +255,7 @@ static struct option builtin_rm_options[] = { int cmd_rm(int argc, const char **argv, const char *prefix) { struct lock_file lock_file = LOCK_INIT; - int i; + int i, ret = 0; struct pathspec pathspec; char *seen; @@ -295,6 +296,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix) for (i = 0; i < active_nr; i++) { const struct cache_entry *ce = active_cache[i]; + if (ce_skip_worktree(ce)) + continue; if (!ce_path_match(&the_index, ce, &pathspec, seen)) continue; ALLOC_GROW(list.entry, list.nr + 1, list.alloc); @@ -308,24 +311,34 @@ int cmd_rm(int argc, const char **argv, const char *prefix) if (pathspec.nr) { const char *original; int seen_any = 0; + char *skip_worktree_seen = NULL; + struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP; + for (i = 0; i < pathspec.nr; i++) { original = pathspec.items[i].original; - if (!seen[i]) { - if (!ignore_unmatch) { - die(_("pathspec '%s' did not match any files"), - original); - } - } - else { + if (seen[i]) seen_any = 1; - } + else if (ignore_unmatch) + continue; + else if (matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) + string_list_append(&only_match_skip_worktree, original); + else + die(_("pathspec '%s' did not match any files"), original); + if (!recursive && seen[i] == MATCHED_RECURSIVELY) die(_("not removing '%s' recursively without -r"), *original ? original : "."); } + if (only_match_skip_worktree.nr) { + advise_on_updating_sparse_paths(&only_match_skip_worktree); + ret = 1; + } + free(skip_worktree_seen); + string_list_clear(&only_match_skip_worktree, 0); + if (!seen_any) - exit(0); + exit(ret); } if (!index_only) @@ -405,5 +418,5 @@ int cmd_rm(int argc, const char **argv, const char *prefix) COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("Unable to write new index file")); - return 0; + return ret; } -- cgit v1.2.3