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

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

30
struct update_callback_data {
31
	int flags;
32 33 34
	int add_errors;
};

35
static void chmod_pathspec(struct pathspec *pathspec, char flip)
36 37 38 39 40 41 42 43 44
{
	int i;

	for (i = 0; i < active_nr; i++) {
		struct cache_entry *ce = active_cache[i];

		if (pathspec && !ce_path_match(ce, pathspec, NULL))
			continue;

45 46
		if (chmod_cache_entry(ce, flip) < 0)
			fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
47 48 49
	}
}

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
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;
}

71 72 73 74 75 76 77 78 79
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;
80
		switch (fix_unmerged_status(p, data)) {
81
		default:
82
			die(_("unexpected diff status %c"), p->status);
83 84
		case DIFF_STATUS_MODIFIED:
		case DIFF_STATUS_TYPE_CHANGED:
85
			if (add_file_to_index(&the_index, path,	data->flags)) {
86
				if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
87
					die(_("updating files failed"));
88 89 90 91 92 93 94 95 96
				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))
97
				printf(_("remove '%s'\n"), path);
98 99 100 101 102
			break;
		}
	}
}

103 104
int add_files_to_cache(const char *prefix,
		       const struct pathspec *pathspec, int flags)
105
{
106
	struct update_callback_data data;
107
	struct rev_info rev;
108

109 110 111
	memset(&data, 0, sizeof(data));
	data.flags = flags;

112 113
	init_revisions(&rev, prefix);
	setup_revisions(0, NULL, &rev, NULL);
114 115
	if (pathspec)
		copy_pathspec(&rev.prune_data, pathspec);
116 117
	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
	rev.diffopt.format_callback = update_callback;
118
	rev.diffopt.format_callback_data = &data;
119
	rev.diffopt.flags |= DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
120
	rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
121 122 123 124
	run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
	return !!data.add_errors;
}

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

131
	seen = xcalloc(pathspec->nr, 1);
132

L
Linus Torvalds 已提交
133 134 135 136
	src = dst = dir->entries;
	i = dir->nr;
	while (--i >= 0) {
		struct dir_entry *entry = *src++;
137
		if (dir_path_match(entry, pathspec, prefix, seen))
J
Junio C Hamano 已提交
138
			*dst++ = entry;
L
Linus Torvalds 已提交
139 140
	}
	dir->nr = dst - dir->entries;
141
	add_pathspec_matches_against_index(pathspec, &the_index, seen);
142
	return seen;
L
Linus Torvalds 已提交
143 144
}

145
static void refresh(int verbose, const struct pathspec *pathspec)
146 147
{
	char *seen;
148
	int i;
149

150
	seen = xcalloc(pathspec->nr, 1);
151
	refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
152
		      pathspec, seen, _("Unstaged changes after refreshing the index:"));
153
	for (i = 0; i < pathspec->nr; i++) {
154
		if (!seen[i])
155 156
			die(_("pathspec '%s' did not match any files"),
			    pathspec->items[i].match);
157
	}
158
        free(seen);
159 160
}

161
int run_add_interactive(const char *revision, const char *patch_mode,
162
			const struct pathspec *pathspec)
163
{
164 165
	int status, i;
	struct argv_array argv = ARGV_ARRAY_INIT;
166

167
	argv_array_push(&argv, "add--interactive");
168
	if (patch_mode)
169
		argv_array_push(&argv, patch_mode);
170
	if (revision)
171 172
		argv_array_push(&argv, revision);
	argv_array_push(&argv, "--");
173 174
	for (i = 0; i < pathspec->nr; i++)
		/* pass original pathspec, to be re-parsed */
175
		argv_array_push(&argv, pathspec->items[i].original);
176

177 178
	status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
	argv_array_clear(&argv);
179
	return status;
180 181
}

182
int interactive_add(int argc, const char **argv, const char *prefix, int patch)
183
{
184
	struct pathspec pathspec;
185

186
	parse_pathspec(&pathspec, 0,
187
		       PATHSPEC_PREFER_FULL |
188 189
		       PATHSPEC_SYMLINK_LEADING_PATH |
		       PATHSPEC_PREFIX_ORIGIN,
190
		       prefix, argv);
191 192

	return run_add_interactive(NULL,
193
				   patch ? "--patch" : NULL,
194
				   &pathspec);
195 196
}

