built-in add -p: implement the "stash" and "reset" patch modes
[git] / builtin / add.c
1 /*
2  * "git add" builtin command
3  *
4  * Copyright (C) 2006 Linus Torvalds
5  */
6 #define USE_THE_INDEX_COMPATIBILITY_MACROS
7 #include "cache.h"
8 #include "config.h"
9 #include "builtin.h"
10 #include "lockfile.h"
11 #include "dir.h"
12 #include "pathspec.h"
13 #include "exec-cmd.h"
14 #include "cache-tree.h"
15 #include "run-command.h"
16 #include "parse-options.h"
17 #include "diff.h"
18 #include "diffcore.h"
19 #include "revision.h"
20 #include "bulk-checkin.h"
21 #include "argv-array.h"
22 #include "submodule.h"
23 #include "add-interactive.h"
24
25 static const char * const builtin_add_usage[] = {
26         N_("git add [<options>] [--] <pathspec>..."),
27         NULL
28 };
29 static int patch_interactive, add_interactive, edit_interactive;
30 static int take_worktree_changes;
31 static int add_renormalize;
32
33 struct update_callback_data {
34         int flags;
35         int add_errors;
36 };
37
38 static void chmod_pathspec(struct pathspec *pathspec, char flip)
39 {
40         int i;
41
42         for (i = 0; i < active_nr; i++) {
43                 struct cache_entry *ce = active_cache[i];
44
45                 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
46                         continue;
47
48                 if (chmod_cache_entry(ce, flip) < 0)
49                         fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
50         }
51 }
52
53 static int fix_unmerged_status(struct diff_filepair *p,
54                                struct update_callback_data *data)
55 {
56         if (p->status != DIFF_STATUS_UNMERGED)
57                 return p->status;
58         if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
59                 /*
60                  * This is not an explicit add request, and the
61                  * path is missing from the working tree (deleted)
62                  */
63                 return DIFF_STATUS_DELETED;
64         else
65                 /*
66                  * Either an explicit add request, or path exists
67                  * in the working tree.  An attempt to explicitly
68                  * add a path that does not exist in the working tree
69                  * will be caught as an error by the caller immediately.
70                  */
71                 return DIFF_STATUS_MODIFIED;
72 }
73
74 static void update_callback(struct diff_queue_struct *q,
75                             struct diff_options *opt, void *cbdata)
76 {
77         int i;
78         struct update_callback_data *data = cbdata;
79
80         for (i = 0; i < q->nr; i++) {
81                 struct diff_filepair *p = q->queue[i];
82                 const char *path = p->one->path;
83                 switch (fix_unmerged_status(p, data)) {
84                 default:
85                         die(_("unexpected diff status %c"), p->status);
86                 case DIFF_STATUS_MODIFIED:
87                 case DIFF_STATUS_TYPE_CHANGED:
88                         if (add_file_to_index(&the_index, path, data->flags)) {
89                                 if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
90                                         die(_("updating files failed"));
91                                 data->add_errors++;
92                         }
93                         break;
94                 case DIFF_STATUS_DELETED:
95                         if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
96                                 break;
97                         if (!(data->flags & ADD_CACHE_PRETEND))
98                                 remove_file_from_index(&the_index, path);
99                         if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
100                                 printf(_("remove '%s'\n"), path);
101                         break;
102                 }
103         }
104 }
105
106 int add_files_to_cache(const char *prefix,
107                        const struct pathspec *pathspec, int flags)
108 {
109         struct update_callback_data data;
110         struct rev_info rev;
111
112         memset(&data, 0, sizeof(data));
113         data.flags = flags;
114
115         repo_init_revisions(the_repository, &rev, prefix);
116         setup_revisions(0, NULL, &rev, NULL);
117         if (pathspec)
118                 copy_pathspec(&rev.prune_data, pathspec);
119         rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
120         rev.diffopt.format_callback = update_callback;
121         rev.diffopt.format_callback_data = &data;
122         rev.diffopt.flags.override_submodule_config = 1;
123         rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
124         run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
125         clear_pathspec(&rev.prune_data);
126         return !!data.add_errors;
127 }
128
129 static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
130 {
131         int i, retval = 0;
132
133         for (i = 0; i < active_nr; i++) {
134                 struct cache_entry *ce = active_cache[i];
135
136                 if (ce_stage(ce))
137                         continue; /* do not touch unmerged paths */
138                 if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
139                         continue; /* do not touch non blobs */
140                 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
141                         continue;
142                 retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE);
143         }
144
145         return retval;
146 }
147
148 static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
149 {
150         char *seen;
151         int i;
152         struct dir_entry **src, **dst;
153
154         seen = xcalloc(pathspec->nr, 1);
155
156         src = dst = dir->entries;
157         i = dir->nr;
158         while (--i >= 0) {
159                 struct dir_entry *entry = *src++;
160                 if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
161                         *dst++ = entry;
162         }
163         dir->nr = dst - dir->entries;
164         add_pathspec_matches_against_index(pathspec, &the_index, seen);
165         return seen;
166 }
167
168 static void refresh(int verbose, const struct pathspec *pathspec)
169 {
170         char *seen;
171         int i;
172
173         seen = xcalloc(pathspec->nr, 1);
174         refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
175                       pathspec, seen, _("Unstaged changes after refreshing the index:"));
176         for (i = 0; i < pathspec->nr; i++) {
177                 if (!seen[i])
178                         die(_("pathspec '%s' did not match any files"),
179                             pathspec->items[i].match);
180         }
181         free(seen);
182 }
183
184 int run_add_interactive(const char *revision, const char *patch_mode,
185                         const struct pathspec *pathspec)
186 {
187         int status, i;
188         struct argv_array argv = ARGV_ARRAY_INIT;
189         int use_builtin_add_i =
190                 git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1);
191
192         if (use_builtin_add_i < 0)
193                 git_config_get_bool("add.interactive.usebuiltin",
194                                     &use_builtin_add_i);
195
196         if (use_builtin_add_i == 1) {
197                 enum add_p_mode mode;
198
199                 if (!patch_mode)
200                         return !!run_add_i(the_repository, pathspec);
201
202                 if (!strcmp(patch_mode, "--patch"))
203                         mode = ADD_P_ADD;
204                 else if (!strcmp(patch_mode, "--patch=stash"))
205                         mode = ADD_P_STASH;
206                 else if (!strcmp(patch_mode, "--patch=reset"))
207                         mode = ADD_P_RESET;
208                 else
209                         die("'%s' not yet supported in the built-in add -p",
210                             patch_mode);
211
212                 return !!run_add_p(the_repository, mode, revision, pathspec);
213         }
214
215         argv_array_push(&argv, "add--interactive");
216         if (patch_mode)
217                 argv_array_push(&argv, patch_mode);
218         if (revision)
219                 argv_array_push(&argv, revision);
220         argv_array_push(&argv, "--");
221         for (i = 0; i < pathspec->nr; i++)
222                 /* pass original pathspec, to be re-parsed */
223                 argv_array_push(&argv, pathspec->items[i].original);
224
225         status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
226         argv_array_clear(&argv);
227         return status;
228 }
229
230 int interactive_add(int argc, const char **argv, const char *prefix, int patch)
231 {
232         struct pathspec pathspec;
233
234         parse_pathspec(&pathspec, 0,
235                        PATHSPEC_PREFER_FULL |
236                        PATHSPEC_SYMLINK_LEADING_PATH |
237                        PATHSPEC_PREFIX_ORIGIN,
238                        prefix, argv);
239
240         return run_add_interactive(NULL,
241                                    patch ? "--patch" : NULL,
242                                    &pathspec);
243 }
244
245 static int edit_patch(int argc, const char **argv, const char *prefix)
246 {
247         char *file = git_pathdup("ADD_EDIT.patch");
248         const char *apply_argv[] = { "apply", "--recount", "--cached",
249                 NULL, NULL };
250         struct child_process child = CHILD_PROCESS_INIT;
251         struct rev_info rev;
252         int out;
253         struct stat st;
254
255         apply_argv[3] = file;
256
257         git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
258
259         if (read_cache() < 0)
260                 die(_("Could not read the index"));
261
262         repo_init_revisions(the_repository, &rev, prefix);
263         rev.diffopt.context = 7;
264
265         argc = setup_revisions(argc, argv, &rev, NULL);
266         rev.diffopt.output_format = DIFF_FORMAT_PATCH;
267         rev.diffopt.use_color = 0;
268         rev.diffopt.flags.ignore_dirty_submodules = 1;
269         out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
270         if (out < 0)
271                 die(_("Could not open '%s' for writing."), file);
272         rev.diffopt.file = xfdopen(out, "w");
273         rev.diffopt.close_file = 1;
274         if (run_diff_files(&rev, 0))
275                 die(_("Could not write patch"));
276
277         if (launch_editor(file, NULL, NULL))
278                 die(_("editing patch failed"));
279
280         if (stat(file, &st))
281                 die_errno(_("Could not stat '%s'"), file);
282         if (!st.st_size)
283                 die(_("Empty patch. Aborted."));
284
285         child.git_cmd = 1;
286         child.argv = apply_argv;
287         if (run_command(&child))
288                 die(_("Could not apply '%s'"), file);
289
290         unlink(file);
291         free(file);
292         return 0;
293 }
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 static int warn_on_embedded_repo = 1;
301
302 #define ADDREMOVE_DEFAULT 1
303 static int addremove = ADDREMOVE_DEFAULT;
304 static int addremove_explicit = -1; /* unspecified */
305
306 static char *chmod_arg;
307
308 static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
309 {
310         /* if we are told to ignore, we are not adding removals */
311         *(int *)opt->value = !unset ? 0 : 1;
312         return 0;
313 }
314
315 static struct option builtin_add_options[] = {
316         OPT__DRY_RUN(&show_only, N_("dry run")),
317         OPT__VERBOSE(&verbose, N_("be verbose")),
318         OPT_GROUP(""),
319         OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
320         OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
321         OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
322         OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
323         OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
324         OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
325         OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
326         OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
327         { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
328           NULL /* takes no arguments */,
329           N_("ignore paths removed in the working tree (same as --no-all)"),
330           PARSE_OPT_NOARG, ignore_removal_cb },
331         OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
332         OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
333         OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
334         OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
335                    N_("override the executable bit of the listed files")),
336         OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
337                         N_("warn when adding an embedded repository")),
338         OPT_END(),
339 };
340
341 static int add_config(const char *var, const char *value, void *cb)
342 {
343         if (!strcmp(var, "add.ignoreerrors") ||
344             !strcmp(var, "add.ignore-errors")) {
345                 ignore_add_errors = git_config_bool(var, value);
346                 return 0;
347         }
348
349         return git_default_config(var, value, cb);
350 }
351
352 static const char embedded_advice[] = N_(
353 "You've added another git repository inside your current repository.\n"
354 "Clones of the outer repository will not contain the contents of\n"
355 "the embedded repository and will not know how to obtain it.\n"
356 "If you meant to add a submodule, use:\n"
357 "\n"
358 "       git submodule add <url> %s\n"
359 "\n"
360 "If you added this path by mistake, you can remove it from the\n"
361 "index with:\n"
362 "\n"
363 "       git rm --cached %s\n"
364 "\n"
365 "See \"git help submodule\" for more information."
366 );
367
368 static void check_embedded_repo(const char *path)
369 {
370         struct strbuf name = STRBUF_INIT;
371
372         if (!warn_on_embedded_repo)
373                 return;
374         if (!ends_with(path, "/"))
375                 return;
376
377         /* Drop trailing slash for aesthetics */
378         strbuf_addstr(&name, path);
379         strbuf_strip_suffix(&name, "/");
380
381         warning(_("adding embedded git repository: %s"), name.buf);
382         if (advice_add_embedded_repo) {
383                 advise(embedded_advice, name.buf, name.buf);
384                 /* there may be multiple entries; advise only once */
385                 advice_add_embedded_repo = 0;
386         }
387
388         strbuf_release(&name);
389 }
390
391 static int add_files(struct dir_struct *dir, int flags)
392 {
393         int i, exit_status = 0;
394
395         if (dir->ignored_nr) {
396                 fprintf(stderr, _(ignore_error));
397                 for (i = 0; i < dir->ignored_nr; i++)
398                         fprintf(stderr, "%s\n", dir->ignored[i]->name);
399                 fprintf(stderr, _("Use -f if you really want to add them.\n"));
400                 exit_status = 1;
401         }
402
403         for (i = 0; i < dir->nr; i++) {
404                 if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
405                         if (!ignore_add_errors)
406                                 die(_("adding files failed"));
407                         exit_status = 1;
408                 } else {
409                         check_embedded_repo(dir->entries[i]->name);
410                 }
411         }
412         return exit_status;
413 }
414
415 int cmd_add(int argc, const char **argv, const char *prefix)
416 {
417         int exit_status = 0;
418         struct pathspec pathspec;
419         struct dir_struct dir;
420         int flags;
421         int add_new_files;
422         int require_pathspec;
423         char *seen = NULL;
424         struct lock_file lock_file = LOCK_INIT;
425
426         git_config(add_config, NULL);
427
428         argc = parse_options(argc, argv, prefix, builtin_add_options,
429                           builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
430         if (patch_interactive)
431                 add_interactive = 1;
432         if (add_interactive)
433                 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
434
435         if (edit_interactive)
436                 return(edit_patch(argc, argv, prefix));
437         argc--;
438         argv++;
439
440         if (0 <= addremove_explicit)
441                 addremove = addremove_explicit;
442         else if (take_worktree_changes && ADDREMOVE_DEFAULT)
443                 addremove = 0; /* "-u" was given but not "-A" */
444
445         if (addremove && take_worktree_changes)
446                 die(_("-A and -u are mutually incompatible"));
447
448         if (!take_worktree_changes && addremove_explicit < 0 && argc)
449                 /* Turn "git add pathspec..." to "git add -A pathspec..." */
450                 addremove = 1;
451
452         if (!show_only && ignore_missing)
453                 die(_("Option --ignore-missing can only be used together with --dry-run"));
454
455         if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
456                           chmod_arg[1] != 'x' || chmod_arg[2]))
457                 die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
458
459         add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
460         require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
461
462         hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
463
464         flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
465                  (show_only ? ADD_CACHE_PRETEND : 0) |
466                  (intent_to_add ? ADD_CACHE_INTENT : 0) |
467                  (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
468                  (!(addremove || take_worktree_changes)
469                   ? ADD_CACHE_IGNORE_REMOVAL : 0));
470
471         if (require_pathspec && argc == 0) {
472                 fprintf(stderr, _("Nothing specified, nothing added.\n"));
473                 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
474                 return 0;
475         }
476
477         /*
478          * Check the "pathspec '%s' did not match any files" block
479          * below before enabling new magic.
480          */
481         parse_pathspec(&pathspec, PATHSPEC_ATTR,
482                        PATHSPEC_PREFER_FULL |
483                        PATHSPEC_SYMLINK_LEADING_PATH,
484                        prefix, argv);
485
486         if (read_cache_preload(&pathspec) < 0)
487                 die(_("index file corrupt"));
488
489         die_in_unpopulated_submodule(&the_index, prefix);
490         die_path_inside_submodule(&the_index, &pathspec);
491
492         if (add_new_files) {
493                 int baselen;
494
495                 /* Set up the default git porcelain excludes */
496                 memset(&dir, 0, sizeof(dir));
497                 if (!ignored_too) {
498                         dir.flags |= DIR_COLLECT_IGNORED;
499                         setup_standard_excludes(&dir);
500                 }
501
502                 /* This picks up the paths that are not tracked */
503                 baselen = fill_directory(&dir, &the_index, &pathspec);
504                 if (pathspec.nr)
505                         seen = prune_directory(&dir, &pathspec, baselen);
506         }
507
508         if (refresh_only) {
509                 refresh(verbose, &pathspec);
510                 goto finish;
511         }
512
513         if (pathspec.nr) {
514                 int i;
515
516                 if (!seen)
517                         seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
518
519                 /*
520                  * file_exists() assumes exact match
521                  */
522                 GUARD_PATHSPEC(&pathspec,
523                                PATHSPEC_FROMTOP |
524                                PATHSPEC_LITERAL |
525                                PATHSPEC_GLOB |
526                                PATHSPEC_ICASE |
527                                PATHSPEC_EXCLUDE);
528
529                 for (i = 0; i < pathspec.nr; i++) {
530                         const char *path = pathspec.items[i].match;
531                         if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
532                                 continue;
533                         if (!seen[i] && path[0] &&
534                             ((pathspec.items[i].magic &
535                               (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
536                              !file_exists(path))) {
537                                 if (ignore_missing) {
538                                         int dtype = DT_UNKNOWN;
539                                         if (is_excluded(&dir, &the_index, path, &dtype))
540                                                 dir_add_ignored(&dir, &the_index,
541                                                                 path, pathspec.items[i].len);
542                                 } else
543                                         die(_("pathspec '%s' did not match any files"),
544                                             pathspec.items[i].original);
545                         }
546                 }
547                 free(seen);
548         }
549
550         plug_bulk_checkin();
551
552         if (add_renormalize)
553                 exit_status |= renormalize_tracked_files(&pathspec, flags);
554         else
555                 exit_status |= add_files_to_cache(prefix, &pathspec, flags);
556
557         if (add_new_files)
558                 exit_status |= add_files(&dir, flags);
559
560         if (chmod_arg && pathspec.nr)
561                 chmod_pathspec(&pathspec, chmod_arg[0]);
562         unplug_bulk_checkin();
563
564 finish:
565         if (write_locked_index(&the_index, &lock_file,
566                                COMMIT_LOCK | SKIP_IF_UNCHANGED))
567                 die(_("Unable to write new index file"));
568
569         UNLEAK(pathspec);
570         UNLEAK(dir);
571         return exit_status;
572 }