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