builtin-update-index.c 19.2 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5
/*
 * GIT - The information manager from hell
 *
 * Copyright (C) Linus Torvalds, 2005
 */
6
#include "cache.h"
7
#include "quote.h"
8
#include "cache-tree.h"
Junio C Hamano's avatar
Junio C Hamano committed
9
#include "tree-walk.h"
10
#include "builtin.h"
11
#include "refs.h"
12

13 14 15 16
/*
 * Default to not allowing changes to the list of files. The
 * tool doesn't actually care, but this makes it harder to add
 * files to the revision control by mistake by doing something
17
 * like "git update-index *" and suddenly having all the object
18 19
 * files be revision controlled.
 */
Junio C Hamano's avatar
Junio C Hamano committed
20 21 22 23
static int allow_add;
static int allow_remove;
static int allow_replace;
static int info_only;
24
static int force_remove;
Junio C Hamano's avatar
Junio C Hamano committed
25
static int verbose;
26
static int mark_valid_only;
Junio C Hamano's avatar
Junio C Hamano committed
27 28 29
#define MARK_VALID 1
#define UNMARK_VALID 2

30
__attribute__((format (printf, 1, 2)))
Junio C Hamano's avatar
Junio C Hamano committed
31 32 33 34 35 36 37 38 39 40 41 42 43
static void report(const char *fmt, ...)
{
	va_list vp;

	if (!verbose)
		return;

	va_start(vp, fmt);
	vprintf(fmt, vp);
	putchar('\n');
	va_end(vp);
}

Junio C Hamano's avatar
Junio C Hamano committed
44 45 46 47 48 49 50
static int mark_valid(const char *path)
{
	int namelen = strlen(path);
	int pos = cache_name_pos(path, namelen);
	if (0 <= pos) {
		switch (mark_valid_only) {
		case MARK_VALID:
51
			active_cache[pos]->ce_flags |= CE_VALID;
Junio C Hamano's avatar
Junio C Hamano committed
52 53
			break;
		case UNMARK_VALID:
54
			active_cache[pos]->ce_flags &= ~CE_VALID;
Junio C Hamano's avatar
Junio C Hamano committed
55 56
			break;
		}
57
		cache_tree_invalidate_path(active_cache_tree, path);
Junio C Hamano's avatar
Junio C Hamano committed
58 59 60 61 62 63
		active_cache_changed = 1;
		return 0;
	}
	return -1;
}

64
static int remove_one_path(const char *path)
65
{
66 67 68 69 70 71
	if (!allow_remove)
		return error("%s: does not exist and --remove not passed", path);
	if (remove_file_from_cache(path))
		return error("%s: cannot remove from the index", path);
	return 0;
}
72

73 74 75 76 77 78 79 80 81 82 83 84 85
/*
 * Handle a path that couldn't be lstat'ed. It's either:
 *  - missing file (ENOENT or ENOTDIR). That's ok if we're
 *    supposed to be removing it and the removal actually
 *    succeeds.
 *  - permission error. That's never ok.
 */
static int process_lstat_error(const char *path, int err)
{
	if (err == ENOENT || err == ENOTDIR)
		return remove_one_path(path);
	return error("lstat(\"%s\"): %s", path, strerror(errno));
}
86

87 88
static int add_one_path(struct cache_entry *old, const char *path, int len, struct stat *st)
{
89 90
	int option, size;
	struct cache_entry *ce;
Junio C Hamano's avatar
Junio C Hamano committed
91

92 93 94 95 96 97
	/* Was the old index entry already up-to-date? */
	if (old && !ce_stage(old) && !ce_match_stat(old, st, 0))
		return 0;

	size = cache_entry_size(len);
	ce = xcalloc(1, size);
98
	memcpy(ce->name, path, len);
99
	ce->ce_flags = len;
100 101
	fill_stat_cache_info(ce, st);
	ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
102

103
	if (index_path(ce->sha1, path, st, !info_only))
104
		return -1;
105 106
	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
107
	if (add_cache_entry(ce, option))
108
		return error("%s: cannot add to the index - missing --add option?", path);
109
	return 0;
110 111
}

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
/*
 * Handle a path that was a directory. Four cases:
 *
 *  - it's already a gitlink in the index, and we keep it that
 *    way, and update it if we can (if we cannot find the HEAD,
 *    we're going to keep it unchanged in the index!)
 *
 *  - it's a *file* in the index, in which case it should be
 *    removed as a file if removal is allowed, since it doesn't
 *    exist as such any more. If removal isn't allowed, it's
 *    an error.
 *
 *    (NOTE! This is old and arguably fairly strange behaviour.
 *    We might want to make this an error unconditionally, and
 *    use "--force-remove" if you actually want to force removal).
 *
 *  - it used to exist as a subdirectory (ie multiple files with
 *    this particular prefix) in the index, in which case it's wrong
 *    to try to update it as a directory.
 *
 *  - it doesn't exist at all in the index, but it is a valid
 *    git directory, and it should be *added* as a gitlink.
 */