197
static int edit_patch(int argc, const char **argv, const char *prefix)
198
{
199
	char *file = git_pathdup("ADD_EDIT.patch");
200
	const char *apply_argv[] = { "apply", "--recount", "--cached",
201
		NULL, NULL };
202
	struct child_process child = CHILD_PROCESS_INIT;
203 204 205 206
	struct rev_info rev;
	int out;
	struct stat st;

207 208
	apply_argv[3] = file;

209 210 211
	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */

	if (read_cache() < 0)
F
Felipe Contreras 已提交
212
		die(_("Could not read the index"));
213 214 215 216 217 218

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

	argc = setup_revisions(argc, argv, &rev, NULL);
	rev.diffopt.output_format = DIFF_FORMAT_PATCH;
219
	rev.diffopt.use_color = 0;
220
	DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
221
	out = open(file, O_CREAT | O_WRONLY, 0666);
222
	if (out < 0)
F
Felipe Contreras 已提交
223
		die(_("Could not open '%s' for writing."), file);
224
	rev.diffopt.file = xfdopen(out, "w");
225 226
	rev.diffopt.close_file = 1;
	if (run_diff_files(&rev, 0))
F
Felipe Contreras 已提交
227
		die(_("Could not write patch"));
228

229 230
	if (launch_editor(file, NULL, NULL))
		die(_("editing patch failed"));
231 232

	if (stat(file, &st))
233
		die_errno(_("Could not stat '%s'"), file);
234
	if (!st.st_size)
235
		die(_("Empty patch. Aborted."));
236 237 238 239

	child.git_cmd = 1;
	child.argv = apply_argv;
	if (run_command(&child))
F
Felipe Contreras 已提交
240
		die(_("Could not apply '%s'"), file);
241 242

	unlink(file);
243
	free(file);
244 245 246
	return 0;
}

247
static struct lock_file lock_file;
L
Linus Torvalds 已提交
248

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

252
static int verbose, show_only, ignored_too, refresh_only;
253
static int ignore_add_errors, intent_to_add, ignore_missing;
254
static int warn_on_embedded_repo = 1;
255

256
#define ADDREMOVE_DEFAULT 1
257 258
static int addremove = ADDREMOVE_DEFAULT;
static int addremove_explicit = -1; /* unspecified */
259

260 261
static char *chmod_arg;

262 263 264 265 266 267 268
static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
{
	/* if we are told to ignore, we are not adding removals */
	*(int *)opt->value = !unset ? 0 : 1;
	return 0;
}

269
static struct option builtin_add_options[] = {
270 271
	OPT__DRY_RUN(&show_only, N_("dry run")),
	OPT__VERBOSE(&verbose, N_("be verbose")),
272
	OPT_GROUP(""),
273 274 275
	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")),
276
	OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
277 278
	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")),
279
	OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
280 281 282 283
	{ OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
	  NULL /* takes no arguments */,
	  N_("ignore paths removed in the working tree (same as --no-all)"),
	  PARSE_OPT_NOARG, ignore_removal_cb },
284 285 286
	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")),
287
	OPT_STRING( 0 , "chmod", &chmod_arg, N_("(+/-)x"), N_("override the executable bit of the listed files")),
288 289
	OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
			N_("warn when adding an embedded repository")),
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 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
static const char embedded_advice[] = N_(
"You've added another git repository inside your current repository.\n"
"Clones of the outer repository will not contain the contents of\n"
"the embedded repository and will not know how to obtain it.\n"
"If you meant to add a submodule, use:\n"
"\n"
"	git submodule add <url> %s\n"
"\n"
"If you added this path by mistake, you can remove it from the\n"
"index with:\n"
"\n"
"	git rm --cached %s\n"
"\n"
"See \"git help submodule\" for more information."
);

static void check_embedded_repo(const char *path)
{
	struct strbuf name = STRBUF_INIT;

	if (!warn_on_embedded_repo)
		return;
	if (!ends_with(path, "/"))
		return;

	/* Drop trailing slash for aesthetics */
	strbuf_addstr(&name, path);
	strbuf_strip_suffix(&name, "/");

	warning(_("adding embedded git repository: %s"), name.buf);
	if (advice_add_embedded_repo) {
		advise(embedded_advice, name.buf, name.buf);
		/* there may be multiple entries; advise only once */
		advice_add_embedded_repo = 0;
	}

	strbuf_release(&name);
}

342
static int add_files(struct dir_struct *dir, int flags)
343 344 345 346
{
	int i, exit_status = 0;

	if (dir->ignored_nr) {
347
		fprintf(stderr, _(ignore_error));
348 349
		for (i = 0; i < dir->ignored_nr; i++)
			fprintf(stderr, "%s\n", dir->ignored[i]->name);
350
		fprintf(stderr, _("Use -f if you really want to add them.\n"));
M
Michael J Gruber 已提交
351
		exit_status = 1;
352 353
	}

354 355
	for (i = 0; i < dir->nr; i++) {
		check_embedded_repo(dir->entries[i]->name);
356
		if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
357
			if (!ignore_add_errors)
358
				die(_("adding files failed"));
359 360
			exit_status = 1;
		}
361
	}
362 363 364
	return exit_status;
}

