]> git.ipfire.org Git - thirdparty/git.git/blame - builtin/add.c
add: make warn_pathless_add() a no-op after first call
[thirdparty/git.git] / builtin / add.c
CommitLineData
0d781539
LT
1/*
2 * "git add" builtin command
3 *
4 * Copyright (C) 2006 Linus Torvalds
5 */
0d781539
LT
6#include "cache.h"
7#include "builtin.h"
8#include "dir.h"
6f525e71 9#include "pathspec.h"
5cde71d6 10#include "exec_cmd.h"
93872e07 11#include "cache-tree.h"
58680165 12#include "run-command.h"
5c46f754 13#include "parse-options.h"
c59cb03a 14#include "diff.h"
fb7d3f32 15#include "diffcore.h"
c59cb03a 16#include "revision.h"
568508e7 17#include "bulk-checkin.h"
0d781539 18
5c46f754 19static const char * const builtin_add_usage[] = {
d32805dc 20 N_("git add [options] [--] <pathspec>..."),
5c46f754
KH
21 NULL
22};
c59cb03a 23static int patch_interactive, add_interactive, edit_interactive;
93c44d49 24static int take_worktree_changes;
896bdfa2 25
9cba13ca 26struct update_callback_data {
fb7d3f32
LT
27 int flags;
28 int add_errors;
29};
30
e24afab0
JN
31static const char *option_with_implicit_dot;
32static const char *short_option_with_implicit_dot;
33
34static void warn_pathless_add(void)
35{
16d41d42 36 static int shown;
e24afab0
JN
37 assert(option_with_implicit_dot && short_option_with_implicit_dot);
38
16d41d42
JN
39 if (shown)
40 return;
41 shown = 1;
42
e24afab0
JN
43 /*
44 * To be consistent with "git add -p" and most Git
45 * commands, we should default to being tree-wide, but
46 * this is not the original behavior and can't be
47 * changed until users trained themselves not to type
48 * "git add -u" or "git add -A". For now, we warn and
49 * keep the old behavior. Later, the behavior can be changed
50 * to tree-wide, keeping the warning for a while, and
51 * eventually we can drop the warning.
52 */
53 warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
54 "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
55 "To add content for the whole tree, run:\n"
56 "\n"
57 " git add %s :/\n"
58 " (or git add %s :/)\n"
59 "\n"
60 "To restrict the command to the current directory, run:\n"
61 "\n"
62 " git add %s .\n"
63 " (or git add %s .)\n"
64 "\n"
c9f35b8b
MM
65 "With the current Git version, the command is restricted to "
66 "the current directory.\n"
67 ""),
e24afab0
JN
68 option_with_implicit_dot, short_option_with_implicit_dot,
69 option_with_implicit_dot, short_option_with_implicit_dot,
70 option_with_implicit_dot, short_option_with_implicit_dot);
71}
72
75973b2c
JH
73static int fix_unmerged_status(struct diff_filepair *p,
74 struct update_callback_data *data)
75{
76 if (p->status != DIFF_STATUS_UNMERGED)
77 return p->status;
78 if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
79 /*
80 * This is not an explicit add request, and the
81 * path is missing from the working tree (deleted)
82 */
83 return DIFF_STATUS_DELETED;
84 else
85 /*
86 * Either an explicit add request, or path exists
87 * in the working tree. An attempt to explicitly
88 * add a path that does not exist in the working tree
89 * will be caught as an error by the caller immediately.
90 */
91 return DIFF_STATUS_MODIFIED;
92}
93
fb7d3f32
LT
94static void update_callback(struct diff_queue_struct *q,
95 struct diff_options *opt, void *cbdata)
96{
97 int i;
98 struct update_callback_data *data = cbdata;
99
100 for (i = 0; i < q->nr; i++) {
101 struct diff_filepair *p = q->queue[i];
102 const char *path = p->one->path;
75973b2c 103 switch (fix_unmerged_status(p, data)) {
fb7d3f32 104 default:
990ac4be 105 die(_("unexpected diff status %c"), p->status);
fb7d3f32
LT
106 case DIFF_STATUS_MODIFIED:
107 case DIFF_STATUS_TYPE_CHANGED:
108 if (add_file_to_index(&the_index, path, data->flags)) {
109 if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
990ac4be 110 die(_("updating files failed"));
fb7d3f32
LT
111 data->add_errors++;
112 }
113 break;
114 case DIFF_STATUS_DELETED:
115 if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
116 break;
117 if (!(data->flags & ADD_CACHE_PRETEND))
118 remove_file_from_index(&the_index, path);
119 if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
475c73eb 120 printf(_("remove '%s'\n"), path);
fb7d3f32
LT
121 break;
122 }
123 }
124}
125
126int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
127{
128 struct update_callback_data data;
129 struct rev_info rev;
130 init_revisions(&rev, prefix);
131 setup_revisions(0, NULL, &rev, NULL);
afe069d1 132 init_pathspec(&rev.prune_data, pathspec);
fb7d3f32
LT
133 rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
134 rev.diffopt.format_callback = update_callback;
135 data.flags = flags;
136 data.add_errors = 0;
137 rev.diffopt.format_callback_data = &data;
75973b2c 138 rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
fb7d3f32
LT
139 run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
140 return !!data.add_errors;
141}
142
81f45e7d 143static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
0d781539 144{
f2593398
LT
145 char *seen;
146 int i, specs;
0d781539
LT
147 struct dir_entry **src, **dst;
148
f2593398
LT
149 for (specs = 0; pathspec[specs]; specs++)
150 /* nothing */;
28f75818 151 seen = xcalloc(specs, 1);
f2593398 152
0d781539
LT
153 src = dst = dir->entries;
154 i = dir->nr;
155 while (--i >= 0) {
156 struct dir_entry *entry = *src++;
4d06f8ac
JH
157 if (match_pathspec(pathspec, entry->name, entry->len,
158 prefix, seen))
159 *dst++ = entry;
0d781539
LT
160 }
161 dir->nr = dst - dir->entries;
4b78d7bc 162 add_pathspec_matches_against_index(pathspec, seen, specs);
81f45e7d 163 return seen;
0d781539
LT
164}
165
9d67b61f
AS
166/*
167 * Checks the index to see whether any path in pathspec refers to
168 * something inside a submodule. If so, dies with an error message.
169 */
2ce53f9b
JS
170static void treat_gitlinks(const char **pathspec)
171{
172 int i;
173
174 if (!pathspec || !*pathspec)
175 return;
176
9d67b61f
AS
177 for (i = 0; pathspec[i]; i++)
178 pathspec[i] = check_path_for_gitlink(pathspec[i]);
2ce53f9b
JS
179}
180
d616813d
AJ
181static void refresh(int verbose, const char **pathspec)
182{
183 char *seen;
184 int i, specs;
185
186 for (specs = 0; pathspec[specs]; specs++)
187 /* nothing */;
188 seen = xcalloc(specs, 1);
43673fdd 189 refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
ed2a808d 190 pathspec, seen, _("Unstaged changes after refreshing the index:"));
d616813d
AJ
191 for (i = 0; i < specs; i++) {
192 if (!seen[i])
990ac4be 193 die(_("pathspec '%s' did not match any files"), pathspec[i]);
d616813d 194 }
399f0a8e 195 free(seen);
d616813d
AJ
196}
197
512aaf94
AS
198/*
199 * Normalizes argv relative to prefix, via get_pathspec(), and then
200 * runs die_if_path_beyond_symlink() on each path in the normalized
201 * list.
202 */
f8a1113b 203static const char **validate_pathspec(const char **argv, const char *prefix)
3f061887
JH
204{
205 const char **pathspec = get_pathspec(prefix, argv);
206
725b0605
JH
207 if (pathspec) {
208 const char **p;
209 for (p = pathspec; *p; p++) {
512aaf94 210 die_if_path_beyond_symlink(*p, prefix);
725b0605
JH
211 }
212 }
213
3f061887
JH
214 return pathspec;
215}
216
46b5139c
TR
217int run_add_interactive(const char *revision, const char *patch_mode,
218 const char **pathspec)
58680165 219{
46b5139c 220 int status, ac, pc = 0;
3f061887 221 const char **args;
3f061887 222
46b5139c
TR
223 if (pathspec)
224 while (pathspec[pc])
225 pc++;
324ccbd6 226
46b5139c 227 args = xcalloc(sizeof(const char *), (pc + 5));
b63e9950
WC
228 ac = 0;
229 args[ac++] = "add--interactive";
46b5139c
TR
230 if (patch_mode)
231 args[ac++] = patch_mode;
232 if (revision)
233 args[ac++] = revision;
b63e9950 234 args[ac++] = "--";
46b5139c
TR
235 if (pc) {
236 memcpy(&(args[ac]), pathspec, sizeof(const char *) * pc);
237 ac += pc;
b63e9950
WC
238 }
239 args[ac] = NULL;
7c0ab445
WC
240
241 status = run_command_v_opt(args, RUN_GIT_CMD);
242 free(args);
243 return status;
58680165
KH
244}
245
b4bd4668 246int interactive_add(int argc, const char **argv, const char *prefix, int patch)
46b5139c
TR
247{
248 const char **pathspec = NULL;
249
250 if (argc) {
f8a1113b 251 pathspec = validate_pathspec(argv, prefix);
46b5139c
TR
252 if (!pathspec)
253 return -1;
254 }
255
256 return run_add_interactive(NULL,
b4bd4668 257 patch ? "--patch" : NULL,
46b5139c
TR
258 pathspec);
259}
260
2af202be 261static int edit_patch(int argc, const char **argv, const char *prefix)
c59cb03a 262{
d292bfaf 263 char *file = git_pathdup("ADD_EDIT.patch");
c59cb03a 264 const char *apply_argv[] = { "apply", "--recount", "--cached",
66dbfd55 265 NULL, NULL };
c59cb03a
JS
266 struct child_process child;
267 struct rev_info rev;
268 int out;
269 struct stat st;
270
66dbfd55
GV
271 apply_argv[3] = file;
272
c59cb03a
JS
273 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
274
275 if (read_cache() < 0)
990ac4be 276 die (_("Could not read the index"));
c59cb03a
JS
277
278 init_revisions(&rev, prefix);
279 rev.diffopt.context = 7;
280
281 argc = setup_revisions(argc, argv, &rev, NULL);
282 rev.diffopt.output_format = DIFF_FORMAT_PATCH;
701825de 283 DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
6ff2b729 284 out = open(file, O_CREAT | O_WRONLY, 0666);
c59cb03a 285 if (out < 0)
990ac4be 286 die (_("Could not open '%s' for writing."), file);
41698375 287 rev.diffopt.file = xfdopen(out, "w");
c59cb03a
JS
288 rev.diffopt.close_file = 1;
289 if (run_diff_files(&rev, 0))
990ac4be 290 die (_("Could not write patch"));
c59cb03a
JS
291
292 launch_editor(file, NULL, NULL);
293
294 if (stat(file, &st))
990ac4be 295 die_errno(_("Could not stat '%s'"), file);
c59cb03a 296 if (!st.st_size)
990ac4be 297 die(_("Empty patch. Aborted."));
c59cb03a
JS
298
299 memset(&child, 0, sizeof(child));
300 child.git_cmd = 1;
301 child.argv = apply_argv;
302 if (run_command(&child))
990ac4be 303 die (_("Could not apply '%s'"), file);
c59cb03a
JS
304
305 unlink(file);
d292bfaf 306 free(file);
c59cb03a
JS
307 return 0;
308}
309
021b6e45 310static struct lock_file lock_file;
0d781539 311
b39c53e6 312static const char ignore_error[] =
439fb829 313N_("The following paths are ignored by one of your .gitignore files:\n");
6a1ad325 314
5c46f754 315static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
108da0db 316static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
5c46f754
KH
317
318static struct option builtin_add_options[] = {
1b56024c
NTND
319 OPT__DRY_RUN(&show_only, N_("dry run")),
320 OPT__VERBOSE(&verbose, N_("be verbose")),
5c46f754 321 OPT_GROUP(""),
1b56024c
NTND
322 OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
323 OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
324 OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
325 OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
326 OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
327 OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
328 OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
329 OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
330 OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
331 OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
5c46f754
KH
332 OPT_END(),
333};
334
9bd81e42 335static int add_config(const char *var, const char *value, void *cb)
dad25e4a 336{
8c2be75f
JN
337 if (!strcmp(var, "add.ignoreerrors") ||
338 !strcmp(var, "add.ignore-errors")) {
dad25e4a
AR
339 ignore_add_errors = git_config_bool(var, value);
340 return 0;
341 }
9bd81e42 342 return git_default_config(var, value, cb);
dad25e4a
AR
343}
344
c972ec04
JH
345static int add_files(struct dir_struct *dir, int flags)
346{
347 int i, exit_status = 0;
348
349 if (dir->ignored_nr) {
439fb829 350 fprintf(stderr, _(ignore_error));
c972ec04
JH
351 for (i = 0; i < dir->ignored_nr; i++)
352 fprintf(stderr, "%s\n", dir->ignored[i]->name);
439fb829
ÆAB
353 fprintf(stderr, _("Use -f if you really want to add them.\n"));
354 die(_("no files added"));
c972ec04
JH
355 }
356
357 for (i = 0; i < dir->nr; i++)
358 if (add_file_to_cache(dir->entries[i]->name, flags)) {
359 if (!ignore_add_errors)
990ac4be 360 die(_("adding files failed"));
c972ec04
JH
361 exit_status = 1;
362 }
363 return exit_status;
364}
365
a633fca0 366int cmd_add(int argc, const char **argv, const char *prefix)
0d781539 367{
7ae02a30 368 int exit_status = 0;
c972ec04 369 int newfd;
0d781539
LT
370 const char **pathspec;
371 struct dir_struct dir;
205ffa94 372 int flags;
c972ec04
JH
373 int add_new_files;
374 int require_pathspec;
81f45e7d 375 char *seen = NULL;
5cde71d6 376
ed342fde
SB
377 git_config(add_config, NULL);
378
37782920 379 argc = parse_options(argc, argv, prefix, builtin_add_options,
c59cb03a 380 builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
b63e9950
WC
381 if (patch_interactive)
382 add_interactive = 1;
7c0ab445 383 if (add_interactive)
b4bd4668 384 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
0d781539 385
c59cb03a
JS
386 if (edit_interactive)
387 return(edit_patch(argc, argv, prefix));
388 argc--;
389 argv++;
390
3ba1f114 391 if (addremove && take_worktree_changes)
990ac4be 392 die(_("-A and -u are mutually incompatible"));
108da0db 393 if (!show_only && ignore_missing)
990ac4be 394 die(_("Option --ignore-missing can only be used together with --dry-run"));
0fa2eb53
MM
395 if (addremove) {
396 option_with_implicit_dot = "--all";
397 short_option_with_implicit_dot = "-A";
398 }
399 if (take_worktree_changes) {
400 option_with_implicit_dot = "--update";
401 short_option_with_implicit_dot = "-u";
402 }
403 if (option_with_implicit_dot && !argc) {
3ba1f114 404 static const char *here[2] = { ".", NULL };
0fa2eb53 405 if (prefix)
e24afab0 406 warn_pathless_add();
3ba1f114
JH
407 argc = 1;
408 argv = here;
409 }
410
c972ec04
JH
411 add_new_files = !take_worktree_changes && !refresh_only;
412 require_pathspec = !take_worktree_changes;
413
30ca07a2 414 newfd = hold_locked_index(&lock_file, 1);
0d781539 415
205ffa94 416 flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
01665924 417 (show_only ? ADD_CACHE_PRETEND : 0) |
39425819 418 (intent_to_add ? ADD_CACHE_INTENT : 0) |
1e5f764c
JH
419 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
420 (!(addremove || take_worktree_changes)
421 ? ADD_CACHE_IGNORE_REMOVAL : 0));
205ffa94 422
c972ec04 423 if (require_pathspec && argc == 0) {
990ac4be
ÆAB
424 fprintf(stderr, _("Nothing specified, nothing added.\n"));
425 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
93b0d86a
JH
426 return 0;
427 }
f8a1113b 428 pathspec = validate_pathspec(argv, prefix);
0d781539 429
366bfcb6 430 if (read_cache() < 0)
990ac4be 431 die(_("index file corrupt"));
2ce53f9b 432 treat_gitlinks(pathspec);
366bfcb6 433
1d8842d9
LT
434 if (add_new_files) {
435 int baselen;
436
437 /* Set up the default git porcelain excludes */
438 memset(&dir, 0, sizeof(dir));
439 if (!ignored_too) {
440 dir.flags |= DIR_COLLECT_IGNORED;
441 setup_standard_excludes(&dir);
442 }
443
1e5f764c 444 /* This picks up the paths that are not tracked */
1d8842d9
LT
445 baselen = fill_directory(&dir, pathspec);
446 if (pathspec)
81f45e7d 447 seen = prune_directory(&dir, pathspec, baselen);
1d8842d9 448 }
1e5f764c 449
c972ec04
JH
450 if (refresh_only) {
451 refresh(verbose, pathspec);
452 goto finish;
6a1ad325
JH
453 }
454
81f45e7d
JH
455 if (pathspec) {
456 int i;
eb69934b
JH
457 struct path_exclude_check check;
458
459 path_exclude_check_init(&check, &dir);
81f45e7d 460 if (!seen)
4b78d7bc 461 seen = find_pathspecs_matching_against_index(pathspec);
81f45e7d
JH
462 for (i = 0; pathspec[i]; i++) {
463 if (!seen[i] && pathspec[i][0]
108da0db
JL
464 && !file_exists(pathspec[i])) {
465 if (ignore_missing) {
0188f6b3 466 int dtype = DT_UNKNOWN;
9013089c 467 if (is_path_excluded(&check, pathspec[i], -1, &dtype))
108da0db
JL
468 dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
469 } else
48168851 470 die(_("pathspec '%s' did not match any files"),
108da0db
JL
471 pathspec[i]);
472 }
81f45e7d
JH
473 }
474 free(seen);
eb69934b 475 path_exclude_check_clear(&check);
81f45e7d
JH
476 }
477
568508e7
JH
478 plug_bulk_checkin();
479
1e5f764c 480 exit_status |= add_files_to_cache(prefix, pathspec, flags);
c972ec04
JH
481
482 if (add_new_files)
483 exit_status |= add_files(&dir, flags);
0d781539 484
568508e7
JH
485 unplug_bulk_checkin();
486
dfdac5d9 487 finish:
0d781539
LT
488 if (active_cache_changed) {
489 if (write_cache(newfd, active_cache, active_nr) ||
4ed7cd3a 490 commit_locked_index(&lock_file))
990ac4be 491 die(_("Unable to write new index file"));
0d781539
LT
492 }
493
7ae02a30 494 return exit_status;
0d781539 495}