static int process_directory(const char *path, int len, struct stat *st)
{
	unsigned char sha1[20];
	int pos = cache_name_pos(path, len);

	/* Exact match: file or existing gitlink */
	if (pos >= 0) {
		struct cache_entry *ce = active_cache[pos];
143
		if (S_ISGITLINK(ce->ce_mode)) {
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

			/* Do nothing to the index if there is no HEAD! */
			if (resolve_gitlink_ref(path, "HEAD", sha1) < 0)
				return 0;

			return add_one_path(ce, path, len, st);
		}
		/* Should this be an unconditional error? */
		return remove_one_path(path);
	}

	/* Inexact match: is there perhaps a subdirectory match? */
	pos = -pos-1;
	while (pos < active_nr) {
		struct cache_entry *ce = active_cache[pos++];

		if (strncmp(ce->name, path, len))
			break;
		if (ce->name[len] > '/')
			break;
		if (ce->name[len] < '/')
			continue;

		/* Subdirectory match - error out */
		return error("%s: is a directory - add individual files instead", path);
	}

	/* No match - should we add it as a gitlink? */
	if (!resolve_gitlink_ref(path, "HEAD", sha1))
		return add_one_path(NULL, path, len, st);

	/* Error out. */
	return error("%s: is a directory - add files inside instead", path);
}

/*
 * Process a regular file
 */
static int process_file(const char *path, int len, struct stat *st)
{
	int pos = cache_name_pos(path, len);
	struct cache_entry *ce = pos < 0 ? NULL : active_cache[pos];

187
	if (ce && S_ISGITLINK(ce->ce_mode))
188 189 190 191 192 193 194 195 196 197
		return error("%s is already a gitlink, not replacing", path);

	return add_one_path(ce, path, len, st);
}

static int process_path(const char *path)
{
	int len;
	struct stat st;

198
	len = strlen(path);
199
	if (has_symlink_leading_path(path, len))
200 201
		return error("'%s' is beyond a symbolic link", path);

202 203 204 205 206 207 208 209 210 211 212 213 214
	/*
	 * First things first: get the stat information, to decide
	 * what to do about the pathname!
	 */
	if (lstat(path, &st) < 0)
		return process_lstat_error(path, errno);

	if (S_ISDIR(st.st_mode))
		return process_directory(path, len, &st);

	return process_file(path, len, &st);
}

215 216
static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
			 const char *path, int stage)
217
{
218
	int size, len, option;
219 220
	struct cache_entry *ce;

221
	if (!verify_path(path))
222
		return error("Invalid path '%s'", path);
223

224
	len = strlen(path);
225
	size = cache_entry_size(len);
226
	ce = xcalloc(1, size);
227

228
	hashcpy(ce->sha1, sha1);
229 230
	memcpy(ce->name, path, len);
	ce->ce_flags = create_ce_flags(len, stage);
231
	ce->ce_mode = create_ce_mode(mode);
Junio C Hamano's avatar
Junio C Hamano committed
232
	if (assume_unchanged)
233
		ce->ce_flags |= CE_VALID;
234 235
	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
Junio C Hamano's avatar
Junio C Hamano committed
236 237
	if (add_cache_entry(ce, option))
		return error("%s: cannot add to the index - missing --add option?",
238 239
			     path);
	report("add '%s'", path);
Junio C Hamano's avatar
Junio C Hamano committed
240
	return 0;
241 242
}

