From 13bb0ce6b77833c0b6a8377d0af7151ee3453a7b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 28 Feb 2010 23:33:46 -0800 Subject: [PATCH] builtin-add: fix exclude handling After we finish walking the working tree to find paths to add, the prune_directory() function checks the pathspecs to find typoes in them. When a given pathspec did not produce any match (either in the untracked files, or paths already in the index), there are two cases: - "git add no-such-file", i.e. the pathspec was misspelled; or - "git add ignored-pattern.o", i.e. the pathspec exactly matches but is ignored by the traversal. For the former, the function immediately errored out. The latter were queued in the dir structure and later used to give an error message with "use -f if you really mean it" advice. e96980e (builtin-add: simplify (and increase accuracy of) exclude handling, 2007-06-12) somehow lost the latter. This adds the logic back, but with a bit of twist, as it uses collect_ignored option that does half the necessary work during the traversal. Signed-off-by: Junio C Hamano --- builtin-add.c | 23 ++++++++++++++++++++--- dir.c | 10 ++++------ dir.h | 2 ++ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/builtin-add.c b/builtin-add.c index cb6e5906fb..c24c1bfa25 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -63,9 +63,26 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p fill_pathspec_matches(pathspec, seen, specs); for (i = 0; i < specs; i++) { - if (!seen[i] && pathspec[i][0] && !file_exists(pathspec[i])) - die("pathspec '%s' did not match any files", - pathspec[i]); + const char *match; + if (seen[i]) + continue; + match = pathspec[i]; + if (!match[0]) + continue; + + /* Existing file? We must have ignored it */ + if (file_exists(match)) { + int len = strlen(match); + int i; + for (i = 0; i < dir->ignored_nr; i++) + if (dir->ignored[i]->len == len && + !memcmp(dir->ignored[i]->name, match, len)) + break; + if (dir->ignored_nr <= i) + dir_add_ignored(dir, match, strlen(match)); + continue; + } + die("pathspec '%s' did not match any files", match); } free(seen); } diff --git a/dir.c b/dir.c index 00d698d79f..11d8954829 100644 --- a/dir.c +++ b/dir.c @@ -413,13 +413,10 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna return dir->entries[dir->nr++] = dir_entry_new(pathname, len); } -static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len) +void dir_add_ignored(struct dir_struct *dir, const char *pathname, int len) { - if (!cache_name_is_other(pathname, len)) - return NULL; - ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc); - return dir->ignored[dir->ignored_nr++] = dir_entry_new(pathname, len); + dir->ignored[dir->ignored_nr++] = dir_entry_new(pathname, len); } enum exist_status { @@ -638,7 +635,8 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, { int exclude = excluded(dir, path, &dtype); if (exclude && (dir->flags & DIR_COLLECT_IGNORED) - && in_pathspec(path, *len, simplify)) + && in_pathspec(path, *len, simplify) + && cache_name_is_other(path, *len)) dir_add_ignored(dir, path, *len); /* diff --git a/dir.h b/dir.h index 320b6a2f38..9bc33379cb 100644 --- a/dir.h +++ b/dir.h @@ -96,4 +96,6 @@ extern int remove_dir_recursively(struct strbuf *path, int flag); /* tries to remove the path with empty directories along it, ignores ENOENT */ extern int remove_path(const char *path); +extern void dir_add_ignored(struct dir_struct *, const char *, int); + #endif