blob: db2dfa43502d0059219189f01731e143982345ab [file] [log] [blame]
Linus Torvalds0d781532006-05-17 09:33:32 -07001/*
2 * "git add" builtin command
3 *
4 * Copyright (C) 2006 Linus Torvalds
5 */
Nguyễn Thái Ngọc Duyf8adbec2019-01-24 15:29:12 +07006#define USE_THE_INDEX_COMPATIBILITY_MACROS
Linus Torvalds0d781532006-05-17 09:33:32 -07007#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07008#include "config.h"
Linus Torvalds0d781532006-05-17 09:33:32 -07009#include "builtin.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +020010#include "lockfile.h"
Linus Torvalds0d781532006-05-17 09:33:32 -070011#include "dir.h"
Adam Spiers6f525e72013-01-06 16:58:08 +000012#include "pathspec.h"
Stefan Bellerd807c4a2018-04-10 14:26:18 -070013#include "exec-cmd.h"
Junio C Hamano93872e02006-05-20 01:28:49 -070014#include "cache-tree.h"
Kristian Høgsberg58680162007-09-17 20:06:44 -040015#include "run-command.h"
Kristian Høgsberg5c46f752007-10-03 17:45:02 -040016#include "parse-options.h"
Johannes Schindelinc59cb032009-04-08 23:30:24 +020017#include "diff.h"
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080018#include "diffcore.h"
Johannes Schindelinc59cb032009-04-08 23:30:24 +020019#include "revision.h"
Junio C Hamano568508e2011-10-28 14:48:40 -070020#include "bulk-checkin.h"
Fabian Ruchc45a18e2014-03-15 12:14:40 +010021#include "argv-array.h"
Brandon Williamsbdab9722017-05-09 12:17:59 -070022#include "submodule.h"
Linus Torvalds0d781532006-05-17 09:33:32 -070023
Kristian Høgsberg5c46f752007-10-03 17:45:02 -040024static const char * const builtin_add_usage[] = {
Alex Henrie9c9b4f22015-01-13 00:44:47 -070025 N_("git add [<options>] [--] <pathspec>..."),
Kristian Høgsberg5c46f752007-10-03 17:45:02 -040026 NULL
27};
Johannes Schindelinc59cb032009-04-08 23:30:24 +020028static int patch_interactive, add_interactive, edit_interactive;
Jeff King93c44d42007-05-12 02:42:00 -040029static int take_worktree_changes;
Torsten Bögershausen94729352017-11-16 17:38:28 +010030static int add_renormalize;
James Bowes896bdfa2007-02-27 22:31:10 -050031
Jonathan Nieder9cba13c2011-03-16 02:08:34 -050032struct update_callback_data {
Thomas Gummerer610d55a2016-09-14 22:07:47 +010033 int flags;
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080034 int add_errors;
35};
36
Ramsay Jones1e22a992017-08-09 01:51:23 +010037static void chmod_pathspec(struct pathspec *pathspec, char flip)
Thomas Gummerer610d55a2016-09-14 22:07:47 +010038{
39 int i;
40
41 for (i = 0; i < active_nr; i++) {
42 struct cache_entry *ce = active_cache[i];
43
Nguyễn Thái Ngọc Duy6d2df282018-08-13 18:14:22 +020044 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
Thomas Gummerer610d55a2016-09-14 22:07:47 +010045 continue;
46
Ramsay Jones1e22a992017-08-09 01:51:23 +010047 if (chmod_cache_entry(ce, flip) < 0)
48 fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
Thomas Gummerer610d55a2016-09-14 22:07:47 +010049 }
50}
51
Junio C Hamano75973b22011-04-20 18:11:19 -070052static int fix_unmerged_status(struct diff_filepair *p,
53 struct update_callback_data *data)
54{
55 if (p->status != DIFF_STATUS_UNMERGED)
56 return p->status;
57 if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
58 /*
59 * This is not an explicit add request, and the
60 * path is missing from the working tree (deleted)
61 */
62 return DIFF_STATUS_DELETED;
63 else
64 /*
65 * Either an explicit add request, or path exists
66 * in the working tree. An attempt to explicitly
67 * add a path that does not exist in the working tree
68 * will be caught as an error by the caller immediately.
69 */
70 return DIFF_STATUS_MODIFIED;
71}
72
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080073static void update_callback(struct diff_queue_struct *q,
74 struct diff_options *opt, void *cbdata)
75{
76 int i;
77 struct update_callback_data *data = cbdata;
78
79 for (i = 0; i < q->nr; i++) {
80 struct diff_filepair *p = q->queue[i];
81 const char *path = p->one->path;
Junio C Hamano75973b22011-04-20 18:11:19 -070082 switch (fix_unmerged_status(p, data)) {
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080083 default:
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +000084 die(_("unexpected diff status %c"), p->status);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080085 case DIFF_STATUS_MODIFIED:
86 case DIFF_STATUS_TYPE_CHANGED:
Thomas Gummerer610d55a2016-09-14 22:07:47 +010087 if (add_file_to_index(&the_index, path, data->flags)) {
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080088 if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +000089 die(_("updating files failed"));
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080090 data->add_errors++;
91 }
92 break;
93 case DIFF_STATUS_DELETED:
94 if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
95 break;
96 if (!(data->flags & ADD_CACHE_PRETEND))
97 remove_file_from_index(&the_index, path);
98 if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
Ævar Arnfjörð Bjarmason475c73e2011-02-22 23:41:32 +000099 printf(_("remove '%s'\n"), path);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800100 break;
101 }
102 }
103}
104
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100105int add_files_to_cache(const char *prefix,
106 const struct pathspec *pathspec, int flags)
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800107{
Junio C Hamanod226b142013-04-17 12:32:21 -0700108 struct update_callback_data data;
Jonathan Nieder71c7b052013-03-19 15:50:50 -0700109 struct rev_info rev;
110
Junio C Hamanod226b142013-04-17 12:32:21 -0700111 memset(&data, 0, sizeof(data));
112 data.flags = flags;
Junio C Hamano160c4b12014-03-07 15:14:47 -0800113
Nguyễn Thái Ngọc Duy2abf3502018-09-21 17:57:38 +0200114 repo_init_revisions(the_repository, &rev, prefix);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800115 setup_revisions(0, NULL, &rev, NULL);
Nguyễn Thái Ngọc Duy3efe8e42013-07-14 15:35:56 +0700116 if (pathspec)
117 copy_pathspec(&rev.prune_data, pathspec);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800118 rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
119 rev.diffopt.format_callback = update_callback;
Junio C Hamano160c4b12014-03-07 15:14:47 -0800120 rev.diffopt.format_callback_data = &data;
Brandon Williams0d1e0e72017-10-31 11:19:11 -0700121 rev.diffopt.flags.override_submodule_config = 1;
Junio C Hamano75973b22011-04-20 18:11:19 -0700122 rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800123 run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
Jeff Kingfe6a01a2017-09-05 09:04:10 -0400124 clear_pathspec(&rev.prune_data);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800125 return !!data.add_errors;
126}
127
Torsten Bögershausen94729352017-11-16 17:38:28 +0100128static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
129{
130 int i, retval = 0;
131
132 for (i = 0; i < active_nr; i++) {
133 struct cache_entry *ce = active_cache[i];
134
135 if (ce_stage(ce))
136 continue; /* do not touch unmerged paths */
137 if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
138 continue; /* do not touch non blobs */
Nguyễn Thái Ngọc Duy6d2df282018-08-13 18:14:22 +0200139 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
Torsten Bögershausen94729352017-11-16 17:38:28 +0100140 continue;
Jeff King9e5da3d2019-01-17 11:27:11 -0500141 retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE);
Torsten Bögershausen94729352017-11-16 17:38:28 +0100142 }
143
144 return retval;
145}
146
Junio C Hamano053a6b12014-03-07 15:14:01 -0800147static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
Linus Torvalds0d781532006-05-17 09:33:32 -0700148{
Linus Torvaldsf2593392006-05-17 13:23:19 -0700149 char *seen;
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700150 int i;
Linus Torvalds0d781532006-05-17 09:33:32 -0700151 struct dir_entry **src, **dst;
152
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700153 seen = xcalloc(pathspec->nr, 1);
Linus Torvaldsf2593392006-05-17 13:23:19 -0700154
Linus Torvalds0d781532006-05-17 09:33:32 -0700155 src = dst = dir->entries;
156 i = dir->nr;
157 while (--i >= 0) {
158 struct dir_entry *entry = *src++;
Nguyễn Thái Ngọc Duy6d2df282018-08-13 18:14:22 +0200159 if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
Junio C Hamano4d06f8a2006-12-29 11:01:31 -0800160 *dst++ = entry;
Linus Torvalds0d781532006-05-17 09:33:32 -0700161 }
162 dir->nr = dst - dir->entries;
Brandon Williams08de9152017-05-11 15:04:27 -0700163 add_pathspec_matches_against_index(pathspec, &the_index, seen);
Junio C Hamano81f45e72010-02-09 17:30:49 -0500164 return seen;
Linus Torvalds0d781532006-05-17 09:33:32 -0700165}
166
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700167static void refresh(int verbose, const struct pathspec *pathspec)
Alexandre Julliardd6168132007-08-11 23:59:01 +0200168{
169 char *seen;
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700170 int i;
Alexandre Julliardd6168132007-08-11 23:59:01 +0200171
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700172 seen = xcalloc(pathspec->nr, 1);
Matthieu Moy43673fd2009-08-21 10:57:58 +0200173 refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
Ævar Arnfjörð Bjarmasoned2a8082011-02-22 23:41:33 +0000174 pathspec, seen, _("Unstaged changes after refreshing the index:"));
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700175 for (i = 0; i < pathspec->nr; i++) {
Alexandre Julliardd6168132007-08-11 23:59:01 +0200176 if (!seen[i])
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700177 die(_("pathspec '%s' did not match any files"),
178 pathspec->items[i].match);
Alexandre Julliardd6168132007-08-11 23:59:01 +0200179 }
Nguyễn Thái Ngọc Duyec36c422018-12-06 16:42:06 +0100180 free(seen);
Alexandre Julliardd6168132007-08-11 23:59:01 +0200181}
182
Thomas Rast46b51392009-08-13 14:29:41 +0200183int run_add_interactive(const char *revision, const char *patch_mode,
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700184 const struct pathspec *pathspec)
Thomas Rast46b51392009-08-13 14:29:41 +0200185{
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100186 int status, i;
187 struct argv_array argv = ARGV_ARRAY_INIT;
Thomas Rast46b51392009-08-13 14:29:41 +0200188
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100189 argv_array_push(&argv, "add--interactive");
Thomas Rast46b51392009-08-13 14:29:41 +0200190 if (patch_mode)
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100191 argv_array_push(&argv, patch_mode);
Thomas Rast46b51392009-08-13 14:29:41 +0200192 if (revision)
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100193 argv_array_push(&argv, revision);
194 argv_array_push(&argv, "--");
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700195 for (i = 0; i < pathspec->nr; i++)
196 /* pass original pathspec, to be re-parsed */
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100197 argv_array_push(&argv, pathspec->items[i].original);
Thomas Rast46b51392009-08-13 14:29:41 +0200198
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100199 status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
200 argv_array_clear(&argv);
Thomas Rast46b51392009-08-13 14:29:41 +0200201 return status;
202}
203
Conrad Irwinb4bd4662011-05-07 10:58:07 -0700204int interactive_add(int argc, const char **argv, const char *prefix, int patch)
Kristian Høgsberg58680162007-09-17 20:06:44 -0400205{
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700206 struct pathspec pathspec;
Junio C Hamano324ccbd2007-11-25 10:07:55 -0800207
Nguyễn Thái Ngọc Duy625c3302013-09-05 10:40:39 +0700208 parse_pathspec(&pathspec, 0,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700209 PATHSPEC_PREFER_FULL |
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700210 PATHSPEC_SYMLINK_LEADING_PATH |
211 PATHSPEC_PREFIX_ORIGIN,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700212 prefix, argv);
Junio C Hamano3f061882007-11-25 10:10:10 -0800213
Thomas Rast46b51392009-08-13 14:29:41 +0200214 return run_add_interactive(NULL,
Conrad Irwinb4bd4662011-05-07 10:58:07 -0700215 patch ? "--patch" : NULL,
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700216 &pathspec);
Kristian Høgsberg58680162007-09-17 20:06:44 -0400217}
218
Linus Torvalds2af202b2009-06-18 10:28:43 -0700219static int edit_patch(int argc, const char **argv, const char *prefix)
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200220{
Ramsay Jonesd292bfa2012-09-04 18:30:21 +0100221 char *file = git_pathdup("ADD_EDIT.patch");
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200222 const char *apply_argv[] = { "apply", "--recount", "--cached",
Gary V. Vaughan66dbfd52010-05-14 09:31:33 +0000223 NULL, NULL };
René Scharfed3180272014-08-19 21:09:35 +0200224 struct child_process child = CHILD_PROCESS_INIT;
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200225 struct rev_info rev;
226 int out;
227 struct stat st;
228
Gary V. Vaughan66dbfd52010-05-14 09:31:33 +0000229 apply_argv[3] = file;
230
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200231 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
232
233 if (read_cache() < 0)
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500234 die(_("Could not read the index"));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200235
Nguyễn Thái Ngọc Duy2abf3502018-09-21 17:57:38 +0200236 repo_init_revisions(the_repository, &rev, prefix);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200237 rev.diffopt.context = 7;
238
239 argc = setup_revisions(argc, argv, &rev, NULL);
240 rev.diffopt.output_format = DIFF_FORMAT_PATCH;
Andrew Wong7f3b8c62013-07-18 18:58:04 -0400241 rev.diffopt.use_color = 0;
Brandon Williams0d1e0e72017-10-31 11:19:11 -0700242 rev.diffopt.flags.ignore_dirty_submodules = 1;
Johannes Schindelinfa6f2252019-01-15 07:42:52 -0800243 out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200244 if (out < 0)
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500245 die(_("Could not open '%s' for writing."), file);
Jim Meyering41698372009-09-12 10:43:27 +0200246 rev.diffopt.file = xfdopen(out, "w");
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200247 rev.diffopt.close_file = 1;
248 if (run_diff_files(&rev, 0))
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500249 die(_("Could not write patch"));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200250
Jeff Kingcb648002015-05-12 21:21:58 -0400251 if (launch_editor(file, NULL, NULL))
252 die(_("editing patch failed"));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200253
254 if (stat(file, &st))
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000255 die_errno(_("Could not stat '%s'"), file);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200256 if (!st.st_size)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000257 die(_("Empty patch. Aborted."));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200258
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200259 child.git_cmd = 1;
260 child.argv = apply_argv;
261 if (run_command(&child))
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500262 die(_("Could not apply '%s'"), file);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200263
264 unlink(file);
Ramsay Jonesd292bfa2012-09-04 18:30:21 +0100265 free(file);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200266 return 0;
267}
268
Petr Baudisb39c53e2007-08-29 00:41:23 +0200269static const char ignore_error[] =
Ævar Arnfjörð Bjarmason439fb822011-02-22 23:41:30 +0000270N_("The following paths are ignored by one of your .gitignore files:\n");
Junio C Hamano6a1ad322006-12-25 17:46:38 -0800271
Junio C Hamano300c0a22013-03-08 22:21:13 -0800272static int verbose, show_only, ignored_too, refresh_only;
Junio C Hamano45c45e32011-04-19 12:18:20 -0700273static int ignore_add_errors, intent_to_add, ignore_missing;
Jeff King53213992017-06-14 06:58:22 -0400274static int warn_on_embedded_repo = 1;
Junio C Hamano45c45e32011-04-19 12:18:20 -0700275
Junio C Hamanofdc97ab2013-04-22 14:30:22 -0700276#define ADDREMOVE_DEFAULT 1
Junio C Hamano45c45e32011-04-19 12:18:20 -0700277static int addremove = ADDREMOVE_DEFAULT;
278static int addremove_explicit = -1; /* unspecified */
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400279
Edward Thomson4e55ed32016-05-31 17:08:18 -0500280static char *chmod_arg;
281
Junio C Hamano9f60f492013-04-22 13:29:20 -0700282static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
283{
284 /* if we are told to ignore, we are not adding removals */
285 *(int *)opt->value = !unset ? 0 : 1;
286 return 0;
287}
288
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400289static struct option builtin_add_options[] = {
Nguyễn Thái Ngọc Duy1b560242012-08-20 19:31:52 +0700290 OPT__DRY_RUN(&show_only, N_("dry run")),
291 OPT__VERBOSE(&verbose, N_("be verbose")),
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400292 OPT_GROUP(""),
Junio C Hamano300c0a22013-03-08 22:21:13 -0800293 OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
294 OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
295 OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
Nguyễn Thái Ngọc Duy12247812018-02-09 18:01:42 +0700296 OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
Junio C Hamano300c0a22013-03-08 22:21:13 -0800297 OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
Torsten Bögershausen94729352017-11-16 17:38:28 +0100298 OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
Junio C Hamano300c0a22013-03-08 22:21:13 -0800299 OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
Junio C Hamano45c45e32011-04-19 12:18:20 -0700300 OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
Junio C Hamano9f60f492013-04-22 13:29:20 -0700301 { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
302 NULL /* takes no arguments */,
303 N_("ignore paths removed in the working tree (same as --no-all)"),
304 PARSE_OPT_NOARG, ignore_removal_cb },
Junio C Hamano300c0a22013-03-08 22:21:13 -0800305 OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
306 OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
307 OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
René Scharfe5f0df442018-08-02 21:18:14 +0200308 OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
309 N_("override the executable bit of the listed files")),
Jeff King53213992017-06-14 06:58:22 -0400310 OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
311 N_("warn when adding an embedded repository")),
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400312 OPT_END(),
313};
314
Junio C Hamano9bd81e42008-05-25 14:25:02 -0700315static int add_config(const char *var, const char *value, void *cb)
Alex Riesendad25e42008-05-12 19:59:23 +0200316{
Jonathan Nieder8c2be752011-05-14 15:19:21 -0500317 if (!strcmp(var, "add.ignoreerrors") ||
318 !strcmp(var, "add.ignore-errors")) {
Alex Riesendad25e42008-05-12 19:59:23 +0200319 ignore_add_errors = git_config_bool(var, value);
320 return 0;
321 }
Junio C Hamano9bd81e42008-05-25 14:25:02 -0700322 return git_default_config(var, value, cb);
Alex Riesendad25e42008-05-12 19:59:23 +0200323}
324
Jeff King53213992017-06-14 06:58:22 -0400325static const char embedded_advice[] = N_(
326"You've added another git repository inside your current repository.\n"
327"Clones of the outer repository will not contain the contents of\n"
328"the embedded repository and will not know how to obtain it.\n"
329"If you meant to add a submodule, use:\n"
330"\n"
331" git submodule add <url> %s\n"
332"\n"
333"If you added this path by mistake, you can remove it from the\n"
334"index with:\n"
335"\n"
336" git rm --cached %s\n"
337"\n"
338"See \"git help submodule\" for more information."
339);
340
341static void check_embedded_repo(const char *path)
342{
343 struct strbuf name = STRBUF_INIT;
344
345 if (!warn_on_embedded_repo)
346 return;
347 if (!ends_with(path, "/"))
348 return;
349
350 /* Drop trailing slash for aesthetics */
351 strbuf_addstr(&name, path);
352 strbuf_strip_suffix(&name, "/");
353
354 warning(_("adding embedded git repository: %s"), name.buf);
355 if (advice_add_embedded_repo) {
356 advise(embedded_advice, name.buf, name.buf);
357 /* there may be multiple entries; advise only once */
358 advice_add_embedded_repo = 0;
359 }
360
361 strbuf_release(&name);
362}
363
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100364static int add_files(struct dir_struct *dir, int flags)
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700365{
366 int i, exit_status = 0;
367
368 if (dir->ignored_nr) {
Ævar Arnfjörð Bjarmason439fb822011-02-22 23:41:30 +0000369 fprintf(stderr, _(ignore_error));
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700370 for (i = 0; i < dir->ignored_nr; i++)
371 fprintf(stderr, "%s\n", dir->ignored[i]->name);
Ævar Arnfjörð Bjarmason439fb822011-02-22 23:41:30 +0000372 fprintf(stderr, _("Use -f if you really want to add them.\n"));
Michael J Gruber1d31e5a2014-11-21 17:08:19 +0100373 exit_status = 1;
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700374 }
375
Jeff King53213992017-06-14 06:58:22 -0400376 for (i = 0; i < dir->nr; i++) {
377 check_embedded_repo(dir->entries[i]->name);
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100378 if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700379 if (!ignore_add_errors)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000380 die(_("adding files failed"));
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700381 exit_status = 1;
382 }
Jeff King53213992017-06-14 06:58:22 -0400383 }
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700384 return exit_status;
385}
386
Linus Torvaldsa633fca2006-07-28 22:44:25 -0700387int cmd_add(int argc, const char **argv, const char *prefix)
Linus Torvalds0d781532006-05-17 09:33:32 -0700388{
Alex Riesen7ae02a32008-05-12 19:58:10 +0200389 int exit_status = 0;
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700390 struct pathspec pathspec;
Linus Torvalds0d781532006-05-17 09:33:32 -0700391 struct dir_struct dir;
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100392 int flags;
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700393 int add_new_files;
394 int require_pathspec;
Junio C Hamano81f45e72010-02-09 17:30:49 -0500395 char *seen = NULL;
Martin Ågren0fa5a2e2018-05-09 22:55:39 +0200396 struct lock_file lock_file = LOCK_INIT;
Junio C Hamano5cde71d2006-12-10 20:55:50 -0800397
Stephen Boyded342fd2009-06-18 02:17:54 -0700398 git_config(add_config, NULL);
399
Stephen Boyd37782922009-05-23 11:53:12 -0700400 argc = parse_options(argc, argv, prefix, builtin_add_options,
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200401 builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
Wincent Colaiutab63e9952007-11-25 14:15:42 +0100402 if (patch_interactive)
403 add_interactive = 1;
Wincent Colaiuta7c0ab442007-11-22 01:02:52 +0100404 if (add_interactive)
Conrad Irwinb4bd4662011-05-07 10:58:07 -0700405 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
Linus Torvalds0d781532006-05-17 09:33:32 -0700406
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200407 if (edit_interactive)
408 return(edit_patch(argc, argv, prefix));
409 argc--;
410 argv++;
411
Junio C Hamano45c45e32011-04-19 12:18:20 -0700412 if (0 <= addremove_explicit)
413 addremove = addremove_explicit;
414 else if (take_worktree_changes && ADDREMOVE_DEFAULT)
415 addremove = 0; /* "-u" was given but not "-A" */
416
Junio C Hamano3ba1f112008-07-19 19:51:11 -0700417 if (addremove && take_worktree_changes)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000418 die(_("-A and -u are mutually incompatible"));
Junio C Hamano45c45e32011-04-19 12:18:20 -0700419
Junio C Hamano45c45e32011-04-19 12:18:20 -0700420 if (!take_worktree_changes && addremove_explicit < 0 && argc)
Junio C Hamanofdc97ab2013-04-22 14:30:22 -0700421 /* Turn "git add pathspec..." to "git add -A pathspec..." */
422 addremove = 1;
Junio C Hamano45c45e32011-04-19 12:18:20 -0700423
Jens Lehmann108da0d2010-07-10 00:18:38 +0200424 if (!show_only && ignore_missing)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000425 die(_("Option --ignore-missing can only be used together with --dry-run"));
Junio C Hamano808d3d72013-03-19 15:53:17 -0700426
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100427 if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
428 chmod_arg[1] != 'x' || chmod_arg[2]))
Edward Thomson4e55ed32016-05-31 17:08:18 -0500429 die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
430
Torsten Bögershausen94729352017-11-16 17:38:28 +0100431 add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
Junio C Hamano29abb332015-10-24 19:31:11 -0700432 require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700433
Junio C Hamanob3e83cc2016-12-07 10:33:54 -0800434 hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
Linus Torvalds0d781532006-05-17 09:33:32 -0700435
Gustaf Hendeby205ffa92008-05-22 23:59:42 +0200436 flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
Junio C Hamano01665922008-05-25 14:03:50 -0700437 (show_only ? ADD_CACHE_PRETEND : 0) |
Junio C Hamano39425812008-08-21 01:44:53 -0700438 (intent_to_add ? ADD_CACHE_INTENT : 0) |
Junio C Hamano1e5f7642008-07-22 22:30:40 -0700439 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
440 (!(addremove || take_worktree_changes)
Junio C Hamano808d3d72013-03-19 15:53:17 -0700441 ? ADD_CACHE_IGNORE_REMOVAL : 0));
Gustaf Hendeby205ffa92008-05-22 23:59:42 +0200442
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700443 if (require_pathspec && argc == 0) {
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000444 fprintf(stderr, _("Nothing specified, nothing added.\n"));
445 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
Junio C Hamano93b0d862006-12-20 13:06:46 -0800446 return 0;
447 }
Linus Torvalds0d781532006-05-17 09:33:32 -0700448
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700449 /*
450 * Check the "pathspec '%s' did not match any files" block
451 * below before enabling new magic.
452 */
Nguyễn Thái Ngọc Duy84d938b2018-09-18 19:31:59 +0200453 parse_pathspec(&pathspec, PATHSPEC_ATTR,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700454 PATHSPEC_PREFER_FULL |
Brandon Williamsc08397e2017-05-11 15:04:24 -0700455 PATHSPEC_SYMLINK_LEADING_PATH,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700456 prefix, argv);
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700457
Ben Peartd1664e72018-11-02 09:30:50 -0400458 if (read_cache_preload(&pathspec) < 0)
459 die(_("index file corrupt"));
460
461 die_in_unpopulated_submodule(&the_index, prefix);
Brandon Williamsc08397e2017-05-11 15:04:24 -0700462 die_path_inside_submodule(&the_index, &pathspec);
463
Linus Torvalds1d8842d2009-05-14 13:22:36 -0700464 if (add_new_files) {
465 int baselen;
466
467 /* Set up the default git porcelain excludes */
468 memset(&dir, 0, sizeof(dir));
469 if (!ignored_too) {
470 dir.flags |= DIR_COLLECT_IGNORED;
471 setup_standard_excludes(&dir);
472 }
473
Junio C Hamano1e5f7642008-07-22 22:30:40 -0700474 /* This picks up the paths that are not tracked */
Brandon Williams0d32c182017-05-05 12:53:34 -0700475 baselen = fill_directory(&dir, &the_index, &pathspec);
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700476 if (pathspec.nr)
Junio C Hamano053a6b12014-03-07 15:14:01 -0800477 seen = prune_directory(&dir, &pathspec, baselen);
Linus Torvalds1d8842d2009-05-14 13:22:36 -0700478 }
Junio C Hamano1e5f7642008-07-22 22:30:40 -0700479
Alexandre Julliardd6168132007-08-11 23:59:01 +0200480 if (refresh_only) {
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700481 refresh(verbose, &pathspec);
Alexandre Julliardd6168132007-08-11 23:59:01 +0200482 goto finish;
483 }
484
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700485 if (pathspec.nr) {
Junio C Hamano81f45e72010-02-09 17:30:49 -0500486 int i;
Junio C Hamanoeb699342012-06-05 21:44:22 -0700487
Junio C Hamano81f45e72010-02-09 17:30:49 -0500488 if (!seen)
Brandon Williams08de9152017-05-11 15:04:27 -0700489 seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700490
491 /*
492 * file_exists() assumes exact match
493 */
Nguyễn Thái Ngọc Duybd30c2e2013-07-14 15:36:08 +0700494 GUARD_PATHSPEC(&pathspec,
495 PATHSPEC_FROMTOP |
496 PATHSPEC_LITERAL |
Nguyễn Thái Ngọc Duy93d93532013-07-14 15:36:09 +0700497 PATHSPEC_GLOB |
Nguyễn Thái Ngọc Duyef79b1f2013-12-06 14:30:48 +0700498 PATHSPEC_ICASE |
499 PATHSPEC_EXCLUDE);
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700500
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700501 for (i = 0; i < pathspec.nr; i++) {
502 const char *path = pathspec.items[i].match;
Nguyễn Thái Ngọc Duyef79b1f2013-12-06 14:30:48 +0700503 if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
504 continue;
Nguyễn Thái Ngọc Duy64ed07c2013-12-23 16:02:41 +0700505 if (!seen[i] && path[0] &&
Nguyễn Thái Ngọc Duy93d93532013-07-14 15:36:09 +0700506 ((pathspec.items[i].magic &
507 (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
Nguyễn Thái Ngọc Duybd30c2e2013-07-14 15:36:08 +0700508 !file_exists(path))) {
Jens Lehmann108da0d2010-07-10 00:18:38 +0200509 if (ignore_missing) {
Nguyễn Thái Ngọc Duy0188f6b2010-11-11 20:03:22 +0700510 int dtype = DT_UNKNOWN;
Brandon Williamsa0bba652017-05-05 12:53:30 -0700511 if (is_excluded(&dir, &the_index, path, &dtype))
Brandon Williams9e58bec2017-05-05 12:53:25 -0700512 dir_add_ignored(&dir, &the_index,
513 path, pathspec.items[i].len);
Jens Lehmann108da0d2010-07-10 00:18:38 +0200514 } else
Ævar Arnfjörð Bjarmason48168852011-02-22 23:41:31 +0000515 die(_("pathspec '%s' did not match any files"),
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700516 pathspec.items[i].original);
Jens Lehmann108da0d2010-07-10 00:18:38 +0200517 }
Junio C Hamano81f45e72010-02-09 17:30:49 -0500518 }
519 free(seen);
520 }
521
Junio C Hamano568508e2011-10-28 14:48:40 -0700522 plug_bulk_checkin();
523
Torsten Bögershausen94729352017-11-16 17:38:28 +0100524 if (add_renormalize)
525 exit_status |= renormalize_tracked_files(&pathspec, flags);
526 else
527 exit_status |= add_files_to_cache(prefix, &pathspec, flags);
Linus Torvalds0d781532006-05-17 09:33:32 -0700528
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700529 if (add_new_files)
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100530 exit_status |= add_files(&dir, flags);
Linus Torvalds0d781532006-05-17 09:33:32 -0700531
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100532 if (chmod_arg && pathspec.nr)
533 chmod_pathspec(&pathspec, chmod_arg[0]);
Junio C Hamano568508e2011-10-28 14:48:40 -0700534 unplug_bulk_checkin();
535
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500536finish:
Martin Ågren61000812018-03-01 21:40:20 +0100537 if (write_locked_index(&the_index, &lock_file,
538 COMMIT_LOCK | SKIP_IF_UNCHANGED))
539 die(_("Unable to write new index file"));
Linus Torvalds0d781532006-05-17 09:33:32 -0700540
Jeff King0e5bba52017-09-08 02:38:41 -0400541 UNLEAK(pathspec);
542 UNLEAK(dir);
Alex Riesen7ae02a32008-05-12 19:58:10 +0200543 return exit_status;
Linus Torvalds0d781532006-05-17 09:33:32 -0700544}