add.c 14.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/*
 * "git add" builtin command
 *
 * Copyright (C) 2006 Linus Torvalds
 */
#include "cache.h"
#include "builtin.h"
#include "dir.h"
9
#include "pathspec.h"
J
Junio C Hamano 已提交
10
#include "exec_cmd.h"
11
#include "cache-tree.h"
12
#include "run-command.h"
13
#include "parse-options.h"
14
#include "diff.h"
15
#include "diffcore.h"
16
#include "revision.h"
17
#include "bulk-checkin.h"
L
Linus Torvalds 已提交
18

19
static const char * const builtin_add_usage[] = {
20
	N_("git add [options] [--] <pathspec>..."),
21 22
	NULL
};
23
static int patch_interactive, add_interactive, edit_interactive;
J
Jeff King 已提交
24
static int take_worktree_changes;
25

26
struct update_callback_data {
27 28
	int flags;
	int add_errors;
29 30 31

	/* only needed for 2.0 transition preparation */
	int warn_add_would_remove;
32 33
};

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
static int fix_unmerged_status(struct diff_filepair *p,
			       struct update_callback_data *data)
{
	if (p->status != DIFF_STATUS_UNMERGED)
		return p->status;
	if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
		/*
		 * This is not an explicit add request, and the
		 * path is missing from the working tree (deleted)
		 */
		return DIFF_STATUS_DELETED;
	else
		/*
		 * Either an explicit add request, or path exists
		 * in the working tree.  An attempt to explicitly
		 * add a path that does not exist in the working tree
		 * will be caught as an error by the caller immediately.
		 */
		return DIFF_STATUS_MODIFIED;
}

55 56 57 58 59 60 61 62 63 64 65
static void warn_add_would_remove(const char *path)
{
	warning(_("In Git 2.0, 'git add <pathspec>...' will also update the\n"
		  "index for paths removed from the working tree that match\n"
		  "the given pathspec. If you want to 'add' only changed\n"
		  "or newly created paths, say 'git add --no-all <pathspec>...'"
		  " instead.\n\n"
		  "'%s' would be removed from the index without --no-all."),
		path);
}

66 67 68 69 70 71 72 73 74
static void update_callback(struct diff_queue_struct *q,
			    struct diff_options *opt, void *cbdata)
{
	int i;
	struct update_callback_data *data = cbdata;

	for (i = 0; i < q->nr; i++) {
		struct diff_filepair *p = q->queue[i];
		const char *path = p->one->path;
75
		switch (fix_unmerged_status(p, data)) {
76
		default:
77
			die(_("unexpected diff status %c"), p->status);
78 79 80 81
		case DIFF_STATUS_MODIFIED:
		case DIFF_STATUS_TYPE_CHANGED:
			if (add_file_to_index(&the_index, path, data->flags)) {
				if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
82
					die(_("updating files failed"));
83 84 85 86
				data->add_errors++;
			}
			break;
		case DIFF_STATUS_DELETED:
87 88 89 90
			if (data->warn_add_would_remove) {
				warn_add_would_remove(path);
				data->warn_add_would_remove = 0;
			}
91 92 93 94 95
			if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
				break;
			if (!(data->flags & ADD_CACHE_PRETEND))
				remove_file_from_index(&the_index, path);
			if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
96
				printf(_("remove '%s'\n"), path);
97 98 99 100 101
			break;
		}
	}
}

102 103
static void update_files_in_cache(const char *prefix, const char **pathspec,
				  struct update_callback_data *data)
104 105 106 107
{
	struct rev_info rev;
	init_revisions(&rev, prefix);
	setup_revisions(0, NULL, &rev, NULL);
108
	init_pathspec(&rev.prune_data, pathspec);
109 110
	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
	rev.diffopt.format_callback = update_callback;
111
	rev.diffopt.format_callback_data = data;
112
	rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
113
	run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
114 115 116 117 118 119 120 121 122
}

int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
{
	struct update_callback_data data;

	memset(&data, 0, sizeof(data));
	data.flags = flags;
	update_files_in_cache(prefix, pathspec, &data);
123 124 125
	return !!data.add_errors;
}

126
static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
L
Linus Torvalds 已提交
127
{
128 129
	char *seen;
	int i, specs;
L
Linus Torvalds 已提交
130 131
	struct dir_entry **src, **dst;

132 133
	for (specs = 0; pathspec[specs];  specs++)
		/* nothing */;
134
	seen = xcalloc(specs, 1);
135

L
Linus Torvalds 已提交
136 137 138 139
	src = dst = dir->entries;
	i = dir->nr;
	while (--i >= 0) {
		struct dir_entry *entry = *src++;
J
Junio C Hamano 已提交
140 141 142
		if (match_pathspec(pathspec, entry->name, entry->len,
				   prefix, seen))
			*dst++ = entry;
L
Linus Torvalds 已提交
143 144
	}
	dir->nr = dst - dir->entries;
145
	add_pathspec_matches_against_index(pathspec, seen, specs);
146
	return seen;
L
Linus Torvalds 已提交
147 148
}

