]> git.ipfire.org Git - thirdparty/git.git/blame - builtin/add.c
add: fail when adding an untracked sparse file
[thirdparty/git.git] / builtin / add.c
CommitLineData
0d781539
LT
1/*
2 * "git add" builtin command
3 *
4 * Copyright (C) 2006 Linus Torvalds
5 */
f8adbec9 6#define USE_THE_INDEX_COMPATIBILITY_MACROS
0d781539 7#include "cache.h"
b2141fc1 8#include "config.h"
0d781539 9#include "builtin.h"
697cc8ef 10#include "lockfile.h"
0d781539 11#include "dir.h"
6f525e71 12#include "pathspec.h"
d807c4a0 13#include "exec-cmd.h"
93872e07 14#include "cache-tree.h"
58680165 15#include "run-command.h"
5c46f754 16#include "parse-options.h"
c59cb03a 17#include "diff.h"
fb7d3f32 18#include "diffcore.h"
c59cb03a 19#include "revision.h"
568508e7 20#include "bulk-checkin.h"
dbbcd44f 21#include "strvec.h"
bdab9721 22#include "submodule.h"
f83dff60 23#include "add-interactive.h"
0d781539 24
5c46f754 25static const char * const builtin_add_usage[] = {
9c9b4f2f 26 N_("git add [<options>] [--] <pathspec>..."),
5c46f754
KH
27 NULL
28};
c59cb03a 29static int patch_interactive, add_interactive, edit_interactive;
93c44d49 30static int take_worktree_changes;
9472935d 31static int add_renormalize;
bebb5d6d
AM
32static int pathspec_file_nul;
33static const char *pathspec_from_file;
90a6bb98 34static int legacy_stash_p; /* support for the scripted `git stash` */
896bdfa2 35
9cba13ca 36struct update_callback_data {
610d55af 37 int flags;
fb7d3f32
LT
38 int add_errors;
39};
40
9ebd7fe1 41static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
610d55af 42{
9ebd7fe1 43 int i, ret = 0;
610d55af
TG
44
45 for (i = 0; i < active_nr; i++) {
46 struct cache_entry *ce = active_cache[i];
c937d70b 47 int err;
610d55af 48
d73dbafc
MT
49 if (ce_skip_worktree(ce))
50 continue;
51
6d2df284 52 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
610d55af
TG
53 continue;
54
c937d70b
MT
55 if (!show_only)
56 err = chmod_cache_entry(ce, flip);
57 else
58 err = S_ISREG(ce->ce_mode) ? 0 : -1;
59
60 if (err < 0)
9ebd7fe1 61 ret = error(_("cannot chmod %cx '%s'"), flip, ce->name);
610d55af 62 }
9ebd7fe1
MT
63
64 return ret;
610d55af
TG
65}
66
75973b2c
JH
67static int fix_unmerged_status(struct diff_filepair *p,
68 struct update_callback_data *data)
69{
70 if (p->status != DIFF_STATUS_UNMERGED)
71 return p->status;
72 if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
73 /*
74 * This is not an explicit add request, and the
75 * path is missing from the working tree (deleted)
76 */
77 return DIFF_STATUS_DELETED;
78 else
79 /*
80 * Either an explicit add request, or path exists
81 * in the working tree. An attempt to explicitly
82 * add a path that does not exist in the working tree
83 * will be caught as an error by the caller immediately.
84 */
85 return DIFF_STATUS_MODIFIED;
86}
87
fb7d3f32
LT
88static void update_callback(struct diff_queue_struct *q,
89 struct diff_options *opt, void *cbdata)
90{
91 int i;
92 struct update_callback_data *data = cbdata;
93
94 for (i = 0; i < q->nr; i++) {
95 struct diff_filepair *p = q->queue[i];
96 const char *path = p->one->path;
75973b2c 97 switch (fix_unmerged_status(p, data)) {
fb7d3f32 98 default:
990ac4be 99 die(_("unexpected diff status %c"), p->status);
fb7d3f32
LT
100 case DIFF_STATUS_MODIFIED:
101 case DIFF_STATUS_TYPE_CHANGED:
610d55af 102 if (add_file_to_index(&the_index, path, data->flags)) {
fb7d3f32 103 if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
990ac4be 104 die(_("updating files failed"));
fb7d3f32
LT
105 data->add_errors++;
106 }
107 break;
108 case DIFF_STATUS_DELETED:
109 if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
110 break;
111 if (!(data->flags & ADD_CACHE_PRETEND))
112 remove_file_from_index(&the_index, path);
113 if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
475c73eb 114 printf(_("remove '%s'\n"), path);
fb7d3f32
LT
115 break;
116 }
117 }
118}
119
610d55af
TG
120int add_files_to_cache(const char *prefix,
121 const struct pathspec *pathspec, int flags)
fb7d3f32 122{
160c4b18 123 struct update_callback_data data;
fb7d3f32 124 struct rev_info rev;
71c7b053 125
160c4b18
JH
126 memset(&data, 0, sizeof(data));
127 data.flags = flags;
128
2abf3503 129 repo_init_revisions(the_repository, &rev, prefix);
fb7d3f32 130 setup_revisions(0, NULL, &rev, NULL);
3efe8e43
NTND
131 if (pathspec)
132 copy_pathspec(&rev.prune_data, pathspec);
fb7d3f32
LT
133 rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
134 rev.diffopt.format_callback = update_callback;
160c4b18 135 rev.diffopt.format_callback_data = &data;
0d1e0e78 136 rev.diffopt.flags.override_submodule_config = 1;
75973b2c 137 rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
fb7d3f32 138 run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
fe6a01af 139 clear_pathspec(&rev.prune_data);
fb7d3f32
LT
140 return !!data.add_errors;
141}
142
9472935d
TB
143static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
144{
145 int i, retval = 0;
146
147 for (i = 0; i < active_nr; i++) {
148 struct cache_entry *ce = active_cache[i];
149
d73dbafc
MT
150 if (ce_skip_worktree(ce))
151 continue;
9472935d
TB
152 if (ce_stage(ce))
153 continue; /* do not touch unmerged paths */
154 if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
155 continue; /* do not touch non blobs */
6d2df284 156 if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
9472935d 157 continue;
9e5da3d0 158 retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE);
9472935d
TB
159 }
160
161 return retval;
162}
163
053a6b18 164static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
0d781539 165{
f2593398 166 char *seen;
84b8b5d1 167 int i;
0d781539
LT
168 struct dir_entry **src, **dst;
169
84b8b5d1 170 seen = xcalloc(pathspec->nr, 1);
f2593398 171
0d781539
LT
172 src = dst = dir->entries;
173 i = dir->nr;
174 while (--i >= 0) {
175 struct dir_entry *entry = *src++;
6d2df284 176 if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
4d06f8ac 177 *dst++ = entry;
0d781539
LT
178 }
179 dir->nr = dst - dir->entries;
719630eb 180 add_pathspec_matches_against_index(pathspec, &the_index, seen,
a20f7047 181 PS_IGNORE_SKIP_WORKTREE);
81f45e7d 182 return seen;
0d781539
LT
183}
184
a20f7047 185static int refresh(int verbose, const struct pathspec *pathspec)
d616813d
AJ
186{
187 char *seen;
a20f7047
MT
188 int i, ret = 0;
189 char *skip_worktree_seen = NULL;
190 struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
191 int flags = REFRESH_IGNORE_SKIP_WORKTREE |
192 (verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET);
d616813d 193
9b2d6149 194 seen = xcalloc(pathspec->nr, 1);
a20f7047
MT
195 refresh_index(&the_index, flags, pathspec, seen,
196 _("Unstaged changes after refreshing the index:"));
9b2d6149 197 for (i = 0; i < pathspec->nr; i++) {
a20f7047 198 if (!seen[i]) {
939fa075 199 const char *path = pathspec->items[i].original;
939fa075
DS
200
201 if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
02155c8c 202 !path_in_sparse_checkout(path, &the_index)) {
a20f7047
MT
203 string_list_append(&only_match_skip_worktree,
204 pathspec->items[i].original);
205 } else {
206 die(_("pathspec '%s' did not match any files"),
207 pathspec->items[i].original);
208 }
209 }
210 }
211
212 if (only_match_skip_worktree.nr) {
213 advise_on_updating_sparse_paths(&only_match_skip_worktree);
214 ret = 1;
d616813d 215 }
a20f7047 216
ec36c42a 217 free(seen);
a20f7047
MT
218 free(skip_worktree_seen);
219 string_list_clear(&only_match_skip_worktree, 0);
220 return ret;
d616813d
AJ
221}
222
46b5139c 223int run_add_interactive(const char *revision, const char *patch_mode,
480ca644 224 const struct pathspec *pathspec)
58680165 225{
c45a18e8 226 int status, i;
22f9b7f3 227 struct strvec argv = STRVEC_INIT;
f83dff60
JS
228 int use_builtin_add_i =
229 git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1);
230
2df2d81d
JH
231 if (use_builtin_add_i < 0) {
232 int experimental;
233 if (!git_config_get_bool("add.interactive.usebuiltin",
234 &use_builtin_add_i))
235 ; /* ok */
236 else if (!git_config_get_bool("feature.experimental", &experimental) &&
237 experimental)
238 use_builtin_add_i = 1;
239 }
f6aa7ecc
JS
240
241 if (use_builtin_add_i == 1) {
d2a233cb
JS
242 enum add_p_mode mode;
243
f6aa7ecc 244 if (!patch_mode)
f83dff60 245 return !!run_add_i(the_repository, pathspec);
d2a233cb
JS
246
247 if (!strcmp(patch_mode, "--patch"))
248 mode = ADD_P_ADD;
36bae1dc
JS
249 else if (!strcmp(patch_mode, "--patch=stash"))
250 mode = ADD_P_STASH;
251 else if (!strcmp(patch_mode, "--patch=reset"))
252 mode = ADD_P_RESET;
52628f94
JS
253 else if (!strcmp(patch_mode, "--patch=checkout"))
254 mode = ADD_P_CHECKOUT;
cee6cb73
JS
255 else if (!strcmp(patch_mode, "--patch=worktree"))
256 mode = ADD_P_WORKTREE;
d2a233cb 257 else
52628f94 258 die("'%s' not supported", patch_mode);
d2a233cb
JS
259
260 return !!run_add_p(the_repository, mode, revision, pathspec);
f83dff60 261 }
3f061887 262
22f9b7f3 263 strvec_push(&argv, "add--interactive");
46b5139c 264 if (patch_mode)
22f9b7f3 265 strvec_push(&argv, patch_mode);
46b5139c 266 if (revision)
22f9b7f3
JK
267 strvec_push(&argv, revision);
268 strvec_push(&argv, "--");
480ca644
NTND
269 for (i = 0; i < pathspec->nr; i++)
270 /* pass original pathspec, to be re-parsed */
22f9b7f3 271 strvec_push(&argv, pathspec->items[i].original);
7c0ab445 272
d70a9eb6 273 status = run_command_v_opt(argv.v, RUN_GIT_CMD);
22f9b7f3 274 strvec_clear(&argv);
7c0ab445 275 return status;
58680165
KH
276}
277
e885a84f 278int interactive_add(const char **argv, const char *prefix, int patch)
46b5139c 279{
5a76aff1 280 struct pathspec pathspec;
46b5139c 281
625c3304 282 parse_pathspec(&pathspec, 0,
5a76aff1 283 PATHSPEC_PREFER_FULL |
480ca644
NTND
284 PATHSPEC_SYMLINK_LEADING_PATH |
285 PATHSPEC_PREFIX_ORIGIN,
5a76aff1 286 prefix, argv);
46b5139c
TR
287
288 return run_add_interactive(NULL,
b4bd4668 289 patch ? "--patch" : NULL,
480ca644 290 &pathspec);
46b5139c
TR
291}
292
2af202be 293static int edit_patch(int argc, const char **argv, const char *prefix)
c59cb03a 294{
d292bfaf 295 char *file = git_pathdup("ADD_EDIT.patch");
c59cb03a 296 const char *apply_argv[] = { "apply", "--recount", "--cached",
66dbfd55 297 NULL, NULL };
d3180279 298 struct child_process child = CHILD_PROCESS_INIT;
c59cb03a
JS
299 struct rev_info rev;
300 int out;
301 struct stat st;
302
66dbfd55
GV
303 apply_argv[3] = file;
304
c59cb03a
JS
305 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
306
307 if (read_cache() < 0)
d521abf8 308 die(_("Could not read the index"));
c59cb03a 309
2abf3503 310 repo_init_revisions(the_repository, &rev, prefix);
c59cb03a
JS
311 rev.diffopt.context = 7;
312
313 argc = setup_revisions(argc, argv, &rev, NULL);
314 rev.diffopt.output_format = DIFF_FORMAT_PATCH;
7f3b8c62 315 rev.diffopt.use_color = 0;
0d1e0e78 316 rev.diffopt.flags.ignore_dirty_submodules = 1;
fa6f225e 317 out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
c59cb03a 318 if (out < 0)
d521abf8 319 die(_("Could not open '%s' for writing."), file);
41698375 320 rev.diffopt.file = xfdopen(out, "w");
c59cb03a
JS
321 rev.diffopt.close_file = 1;
322 if (run_diff_files(&rev, 0))
d521abf8 323 die(_("Could not write patch"));
c59cb03a 324
cb64800d
JK
325 if (launch_editor(file, NULL, NULL))
326 die(_("editing patch failed"));
c59cb03a
JS
327
328 if (stat(file, &st))
990ac4be 329 die_errno(_("Could not stat '%s'"), file);
c59cb03a 330 if (!st.st_size)
990ac4be 331 die(_("Empty patch. Aborted."));
c59cb03a 332
c59cb03a
JS
333 child.git_cmd = 1;
334 child.argv = apply_argv;
335 if (run_command(&child))
d521abf8 336 die(_("Could not apply '%s'"), file);
c59cb03a
JS
337
338 unlink(file);
d292bfaf 339 free(file);
c59cb03a
JS
340 return 0;
341}
342
b39c53e6 343static const char ignore_error[] =
439fb829 344N_("The following paths are ignored by one of your .gitignore files:\n");
6a1ad325 345
300c0a22 346static int verbose, show_only, ignored_too, refresh_only;
45c45e30 347static int ignore_add_errors, intent_to_add, ignore_missing;
53213994 348static int warn_on_embedded_repo = 1;
45c45e30 349
fdc97abd 350#define ADDREMOVE_DEFAULT 1
45c45e30
JH
351static int addremove = ADDREMOVE_DEFAULT;
352static int addremove_explicit = -1; /* unspecified */
5c46f754 353
4e55ed32
ET
354static char *chmod_arg;
355
9f60f49b
JH
356static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
357{
358 /* if we are told to ignore, we are not adding removals */
359 *(int *)opt->value = !unset ? 0 : 1;
360 return 0;
361}
362
5c46f754 363static struct option builtin_add_options[] = {
1b56024c
NTND
364 OPT__DRY_RUN(&show_only, N_("dry run")),
365 OPT__VERBOSE(&verbose, N_("be verbose")),
5c46f754 366 OPT_GROUP(""),
300c0a22
JH
367 OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
368 OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
369 OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
1224781d 370 OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
300c0a22 371 OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
9472935d 372 OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
300c0a22 373 OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
45c45e30 374 OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
203c8533 375 OPT_CALLBACK_F(0, "ignore-removal", &addremove_explicit,
9f60f49b
JH
376 NULL /* takes no arguments */,
377 N_("ignore paths removed in the working tree (same as --no-all)"),
203c8533 378 PARSE_OPT_NOARG, ignore_removal_cb),
300c0a22
JH
379 OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
380 OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
381 OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
5f0df44c
RS
382 OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
383 N_("override the executable bit of the listed files")),
53213994
JK
384 OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
385 N_("warn when adding an embedded repository")),
90a6bb98
JS
386 OPT_HIDDEN_BOOL(0, "legacy-stash-p", &legacy_stash_p,
387 N_("backend for `git stash -p`")),
bebb5d6d
AM
388 OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
389 OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
5c46f754
KH
390 OPT_END(),
391};
392
9bd81e42 393static int add_config(const char *var, const char *value, void *cb)
dad25e4a 394{
8c2be75f
JN
395 if (!strcmp(var, "add.ignoreerrors") ||
396 !strcmp(var, "add.ignore-errors")) {
dad25e4a
AR
397 ignore_add_errors = git_config_bool(var, value);
398 return 0;
399 }
f83dff60 400
9bd81e42 401 return git_default_config(var, value, cb);
dad25e4a
AR
402}
403
53213994
JK
404static const char embedded_advice[] = N_(
405"You've added another git repository inside your current repository.\n"
406"Clones of the outer repository will not contain the contents of\n"
407"the embedded repository and will not know how to obtain it.\n"
408"If you meant to add a submodule, use:\n"
409"\n"
410" git submodule add <url> %s\n"
411"\n"
412"If you added this path by mistake, you can remove it from the\n"
413"index with:\n"
414"\n"
415" git rm --cached %s\n"
416"\n"
417"See \"git help submodule\" for more information."
418);
419
420static void check_embedded_repo(const char *path)
421{
422 struct strbuf name = STRBUF_INIT;
423
424 if (!warn_on_embedded_repo)
425 return;
426 if (!ends_with(path, "/"))
427 return;
428
429 /* Drop trailing slash for aesthetics */
430 strbuf_addstr(&name, path);
431 strbuf_strip_suffix(&name, "/");
432
433 warning(_("adding embedded git repository: %s"), name.buf);
434 if (advice_add_embedded_repo) {
435 advise(embedded_advice, name.buf, name.buf);
436 /* there may be multiple entries; advise only once */
437 advice_add_embedded_repo = 0;
438 }
439
440 strbuf_release(&name);
441}
442
610d55af 443static int add_files(struct dir_struct *dir, int flags)
c972ec04
JH
444{
445 int i, exit_status = 0;
105e8b01 446 struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP;
c972ec04
JH
447
448 if (dir->ignored_nr) {
439fb829 449 fprintf(stderr, _(ignore_error));
c972ec04
JH
450 for (i = 0; i < dir->ignored_nr; i++)
451 fprintf(stderr, "%s\n", dir->ignored[i]->name);
887a0fd5
HW
452 if (advice_add_ignored_file)
453 advise(_("Use -f if you really want to add them.\n"
454 "Turn this message off by running\n"
455 "\"git config advice.addIgnoredFile false\""));
1d31e5a2 456 exit_status = 1;
c972ec04
JH
457 }
458
53213994 459 for (i = 0; i < dir->nr; i++) {
105e8b01
DS
460 if (!path_in_sparse_checkout(dir->entries[i]->name, &the_index)) {
461 string_list_append(&matched_sparse_paths,
462 dir->entries[i]->name);
463 continue;
464 }
610d55af 465 if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
c972ec04 466 if (!ignore_add_errors)
990ac4be 467 die(_("adding files failed"));
c972ec04 468 exit_status = 1;
f937bc2f
KM
469 } else {
470 check_embedded_repo(dir->entries[i]->name);
c972ec04 471 }
53213994 472 }
105e8b01
DS
473
474 if (matched_sparse_paths.nr) {
475 advise_on_updating_sparse_paths(&matched_sparse_paths);
476 exit_status = 1;
477 }
478
479 string_list_clear(&matched_sparse_paths, 0);
480
c972ec04
JH
481 return exit_status;
482}
483
a633fca0 484int cmd_add(int argc, const char **argv, const char *prefix)
0d781539 485{
7ae02a30 486 int exit_status = 0;
5a76aff1 487 struct pathspec pathspec;
ce93a4c6 488 struct dir_struct dir = DIR_INIT;
610d55af 489 int flags;
c972ec04
JH
490 int add_new_files;
491 int require_pathspec;
81f45e7d 492 char *seen = NULL;
0fa5a2ed 493 struct lock_file lock_file = LOCK_INIT;
5cde71d6 494
ed342fde
SB
495 git_config(add_config, NULL);
496
37782920 497 argc = parse_options(argc, argv, prefix, builtin_add_options,
c59cb03a 498 builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
b63e9950
WC
499 if (patch_interactive)
500 add_interactive = 1;
bebb5d6d 501 if (add_interactive) {
a1989cf7
ØW
502 if (show_only)
503 die(_("--dry-run is incompatible with --interactive/--patch"));
bebb5d6d
AM
504 if (pathspec_from_file)
505 die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
e885a84f 506 exit(interactive_add(argv + 1, prefix, patch_interactive));
bebb5d6d 507 }
90a6bb98
JS
508 if (legacy_stash_p) {
509 struct pathspec pathspec;
510
511 parse_pathspec(&pathspec, 0,
512 PATHSPEC_PREFER_FULL |
513 PATHSPEC_SYMLINK_LEADING_PATH |
514 PATHSPEC_PREFIX_ORIGIN,
515 prefix, argv);
516
517 return run_add_interactive(NULL, "--patch=stash", &pathspec);
518 }
0d781539 519
bebb5d6d
AM
520 if (edit_interactive) {
521 if (pathspec_from_file)
522 die(_("--pathspec-from-file is incompatible with --edit"));
c59cb03a 523 return(edit_patch(argc, argv, prefix));
bebb5d6d 524 }
c59cb03a
JS
525 argc--;
526 argv++;
527
45c45e30
JH
528 if (0 <= addremove_explicit)
529 addremove = addremove_explicit;
530 else if (take_worktree_changes && ADDREMOVE_DEFAULT)
531 addremove = 0; /* "-u" was given but not "-A" */
532
3ba1f114 533 if (addremove && take_worktree_changes)
990ac4be 534 die(_("-A and -u are mutually incompatible"));
45c45e30 535
108da0db 536 if (!show_only && ignore_missing)
990ac4be 537 die(_("Option --ignore-missing can only be used together with --dry-run"));
808d3d71 538
610d55af
TG
539 if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
540 chmod_arg[1] != 'x' || chmod_arg[2]))
4e55ed32
ET
541 die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
542
9472935d 543 add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
29abb339 544 require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
c972ec04 545
5e7cbab1
DS
546 prepare_repo_settings(the_repository);
547 the_repository->settings.command_requires_full_index = 0;
548
b3e83cc7 549 hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
0d781539 550
5a76aff1
NTND
551 /*
552 * Check the "pathspec '%s' did not match any files" block
553 * below before enabling new magic.
554 */
84d938b7 555 parse_pathspec(&pathspec, PATHSPEC_ATTR,
5a76aff1 556 PATHSPEC_PREFER_FULL |
c08397e3 557 PATHSPEC_SYMLINK_LEADING_PATH,
5a76aff1 558 prefix, argv);
366bfcb6 559
bebb5d6d
AM
560 if (pathspec_from_file) {
561 if (pathspec.nr)
562 die(_("--pathspec-from-file is incompatible with pathspec arguments"));
563
564 parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
565 PATHSPEC_PREFER_FULL |
566 PATHSPEC_SYMLINK_LEADING_PATH,
567 prefix, pathspec_from_file, pathspec_file_nul);
568 } else if (pathspec_file_nul) {
569 die(_("--pathspec-file-nul requires --pathspec-from-file"));
570 }
571
572 if (require_pathspec && pathspec.nr == 0) {
21bb3083 573 fprintf(stderr, _("Nothing specified, nothing added.\n"));
887a0fd5
HW
574 if (advice_add_empty_pathspec)
575 advise( _("Maybe you wanted to say 'git add .'?\n"
576 "Turn this message off by running\n"
577 "\"git config advice.addEmptyPathspec false\""));
21bb3083
AM
578 return 0;
579 }
580
bebb5d6d 581 if (!take_worktree_changes && addremove_explicit < 0 && pathspec.nr)
21bb3083
AM
582 /* Turn "git add pathspec..." to "git add -A pathspec..." */
583 addremove = 1;
584
585 flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
586 (show_only ? ADD_CACHE_PRETEND : 0) |
587 (intent_to_add ? ADD_CACHE_INTENT : 0) |
588 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
589 (!(addremove || take_worktree_changes)
590 ? ADD_CACHE_IGNORE_REMOVAL : 0));
591
d1664e73
BP
592 if (read_cache_preload(&pathspec) < 0)
593 die(_("index file corrupt"));
594
595 die_in_unpopulated_submodule(&the_index, prefix);
c08397e3
BW
596 die_path_inside_submodule(&the_index, &pathspec);
597
1d8842d9
LT
598 if (add_new_files) {
599 int baselen;
600
601 /* Set up the default git porcelain excludes */
1d8842d9
LT
602 if (!ignored_too) {
603 dir.flags |= DIR_COLLECT_IGNORED;
604 setup_standard_excludes(&dir);
605 }
606
1e5f764c 607 /* This picks up the paths that are not tracked */
0d32c183 608 baselen = fill_directory(&dir, &the_index, &pathspec);
5a76aff1 609 if (pathspec.nr)
053a6b18 610 seen = prune_directory(&dir, &pathspec, baselen);
1d8842d9 611 }
1e5f764c 612
c972ec04 613 if (refresh_only) {
a20f7047 614 exit_status |= refresh(verbose, &pathspec);
c972ec04 615 goto finish;
6a1ad325
JH
616 }
617
5a76aff1 618 if (pathspec.nr) {
81f45e7d 619 int i;
a20f7047
MT
620 char *skip_worktree_seen = NULL;
621 struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
eb69934b 622
81f45e7d 623 if (!seen)
719630eb 624 seen = find_pathspecs_matching_against_index(&pathspec,
a20f7047 625 &the_index, PS_IGNORE_SKIP_WORKTREE);
5a76aff1
NTND
626
627 /*
628 * file_exists() assumes exact match
629 */
bd30c2e4
NTND
630 GUARD_PATHSPEC(&pathspec,
631 PATHSPEC_FROMTOP |
632 PATHSPEC_LITERAL |
93d93537 633 PATHSPEC_GLOB |
ef79b1f8
NTND
634 PATHSPEC_ICASE |
635 PATHSPEC_EXCLUDE);
5a76aff1 636
84b8b5d1
NTND
637 for (i = 0; i < pathspec.nr; i++) {
638 const char *path = pathspec.items[i].match;
a20f7047 639
ef79b1f8
NTND
640 if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
641 continue;
a20f7047
MT
642 if (seen[i])
643 continue;
644
645 if (matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
646 string_list_append(&only_match_skip_worktree,
647 pathspec.items[i].original);
648 continue;
649 }
650
651 /* Don't complain at 'git add .' on empty repo */
652 if (!path[0])
653 continue;
654
655 if ((pathspec.items[i].magic & (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
656 !file_exists(path)) {
108da0db 657 if (ignore_missing) {
0188f6b3 658 int dtype = DT_UNKNOWN;
a0bba65b 659 if (is_excluded(&dir, &the_index, path, &dtype))
9e58beca
BW
660 dir_add_ignored(&dir, &the_index,
661 path, pathspec.items[i].len);
108da0db 662 } else
48168851 663 die(_("pathspec '%s' did not match any files"),
84b8b5d1 664 pathspec.items[i].original);
108da0db 665 }
81f45e7d 666 }
a20f7047
MT
667
668
669 if (only_match_skip_worktree.nr) {
670 advise_on_updating_sparse_paths(&only_match_skip_worktree);
671 exit_status = 1;
672 }
673
81f45e7d 674 free(seen);
a20f7047
MT
675 free(skip_worktree_seen);
676 string_list_clear(&only_match_skip_worktree, 0);
81f45e7d
JH
677 }
678
568508e7
JH
679 plug_bulk_checkin();
680
9472935d
TB
681 if (add_renormalize)
682 exit_status |= renormalize_tracked_files(&pathspec, flags);
683 else
684 exit_status |= add_files_to_cache(prefix, &pathspec, flags);
c972ec04
JH
685
686 if (add_new_files)
610d55af 687 exit_status |= add_files(&dir, flags);
0d781539 688
610d55af 689 if (chmod_arg && pathspec.nr)
9ebd7fe1 690 exit_status |= chmod_pathspec(&pathspec, chmod_arg[0], show_only);
568508e7
JH
691 unplug_bulk_checkin();
692
d521abf8 693finish:
61000814
694 if (write_locked_index(&the_index, &lock_file,
695 COMMIT_LOCK | SKIP_IF_UNCHANGED))
696 die(_("Unable to write new index file"));
0d781539 697
eceba532 698 dir_clear(&dir);
0e5bba53 699 UNLEAK(pathspec);
7ae02a30 700 return exit_status;
0d781539 701}