add.c 13.1 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 29 30
	int flags;
	int add_errors;
};

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
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;
}

52 53 54 55 56 57 58 59 60
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;
61
		switch (fix_unmerged_status(p, data)) {
62
		default:
63
			die(_("unexpected diff status %c"), p->status);
64 65 66 67
		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))
68
					die(_("updating files failed"));
69 70 71 72 73 74 75 76 77
				data->add_errors++;
			}
			break;
		case DIFF_STATUS_DELETED:
			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))
78
				printf(_("remove '%s'\n"), path);
79 80 81 82 83 84 85 86 87 88 89
			break;
		}
	}
}

int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
{
	struct update_callback_data data;
	struct rev_info rev;
	init_revisions(&rev, prefix);
	setup_revisions(0, NULL, &rev, NULL);
90
	init_pathspec(&rev.prune_data, pathspec);
91 92 93 94 95
	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
	rev.diffopt.format_callback = update_callback;
	data.flags = flags;
	data.add_errors = 0;
	rev.diffopt.format_callback_data = &data;
96
	rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
97 98 99 100
	run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
	return !!data.add_errors;
}

101
static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
L
Linus Torvalds 已提交
102
{
103 104
	char *seen;
	int i, specs;
L
Linus Torvalds 已提交
105 106
	struct dir_entry **src, **dst;

107 108
	for (specs = 0; pathspec[specs];  specs++)
		/* nothing */;
109
	seen = xcalloc(specs, 1);
110

L
Linus Torvalds 已提交
111 112 113 114
	src = dst = dir->entries;
	i = dir->nr;
	while (--i >= 0) {
		struct dir_entry *entry = *src++;
J
Junio C Hamano 已提交
115 116 117
		if (match_pathspec(pathspec, entry->name, entry->len,
				   prefix, seen))
			*dst++ = entry;
L
Linus Torvalds 已提交
118 119
	}
	dir->nr = dst - dir->entries;
120
	add_pathspec_matches_against_index(pathspec, seen, specs);
121
	return seen;
L
Linus Torvalds 已提交
122 123
}

124 125 126 127
/*
 * Checks the index to see whether any path in pathspec refers to
 * something inside a submodule.  If so, dies with an error message.
 */
128 129 130 131 132 133 134
static void treat_gitlinks(const char **pathspec)
{
	int i;

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

135 136
	for (i = 0; pathspec[i]; i++)
		pathspec[i] = check_path_for_gitlink(pathspec[i]);
137 138
}

139 140 141 142 143 144 145 146
static void refresh(int verbose, const char **pathspec)
{
	char *seen;
	int i, specs;

	for (specs = 0; pathspec[specs];  specs++)
		/* nothing */;
	seen = xcalloc(specs, 1);
147
	refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
148
		      pathspec, seen, _("Unstaged changes after refreshing the index:"));
149 150
	for (i = 0; i < specs; i++) {
		if (!seen[i])
151
			die(_("pathspec '%s' did not match any files"), pathspec[i]);
152
	}
153
        free(seen);
154 155
}

156 157 158 159 160
/*
 * Normalizes argv relative to prefix, via get_pathspec(), and then
 * runs die_if_path_beyond_symlink() on each path in the normalized
 * list.
 */
161
static const char **validate_pathspec(const char **argv, const char *prefix)
162 163 164
{
	const char **pathspec = get_pathspec(prefix, argv);

165 166 167
	if (pathspec) {
		const char **p;
		for (p = pathspec; *p; p++) {
168
			die_if_path_beyond_symlink(*p, prefix);
169 170 171
		}
	}

172 173 174
	return pathspec;
}

175 176
int run_add_interactive(const char *revision, const char *patch_mode,
			const char **pathspec)
177
{
178
	int status, ac, pc = 0;
179 180
	const char **args;

181 182 183
	if (pathspec)
		while (pathspec[pc])
			pc++;
184

185
	args = xcalloc(sizeof(const char *), (pc + 5));
186 187
	ac = 0;
	args[ac++] = "add--interactive";
188 189 190 191
	if (patch_mode)
		args[ac++] = patch_mode;
	if (revision)
		args[ac++] = revision;
192
	args[ac++] = "--";
193 194 195
	if (pc) {
		memcpy(&(args[ac]), pathspec, sizeof(const char *) * pc);
		ac += pc;
196 197
	}
	args[ac] = NULL;
198 199 200 201

	status = run_command_v_opt(args, RUN_GIT_CMD);
	free(args);
	return status;
202 203
}