149 150 151 152
/*
 * Checks the index to see whether any path in pathspec refers to
 * something inside a submodule.  If so, dies with an error message.
 */
153 154 155 156 157 158 159
static void treat_gitlinks(const char **pathspec)
{
	int i;

	if (!pathspec || !*pathspec)
		return;

160 161
	for (i = 0; pathspec[i]; i++)
		pathspec[i] = check_path_for_gitlink(pathspec[i]);
162 163
}

164 165 166 167 168 169 170 171
static void refresh(int verbose, const char **pathspec)
{
	char *seen;
	int i, specs;

	for (specs = 0; pathspec[specs];  specs++)
		/* nothing */;
	seen = xcalloc(specs, 1);
172
	refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
173
		      pathspec, seen, _("Unstaged changes after refreshing the index:"));
174 175
	for (i = 0; i < specs; i++) {
		if (!seen[i])
176
			die(_("pathspec '%s' did not match any files"), pathspec[i]);
177
	}
178
        free(seen);
179 180
}

181 182 183 184 185
/*
 * Normalizes argv relative to prefix, via get_pathspec(), and then
 * runs die_if_path_beyond_symlink() on each path in the normalized
 * list.
 */
186
static const char **validate_pathspec(const char **argv, const char *prefix)
187 188 189
{
	const char **pathspec = get_pathspec(prefix, argv);

190 191 192
	if (pathspec) {
		const char **p;
		for (p = pathspec; *p; p++) {
193
			die_if_path_beyond_symlink(*p, prefix);
194 195 196
		}
	}

197 198 199
	return pathspec;
}

200 201
int run_add_interactive(const char *revision, const char *patch_mode,
			const char **pathspec)
202
{
203
	int status, ac, pc = 0;
204 205
	const char **args;

206 207 208
	if (pathspec)
		while (pathspec[pc])
			pc++;
209

210
	args = xcalloc(sizeof(const char *), (pc + 5));
211 212
	ac = 0;
	args[ac++] = "add--interactive";
213 214 215 216
	if (patch_mode)
		args[ac++] = patch_mode;
	if (revision)
		args[ac++] = revision;
217
	args[ac++] = "--";
218 219 220
	if (pc) {
		memcpy(&(args[ac]), pathspec, sizeof(const char *) * pc);
		ac += pc;
221 222
	}
	args[ac] = NULL;
223 224 225 226

	status = run_command_v_opt(args, RUN_GIT_CMD);
	free(args);
	return status;
227 228
}

229
int interactive_add(int argc, const char **argv, const char *prefix, int patch)
230 231 232 233
{
	const char **pathspec = NULL;

	if (argc) {
234
		pathspec = validate_pathspec(argv, prefix);
235 236 237 238 239
		if (!pathspec)
			return -1;
	}

	return run_add_interactive(NULL,
240
				   patch ? "--patch" : NULL,
241 242 243
				   pathspec);
}

244
static int edit_patch(int argc, const char **argv, const char *prefix)
245
{
246
	char *file = git_pathdup("ADD_EDIT.patch");
247
	const char *apply_argv[] = { "apply", "--recount", "--cached",
248
		NULL, NULL };
249 250 251 252 253
	struct child_process child;
	struct rev_info rev;
	int out;
	struct stat st;

254 255
	apply_argv[3] = file;

256 257 258
	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */

	if (read_cache() < 0)
259
		die (_("Could not read the index"));
260 261 262 263 264 265

	init_revisions(&rev, prefix);
	rev.diffopt.context = 7;

	argc = setup_revisions(argc, argv, &rev, NULL);
	rev.diffopt.output_format = DIFF_FORMAT_PATCH;
266
	DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
267
	out = open(file, O_CREAT | O_WRONLY, 0666);
268
	if (out < 0)
269
		die (_("Could not open '%s' for writing."), file);
270
	rev.diffopt.file = xfdopen(out, "w");
271 272
	rev.diffopt.close_file = 1;
	if (run_diff_files(&rev, 0))
273
		die (_("Could not write patch"));
274 275 276 277

	launch_editor(file, NULL, NULL);

	if (stat(file, &st))
278
		die_errno(_("Could not stat '%s'"), file);
279
	if (!st.st_size)
280
		die(_("Empty patch. Aborted."));
281 282 283 284 285

	memset(&child, 0, sizeof(child));
	child.git_cmd = 1;
	child.argv = apply_argv;
	if (run_command(&child))
286
		die (_("Could not apply '%s'"), file);
287 288

	unlink(file);
289
	free(file);
290 291 292
	return 0;
}