365
int cmd_add(int argc, const char **argv, const char *prefix)
L
Linus Torvalds 已提交
366
{
367
	int exit_status = 0;
368
	struct pathspec pathspec;
L
Linus Torvalds 已提交
369
	struct dir_struct dir;
370
	int flags;
371 372
	int add_new_files;
	int require_pathspec;
373
	char *seen = NULL;
J
Junio C Hamano 已提交
374

375 376
	git_config(add_config, NULL);

377
	argc = parse_options(argc, argv, prefix, builtin_add_options,
378
			  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
379 380
	if (patch_interactive)
		add_interactive = 1;
381
	if (add_interactive)
382
		exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
L
Linus Torvalds 已提交
383

384 385 386 387 388
	if (edit_interactive)
		return(edit_patch(argc, argv, prefix));
	argc--;
	argv++;

389 390 391 392 393
	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 已提交
394
	if (addremove && take_worktree_changes)
395
		die(_("-A and -u are mutually incompatible"));
396 397

	if (!take_worktree_changes && addremove_explicit < 0 && argc)
398 399
		/* Turn "git add pathspec..." to "git add -A pathspec..." */
		addremove = 1;
400

401
	if (!show_only && ignore_missing)
402
		die(_("Option --ignore-missing can only be used together with --dry-run"));
403

404 405
	if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
			  chmod_arg[1] != 'x' || chmod_arg[2]))
406 407
		die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);

408
	add_new_files = !take_worktree_changes && !refresh_only;
409
	require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
410

411
	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
L
Linus Torvalds 已提交
412

413
	flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
J
Junio C Hamano 已提交
414
		 (show_only ? ADD_CACHE_PRETEND : 0) |
J
Junio C Hamano 已提交
415
		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
416 417
		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
		 (!(addremove || take_worktree_changes)
418
		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
419

420
	if (require_pathspec && argc == 0) {
421 422
		fprintf(stderr, _("Nothing specified, nothing added.\n"));
		fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
423 424
		return 0;
	}
L
Linus Torvalds 已提交
425

426
	if (read_cache() < 0)
427
		die(_("index file corrupt"));
428

429 430
	die_in_unpopulated_submodule(&the_index, prefix);

431 432 433 434 435 436
	/*
	 * Check the "pathspec '%s' did not match any files" block
	 * below before enabling new magic.
	 */
	parse_pathspec(&pathspec, 0,
		       PATHSPEC_PREFER_FULL |
437
		       PATHSPEC_SYMLINK_LEADING_PATH,
438
		       prefix, argv);
439

440 441
	die_path_inside_submodule(&the_index, &pathspec);

442 443 444 445 446 447 448 449 450 451
	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);
		}

452
		/* This picks up the paths that are not tracked */
453
		baselen = fill_directory(&dir, &the_index, &pathspec);
454
		if (pathspec.nr)
455
			seen = prune_directory(&dir, &pathspec, baselen);
456
	}
457

458
	if (refresh_only) {
459
		refresh(verbose, &pathspec);
460
		goto finish;
461 462
	}

463
	if (pathspec.nr) {
464
		int i;
465

466
		if (!seen)
467
			seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
468 469 470 471

		/*
		 * file_exists() assumes exact match
		 */
472 473 474
		GUARD_PATHSPEC(&pathspec,
			       PATHSPEC_FROMTOP |
			       PATHSPEC_LITERAL |
475
			       PATHSPEC_GLOB |
476 477
			       PATHSPEC_ICASE |
			       PATHSPEC_EXCLUDE);
478

479 480
		for (i = 0; i < pathspec.nr; i++) {
			const char *path = pathspec.items[i].match;
481 482
			if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
				continue;
483
			if (!seen[i] && path[0] &&
484 485
			    ((pathspec.items[i].magic &
			      (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
486
			     !file_exists(path))) {
487
				if (ignore_missing) {
488
					int dtype = DT_UNKNOWN;
489
					if (is_excluded(&dir, &the_index, path, &dtype))
490 491
						dir_add_ignored(&dir, &the_index,
								path, pathspec.items[i].len);
492
				} else
493
					die(_("pathspec '%s' did not match any files"),
494
					    pathspec.items[i].original);
495
			}
496 497 498 499
		}
		free(seen);
	}

500 501
	plug_bulk_checkin();

502
	exit_status |= add_files_to_cache(prefix, &pathspec, flags);
503 504

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

507 508
	if (chmod_arg && pathspec.nr)
		chmod_pathspec(&pathspec, chmod_arg[0]);
509 510
	unplug_bulk_checkin();

F
Felipe Contreras 已提交
511
finish:
L
Linus Torvalds 已提交
512
	if (active_cache_changed) {
513
		if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
514
			die(_("Unable to write new index file"));
L
Linus Torvalds 已提交
515 516
	}

517
	return exit_status;
L
Linus Torvalds 已提交
518
}