built-in add -p: coalesce hunks after splitting them
[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                 if (!patch_mode)
198                         return !!run_add_i(the_repository, pathspec);
199                 if (strcmp(patch_mode, "--patch"))
200                         die("'%s' not yet supported in the built-in add -p",
201                             patch_mode);
202                 return !!run_add_p(the_repository, pathspec);
203         }
204
205         argv_array_push(&argv, "add--interactive");
206         if (patch_mode)
207                 argv_array_push(&argv, patch_mode);
208         if (revision)
209                 argv_array_push(&argv, revision);
210         argv_array_push(&argv, "--");
211         for (i = 0; i < pathspec->nr; i++)
212                 /* pass original pathspec, to be re-parsed */
213                 argv_array_push(&argv, pathspec->items[i].original);
214
215         status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
216         argv_array_clear(&argv);
217         return status;
218 }
219
220 int interactive_add(int argc, const char **argv, const char *prefix, int patch)
221 {
222         struct pathspec pathspec;
223
224         parse_pathspec(&pathspec, 0,
225                        PATHSPEC_PREFER_FULL |
226                        PATHSPEC_SYMLINK_LEADING_PATH |
227                        PATHSPEC_PREFIX_ORIGIN,
228                        prefix, argv);
229
230         return run_add_interactive(NULL,
231                                    patch ? "--patch" : NULL,
232                                    &pathspec);
233 }
234
235 static int edit_patch(int argc, const char **argv, const char *prefix)
236 {
237         char *file = git_pathdup("ADD_EDIT.patch");
238         const char *apply_argv[] = { "apply", "--recount", "--cached",
239                 NULL, NULL };
240         struct child_process child = CHILD_PROCESS_INIT;
241         struct rev_info rev;
242         int out;
243         struct stat st;
244
245         apply_argv[3] = file;
246
247         git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
248
249         if (read_cache() < 0)
250                 die(_("Could not read the index"));
251
252         repo_init_revisions(the_repository, &rev, prefix);
253         rev.diffopt.context = 7;
254
255         argc = setup_revisions(argc, argv, &rev, NULL);
256         rev.diffopt.output_format = DIFF_FORMAT_PATCH;
257         rev.diffopt.use_color = 0;
258         rev.diffopt.flags.ignore_dirty_submodules = 1;
259         out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
260         if (out < 0)
261                 die(_("Could not open '%s' for writing."), file);
262         rev.diffopt.file = xfdopen(out, "w");
263         rev.diffopt.close_file = 1;
264         if (run_diff_files(&rev, 0))
265                 die(_("Could not write patch"));
266
267         if (launch_editor(file, NULL, NULL))
268                 die(_("editing patch failed"));
269
270         if (stat(file, &st))
271                 die_errno(_("Could not stat '%s'"), file);
272         if (!st.st_size)
273                 die(_("Empty patch. Aborted."));
274
275         child.git_cmd = 1;
276         child.argv = apply_argv;
277         if (run_command(&child))
278                 die(_("Could not apply '%s'"), file);
279
280         unlink(file);
281         free(file);
282         return 0;
283 }
284
285 static const char ignore_error[] =
286 N_("The following paths are ignored by one of your .gitignore files:\n");
287
288 static int verbose, show_only, ignored_too, refresh_only;
289 static int ignore_add_errors, intent_to_add, ignore_missing;
290 static int warn_on_embedded_repo = 1;
291
292 #define ADDREMOVE_DEFAULT 1
293 static int addremove = ADDREMOVE_DEFAULT;
294 static int addremove_explicit = -1; /* unspecified */
295
296 static char *chmod_arg;
297
298 static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
299 {
300         /* if we are told to ignore, we are not adding removals */
301         *(int *)opt->value = !unset ? 0 : 1;
302         return 0;
303 }
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"), 0),
313         OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
314         OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
315         OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
316         OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
317         { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
318           NULL /* takes no arguments */,
319           N_("ignore paths removed in the working tree (same as --no-all)"),
320           PARSE_OPT_NOARG, ignore_removal_cb },
321         OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
322         OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
323         OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
324         OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
325                    N_("override the executable bit of the listed files")),
326         OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
327                         N_("warn when adding an embedded repository")),
328         OPT_END(),
329 };
330
331 static int add_config(const char *var, const char *value, void *cb)
332 {
333         if (!strcmp(var, "add.ignoreerrors") ||
334             !strcmp(var, "add.ignore-errors")) {
335                 ignore_add_errors = git_config_bool(var, value);
336                 return 0;
337         }
338
339         return git_default_config(var, value, cb);
340 }
341
342 static const char embedded_advice[] = N_(
343 "You've added another git repository inside your current repository.\n"
344 "Clones of the outer repository will not contain the contents of\n"
345 "the embedded repository and will not know how to obtain it.\n"
346 "If you meant to add a submodule, use:\n"
347 "\n"
348 "       git submodule add <url> %s\n"
349 "\n"
350 "If you added this path by mistake, you can remove it from the\n"
351 "index with:\n"
352 "\n"
353 "       git rm --cached %s\n"
354 "\n"
355 "See \"git help submodule\" for more information."
356 );
357
358 static void check_embedded_repo(const char *path)
359 {
360         struct strbuf name = STRBUF_INIT;
361
362         if (!warn_on_embedded_repo)
363                 return;
364         if (!ends_with(path, "/"))
365                 return;
366
367         /* Drop trailing slash for aesthetics */
368         strbuf_addstr(&name, path);
369         strbuf_strip_suffix(&name, "/");
370
371         warning(_("adding embedded git repository: %s"), name.buf);
372         if (advice_add_embedded_repo) {
373                 advise(embedded_advice, name.buf, name.buf);
374                 /* there may be multiple entries; advise only once */
375                 advice_add_embedded_repo = 0;
376         }
377
378         strbuf_release(&name);
379 }
380
381 static int add_files(struct dir_struct *dir, int flags)
382 {
383         int i, exit_status = 0;
384
385         if (dir->ignored_nr) {
386                 fprintf(stderr, _(ignore_error));
387                 for (i = 0; i < dir->ignored_nr; i++)
388                         fprintf(stderr, "%s\n", dir->ignored[i]->name);
389                 fprintf(stderr, _("Use -f if you really want to add them.\n"));
390                 exit_status = 1;
391         }
392
393         for (i = 0; i < dir->nr; i++) {
394                 if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
395                         if (!ignore_add_errors)
396                                 die(_("adding files failed"));
397                         exit_status = 1;
398                 } else {
399                         check_embedded_repo(dir->entries[i]->name);
400                 }
401         }
402         return exit_status;
403 }
404
405 int cmd_add(int argc, const char **argv, const char *prefix)
406 {
407         int exit_status = 0;
408         struct pathspec pathspec;
409         struct dir_struct dir;
410         int flags;
411         int add_new_files;
412         int require_pathspec;
413         char *seen = NULL;
414         struct lock_file lock_file = LOCK_INIT;
415
416         git_config(add_config, NULL);
417
418         argc = parse_options(argc, argv, prefix, builtin_add_options,
419                           builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
420         if (patch_interactive)
421                 add_interactive = 1;
422         if (add_interactive)
423                 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
424
425         if (edit_interactive)
426                 return(edit_patch(argc, argv, prefix));
427         argc--;
428         argv++;
429
430         if (0 <= addremove_explicit)
431                 addremove = addremove_explicit;
432         else if (take_worktree_changes && ADDREMOVE_DEFAULT)
433                 addremove = 0; /* "-u" was given but not "-A" */
434
435         if (addremove && take_worktree_changes)
436                 die(_("-A and -u are mutually incompatible"));
437
438         if (!take_worktree_changes && addremove_explicit < 0 && argc)
439                 /* Turn "git add pathspec..." to "git add -A pathspec..." */
440                 addremove = 1;
441
442         if (!show_only && ignore_missing)
443                 die(_("Option --ignore-missing can only be used together with --dry-run"));
444
445         if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
446                           chmod_arg[1] != 'x' || chmod_arg[2]))
447                 die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
448
449         add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
450         require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
451
452         hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
453
454         flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
455                  (show_only ? ADD_CACHE_PRETEND : 0) |
456                  (intent_to_add ? ADD_CACHE_INTENT : 0) |
457                  (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
458                  (!(addremove || take_worktree_changes)
459                   ? ADD_CACHE_IGNORE_REMOVAL : 0));
460
461         if (require_pathspec && argc == 0) {
462                 fprintf(stderr, _("Nothing specified, nothing added.\n"));
463                 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
464                 return 0;
465         }
466
467         /*
468          * Check the "pathspec '%s' did not match any files" block
469          * below before enabling new magic.
470          */
471         parse_pathspec(&pathspec, PATHSPEC_ATTR,
472                        PATHSPEC_PREFER_FULL |
473                        PATHSPEC_SYMLINK_LEADING_PATH,
474                        prefix, argv);
475
476         if (read_cache_preload(&pathspec) < 0)
477                 die(_("index file corrupt"));
478
479         die_in_unpopulated_submodule(&the_index, prefix);
480         die_path_inside_submodule(&the_index, &pathspec);
481
482         if (add_new_files) {
483                 int baselen;
484
485                 /* Set up the default git porcelain excludes */
486                 memset(&dir, 0, sizeof(dir));
487                 if (!ignored_too) {
488                         dir.flags |= DIR_COLLECT_IGNORED;
489                         setup_standard_excludes(&dir);
490                 }
491
492                 /* This picks up the paths that are not tracked */
493                 baselen = fill_directory(&dir, &the_index, &pathspec);
494                 if (pathspec.nr)
495                         seen = prune_directory(&dir, &pathspec, baselen);
496         }
497
498         if (refresh_only) {
499                 refresh(verbose, &pathspec);
500                 goto finish;
501         }
502
503         if (pathspec.nr) {
504                 int i;
505
506                 if (!seen)
507                         seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
508
509                 /*
510                  * file_exists() assumes exact match
511                  */
512                 GUARD_PATHSPEC(&pathspec,
513                                PATHSPEC_FROMTOP |
514                                PATHSPEC_LITERAL |
515                                PATHSPEC_GLOB |
516                                PATHSPEC_ICASE |
517                                PATHSPEC_EXCLUDE);
518
519                 for (i = 0; i < pathspec.nr; i++) {
520                         const char *path = pathspec.items[i].match;
521                         if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
522                                 continue;
523                         if (!seen[i] && path[0] &&
524                             ((pathspec.items[i].magic &
525                               (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
526                              !file_exists(path))) {
527                                 if (ignore_missing) {
528                                         int dtype = DT_UNKNOWN;
529                                         if (is_excluded(&dir, &the_index, path, &dtype))
530                                                 dir_add_ignored(&dir, &the_index,
531                                                                 path, pathspec.items[i].len);
532                                 } else
533                                         die(_("pathspec '%s' did not match any files"),
534                                             pathspec.items[i].original);
535                         }
536                 }
537                 free(seen);
538         }
539
540         plug_bulk_checkin();
541
542         if (add_renormalize)
543                 exit_status |= renormalize_tracked_files(&pathspec, flags);
544         else
545                 exit_status |= add_files_to_cache(prefix, &pathspec, flags);
546
547         if (add_new_files)
548                 exit_status |= add_files(&dir, flags);
549
550         if (chmod_arg && pathspec.nr)
551                 chmod_pathspec(&pathspec, chmod_arg[0]);
552         unplug_bulk_checkin();
553
554 finish:
555         if (write_locked_index(&the_index, &lock_file,
556                                COMMIT_LOCK | SKIP_IF_UNCHANGED))
557                 die(_("Unable to write new index file"));
558
559         UNLEAK(pathspec);
560         UNLEAK(dir);
561         return exit_status;
562 }