293
static struct lock_file lock_file;
L
Linus Torvalds 已提交
294

295
static const char ignore_error[] =
296
N_("The following paths are ignored by one of your .gitignore files:\n");
297

298
static int verbose, show_only, ignored_too, refresh_only;
299 300 301 302 303
static int ignore_add_errors, intent_to_add, ignore_missing;

#define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */
static int addremove = ADDREMOVE_DEFAULT;
static int addremove_explicit = -1; /* unspecified */
304 305

static struct option builtin_add_options[] = {
306 307
	OPT__DRY_RUN(&show_only, N_("dry run")),
	OPT__VERBOSE(&verbose, N_("be verbose")),
308
	OPT_GROUP(""),
309 310 311
	OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
	OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
	OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
312
	OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
313 314
	OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
	OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
315
	OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
316 317 318
	OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
	OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
	OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
319 320 321
	OPT_END(),
};

J
Junio C Hamano 已提交
322
static int add_config(const char *var, const char *value, void *cb)
323
{
324 325
	if (!strcmp(var, "add.ignoreerrors") ||
	    !strcmp(var, "add.ignore-errors")) {
326 327 328
		ignore_add_errors = git_config_bool(var, value);
		return 0;
	}
J
Junio C Hamano 已提交
329
	return git_default_config(var, value, cb);
330 331
}

332 333 334 335 336
static int add_files(struct dir_struct *dir, int flags)
{
	int i, exit_status = 0;

	if (dir->ignored_nr) {
337
		fprintf(stderr, _(ignore_error));
338 339
		for (i = 0; i < dir->ignored_nr; i++)
			fprintf(stderr, "%s\n", dir->ignored[i]->name);
340 341
		fprintf(stderr, _("Use -f if you really want to add them.\n"));
		die(_("no files added"));
342 343 344 345 346
	}

	for (i = 0; i < dir->nr; i++)
		if (add_file_to_cache(dir->entries[i]->name, flags)) {
			if (!ignore_add_errors)
347
				die(_("adding files failed"));
348 349 350 351 352
			exit_status = 1;
		}
	return exit_status;
}

353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
static void warn_pathless_add(const char *option_name, const char *short_name) {
	/*
	 * To be consistent with "git add -p" and most Git
	 * commands, we should default to being tree-wide, but
	 * this is not the original behavior and can't be
	 * changed until users trained themselves not to type
	 * "git add -u" or "git add -A". For now, we warn and
	 * keep the old behavior. Later, this warning can be
	 * turned into a die(...), and eventually we may
	 * reallow the command with a new behavior.
	 */
	warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
		  "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
		  "To add content for the whole tree, run:\n"
		  "\n"
		  "  git add %s :/\n"
		  "  (or git add %s :/)\n"
		  "\n"
		  "To restrict the command to the current directory, run:\n"
		  "\n"
		  "  git add %s .\n"
		  "  (or git add %s .)\n"
		  "\n"
		  "With the current Git version, the command is restricted to the current directory."),
		option_name, short_name,
		option_name, short_name,
		option_name, short_name);
}