243
static void chmod_path(int flip, const char *path)
Junio C Hamano's avatar
Junio C Hamano committed
244 245 246 247
{
	int pos;
	struct cache_entry *ce;
	unsigned int mode;
248

Junio C Hamano's avatar
Junio C Hamano committed
249 250
	pos = cache_name_pos(path, strlen(path));
	if (pos < 0)
251
		goto fail;
Junio C Hamano's avatar
Junio C Hamano committed
252
	ce = active_cache[pos];
253
	mode = ce->ce_mode;
Junio C Hamano's avatar
Junio C Hamano committed
254
	if (!S_ISREG(mode))
255
		goto fail;
Junio C Hamano's avatar
Junio C Hamano committed
256 257
	switch (flip) {
	case '+':
258
		ce->ce_mode |= 0111; break;
Junio C Hamano's avatar
Junio C Hamano committed
259
	case '-':
260
		ce->ce_mode &= ~0111; break;
Junio C Hamano's avatar
Junio C Hamano committed
261
	default:
262
		goto fail;
Junio C Hamano's avatar
Junio C Hamano committed
263
	}
264
	cache_tree_invalidate_path(active_cache_tree, path);
Junio C Hamano's avatar
Junio C Hamano committed
265
	active_cache_changed = 1;
266 267 268
	report("chmod %cx '%s'", flip, path);
	return;
 fail:
269
	die("git update-index: cannot chmod %cx '%s'", flip, path);
Junio C Hamano's avatar
Junio C Hamano committed
270 271
}

Junio C Hamano's avatar
Junio C Hamano committed
272 273 274 275 276
static void update_one(const char *path, const char *prefix, int prefix_length)
{
	const char *p = prefix_path(prefix, prefix_length, path);
	if (!verify_path(p)) {
		fprintf(stderr, "Ignoring path %s\n", path);
277
		goto free_return;
Junio C Hamano's avatar
Junio C Hamano committed
278
	}
Junio C Hamano's avatar
Junio C Hamano committed
279 280 281
	if (mark_valid_only) {
		if (mark_valid(p))
			die("Unable to mark file %s", path);
282
		goto free_return;
Junio C Hamano's avatar
Junio C Hamano committed
283 284
	}

Junio C Hamano's avatar
Junio C Hamano committed
285 286
	if (force_remove) {
		if (remove_file_from_cache(p))
287
			die("git update-index: unable to remove %s", path);
Junio C Hamano's avatar
Junio C Hamano committed
288
		report("remove '%s'", path);
289
		goto free_return;
Junio C Hamano's avatar
Junio C Hamano committed
290
	}
291 292
	if (process_path(p))
		die("Unable to process path %s", path);
Junio C Hamano's avatar
Junio C Hamano committed
293
	report("add '%s'", path);
294
 free_return:
295
	if (p < path || p > path + strlen(path))
296
		free((char *)p);
Junio C Hamano's avatar
Junio C Hamano committed
297 298
}

299 300
static void read_index_info(int line_termination)
{
301 302
	struct strbuf buf = STRBUF_INIT;
	struct strbuf uq = STRBUF_INIT;
303 304

	while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
305
		char *ptr, *tab;
306
		char *path_name;
307 308
		unsigned char sha1[20];
		unsigned int mode;
309
		unsigned long ul;
310 311 312 313 314
		int stage;

		/* This reads lines formatted in one of three formats:
		 *
		 * (1) mode         SP sha1          TAB path
315
		 * The first format is what "git apply --index-info"
316 317 318 319 320
		 * reports, and used to reconstruct a partial tree
		 * that is used for phony merge base tree when falling
		 * back on 3-way merge.
		 *
		 * (2) mode SP type SP sha1          TAB path
321
		 * The second format is to stuff "git ls-tree" output
322
		 * into the index file.
323
		 *
324 325
		 * (3) mode         SP sha1 SP stage TAB path
		 * This format is to put higher order stages into the
326
		 * index file and matches "git ls-files --stage" output.
327
		 */
328 329 330 331
		errno = 0;
		ul = strtoul(buf.buf, &ptr, 8);
		if (ptr == buf.buf || *ptr != ' '
		    || errno || (unsigned int) ul != ul)
332
			goto bad_line;
333
		mode = ul;
334

335 336 337
		tab = strchr(ptr, '\t');
		if (!tab || tab - ptr < 41)
			goto bad_line;
338

339
		if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') {
340 341 342 343 344 345 346 347 348
			stage = tab[-1] - '0';
			ptr = tab + 1; /* point at the head of path */
			tab = tab - 2; /* point at tail of sha1 */
		}
		else {
			stage = 0;
			ptr = tab + 1; /* point at the head of path */
		}