204
int interactive_add(int argc, const char **argv, const char *prefix, int patch)
205 206 207 208
{
	const char **pathspec = NULL;

	if (argc) {
209
		pathspec = validate_pathspec(argv, prefix);
210 211 212 213 214
		if (!pathspec)
			return -1;
	}

	return run_add_interactive(NULL,
215
				   patch ? "--patch" : NULL,
216 217 218
				   pathspec);
}

219
static int edit_patch(int argc, const char **argv, const char *prefix)
220
{
221
	char *file = git_pathdup("ADD_EDIT.patch");
222
	const char *apply_argv[] = { "apply", "--recount", "--cached",
223
		NULL, NULL };
224 225 226 227 228
	struct child_process child;
	struct rev_info rev;
	int out;
	struct stat st;

229 230
	apply_argv[3] = file;

231 232 233
	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */

	if (read_cache() < 0)
234
		die (_("Could not read the index"));
235 236 237 238 239 240

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

	argc = setup_revisions(argc, argv, &rev, NULL);
	rev.diffopt.output_format = DIFF_FORMAT_PATCH;
241
	DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
242
	out = open(file, O_CREAT | O_WRONLY, 0666);
243
	if (out < 0)
244
		die (_("Could not open '%s' for writing."), file);
245
	rev.diffopt.file = xfdopen(out, "w");
246 247
	rev.diffopt.close_file = 1;
	if (run_diff_files(&rev, 0))
248
		die (_("Could not write patch"));
249 250 251 252

	launch_editor(file, NULL, NULL);

	if (stat(file, &st))
253
		die_errno(_("Could not stat '%s'"), file);
254
	if (!st.st_size)
255
		die(_("Empty patch. Aborted."));
256 257 258 259 260

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

	unlink(file);
264
	free(file);
265 266 267
	return 0;
}

268
static struct lock_file lock_file;
L
Linus Torvalds 已提交
269

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

273
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
274
static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
275 276

static struct option builtin_add_options[] = {
277 278
	OPT__DRY_RUN(&show_only, N_("dry run")),
	OPT__VERBOSE(&verbose, N_("be verbose")),
279
	OPT_GROUP(""),
280 281 282 283 284 285 286 287 288 289
	OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
	OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
	OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
	OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
	OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
	OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
	OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
	OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
	OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
	OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
290 291 292
	OPT_END(),
};

J
Junio C Hamano 已提交
293
static int add_config(const char *var, const char *value, void *cb)
294
{
295 296
	if (!strcmp(var, "add.ignoreerrors") ||
	    !strcmp(var, "add.ignore-errors")) {
297 298 299
		ignore_add_errors = git_config_bool(var, value);
		return 0;
	}
J
Junio C Hamano 已提交
300
	return git_default_config(var, value, cb);
301 302
}

303 304 305 306 307
static int add_files(struct dir_struct *dir, int flags)
{
	int i, exit_status = 0;

	if (dir->ignored_nr) {
308
		fprintf(stderr, _(ignore_error));
309 310
		for (i = 0; i < dir->ignored_nr; i++)
			fprintf(stderr, "%s\n", dir->ignored[i]->name);
311 312
		fprintf(stderr, _("Use -f if you really want to add them.\n"));
		die(_("no files added"));
313 314 315 316 317
	}

	for (i = 0; i < dir->nr; i++)
		if (add_file_to_cache(dir->entries[i]->name, flags)) {
			if (!ignore_add_errors)
318
				die(_("adding files failed"));
319 320 321 322 323
			exit_status = 1;
		}
	return exit_status;
}

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
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);
}

