From: Junio C Hamano Date: Mon, 29 Mar 2010 04:21:42 +0000 (-0700) Subject: Merge branch 'cp/add-u-pathspec' into maint X-Git-Tag: v1.7.0.4~12 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/cc64c6970a0d50ecb75ba902d406bac7ea461f97?ds=inline;hp=-c Merge branch 'cp/add-u-pathspec' into maint * cp/add-u-pathspec: test for add with non-existent pathspec git add -u: die on unmatched pathspec --- cc64c6970a0d50ecb75ba902d406bac7ea461f97 diff --combined builtin-add.c index 2705f8d057,016987c224..87d2980313 --- a/builtin-add.c +++ b/builtin-add.c @@@ -11,7 -11,6 +11,7 @@@ #include "run-command.h" #include "parse-options.h" #include "diff.h" +#include "diffcore.h" #include "revision.h" static const char * const builtin_add_usage[] = { @@@ -21,81 -20,6 +21,81 @@@ static int patch_interactive, add_interactive, edit_interactive; static int take_worktree_changes; +struct update_callback_data +{ + int flags; + int add_errors; +}; + +static void update_callback(struct diff_queue_struct *q, + struct diff_options *opt, void *cbdata) +{ + int i; + struct update_callback_data *data = cbdata; + + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + const char *path = p->one->path; + switch (p->status) { + default: + die("unexpected diff status %c", p->status); + case DIFF_STATUS_UNMERGED: + /* + * ADD_CACHE_IGNORE_REMOVAL is unset if "git + * add -u" is calling us, In such a case, a + * missing work tree file needs to be removed + * if there is an unmerged entry at stage #2, + * but such a diff record is followed by + * another with DIFF_STATUS_DELETED (and if + * there is no stage #2, we won't see DELETED + * nor MODIFIED). We can simply continue + * either way. + */ + if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL)) + continue; + /* + * Otherwise, it is "git add path" is asking + * to explicitly add it; we fall through. A + * missing work tree file is an error and is + * caught by add_file_to_index() in such a + * case. + */ + case DIFF_STATUS_MODIFIED: + case DIFF_STATUS_TYPE_CHANGED: + if (add_file_to_index(&the_index, path, data->flags)) { + if (!(data->flags & ADD_CACHE_IGNORE_ERRORS)) + die("updating files failed"); + data->add_errors++; + } + break; + case DIFF_STATUS_DELETED: + if (data->flags & ADD_CACHE_IGNORE_REMOVAL) + break; + if (!(data->flags & ADD_CACHE_PRETEND)) + remove_file_from_index(&the_index, path); + if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE)) + printf("remove '%s'\n", path); + break; + } + } +} + +int add_files_to_cache(const char *prefix, const char **pathspec, int flags) +{ + struct update_callback_data data; + struct rev_info rev; + init_revisions(&rev, prefix); + setup_revisions(0, NULL, &rev, NULL); + rev.prune_data = pathspec; + rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; + rev.diffopt.format_callback = update_callback; + data.flags = flags; + data.add_errors = 0; + rev.diffopt.format_callback_data = &data; + run_diff_files(&rev, DIFF_RACY_IS_MODIFIED); + return !!data.add_errors; +} + static void fill_pathspec_matches(const char **pathspec, char *seen, int specs) { int num_unmatched = 0, i; @@@ -117,7 -41,19 +117,19 @@@ } } - static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) + static char *find_used_pathspec(const char **pathspec) + { + char *seen; + int i; + + for (i = 0; pathspec[i]; i++) + ; /* just counting */ + seen = xcalloc(i, 1); + fill_pathspec_matches(pathspec, seen, i); + return seen; + } + + static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) { char *seen; int i, specs; @@@ -137,13 -73,7 +149,7 @@@ } dir->nr = dst - dir->entries; 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]); - } - free(seen); + return seen; } static void treat_gitlinks(const char **pathspec) @@@ -359,6 -289,7 +365,7 @@@ int cmd_add(int argc, const char **argv int flags; int add_new_files; int require_pathspec; + char *seen = NULL; git_config(add_config, NULL); @@@ -418,7 -349,7 +425,7 @@@ /* This picks up the paths that are not tracked */ baselen = fill_directory(&dir, pathspec); if (pathspec) - prune_directory(&dir, pathspec, baselen); + seen = prune_directory(&dir, pathspec, baselen); } if (refresh_only) { @@@ -426,6 -357,19 +433,19 @@@ goto finish; } + if (pathspec) { + int i; + if (!seen) + seen = find_used_pathspec(pathspec); + for (i = 0; pathspec[i]; i++) { + if (!seen[i] && pathspec[i][0] + && !file_exists(pathspec[i])) + die("pathspec '%s' did not match any files", + pathspec[i]); + } + free(seen); + } + exit_status |= add_files_to_cache(prefix, pathspec, flags); if (add_new_files)