349 350
		if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
			goto bad_line;
351

352 353 354 355
		path_name = ptr;
		if (line_termination && path_name[0] == '"') {
			strbuf_reset(&uq);
			if (unquote_c_style(&uq, path_name, NULL)) {
356
				die("git update-index: bad quoting of path name");
357 358 359
			}
			path_name = uq.buf;
		}
360 361 362

		if (!verify_path(path_name)) {
			fprintf(stderr, "Ignoring path %s\n", path_name);
363 364 365 366 367
			continue;
		}

		if (!mode) {
			/* mode == 0 means there is no such path -- remove */
368
			if (remove_file_from_cache(path_name))
369
				die("git update-index: unable to remove %s",
370 371 372 373 374 375 376 377
				    ptr);
		}
		else {
			/* mode ' ' sha1 '\t' name
			 * ptr[-1] points at tab,
			 * ptr[-41] is at the beginning of sha1
			 */
			ptr[-42] = ptr[-1] = 0;
378
			if (add_cacheinfo(mode, sha1, path_name, stage))
379
				die("git update-index: unable to update %s",
380
				    path_name);
381 382 383 384 385 386
		}
		continue;

	bad_line:
		die("malformed index info %s", buf.buf);
	}
387
	strbuf_release(&buf);
388
	strbuf_release(&uq);
389 390
}

391
static const char update_index_usage[] =
Stephan Beyer's avatar
Stephan Beyer committed
392
"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
393

Junio C Hamano's avatar
Junio C Hamano committed
394 395 396 397 398 399 400 401 402 403 404 405 406
static unsigned char head_sha1[20];
static unsigned char merge_head_sha1[20];

static struct cache_entry *read_one_ent(const char *which,
					unsigned char *ent, const char *path,
					int namelen, int stage)
{
	unsigned mode;
	unsigned char sha1[20];
	int size;
	struct cache_entry *ce;

	if (get_tree_entry(ent, path, sha1, &mode)) {
Junio C Hamano's avatar
Junio C Hamano committed
407 408
		if (which)
			error("%s: not in %s branch.", path, which);
Junio C Hamano's avatar
Junio C Hamano committed
409 410 411
		return NULL;
	}
	if (mode == S_IFDIR) {
Junio C Hamano's avatar
Junio C Hamano committed
412 413
		if (which)
			error("%s: not a blob in %s branch.", path, which);
Junio C Hamano's avatar
Junio C Hamano committed
414 415 416 417 418
		return NULL;
	}
	size = cache_entry_size(namelen);
	ce = xcalloc(1, size);

419
	hashcpy(ce->sha1, sha1);
Junio C Hamano's avatar
Junio C Hamano committed
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
	memcpy(ce->name, path, namelen);
	ce->ce_flags = create_ce_flags(namelen, stage);
	ce->ce_mode = create_ce_mode(mode);
	return ce;
}

static int unresolve_one(const char *path)
{
	int namelen = strlen(path);
	int pos;
	int ret = 0;
	struct cache_entry *ce_2 = NULL, *ce_3 = NULL;

	/* See if there is such entry in the index. */
	pos = cache_name_pos(path, namelen);
	if (pos < 0) {
		/* If there isn't, either it is unmerged, or
		 * resolved as "removed" by mistake.  We do not
		 * want to do anything in the former case.
		 */
		pos = -pos-1;
		if (pos < active_nr) {
			struct cache_entry *ce = active_cache[pos];
			if (ce_namelen(ce) == namelen &&
			    !memcmp(ce->name, path, namelen)) {
				fprintf(stderr,
					"%s: skipping still unmerged path.\n",
					path);
				goto free_return;
			}
		}
	}

	/* Grab blobs from given path from HEAD and MERGE_HEAD,
	 * stuff HEAD version in stage #2,
	 * stuff MERGE_HEAD version in stage #3.
	 */
	ce_2 = read_one_ent("our", head_sha1, path, namelen, 2);
	ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3);

	if (!ce_2 || !ce_3) {
		ret = -1;
		goto free_return;
	}
