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 = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
274static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
275
276static struct option builtin_add_options[] = {
277 OPT__DRY_RUN(&show_only, N_("dry run")),
278 OPT__VERBOSE(&verbose, N_("be verbose")),
279 OPT_GROUP(""),
280 OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
281 OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
282 OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
283 OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
284 OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
285 OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
286 OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
287 OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
288 OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
289 OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
290 OPT_END(),
291};
292
293static int add_config(const char *var, const char *value, void *cb)
294{
295 if (!strcmp(var, "add.ignoreerrors") ||
296 !strcmp(var, "add.ignore-errors")) {
297 ignore_add_errors = git_config_bool(var, value);
298 return 0;
299 }
300 return git_default_config(var, value, cb);
301}
302
303static int add_files(struct dir_struct *dir, int flags)
304{
305 int i, exit_status = 0;
306
307 if (dir->ignored_nr) {
308 fprintf(stderr, _(ignore_error));
309 for (i = 0; i < dir->ignored_nr; i++)
310 fprintf(stderr, "%s\n", dir->ignored[i]->name);
311 fprintf(stderr, _("Use -f if you really want to add them.\n"));
312 die(_("no files added"));
313 }
314
315 for (i = 0; i < dir->nr; i++)
316 if (add_file_to_cache(dir->entries[i]->name, flags)) {
317 if (!ignore_add_errors)
318 die(_("adding files failed"));
319 exit_status = 1;
320 }
321 return exit_status;
322}
323
324static void warn_pathless_add(const char *option_name, const char *short_name) {
325 /*
326 * To be consistent with "git add -p" and most Git
327 * commands, we should default to being tree-wide, but
328 * this is not the original behavior and can't be
329 * changed until users trained themselves not to type
330 * "git add -u" or "git add -A". For now, we warn and
331 * keep the old behavior. Later, the behavior can be changed
332 * to tree-wide, keeping the warning for a while, and
333 * eventually we can drop the warning.
334 */
335 warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
336 "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
337 "To add content for the whole tree, run:\n"
338 "\n"
339 " git add %s :/\n"
340 " (or git add %s :/)\n"
341 "\n"
342 "To restrict the command to the current directory, run:\n"
343 "\n"
344 " git add %s .\n"
345 " (or git add %s .)\n"
346 "\n"
347 "With the current Git version, the command is restricted to the current directory."),
348 option_name, short_name,
349 option_name, short_name,
350 option_name, short_name);
351}
352
353int cmd_add(int argc, const char **argv, const char *prefix)
354{
355 int exit_status = 0;
356 int newfd;
357 const char **pathspec;
358 struct dir_struct dir;
359 int flags;
360 int add_new_files;
361 int require_pathspec;
362 char *seen = NULL;
363 const char *option_with_implicit_dot = NULL;
364 const char *short_option_with_implicit_dot = NULL;
365
366 git_config(add_config, NULL);
367
368 argc = parse_options(argc, argv, prefix, builtin_add_options,
369 builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
370 if (patch_interactive)
371 add_interactive = 1;
372 if (add_interactive)
373 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
374
375 if (edit_interactive)
376 return(edit_patch(argc, argv, prefix));
377 argc--;
378 argv++;
379
380 if (addremove && take_worktree_changes)
381 die(_("-A and -u are mutually incompatible"));
382 if (!show_only && ignore_missing)
383 die(_("Option --ignore-missing can only be used together with --dry-run"));
384 if (addremove) {
385 option_with_implicit_dot = "--all";
386 short_option_with_implicit_dot = "-A";
387 }
388 if (take_worktree_changes) {
389 option_with_implicit_dot = "--update";
390 short_option_with_implicit_dot = "-u";
391 }
392 if (option_with_implicit_dot && !argc) {
393 static const char *here[2] = { ".", NULL };
394 if (prefix)
395 warn_pathless_add(option_with_implicit_dot,
396 short_option_with_implicit_dot);
397 argc = 1;
398 argv = here;
399 }
400
401 add_new_files = !take_worktree_changes && !refresh_only;
402 require_pathspec = !take_worktree_changes;
403
404 newfd = hold_locked_index(&lock_file, 1);
405
406 flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
407 (show_only ? ADD_CACHE_PRETEND : 0) |
408 (intent_to_add ? ADD_CACHE_INTENT : 0) |
409 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
410 (!(addremove || take_worktree_changes)
411 ? ADD_CACHE_IGNORE_REMOVAL : 0));
412
413 if (require_pathspec && argc == 0) {
414 fprintf(stderr, _("Nothing specified, nothing added.\n"));
415 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
416 return 0;
417 }
418 pathspec = validate_pathspec(argv, prefix);
419
420 if (read_cache() < 0)
421 die(_("index file corrupt"));
422 treat_gitlinks(pathspec);
423
424 if (add_new_files) {
425 int baselen;
426
427 /* Set up the default git porcelain excludes */
428 memset(&dir, 0, sizeof(dir));
429 if (!ignored_too) {
430 dir.flags |= DIR_COLLECT_IGNORED;
431 setup_standard_excludes(&dir);
432 }
433
434 /* This picks up the paths that are not tracked */
435 baselen = fill_directory(&dir, pathspec);
436 if (pathspec)
437 seen = prune_directory(&dir, pathspec, baselen);
438 }
439
440 if (refresh_only) {
441 refresh(verbose, pathspec);
442 goto finish;
443 }
444
445 if (pathspec) {
446 int i;
447 struct path_exclude_check check;
448
449 path_exclude_check_init(&check, &dir);
450 if (!seen)
451 seen = find_pathspecs_matching_against_index(pathspec);
452 for (i = 0; pathspec[i]; i++) {
453 if (!seen[i] && pathspec[i][0]
454 && !file_exists(pathspec[i])) {
455 if (ignore_missing) {
456 int dtype = DT_UNKNOWN;
457 if (is_path_excluded(&check, pathspec[i], -1, &dtype))
458 dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
459 } else
460 die(_("pathspec '%s' did not match any files"),
461 pathspec[i]);
462 }
463 }
464 free(seen);
465 path_exclude_check_clear(&check);
466 }
467
468 plug_bulk_checkin();
469
470 exit_status |= add_files_to_cache(prefix, pathspec, flags);
471
472 if (add_new_files)
473 exit_status |= add_files(&dir, flags);
474
475 unplug_bulk_checkin();
476
477 finish:
478 if (active_cache_changed) {
479 if (write_cache(newfd, active_cache, active_nr) ||
480 commit_locked_index(&lock_file))
481 die(_("Unable to write new index file"));
482 }
483
484 return exit_status;
485}