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