blob: f65c1722993b62e93feb85e506dffbc77b7ce921 [file] [log] [blame]
Linus Torvalds0d781532006-05-17 09:33:32 -07001/*
2 * "git add" builtin command
3 *
4 * Copyright (C) 2006 Linus Torvalds
5 */
Linus Torvalds0d781532006-05-17 09:33:32 -07006#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07007#include "config.h"
Linus Torvalds0d781532006-05-17 09:33:32 -07008#include "builtin.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +02009#include "lockfile.h"
Linus Torvalds0d781532006-05-17 09:33:32 -070010#include "dir.h"
Adam Spiers6f525e72013-01-06 16:58:08 +000011#include "pathspec.h"
Stefan Bellerd807c4a2018-04-10 14:26:18 -070012#include "exec-cmd.h"
Junio C Hamano93872e02006-05-20 01:28:49 -070013#include "cache-tree.h"
Kristian Høgsberg58680162007-09-17 20:06:44 -040014#include "run-command.h"
Kristian Høgsberg5c46f752007-10-03 17:45:02 -040015#include "parse-options.h"
Johannes Schindelinc59cb032009-04-08 23:30:24 +020016#include "diff.h"
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080017#include "diffcore.h"
Johannes Schindelinc59cb032009-04-08 23:30:24 +020018#include "revision.h"
Junio C Hamano568508e2011-10-28 14:48:40 -070019#include "bulk-checkin.h"
Fabian Ruchc45a18e2014-03-15 12:14:40 +010020#include "argv-array.h"
Brandon Williamsbdab9722017-05-09 12:17:59 -070021#include "submodule.h"
Linus Torvalds0d781532006-05-17 09:33:32 -070022
Kristian Høgsberg5c46f752007-10-03 17:45:02 -040023static const char * const builtin_add_usage[] = {
Alex Henrie9c9b4f22015-01-13 00:44:47 -070024 N_("git add [<options>] [--] <pathspec>..."),
Kristian Høgsberg5c46f752007-10-03 17:45:02 -040025 NULL
26};
Johannes Schindelinc59cb032009-04-08 23:30:24 +020027static int patch_interactive, add_interactive, edit_interactive;
Jeff King93c44d42007-05-12 02:42:00 -040028static int take_worktree_changes;
Torsten Bögershausen94729352017-11-16 17:38:28 +010029static int add_renormalize;
James Bowes896bdfa2007-02-27 22:31:10 -050030
Jonathan Nieder9cba13c2011-03-16 02:08:34 -050031struct update_callback_data {
Thomas Gummerer610d55a2016-09-14 22:07:47 +010032 int flags;
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080033 int add_errors;
34};
35
Ramsay Jones1e22a992017-08-09 01:51:23 +010036static void chmod_pathspec(struct pathspec *pathspec, char flip)
Thomas Gummerer610d55a2016-09-14 22:07:47 +010037{
38 int i;
39
40 for (i = 0; i < active_nr; i++) {
41 struct cache_entry *ce = active_cache[i];
42
Nguyễn Thái Ngọc Duy6d2df282018-08-13 18:14:22 +020043 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
Thomas Gummerer610d55a2016-09-14 22:07:47 +010044 continue;
45
Ramsay Jones1e22a992017-08-09 01:51:23 +010046 if (chmod_cache_entry(ce, flip) < 0)
47 fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
Thomas Gummerer610d55a2016-09-14 22:07:47 +010048 }
49}
50
Junio C Hamano75973b22011-04-20 18:11:19 -070051static int fix_unmerged_status(struct diff_filepair *p,
52 struct update_callback_data *data)
53{
54 if (p->status != DIFF_STATUS_UNMERGED)
55 return p->status;
56 if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
57 /*
58 * This is not an explicit add request, and the
59 * path is missing from the working tree (deleted)
60 */
61 return DIFF_STATUS_DELETED;
62 else
63 /*
64 * Either an explicit add request, or path exists
65 * in the working tree. An attempt to explicitly
66 * add a path that does not exist in the working tree
67 * will be caught as an error by the caller immediately.
68 */
69 return DIFF_STATUS_MODIFIED;
70}
71
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080072static void update_callback(struct diff_queue_struct *q,
73 struct diff_options *opt, void *cbdata)
74{
75 int i;
76 struct update_callback_data *data = cbdata;
77
78 for (i = 0; i < q->nr; i++) {
79 struct diff_filepair *p = q->queue[i];
80 const char *path = p->one->path;
Junio C Hamano75973b22011-04-20 18:11:19 -070081 switch (fix_unmerged_status(p, data)) {
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080082 default:
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +000083 die(_("unexpected diff status %c"), p->status);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080084 case DIFF_STATUS_MODIFIED:
85 case DIFF_STATUS_TYPE_CHANGED:
Thomas Gummerer610d55a2016-09-14 22:07:47 +010086 if (add_file_to_index(&the_index, path, data->flags)) {
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080087 if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +000088 die(_("updating files failed"));
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080089 data->add_errors++;
90 }
91 break;
92 case DIFF_STATUS_DELETED:
93 if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
94 break;
95 if (!(data->flags & ADD_CACHE_PRETEND))
96 remove_file_from_index(&the_index, path);
97 if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
Ævar Arnfjörð Bjarmason475c73e2011-02-22 23:41:32 +000098 printf(_("remove '%s'\n"), path);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -080099 break;
100 }
101 }
102}
103
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100104int add_files_to_cache(const char *prefix,
105 const struct pathspec *pathspec, int flags)
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800106{
Junio C Hamanod226b142013-04-17 12:32:21 -0700107 struct update_callback_data data;
Jonathan Nieder71c7b052013-03-19 15:50:50 -0700108 struct rev_info rev;
109
Junio C Hamanod226b142013-04-17 12:32:21 -0700110 memset(&data, 0, sizeof(data));
111 data.flags = flags;
Junio C Hamano160c4b12014-03-07 15:14:47 -0800112
Nguyễn Thái Ngọc Duy2abf3502018-09-21 17:57:38 +0200113 repo_init_revisions(the_repository, &rev, prefix);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800114 setup_revisions(0, NULL, &rev, NULL);
Nguyễn Thái Ngọc Duy3efe8e42013-07-14 15:35:56 +0700115 if (pathspec)
116 copy_pathspec(&rev.prune_data, pathspec);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800117 rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
118 rev.diffopt.format_callback = update_callback;
Junio C Hamano160c4b12014-03-07 15:14:47 -0800119 rev.diffopt.format_callback_data = &data;
Brandon Williams0d1e0e72017-10-31 11:19:11 -0700120 rev.diffopt.flags.override_submodule_config = 1;
Junio C Hamano75973b22011-04-20 18:11:19 -0700121 rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800122 run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
Jeff Kingfe6a01a2017-09-05 09:04:10 -0400123 clear_pathspec(&rev.prune_data);
Linus Torvaldsfb7d3f32010-01-21 11:37:38 -0800124 return !!data.add_errors;
125}
126
Torsten Bögershausen94729352017-11-16 17:38:28 +0100127static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
128{
129 int i, retval = 0;
130
131 for (i = 0; i < active_nr; i++) {
132 struct cache_entry *ce = active_cache[i];
133
134 if (ce_stage(ce))
135 continue; /* do not touch unmerged paths */
136 if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
137 continue; /* do not touch non blobs */
Nguyễn Thái Ngọc Duy6d2df282018-08-13 18:14:22 +0200138 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
Torsten Bögershausen94729352017-11-16 17:38:28 +0100139 continue;
140 retval |= add_file_to_cache(ce->name, flags | HASH_RENORMALIZE);
141 }
142
143 return retval;
144}
145
Junio C Hamano053a6b12014-03-07 15:14:01 -0800146static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
Linus Torvalds0d781532006-05-17 09:33:32 -0700147{
Linus Torvaldsf2593392006-05-17 13:23:19 -0700148 char *seen;
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700149 int i;
Linus Torvalds0d781532006-05-17 09:33:32 -0700150 struct dir_entry **src, **dst;
151
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700152 seen = xcalloc(pathspec->nr, 1);
Linus Torvaldsf2593392006-05-17 13:23:19 -0700153
Linus Torvalds0d781532006-05-17 09:33:32 -0700154 src = dst = dir->entries;
155 i = dir->nr;
156 while (--i >= 0) {
157 struct dir_entry *entry = *src++;
Nguyễn Thái Ngọc Duy6d2df282018-08-13 18:14:22 +0200158 if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
Junio C Hamano4d06f8a2006-12-29 11:01:31 -0800159 *dst++ = entry;
Linus Torvalds0d781532006-05-17 09:33:32 -0700160 }
161 dir->nr = dst - dir->entries;
Brandon Williams08de9152017-05-11 15:04:27 -0700162 add_pathspec_matches_against_index(pathspec, &the_index, seen);
Junio C Hamano81f45e72010-02-09 17:30:49 -0500163 return seen;
Linus Torvalds0d781532006-05-17 09:33:32 -0700164}
165
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700166static void refresh(int verbose, const struct pathspec *pathspec)
Alexandre Julliardd6168132007-08-11 23:59:01 +0200167{
168 char *seen;
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700169 int i;
Alexandre Julliardd6168132007-08-11 23:59:01 +0200170
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700171 seen = xcalloc(pathspec->nr, 1);
Matthieu Moy43673fd2009-08-21 10:57:58 +0200172 refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
Ævar Arnfjörð Bjarmasoned2a8082011-02-22 23:41:33 +0000173 pathspec, seen, _("Unstaged changes after refreshing the index:"));
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700174 for (i = 0; i < pathspec->nr; i++) {
Alexandre Julliardd6168132007-08-11 23:59:01 +0200175 if (!seen[i])
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700176 die(_("pathspec '%s' did not match any files"),
177 pathspec->items[i].match);
Alexandre Julliardd6168132007-08-11 23:59:01 +0200178 }
Benoit Sigoure399f0a82007-10-29 08:00:33 +0100179 free(seen);
Alexandre Julliardd6168132007-08-11 23:59:01 +0200180}
181
Thomas Rast46b51392009-08-13 14:29:41 +0200182int run_add_interactive(const char *revision, const char *patch_mode,
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700183 const struct pathspec *pathspec)
Thomas Rast46b51392009-08-13 14:29:41 +0200184{
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100185 int status, i;
186 struct argv_array argv = ARGV_ARRAY_INIT;
Thomas Rast46b51392009-08-13 14:29:41 +0200187
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100188 argv_array_push(&argv, "add--interactive");
Thomas Rast46b51392009-08-13 14:29:41 +0200189 if (patch_mode)
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100190 argv_array_push(&argv, patch_mode);
Thomas Rast46b51392009-08-13 14:29:41 +0200191 if (revision)
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100192 argv_array_push(&argv, revision);
193 argv_array_push(&argv, "--");
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700194 for (i = 0; i < pathspec->nr; i++)
195 /* pass original pathspec, to be re-parsed */
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100196 argv_array_push(&argv, pathspec->items[i].original);
Thomas Rast46b51392009-08-13 14:29:41 +0200197
Fabian Ruchc45a18e2014-03-15 12:14:40 +0100198 status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
199 argv_array_clear(&argv);
Thomas Rast46b51392009-08-13 14:29:41 +0200200 return status;
201}
202
Conrad Irwinb4bd4662011-05-07 10:58:07 -0700203int interactive_add(int argc, const char **argv, const char *prefix, int patch)
Kristian Høgsberg58680162007-09-17 20:06:44 -0400204{
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700205 struct pathspec pathspec;
Junio C Hamano324ccbd2007-11-25 10:07:55 -0800206
Nguyễn Thái Ngọc Duy625c3302013-09-05 10:40:39 +0700207 parse_pathspec(&pathspec, 0,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700208 PATHSPEC_PREFER_FULL |
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700209 PATHSPEC_SYMLINK_LEADING_PATH |
210 PATHSPEC_PREFIX_ORIGIN,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700211 prefix, argv);
Junio C Hamano3f061882007-11-25 10:10:10 -0800212
Thomas Rast46b51392009-08-13 14:29:41 +0200213 return run_add_interactive(NULL,
Conrad Irwinb4bd4662011-05-07 10:58:07 -0700214 patch ? "--patch" : NULL,
Nguyễn Thái Ngọc Duy480ca642013-07-14 15:35:50 +0700215 &pathspec);
Kristian Høgsberg58680162007-09-17 20:06:44 -0400216}
217
Linus Torvalds2af202b2009-06-18 10:28:43 -0700218static int edit_patch(int argc, const char **argv, const char *prefix)
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200219{
Ramsay Jonesd292bfa2012-09-04 18:30:21 +0100220 char *file = git_pathdup("ADD_EDIT.patch");
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200221 const char *apply_argv[] = { "apply", "--recount", "--cached",
Gary V. Vaughan66dbfd52010-05-14 09:31:33 +0000222 NULL, NULL };
René Scharfed3180272014-08-19 21:09:35 +0200223 struct child_process child = CHILD_PROCESS_INIT;
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200224 struct rev_info rev;
225 int out;
226 struct stat st;
227
Gary V. Vaughan66dbfd52010-05-14 09:31:33 +0000228 apply_argv[3] = file;
229
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200230 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
231
232 if (read_cache() < 0)
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500233 die(_("Could not read the index"));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200234
Nguyễn Thái Ngọc Duy2abf3502018-09-21 17:57:38 +0200235 repo_init_revisions(the_repository, &rev, prefix);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200236 rev.diffopt.context = 7;
237
238 argc = setup_revisions(argc, argv, &rev, NULL);
239 rev.diffopt.output_format = DIFF_FORMAT_PATCH;
Andrew Wong7f3b8c62013-07-18 18:58:04 -0400240 rev.diffopt.use_color = 0;
Brandon Williams0d1e0e72017-10-31 11:19:11 -0700241 rev.diffopt.flags.ignore_dirty_submodules = 1;
Jeff King6ff2b722012-07-10 02:37:22 -0400242 out = open(file, O_CREAT | O_WRONLY, 0666);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200243 if (out < 0)
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500244 die(_("Could not open '%s' for writing."), file);
Jim Meyering41698372009-09-12 10:43:27 +0200245 rev.diffopt.file = xfdopen(out, "w");
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200246 rev.diffopt.close_file = 1;
247 if (run_diff_files(&rev, 0))
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500248 die(_("Could not write patch"));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200249
Jeff Kingcb648002015-05-12 21:21:58 -0400250 if (launch_editor(file, NULL, NULL))
251 die(_("editing patch failed"));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200252
253 if (stat(file, &st))
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000254 die_errno(_("Could not stat '%s'"), file);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200255 if (!st.st_size)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000256 die(_("Empty patch. Aborted."));
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200257
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200258 child.git_cmd = 1;
259 child.argv = apply_argv;
260 if (run_command(&child))
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500261 die(_("Could not apply '%s'"), file);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200262
263 unlink(file);
Ramsay Jonesd292bfa2012-09-04 18:30:21 +0100264 free(file);
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200265 return 0;
266}
267
Petr Baudisb39c53e2007-08-29 00:41:23 +0200268static const char ignore_error[] =
Ævar Arnfjörð Bjarmason439fb822011-02-22 23:41:30 +0000269N_("The following paths are ignored by one of your .gitignore files:\n");
Junio C Hamano6a1ad322006-12-25 17:46:38 -0800270
Junio C Hamano300c0a22013-03-08 22:21:13 -0800271static int verbose, show_only, ignored_too, refresh_only;
Junio C Hamano45c45e32011-04-19 12:18:20 -0700272static int ignore_add_errors, intent_to_add, ignore_missing;
Jeff King53213992017-06-14 06:58:22 -0400273static int warn_on_embedded_repo = 1;
Junio C Hamano45c45e32011-04-19 12:18:20 -0700274
Junio C Hamanofdc97ab2013-04-22 14:30:22 -0700275#define ADDREMOVE_DEFAULT 1
Junio C Hamano45c45e32011-04-19 12:18:20 -0700276static int addremove = ADDREMOVE_DEFAULT;
277static int addremove_explicit = -1; /* unspecified */
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400278
Edward Thomson4e55ed32016-05-31 17:08:18 -0500279static char *chmod_arg;
280
Junio C Hamano9f60f492013-04-22 13:29:20 -0700281static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
282{
283 /* if we are told to ignore, we are not adding removals */
284 *(int *)opt->value = !unset ? 0 : 1;
285 return 0;
286}
287
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400288static struct option builtin_add_options[] = {
Nguyễn Thái Ngọc Duy1b560242012-08-20 19:31:52 +0700289 OPT__DRY_RUN(&show_only, N_("dry run")),
290 OPT__VERBOSE(&verbose, N_("be verbose")),
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400291 OPT_GROUP(""),
Junio C Hamano300c0a22013-03-08 22:21:13 -0800292 OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
293 OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
294 OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
Nguyễn Thái Ngọc Duy12247812018-02-09 18:01:42 +0700295 OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
Junio C Hamano300c0a22013-03-08 22:21:13 -0800296 OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
Torsten Bögershausen94729352017-11-16 17:38:28 +0100297 OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
Junio C Hamano300c0a22013-03-08 22:21:13 -0800298 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 -0700299 OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
Junio C Hamano9f60f492013-04-22 13:29:20 -0700300 { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
301 NULL /* takes no arguments */,
302 N_("ignore paths removed in the working tree (same as --no-all)"),
303 PARSE_OPT_NOARG, ignore_removal_cb },
Junio C Hamano300c0a22013-03-08 22:21:13 -0800304 OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
305 OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
306 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 +0200307 OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
308 N_("override the executable bit of the listed files")),
Jeff King53213992017-06-14 06:58:22 -0400309 OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
310 N_("warn when adding an embedded repository")),
Kristian Høgsberg5c46f752007-10-03 17:45:02 -0400311 OPT_END(),
312};
313
Junio C Hamano9bd81e42008-05-25 14:25:02 -0700314static int add_config(const char *var, const char *value, void *cb)
Alex Riesendad25e42008-05-12 19:59:23 +0200315{
Jonathan Nieder8c2be752011-05-14 15:19:21 -0500316 if (!strcmp(var, "add.ignoreerrors") ||
317 !strcmp(var, "add.ignore-errors")) {
Alex Riesendad25e42008-05-12 19:59:23 +0200318 ignore_add_errors = git_config_bool(var, value);
319 return 0;
320 }
Junio C Hamano9bd81e42008-05-25 14:25:02 -0700321 return git_default_config(var, value, cb);
Alex Riesendad25e42008-05-12 19:59:23 +0200322}
323
Jeff King53213992017-06-14 06:58:22 -0400324static const char embedded_advice[] = N_(
325"You've added another git repository inside your current repository.\n"
326"Clones of the outer repository will not contain the contents of\n"
327"the embedded repository and will not know how to obtain it.\n"
328"If you meant to add a submodule, use:\n"
329"\n"
330" git submodule add <url> %s\n"
331"\n"
332"If you added this path by mistake, you can remove it from the\n"
333"index with:\n"
334"\n"
335" git rm --cached %s\n"
336"\n"
337"See \"git help submodule\" for more information."
338);
339
340static void check_embedded_repo(const char *path)
341{
342 struct strbuf name = STRBUF_INIT;
343
344 if (!warn_on_embedded_repo)
345 return;
346 if (!ends_with(path, "/"))
347 return;
348
349 /* Drop trailing slash for aesthetics */
350 strbuf_addstr(&name, path);
351 strbuf_strip_suffix(&name, "/");
352
353 warning(_("adding embedded git repository: %s"), name.buf);
354 if (advice_add_embedded_repo) {
355 advise(embedded_advice, name.buf, name.buf);
356 /* there may be multiple entries; advise only once */
357 advice_add_embedded_repo = 0;
358 }
359
360 strbuf_release(&name);
361}
362
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100363static int add_files(struct dir_struct *dir, int flags)
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700364{
365 int i, exit_status = 0;
366
367 if (dir->ignored_nr) {
Ævar Arnfjörð Bjarmason439fb822011-02-22 23:41:30 +0000368 fprintf(stderr, _(ignore_error));
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700369 for (i = 0; i < dir->ignored_nr; i++)
370 fprintf(stderr, "%s\n", dir->ignored[i]->name);
Ævar Arnfjörð Bjarmason439fb822011-02-22 23:41:30 +0000371 fprintf(stderr, _("Use -f if you really want to add them.\n"));
Michael J Gruber1d31e5a2014-11-21 17:08:19 +0100372 exit_status = 1;
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700373 }
374
Jeff King53213992017-06-14 06:58:22 -0400375 for (i = 0; i < dir->nr; i++) {
376 check_embedded_repo(dir->entries[i]->name);
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100377 if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700378 if (!ignore_add_errors)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000379 die(_("adding files failed"));
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700380 exit_status = 1;
381 }
Jeff King53213992017-06-14 06:58:22 -0400382 }
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700383 return exit_status;
384}
385
Linus Torvaldsa633fca2006-07-28 22:44:25 -0700386int cmd_add(int argc, const char **argv, const char *prefix)
Linus Torvalds0d781532006-05-17 09:33:32 -0700387{
Alex Riesen7ae02a32008-05-12 19:58:10 +0200388 int exit_status = 0;
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700389 struct pathspec pathspec;
Linus Torvalds0d781532006-05-17 09:33:32 -0700390 struct dir_struct dir;
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100391 int flags;
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700392 int add_new_files;
393 int require_pathspec;
Junio C Hamano81f45e72010-02-09 17:30:49 -0500394 char *seen = NULL;
Martin Ågren0fa5a2e2018-05-09 22:55:39 +0200395 struct lock_file lock_file = LOCK_INIT;
Junio C Hamano5cde71d2006-12-10 20:55:50 -0800396
Stephen Boyded342fd2009-06-18 02:17:54 -0700397 git_config(add_config, NULL);
398
Stephen Boyd37782922009-05-23 11:53:12 -0700399 argc = parse_options(argc, argv, prefix, builtin_add_options,
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200400 builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
Wincent Colaiutab63e9952007-11-25 14:15:42 +0100401 if (patch_interactive)
402 add_interactive = 1;
Wincent Colaiuta7c0ab442007-11-22 01:02:52 +0100403 if (add_interactive)
Conrad Irwinb4bd4662011-05-07 10:58:07 -0700404 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
Linus Torvalds0d781532006-05-17 09:33:32 -0700405
Johannes Schindelinc59cb032009-04-08 23:30:24 +0200406 if (edit_interactive)
407 return(edit_patch(argc, argv, prefix));
408 argc--;
409 argv++;
410
Junio C Hamano45c45e32011-04-19 12:18:20 -0700411 if (0 <= addremove_explicit)
412 addremove = addremove_explicit;
413 else if (take_worktree_changes && ADDREMOVE_DEFAULT)
414 addremove = 0; /* "-u" was given but not "-A" */
415
Junio C Hamano3ba1f112008-07-19 19:51:11 -0700416 if (addremove && take_worktree_changes)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000417 die(_("-A and -u are mutually incompatible"));
Junio C Hamano45c45e32011-04-19 12:18:20 -0700418
Junio C Hamano45c45e32011-04-19 12:18:20 -0700419 if (!take_worktree_changes && addremove_explicit < 0 && argc)
Junio C Hamanofdc97ab2013-04-22 14:30:22 -0700420 /* Turn "git add pathspec..." to "git add -A pathspec..." */
421 addremove = 1;
Junio C Hamano45c45e32011-04-19 12:18:20 -0700422
Jens Lehmann108da0d2010-07-10 00:18:38 +0200423 if (!show_only && ignore_missing)
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000424 die(_("Option --ignore-missing can only be used together with --dry-run"));
Junio C Hamano808d3d72013-03-19 15:53:17 -0700425
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100426 if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
427 chmod_arg[1] != 'x' || chmod_arg[2]))
Edward Thomson4e55ed32016-05-31 17:08:18 -0500428 die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
429
Torsten Bögershausen94729352017-11-16 17:38:28 +0100430 add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
Junio C Hamano29abb332015-10-24 19:31:11 -0700431 require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700432
Junio C Hamanob3e83cc2016-12-07 10:33:54 -0800433 hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
Linus Torvalds0d781532006-05-17 09:33:32 -0700434
Gustaf Hendeby205ffa92008-05-22 23:59:42 +0200435 flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
Junio C Hamano01665922008-05-25 14:03:50 -0700436 (show_only ? ADD_CACHE_PRETEND : 0) |
Junio C Hamano39425812008-08-21 01:44:53 -0700437 (intent_to_add ? ADD_CACHE_INTENT : 0) |
Junio C Hamano1e5f7642008-07-22 22:30:40 -0700438 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
439 (!(addremove || take_worktree_changes)
Junio C Hamano808d3d72013-03-19 15:53:17 -0700440 ? ADD_CACHE_IGNORE_REMOVAL : 0));
Gustaf Hendeby205ffa92008-05-22 23:59:42 +0200441
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700442 if (require_pathspec && argc == 0) {
Ævar Arnfjörð Bjarmason990ac4b2011-02-22 23:41:29 +0000443 fprintf(stderr, _("Nothing specified, nothing added.\n"));
444 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
Junio C Hamano93b0d862006-12-20 13:06:46 -0800445 return 0;
446 }
Linus Torvalds0d781532006-05-17 09:33:32 -0700447
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700448 /*
449 * Check the "pathspec '%s' did not match any files" block
450 * below before enabling new magic.
451 */
Nguyễn Thái Ngọc Duy84d938b2018-09-18 19:31:59 +0200452 parse_pathspec(&pathspec, PATHSPEC_ATTR,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700453 PATHSPEC_PREFER_FULL |
Brandon Williamsc08397e2017-05-11 15:04:24 -0700454 PATHSPEC_SYMLINK_LEADING_PATH,
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700455 prefix, argv);
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700456
Ben Peartd1664e72018-11-02 09:30:50 -0400457 if (read_cache_preload(&pathspec) < 0)
458 die(_("index file corrupt"));
459
460 die_in_unpopulated_submodule(&the_index, prefix);
Brandon Williamsc08397e2017-05-11 15:04:24 -0700461 die_path_inside_submodule(&the_index, &pathspec);
462
Linus Torvalds1d8842d2009-05-14 13:22:36 -0700463 if (add_new_files) {
464 int baselen;
465
466 /* Set up the default git porcelain excludes */
467 memset(&dir, 0, sizeof(dir));
468 if (!ignored_too) {
469 dir.flags |= DIR_COLLECT_IGNORED;
470 setup_standard_excludes(&dir);
471 }
472
Junio C Hamano1e5f7642008-07-22 22:30:40 -0700473 /* This picks up the paths that are not tracked */
Brandon Williams0d32c182017-05-05 12:53:34 -0700474 baselen = fill_directory(&dir, &the_index, &pathspec);
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700475 if (pathspec.nr)
Junio C Hamano053a6b12014-03-07 15:14:01 -0800476 seen = prune_directory(&dir, &pathspec, baselen);
Linus Torvalds1d8842d2009-05-14 13:22:36 -0700477 }
Junio C Hamano1e5f7642008-07-22 22:30:40 -0700478
Alexandre Julliardd6168132007-08-11 23:59:01 +0200479 if (refresh_only) {
Nguyễn Thái Ngọc Duy9b2d6142013-07-14 15:35:54 +0700480 refresh(verbose, &pathspec);
Alexandre Julliardd6168132007-08-11 23:59:01 +0200481 goto finish;
482 }
483
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700484 if (pathspec.nr) {
Junio C Hamano81f45e72010-02-09 17:30:49 -0500485 int i;
Junio C Hamanoeb699342012-06-05 21:44:22 -0700486
Junio C Hamano81f45e72010-02-09 17:30:49 -0500487 if (!seen)
Brandon Williams08de9152017-05-11 15:04:27 -0700488 seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700489
490 /*
491 * file_exists() assumes exact match
492 */
Nguyễn Thái Ngọc Duybd30c2e2013-07-14 15:36:08 +0700493 GUARD_PATHSPEC(&pathspec,
494 PATHSPEC_FROMTOP |
495 PATHSPEC_LITERAL |
Nguyễn Thái Ngọc Duy93d93532013-07-14 15:36:09 +0700496 PATHSPEC_GLOB |
Nguyễn Thái Ngọc Duyef79b1f2013-12-06 14:30:48 +0700497 PATHSPEC_ICASE |
498 PATHSPEC_EXCLUDE);
Nguyễn Thái Ngọc Duy5a76aff2013-07-14 15:35:46 +0700499
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700500 for (i = 0; i < pathspec.nr; i++) {
501 const char *path = pathspec.items[i].match;
Nguyễn Thái Ngọc Duyef79b1f2013-12-06 14:30:48 +0700502 if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
503 continue;
Nguyễn Thái Ngọc Duy64ed07c2013-12-23 16:02:41 +0700504 if (!seen[i] && path[0] &&
Nguyễn Thái Ngọc Duy93d93532013-07-14 15:36:09 +0700505 ((pathspec.items[i].magic &
506 (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
Nguyễn Thái Ngọc Duybd30c2e2013-07-14 15:36:08 +0700507 !file_exists(path))) {
Jens Lehmann108da0d2010-07-10 00:18:38 +0200508 if (ignore_missing) {
Nguyễn Thái Ngọc Duy0188f6b2010-11-11 20:03:22 +0700509 int dtype = DT_UNKNOWN;
Brandon Williamsa0bba652017-05-05 12:53:30 -0700510 if (is_excluded(&dir, &the_index, path, &dtype))
Brandon Williams9e58bec2017-05-05 12:53:25 -0700511 dir_add_ignored(&dir, &the_index,
512 path, pathspec.items[i].len);
Jens Lehmann108da0d2010-07-10 00:18:38 +0200513 } else
Ævar Arnfjörð Bjarmason48168852011-02-22 23:41:31 +0000514 die(_("pathspec '%s' did not match any files"),
Nguyễn Thái Ngọc Duy84b8b5d2013-07-14 15:36:00 +0700515 pathspec.items[i].original);
Jens Lehmann108da0d2010-07-10 00:18:38 +0200516 }
Junio C Hamano81f45e72010-02-09 17:30:49 -0500517 }
518 free(seen);
519 }
520
Junio C Hamano568508e2011-10-28 14:48:40 -0700521 plug_bulk_checkin();
522
Torsten Bögershausen94729352017-11-16 17:38:28 +0100523 if (add_renormalize)
524 exit_status |= renormalize_tracked_files(&pathspec, flags);
525 else
526 exit_status |= add_files_to_cache(prefix, &pathspec, flags);
Linus Torvalds0d781532006-05-17 09:33:32 -0700527
Junio C Hamanoc972ec02008-07-19 19:22:25 -0700528 if (add_new_files)
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100529 exit_status |= add_files(&dir, flags);
Linus Torvalds0d781532006-05-17 09:33:32 -0700530
Thomas Gummerer610d55a2016-09-14 22:07:47 +0100531 if (chmod_arg && pathspec.nr)
532 chmod_pathspec(&pathspec, chmod_arg[0]);
Junio C Hamano568508e2011-10-28 14:48:40 -0700533 unplug_bulk_checkin();
534
Felipe Contrerasd521abf2013-08-30 16:56:49 -0500535finish:
Martin Ågren61000812018-03-01 21:40:20 +0100536 if (write_locked_index(&the_index, &lock_file,
537 COMMIT_LOCK | SKIP_IF_UNCHANGED))
538 die(_("Unable to write new index file"));
Linus Torvalds0d781532006-05-17 09:33:32 -0700539
Jeff King0e5bba52017-09-08 02:38:41 -0400540 UNLEAK(pathspec);
541 UNLEAK(dir);
Alex Riesen7ae02a32008-05-12 19:58:10 +0200542 return exit_status;
Linus Torvalds0d781532006-05-17 09:33:32 -0700543}