464
	if (!hashcmp(ce_2->sha1, ce_3->sha1) &&
Junio C Hamano's avatar
Junio C Hamano committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
	    ce_2->ce_mode == ce_3->ce_mode) {
		fprintf(stderr, "%s: identical in both, skipping.\n",
			path);
		goto free_return;
	}

	remove_file_from_cache(path);
	if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
		error("%s: cannot add our version to the index.", path);
		ret = -1;
		goto free_return;
	}
	if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD))
		return 0;
	error("%s: cannot add their version to the index.", path);
	ret = -1;
 free_return:
	free(ce_2);
	free(ce_3);
	return ret;
}

static void read_head_pointers(void)
{
489
	if (read_ref("HEAD", head_sha1))
490
		die("No HEAD -- no initial commit yet?");
491
	if (read_ref("MERGE_HEAD", merge_head_sha1)) {
Junio C Hamano's avatar
Junio C Hamano committed
492 493 494 495 496
		fprintf(stderr, "Not in the middle of a merge.\n");
		exit(0);
	}
}

497 498
static int do_unresolve(int ac, const char **av,
			const char *prefix, int prefix_length)
Junio C Hamano's avatar
Junio C Hamano committed
499 500 501 502 503 504 505 506 507 508 509
{
	int i;
	int err = 0;

	/* Read HEAD and MERGE_HEAD; if MERGE_HEAD does not exist, we
	 * are not doing a merge, so exit with success status.
	 */
	read_head_pointers();

	for (i = 1; i < ac; i++) {
		const char *arg = av[i];
510 511
		const char *p = prefix_path(prefix, prefix_length, arg);
		err |= unresolve_one(p);
512
		if (p < arg || p > arg + strlen(arg))
513
			free((char *)p);
Junio C Hamano's avatar
Junio C Hamano committed
514 515 516 517
	}
	return err;
}

Junio C Hamano's avatar
Junio C Hamano committed
518 519 520 521 522 523 524 525
static int do_reupdate(int ac, const char **av,
		       const char *prefix, int prefix_length)
{
	/* Read HEAD and run update-index on paths that are
	 * merged and already different between index and HEAD.
	 */
	int pos;
	int has_head = 1;
526
	const char **pathspec = get_pathspec(prefix, av + 1);
Junio C Hamano's avatar
Junio C Hamano committed
527

528
	if (read_ref("HEAD", head_sha1))
Junio C Hamano's avatar
Junio C Hamano committed
529 530 531 532 533 534 535 536 537
		/* If there is no HEAD, that means it is an initial
		 * commit.  Update everything in the index.
		 */
		has_head = 0;
 redo:
	for (pos = 0; pos < active_nr; pos++) {
		struct cache_entry *ce = active_cache[pos];
		struct cache_entry *old = NULL;
		int save_nr;
538 539

		if (ce_stage(ce) || !ce_path_match(ce, pathspec))
Junio C Hamano's avatar
Junio C Hamano committed
540 541 542 543 544
			continue;
		if (has_head)
			old = read_one_ent(NULL, head_sha1,
					   ce->name, ce_namelen(ce), 0);
		if (old && ce->ce_mode == old->ce_mode &&
545
		    !hashcmp(ce->sha1, old->sha1)) {
Junio C Hamano's avatar
Junio C Hamano committed
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
			free(old);
			continue; /* unchanged */
		}
		/* Be careful.  The working tree may not have the
		 * path anymore, in which case, under 'allow_remove',
		 * or worse yet 'allow_replace', active_nr may decrease.
		 */
		save_nr = active_nr;
		update_one(ce->name + prefix_length, prefix, prefix_length);
		if (save_nr != active_nr)
			goto redo;
	}
	return 0;
}

