git add: rework the logic to warn "git add <pathspec>..." default change
[git] / builtin / add.c
1 /*
2  * "git add" builtin command
3  *
4  * Copyright (C) 2006 Linus Torvalds
5  */
6 #include "cache.h"
7 #include "builtin.h"
8 #include "dir.h"
9 #include "pathspec.h"
10 #include "exec_cmd.h"
11 #include "cache-tree.h"
12 #include "run-command.h"
13 #include "parse-options.h"
14 #include "diff.h"
15 #include "diffcore.h"
16 #include "revision.h"
17 #include "bulk-checkin.h"
18
19 static const char * const builtin_add_usage[] = {
20         N_("git add [options] [--] <pathspec>..."),
21         NULL
22 };
23 static int patch_interactive, add_interactive, edit_interactive;
24 static int take_worktree_changes;
25
26 struct update_callback_data {
27         int flags;
28         int add_errors;
29
30         /* only needed for 2.0 transition preparation */
31         int warn_add_would_remove;
32 };
33
34 static int fix_unmerged_status(struct diff_filepair *p,
35                                struct update_callback_data *data)
36 {
37         if (p->status != DIFF_STATUS_UNMERGED)
38                 return p->status;
39         if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
40                 /*
41                  * This is not an explicit add request, and the
42                  * path is missing from the working tree (deleted)
43                  */
44                 return DIFF_STATUS_DELETED;
45         else
46                 /*
47                  * Either an explicit add request, or path exists
48                  * in the working tree.  An attempt to explicitly
49                  * add a path that does not exist in the working tree
50                  * will be caught as an error by the caller immediately.
51                  */
52                 return DIFF_STATUS_MODIFIED;
53 }
54
55 static void warn_add_would_remove(const char *path)
56 {
57         warning(_("In Git 2.0, 'git add <pathspec>...' will also update the\n"
58                   "index for paths removed from the working tree that match\n"
59                   "the given pathspec. If you want to 'add' only changed\n"
60                   "or newly created paths, say 'git add --no-all <pathspec>...'"
61                   " instead.\n\n"
62                   "'%s' would be removed from the index without --no-all."),
63                 path);
64 }
65
66 static void update_callback(struct diff_queue_struct *q,
67                             struct diff_options *opt, void *cbdata)
68 {
69         int i;
70         struct update_callback_data *data = cbdata;
71
72         for (i = 0; i < q->nr; i++) {
73                 struct diff_filepair *p = q->queue[i];
74                 const char *path = p->one->path;
75                 switch (fix_unmerged_status(p, data)) {
76                 default:
77                         die(_("unexpected diff status %c"), p->status);
78                 case DIFF_STATUS_MODIFIED:
79                 case DIFF_STATUS_TYPE_CHANGED:
80                         if (add_file_to_index(&the_index, path, data->flags)) {
81                                 if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
82                                         die(_("updating files failed"));
83                                 data->add_errors++;
84                         }
85                         break;
86                 case DIFF_STATUS_DELETED:
87                         if (data->warn_add_would_remove) {
88                                 warn_add_would_remove(path);
89                                 data->warn_add_would_remove = 0;
90                         }
91                         if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
92                                 break;
93                         if (!(data->flags & ADD_CACHE_PRETEND))
94                                 remove_file_from_index(&the_index, path);
95                         if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
96                                 printf(_("remove '%s'\n"), path);
97                         break;
98                 }
99         }
100 }
101
102 static void update_files_in_cache(const char *prefix, const char **pathspec,
103                                   struct update_callback_data *data)
104 {
105         struct rev_info rev;
106         init_revisions(&rev, prefix);
107         setup_revisions(0, NULL, &rev, NULL);
108         init_pathspec(&rev.prune_data, pathspec);
109         rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
110         rev.diffopt.format_callback = update_callback;
111         rev.diffopt.format_callback_data = data;
112         rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
113         run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
114 }
115
116 int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
117 {
118         struct update_callback_data data;
119
120         memset(&data, 0, sizeof(data));
121         data.flags = flags;
122         update_files_in_cache(prefix, pathspec, &data);
123         return !!data.add_errors;
124 }
125
126 static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
127 {
128         char *seen;
129         int i, specs;
130         struct dir_entry **src, **dst;
131
132         for (specs = 0; pathspec[specs];  specs++)
133                 /* nothing */;
134         seen = xcalloc(specs, 1);
135
136         src = dst = dir->entries;
137         i = dir->nr;
138         while (--i >= 0) {
139                 struct dir_entry *entry = *src++;
140                 if (match_pathspec(pathspec, entry->name, entry->len,
141                                    prefix, seen))
142                         *dst++ = entry;
143         }
144         dir->nr = dst - dir->entries;
145         add_pathspec_matches_against_index(pathspec, seen, specs);
146         return seen;
147 }
148
149 /*
150  * Checks the index to see whether any path in pathspec refers to
151  * something inside a submodule.  If so, dies with an error message.
152  */
153 static void treat_gitlinks(const char **pathspec)
154 {
155         int i;
156
157         if (!pathspec || !*pathspec)
158                 return;
159
160         for (i = 0; pathspec[i]; i++)
161                 pathspec[i] = check_path_for_gitlink(pathspec[i]);
162 }
163
164 static void refresh(int verbose, const char **pathspec)
165 {
166         char *seen;
167         int i, specs;
168
169         for (specs = 0; pathspec[specs];  specs++)
170                 /* nothing */;
171         seen = xcalloc(specs, 1);
172         refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
173                       pathspec, seen, _("Unstaged changes after refreshing the index:"));
174         for (i = 0; i < specs; i++) {
175                 if (!seen[i])
176                         die(_("pathspec '%s' did not match any files"), pathspec[i]);
177         }
178         free(seen);
179 }
180
181 /*
182  * Normalizes argv relative to prefix, via get_pathspec(), and then
183  * runs die_if_path_beyond_symlink() on each path in the normalized
184  * list.
185  */
186 static const char **validate_pathspec(const char **argv, const char *prefix)
187 {
188         const char **pathspec = get_pathspec(prefix, argv);
189
190         if (pathspec) {
191                 const char **p;
192                 for (p = pathspec; *p; p++) {
193                         die_if_path_beyond_symlink(*p, prefix);
194                 }
195         }
196
197         return pathspec;
198 }
199
200 int run_add_interactive(const char *revision, const char *patch_mode,
201                         const char **pathspec)
202 {
203         int status, ac, pc = 0;
204         const char **args;
205
206         if (pathspec)
207                 while (pathspec[pc])
208                         pc++;
209
210         args = xcalloc(sizeof(const char *), (pc + 5));
211         ac = 0;
212         args[ac++] = "add--interactive";
213         if (patch_mode)
214                 args[ac++] = patch_mode;
215         if (revision)
216                 args[ac++] = revision;
217         args[ac++] = "--";
218         if (pc) {
219                 memcpy(&(args[ac]), pathspec, sizeof(const char *) * pc);
220                 ac += pc;
221         }
222         args[ac] = NULL;
223
224         status = run_command_v_opt(args, RUN_GIT_CMD);
225         free(args);
226         return status;
227 }
228
229 int interactive_add(int argc, const char **argv, const char *prefix, int patch)
230 {
231         const char **pathspec = NULL;
232
233         if (argc) {
234                 pathspec = validate_pathspec(argv, prefix);
235                 if (!pathspec)
236                         return -1;
237         }
238
239         return run_add_interactive(NULL,
240                                    patch ? "--patch" : NULL,
241                                    pathspec);
242 }
243
244 static int edit_patch(int argc, const char **argv, const char *prefix)
245 {
246         char *file = git_pathdup("ADD_EDIT.patch");
247         const char *apply_argv[] = { "apply", "--recount", "--cached",
248                 NULL, NULL };
249         struct child_process child;
250         struct rev_info rev;
251         int out;
252         struct stat st;
253
254         apply_argv[3] = file;
255
256         git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
257
258         if (read_cache() < 0)
259                 die (_("Could not read the index"));
260
261         init_revisions(&rev, prefix);
262         rev.diffopt.context = 7;
263
264         argc = setup_revisions(argc, argv, &rev, NULL);
265         rev.diffopt.output_format = DIFF_FORMAT_PATCH;
266         DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
267         out = open(file, O_CREAT | O_WRONLY, 0666);
268         if (out < 0)
269                 die (_("Could not open '%s' for writing."), file);
270         rev.diffopt.file = xfdopen(out, "w");
271         rev.diffopt.close_file = 1;
272         if (run_diff_files(&rev, 0))
273                 die (_("Could not write patch"));
274
275         launch_editor(file, NULL, NULL);
276
277         if (stat(file, &st))
278                 die_errno(_("Could not stat '%s'"), file);
279         if (!st.st_size)
280                 die(_("Empty patch. Aborted."));
281
282         memset(&child, 0, sizeof(child));
283         child.git_cmd = 1;
284         child.argv = apply_argv;
285         if (run_command(&child))
286                 die (_("Could not apply '%s'"), file);
287
288         unlink(file);
289         free(file);
290         return 0;
291 }
292
293 static struct lock_file lock_file;
294
295 static const char ignore_error[] =
296 N_("The following paths are ignored by one of your .gitignore files:\n");
297
298 static int verbose, show_only, ignored_too, refresh_only;
299 static int ignore_add_errors, intent_to_add, ignore_missing;
300
301 #define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */
302 static int addremove = ADDREMOVE_DEFAULT;
303 static int addremove_explicit = -1; /* unspecified */
304
305 static struct option builtin_add_options[] = {
306         OPT__DRY_RUN(&show_only, N_("dry run")),
307         OPT__VERBOSE(&verbose, N_("be verbose")),
308         OPT_GROUP(""),
309         OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
310         OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
311         OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
312         OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
313         OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
314         OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
315         OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
316         OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
317         OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
318         OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
319         OPT_END(),
320 };
321
322 static int add_config(const char *var, const char *value, void *cb)
323 {
324         if (!strcmp(var, "add.ignoreerrors") ||
325             !strcmp(var, "add.ignore-errors")) {
326                 ignore_add_errors = git_config_bool(var, value);
327                 return 0;
328         }
329         return git_default_config(var, value, cb);
330 }
331
332 static int add_files(struct dir_struct *dir, int flags)
333 {
334         int i, exit_status = 0;
335
336         if (dir->ignored_nr) {
337                 fprintf(stderr, _(ignore_error));
338                 for (i = 0; i < dir->ignored_nr; i++)
339                         fprintf(stderr, "%s\n", dir->ignored[i]->name);
340                 fprintf(stderr, _("Use -f if you really want to add them.\n"));
341                 die(_("no files added"));
342         }
343
344         for (i = 0; i < dir->nr; i++)
345                 if (add_file_to_cache(dir->entries[i]->name, flags)) {
346                         if (!ignore_add_errors)
347                                 die(_("adding files failed"));
348                         exit_status = 1;
349                 }
350         return exit_status;
351 }
352
353 static void warn_pathless_add(const char *option_name, const char *short_name) {
354         /*
355          * To be consistent with "git add -p" and most Git
356          * commands, we should default to being tree-wide, but
357          * this is not the original behavior and can't be
358          * changed until users trained themselves not to type
359          * "git add -u" or "git add -A". For now, we warn and
360          * keep the old behavior. Later, this warning can be
361          * turned into a die(...), and eventually we may
362          * reallow the command with a new behavior.
363          */
364         warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
365                   "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
366                   "To add content for the whole tree, run:\n"
367                   "\n"
368                   "  git add %s :/\n"
369                   "  (or git add %s :/)\n"
370                   "\n"
371                   "To restrict the command to the current directory, run:\n"
372                   "\n"
373                   "  git add %s .\n"
374                   "  (or git add %s .)\n"
375                   "\n"
376                   "With the current Git version, the command is restricted to the current directory."),
377                 option_name, short_name,
378                 option_name, short_name,
379                 option_name, short_name);
380 }
381
382 int cmd_add(int argc, const char **argv, const char *prefix)
383 {
384         int exit_status = 0;
385         int newfd;
386         const char **pathspec;
387         struct dir_struct dir;
388         int flags;
389         int add_new_files;
390         int require_pathspec;
391         char *seen = NULL;
392         const char *option_with_implicit_dot = NULL;
393         const char *short_option_with_implicit_dot = NULL;
394         struct update_callback_data update_data;
395
396         git_config(add_config, NULL);
397
398         argc = parse_options(argc, argv, prefix, builtin_add_options,
399                           builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
400         if (patch_interactive)
401                 add_interactive = 1;
402         if (add_interactive)
403                 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
404
405         if (edit_interactive)
406                 return(edit_patch(argc, argv, prefix));
407         argc--;
408         argv++;
409
410         if (0 <= addremove_explicit)
411                 addremove = addremove_explicit;
412         else if (take_worktree_changes && ADDREMOVE_DEFAULT)
413                 addremove = 0; /* "-u" was given but not "-A" */
414
415         if (addremove && take_worktree_changes)
416                 die(_("-A and -u are mutually incompatible"));
417
418         /*
419          * Warn when "git add pathspec..." was given without "-u" or "-A"
420          * and pathspec... covers a removed path.
421          */
422         memset(&update_data, 0, sizeof(update_data));
423         if (!take_worktree_changes && addremove_explicit < 0)
424                 update_data.warn_add_would_remove = 1;
425
426         if (!take_worktree_changes && addremove_explicit < 0 && argc)
427                 /*
428                  * Turn "git add pathspec..." to "git add -A pathspec..."
429                  * in Git 2.0 but not yet
430                  */
431                 ; /* addremove = 1; */
432
433         if (!show_only && ignore_missing)
434                 die(_("Option --ignore-missing can only be used together with --dry-run"));
435         if (addremove) {
436                 option_with_implicit_dot = "--all";
437                 short_option_with_implicit_dot = "-A";
438         }
439         if (take_worktree_changes) {
440                 option_with_implicit_dot = "--update";
441                 short_option_with_implicit_dot = "-u";
442         }
443         if (option_with_implicit_dot && !argc) {
444                 static const char *here[2] = { ".", NULL };
445                 if (prefix)
446                         warn_pathless_add(option_with_implicit_dot,
447                                           short_option_with_implicit_dot);
448                 argc = 1;
449                 argv = here;
450         }
451
452         add_new_files = !take_worktree_changes && !refresh_only;
453         require_pathspec = !take_worktree_changes;
454
455         newfd = hold_locked_index(&lock_file, 1);
456
457         flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
458                  (show_only ? ADD_CACHE_PRETEND : 0) |
459                  (intent_to_add ? ADD_CACHE_INTENT : 0) |
460                  (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
461                  (!(addremove || take_worktree_changes)
462                   ? ADD_CACHE_IGNORE_REMOVAL : 0));
463
464         if (require_pathspec && argc == 0) {
465                 fprintf(stderr, _("Nothing specified, nothing added.\n"));
466                 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
467                 return 0;
468         }
469         pathspec = validate_pathspec(argv, prefix);
470
471         if (read_cache() < 0)
472                 die(_("index file corrupt"));
473         treat_gitlinks(pathspec);
474
475         if (add_new_files) {
476                 int baselen;
477
478                 /* Set up the default git porcelain excludes */
479                 memset(&dir, 0, sizeof(dir));
480                 if (!ignored_too) {
481                         dir.flags |= DIR_COLLECT_IGNORED;
482                         setup_standard_excludes(&dir);
483                 }
484
485                 /* This picks up the paths that are not tracked */
486                 baselen = fill_directory(&dir, pathspec);
487                 if (pathspec)
488                         seen = prune_directory(&dir, pathspec, baselen);
489         }
490
491         if (refresh_only) {
492                 refresh(verbose, pathspec);
493                 goto finish;
494         }
495
496         if (pathspec) {
497                 int i;
498                 struct path_exclude_check check;
499
500                 path_exclude_check_init(&check, &dir);
501                 if (!seen)
502                         seen = find_pathspecs_matching_against_index(pathspec);
503                 for (i = 0; pathspec[i]; i++) {
504                         if (!seen[i] && pathspec[i][0]
505                             && !file_exists(pathspec[i])) {
506                                 if (ignore_missing) {
507                                         int dtype = DT_UNKNOWN;
508                                         if (is_path_excluded(&check, pathspec[i], -1, &dtype))
509                                                 dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
510                                 } else
511                                         die(_("pathspec '%s' did not match any files"),
512                                             pathspec[i]);
513                         }
514                 }
515                 free(seen);
516                 path_exclude_check_clear(&check);
517         }
518
519         plug_bulk_checkin();
520
521         update_data.flags = flags;
522         update_files_in_cache(prefix, pathspec, &update_data);
523
524         exit_status |= !!update_data.add_errors;
525         if (add_new_files)
526                 exit_status |= add_files(&dir, flags);
527
528         unplug_bulk_checkin();
529
530  finish:
531         if (active_cache_changed) {
532                 if (write_cache(newfd, active_cache, active_nr) ||
533                     commit_locked_index(&lock_file))
534                         die(_("Unable to write new index file"));
535         }
536
537         return exit_status;
538 }