353
int cmd_add(int argc, const char **argv, const char *prefix)
L
Linus Torvalds 已提交
354
{
355
	int exit_status = 0;
356
	int newfd;
L
Linus Torvalds 已提交
357 358
	const char **pathspec;
	struct dir_struct dir;
359
	int flags;
360 361
	int add_new_files;
	int require_pathspec;
362
	char *seen = NULL;
363 364
	const char *option_with_implicit_dot = NULL;
	const char *short_option_with_implicit_dot = NULL;
J
Junio C Hamano 已提交
365

366 367
	git_config(add_config, NULL);

368
	argc = parse_options(argc, argv, prefix, builtin_add_options,
369
			  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
370 371
	if (patch_interactive)
		add_interactive = 1;
372
	if (add_interactive)
373
		exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
L
Linus Torvalds 已提交
374

375 376 377 378 379
	if (edit_interactive)
		return(edit_patch(argc, argv, prefix));
	argc--;
	argv++;

J
Junio C Hamano 已提交
380
	if (addremove && take_worktree_changes)
381
		die(_("-A and -u are mutually incompatible"));
382
	if (!show_only && ignore_missing)
383
		die(_("Option --ignore-missing can only be used together with --dry-run"));
384 385 386 387 388 389 390 391 392
	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 已提交
393
		static const char *here[2] = { ".", NULL };
394 395 396
		if (prefix)
			warn_pathless_add(option_with_implicit_dot,
					  short_option_with_implicit_dot);
J
Junio C Hamano 已提交
397 398 399 400
		argc = 1;
		argv = here;
	}

401 402 403
	add_new_files = !take_worktree_changes && !refresh_only;
	require_pathspec = !take_worktree_changes;

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

406
	flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
J
Junio C Hamano 已提交
407
		 (show_only ? ADD_CACHE_PRETEND : 0) |
J
Junio C Hamano 已提交
408
		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
409 410 411
		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
		 (!(addremove || take_worktree_changes)
		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
412

413
	if (require_pathspec && argc == 0) {
414 415
		fprintf(stderr, _("Nothing specified, nothing added.\n"));
		fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
416 417
		return 0;
	}
418
	pathspec = validate_pathspec(argv, prefix);
L
Linus Torvalds 已提交
419

420
	if (read_cache() < 0)
421
		die(_("index file corrupt"));
422
	treat_gitlinks(pathspec);
423

424 425 426 427 428 429 430 431 432 433
	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);
		}

434
		/* This picks up the paths that are not tracked */
435 436
		baselen = fill_directory(&dir, pathspec);
		if (pathspec)
437
			seen = prune_directory(&dir, pathspec, baselen);
438
	}
439

440 441 442
	if (refresh_only) {
		refresh(verbose, pathspec);
		goto finish;
443 444
	}

445 446
	if (pathspec) {
		int i;
447 448 449
		struct path_exclude_check check;

		path_exclude_check_init(&check, &dir);
450
		if (!seen)
451
			seen = find_pathspecs_matching_against_index(pathspec);
452 453
		for (i = 0; pathspec[i]; i++) {
			if (!seen[i] && pathspec[i][0]
454 455
			    && !file_exists(pathspec[i])) {
				if (ignore_missing) {
456
					int dtype = DT_UNKNOWN;
457
					if (is_path_excluded(&check, pathspec[i], -1, &dtype))
458 459
						dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
				} else
460
					die(_("pathspec '%s' did not match any files"),
461 462
					    pathspec[i]);
			}
463 464
		}
		free(seen);
465
		path_exclude_check_clear(&check);
466 467
	}

468 469
	plug_bulk_checkin();

470
	exit_status |= add_files_to_cache(prefix, pathspec, flags);
471 472 473

	if (add_new_files)
		exit_status |= add_files(&dir, flags);
L
Linus Torvalds 已提交
474

475 476
	unplug_bulk_checkin();

477
 finish:
L
Linus Torvalds 已提交
478 479
	if (active_cache_changed) {
		if (write_cache(newfd, active_cache, active_nr) ||
B
Brandon Casey 已提交
480
		    commit_locked_index(&lock_file))
481
			die(_("Unable to write new index file"));
L
Linus Torvalds 已提交
482 483
	}

484
	return exit_status;
L
Linus Torvalds 已提交
485
}