561
int cmd_update_index(int argc, const char **argv, const char *prefix)
562
{
Junio C Hamano's avatar
Junio C Hamano committed
563
	int i, newfd, entries, has_errors = 0, line_termination = '\n';
564
	int allow_options = 1;
Junio C Hamano's avatar
Junio C Hamano committed
565 566
	int read_from_stdin = 0;
	int prefix_length = prefix ? strlen(prefix) : 0;
567
	char set_executable_bit = 0;
568
	unsigned int refresh_flags = 0;
569
	int lock_error = 0;
570
	struct lock_file *lock_file;
571

572
	git_config(git_default_config, NULL);
Junio C Hamano's avatar
Junio C Hamano committed
573

574
	/* We can't free this memory, it becomes part of a linked list parsed atexit() */
575
	lock_file = xcalloc(1, sizeof(struct lock_file));
576

577
	newfd = hold_locked_index(lock_file, 0);
578 579
	if (newfd < 0)
		lock_error = errno;
580

581
	entries = read_cache();
582
	if (entries < 0)
583
		die("cache corrupted");
584 585

	for (i = 1 ; i < argc; i++) {
Junio C Hamano's avatar
Junio C Hamano committed
586
		const char *path = argv[i];
587
		const char *p;
588 589 590 591 592 593

		if (allow_options && *path == '-') {
			if (!strcmp(path, "--")) {
				allow_options = 0;
				continue;
			}
594
			if (!strcmp(path, "-q")) {
595
				refresh_flags |= REFRESH_QUIET;
596 597
				continue;
			}
598 599 600 601
			if (!strcmp(path, "--ignore-submodules")) {
				refresh_flags |= REFRESH_IGNORE_SUBMODULES;
				continue;
			}
602 603 604 605
			if (!strcmp(path, "--add")) {
				allow_add = 1;
				continue;
			}
606 607 608 609
			if (!strcmp(path, "--replace")) {
				allow_replace = 1;
				continue;
			}
610 611 612 613
			if (!strcmp(path, "--remove")) {
				allow_remove = 1;
				continue;
			}
614
			if (!strcmp(path, "--unmerged")) {
615
				refresh_flags |= REFRESH_UNMERGED;
616 617
				continue;
			}
618
			if (!strcmp(path, "--refresh")) {
Duy Nguyen's avatar
Duy Nguyen committed
619
				setup_work_tree();
620
				has_errors |= refresh_cache(refresh_flags);
Junio C Hamano's avatar
Junio C Hamano committed
621 622 623
				continue;
			}
			if (!strcmp(path, "--really-refresh")) {
Duy Nguyen's avatar
Duy Nguyen committed
624
				setup_work_tree();
625
				has_errors |= refresh_cache(REFRESH_REALLY | refresh_flags);
626 627
				continue;
			}
628
			if (!strcmp(path, "--cacheinfo")) {
629 630 631
				unsigned char sha1[20];
				unsigned int mode;

632
				if (i+3 >= argc)
633
					die("git update-index: --cacheinfo <mode> <sha1> <path>");
634

635
				if (strtoul_ui(argv[i+1], 8, &mode) ||
636 637
				    get_sha1_hex(argv[i+2], sha1) ||
				    add_cacheinfo(mode, sha1, argv[i+3], 0))
638
					die("git update-index: --cacheinfo"
639
					    " cannot add %s", argv[i+3]);
640 641 642
				i += 3;
				continue;
			}
Junio C Hamano's avatar
Junio C Hamano committed
643 644 645
			if (!strcmp(path, "--chmod=-x") ||
			    !strcmp(path, "--chmod=+x")) {
				if (argc <= i+1)
646
					die("git update-index: %s <path>", path);
647
				set_executable_bit = path[8];
Junio C Hamano's avatar
Junio C Hamano committed
648 649
				continue;
			}
Junio C Hamano's avatar
Junio C Hamano committed
650 651 652 653 654 655 656 657
			if (!strcmp(path, "--assume-unchanged")) {
				mark_valid_only = MARK_VALID;
				continue;
			}
			if (!strcmp(path, "--no-assume-unchanged")) {
				mark_valid_only = UNMARK_VALID;
				continue;
			}
658 659 660 661
			if (!strcmp(path, "--info-only")) {
				info_only = 1;
				continue;
			}
662
			if (!strcmp(path, "--force-remove")) {
663
				force_remove = 1;
664 665
				continue;
			}
Junio C Hamano's avatar
Junio C Hamano committed
666 667 668 669 670 671 672 673 674 675
			if (!strcmp(path, "-z")) {
				line_termination = 0;
				continue;
			}
			if (!strcmp(path, "--stdin")) {
				if (i != argc - 1)
					die("--stdin must be at the end");
				read_from_stdin = 1;
				break;
			}
676
			if (!strcmp(path, "--index-info")) {
677 678
				if (i != argc - 1)
					die("--index-info must be at the end");
679 680
				allow_add = allow_replace = allow_remove = 1;
				read_index_info(line_termination);
681
				break;
682
			}
Junio C Hamano's avatar
Junio C Hamano committed
683
			if (!strcmp(path, "--unresolve")) {
684 685
				has_errors = do_unresolve(argc - i, argv + i,
							  prefix, prefix_length);
Junio C Hamano's avatar
Junio C Hamano committed
686 687 688 689
				if (has_errors)
					active_cache_changed = 0;
				goto finish;
			}
Junio C Hamano's avatar
Junio C Hamano committed
690
			if (!strcmp(path, "--again") || !strcmp(path, "-g")) {
Duy Nguyen's avatar
Duy Nguyen committed
691
				setup_work_tree();
Junio C Hamano's avatar
Junio C Hamano committed
692 693 694 695 696 697
				has_errors = do_reupdate(argc - i, argv + i,
							 prefix, prefix_length);
				if (has_errors)
					active_cache_changed = 0;
				goto finish;
			}
698
			if (!strcmp(path, "--ignore-missing")) {
699
				refresh_flags |= REFRESH_IGNORE_MISSING;
700 701
				continue;
			}
Junio C Hamano's avatar
Junio C Hamano committed
702 703 704 705
			if (!strcmp(path, "--verbose")) {
				verbose = 1;
				continue;
			}
706 707
			if (!strcmp(path, "-h") || !strcmp(path, "--help"))
				usage(update_index_usage);
708
			die("unknown option %s", path);
709
		}
Duy Nguyen's avatar
Duy Nguyen committed
710
		setup_work_tree();
711 712
		p = prefix_path(prefix, prefix_length, path);
		update_one(p, NULL, 0);
713
		if (set_executable_bit)
714 715
			chmod_path(set_executable_bit, p);
		if (p < path || p > path + strlen(path))
716
			free((char *)p);
Junio C Hamano's avatar
Junio C Hamano committed
717 718
	}
	if (read_from_stdin) {
719
		struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
720

Duy Nguyen's avatar
Duy Nguyen committed
721
		setup_work_tree();
722
		while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
723
			const char *p;
724 725 726 727 728 729 730
			if (line_termination && buf.buf[0] == '"') {
				strbuf_reset(&nbuf);
				if (unquote_c_style(&nbuf, buf.buf, NULL))
					die("line is badly quoted");
				strbuf_swap(&buf, &nbuf);
			}
			p = prefix_path(prefix, prefix_length, buf.buf);
731 732
			update_one(p, NULL, 0);
			if (set_executable_bit)
733
				chmod_path(set_executable_bit, p);
734 735
			if (p < buf.buf || p > buf.buf + buf.len)
				free((char *)p);
736
		}
737
		strbuf_release(&nbuf);
738
		strbuf_release(&buf);
739
	}
Junio C Hamano's avatar
Junio C Hamano committed
740 741

 finish:
742
	if (active_cache_changed) {
743 744 745
		if (newfd < 0) {
			if (refresh_flags & REFRESH_QUIET)
				exit(128);
746
			unable_to_lock_index_die(get_index_file(), lock_error);
747
		}
748
		if (write_cache(newfd, active_cache, active_nr) ||
Brandon Casey's avatar
Brandon Casey committed
749
		    commit_locked_index(lock_file))
750
			die("Unable to write new index file");
751
	}
752

753 754
	rollback_lock_file(lock_file);

755
	return has_errors ? 1 : 0;
756
}