382
int cmd_add(int argc, const char **argv, const char *prefix)
L
Linus Torvalds 已提交
383
{
384
	int exit_status = 0;
385
	int newfd;
L
Linus Torvalds 已提交
386 387
	const char **pathspec;
	struct dir_struct dir;
388
	int flags;
389 390
	int add_new_files;
	int require_pathspec;
391
	char *seen = NULL;
392 393
	const char *option_with_implicit_dot = NULL;
	const char *short_option_with_implicit_dot = NULL;
394
	struct update_callback_data update_data;
J
Junio C Hamano 已提交
395

396 397
	git_config(add_config, NULL);

398
	argc = parse_options(argc, argv, prefix, builtin_add_options,
399
			  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
400 401
	if (patch_interactive)
		add_interactive = 1;
402
	if (add_interactive)
403
		exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
L
Linus Torvalds 已提交
404

405 406 407 408 409
	if (edit_interactive)
		return(edit_patch(argc, argv, prefix));
	argc--;
	argv++;

410 411 412 413 414
	if (0 <= addremove_explicit)
		addremove = addremove_explicit;
	else if (take_worktree_changes && ADDREMOVE_DEFAULT)
		addremove = 0; /* "-u" was given but not "-A" */

J
Junio C Hamano 已提交
415
	if (addremove && take_worktree_changes)
416
		die(_("-A and -u are mutually incompatible"));
417 418 419

	/*
	 * Warn when "git add pathspec..." was given without "-u" or "-A"
420
	 * and pathspec... covers a removed path.
421
	 */
422 423 424
	memset(&update_data, 0, sizeof(update_data));
	if (!take_worktree_changes && addremove_explicit < 0)
		update_data.warn_add_would_remove = 1;
425 426 427 428 429 430 431 432

	if (!take_worktree_changes && addremove_explicit < 0 && argc)
		/*
		 * Turn "git add pathspec..." to "git add -A pathspec..."
		 * in Git 2.0 but not yet
		 */
		; /* addremove = 1; */

433
	if (!show_only && ignore_missing)
434
		die(_("Option --ignore-missing can only be used together with --dry-run"));
435 436 437 438 439 440 441 442 443
	if (addremove) {
		option_with_implicit_dot = "--all";
		short_option_with_implicit_dot = "-A";
	}
	if (take_worktree_changes) {
		option_with_implicit_dot = "--update";
		short_option_with_implicit_dot = "-u";
	}
	if (option_with_implicit_dot && !argc) {
J
Junio C Hamano 已提交
444
		static const char *here[2] = { ".", NULL };
445 446 447
		if (prefix)
			warn_pathless_add(option_with_implicit_dot,
					  short_option_with_implicit_dot);
J
Junio C Hamano 已提交
448 449 450 451
		argc = 1;
		argv = here;
	}

452 453 454
	add_new_files = !take_worktree_changes && !refresh_only;
	require_pathspec = !take_worktree_changes;

455
	newfd = hold_locked_index(&lock_file, 1);
L
Linus Torvalds 已提交
456

457
	flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
J
Junio C Hamano 已提交
458
		 (show_only ? ADD_CACHE_PRETEND : 0) |
J
Junio C Hamano 已提交
459
		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
460 461 462
		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
		 (!(addremove || take_worktree_changes)
		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
463

464
	if (require_pathspec && argc == 0) {
465 466
		fprintf(stderr, _("Nothing specified, nothing added.\n"));
		fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
467 468
		return 0;
	}
469
	pathspec = validate_pathspec(argv, prefix);
L
Linus Torvalds 已提交
470

471
	if (read_cache() < 0)
472
		die(_("index file corrupt"));
473
	treat_gitlinks(pathspec);
474

475 476 477 478 479 480 481 482 483 484
	if (add_new_files) {
		int baselen;

		/* Set up the default git porcelain excludes */
		memset(&dir, 0, sizeof(dir));
		if (!ignored_too) {
			dir.flags |= DIR_COLLECT_IGNORED;
			setup_standard_excludes(&dir);
		}

485
		/* This picks up the paths that are not tracked */
486 487
		baselen = fill_directory(&dir, pathspec);
		if (pathspec)
488
			seen = prune_directory(&dir, pathspec, baselen);
489
	}
490

491 492 493
	if (refresh_only) {
		refresh(verbose, pathspec);
		goto finish;
494 495
	}

496 497
	if (pathspec) {
		int i;
498 499 500
		struct path_exclude_check check;

		path_exclude_check_init(&check, &dir);
501
		if (!seen)
502
			seen = find_pathspecs_matching_against_index(pathspec);
503 504
		for (i = 0; pathspec[i]; i++) {
			if (!seen[i] && pathspec[i][0]
505 506
			    && !file_exists(pathspec[i])) {
				if (ignore_missing) {
507
					int dtype = DT_UNKNOWN;
508
					if (is_path_excluded(&check, pathspec[i], -1, &dtype))
509 510
						dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
				} else
511
					die(_("pathspec '%s' did not match any files"),
512 513
					    pathspec[i]);
			}
514 515
		}
		free(seen);
516
		path_exclude_check_clear(&check);
517 518
	}

519 520
	plug_bulk_checkin();

521 522
	update_data.flags = flags;
	update_files_in_cache(prefix, pathspec, &update_data);
523

524
	exit_status |= !!update_data.add_errors;
525 526
	if (add_new_files)
		exit_status |= add_files(&dir, flags);
L
Linus Torvalds 已提交
527

528 529
	unplug_bulk_checkin();

530
 finish:
L
Linus Torvalds 已提交
531 532
	if (active_cache_changed) {
		if (write_cache(newfd, active_cache, active_nr) ||
B
Brandon Casey 已提交
533
		    commit_locked_index(&lock_file))
534
			die(_("Unable to write new index file"));
L
Linus Torvalds 已提交
535 536
	}

537
	return exit_status;
L
Linus Torvalds 已提交
538
}