ls-files.c 15.7 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * This merges the file listing in the directory cache index
 * with the actual working directory list, and shows different
 * combinations of the two.
 *
 * Copyright (C) Linus Torvalds, 2005
 */
#include "cache.h"
9
#include "quote.h"
10
#include "dir.h"
P
Peter Eriksen 已提交
11
#include "builtin.h"
12
#include "tree.h"
13
#include "parse-options.h"
J
Junio C Hamano 已提交
14 15
#include "resolve-undo.h"
#include "string-list.h"
16

17 18 19 20 21 22
static int abbrev;
static int show_deleted;
static int show_cached;
static int show_others;
static int show_stage;
static int show_unmerged;
J
Junio C Hamano 已提交
23
static int show_resolve_undo;
24 25 26
static int show_modified;
static int show_killed;
static int show_valid_bit;
27
static int line_terminator = '\n';
28
static int debug_mode;
29

30 31
static const char *prefix;
static int max_prefix_len;
32 33 34 35
static int prefix_len;
static const char **pathspec;
static int error_unmatch;
static char *ps_matched;
36
static const char *with_tree;
37
static int exc_given;
38

39 40 41 42
static const char *tag_cached = "";
static const char *tag_unmerged = "";
static const char *tag_removed = "";
static const char *tag_other = "";
43
static const char *tag_killed = "";
44
static const char *tag_modified = "";
45
static const char *tag_skip_worktree = "";
J
Junio C Hamano 已提交
46
static const char *tag_resolve_undo = "";
47

48 49 50 51 52 53
static void write_name(const char* name, size_t len)
{
	write_name_quoted_relative(name, len, prefix, prefix_len, stdout,
			line_terminator);
}

54
static void show_dir_entry(const char *tag, struct dir_entry *ent)
55
{
56
	int len = max_prefix_len;
57 58

	if (len >= ent->len)
59
		die("git ls-files: internal error - directory entry not superset of prefix");
60

61
	if (!match_pathspec(pathspec, ent->name, ent->len, len, ps_matched))
62 63
		return;

64
	fputs(tag, stdout);
65
	write_name(ent->name, ent->len);
66 67
}

68
static void show_other_files(struct dir_struct *dir)
69 70
{
	int i;
71

72 73
	for (i = 0; i < dir->nr; i++) {
		struct dir_entry *ent = dir->entries[i];
74 75
		if (!cache_name_is_other(ent->name, ent->len))
			continue;
76 77 78 79
		show_dir_entry(tag_other, ent);
	}
}

80
static void show_killed_files(struct dir_struct *dir)
81 82
{
	int i;
83 84
	for (i = 0; i < dir->nr; i++) {
		struct dir_entry *ent = dir->entries[i];
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
		char *cp, *sp;
		int pos, len, killed = 0;

		for (cp = ent->name; cp - ent->name < ent->len; cp = sp + 1) {
			sp = strchr(cp, '/');
			if (!sp) {
				/* If ent->name is prefix of an entry in the
				 * cache, it will be killed.
				 */
				pos = cache_name_pos(ent->name, ent->len);
				if (0 <= pos)
					die("bug in show-killed-files");
				pos = -pos - 1;
				while (pos < active_nr &&
				       ce_stage(active_cache[pos]))
					pos++; /* skip unmerged */
				if (active_nr <= pos)
					break;
				/* pos points at a name immediately after
				 * ent->name in the cache.  Does it expect
				 * ent->name to be a directory?
				 */
				len = ce_namelen(active_cache[pos]);
				if ((ent->len < len) &&
				    !strncmp(active_cache[pos]->name,
					     ent->name, ent->len) &&
				    active_cache[pos]->name[ent->len] == '/')
					killed = 1;
				break;
			}
			if (0 <= cache_name_pos(ent->name, sp - ent->name)) {
				/* If any of the leading directories in
				 * ent->name is registered in the cache,
				 * ent->name will be killed.
				 */
				killed = 1;
				break;
			}
		}
		if (killed)
125
			show_dir_entry(tag_killed, dir->entries[i]);
126
	}
127 128
}

129 130
static void show_ce_entry(const char *tag, struct cache_entry *ce)
{
131
	int len = max_prefix_len;
132 133

	if (len >= ce_namelen(ce))
134
		die("git ls-files: internal error - cache entry not superset of prefix");
135

136
	if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), len, ps_matched))
137 138
		return;

139
	if (tag && *tag && show_valid_bit &&
140
	    (ce->ce_flags & CE_VALID)) {
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
		static char alttag[4];
		memcpy(alttag, tag, 3);
		if (isalpha(tag[0]))
			alttag[0] = tolower(tag[0]);
		else if (tag[0] == '?')
			alttag[0] = '!';
		else {
			alttag[0] = 'v';
			alttag[1] = tag[0];
			alttag[2] = ' ';
			alttag[3] = 0;
		}
		tag = alttag;
	}

156 157
	if (!show_stage) {
		fputs(tag, stdout);
158
	} else {
159
		printf("%s%06o %s %d\t",
160
		       tag,
161
		       ce->ce_mode,
E
Erik Faye-Lund 已提交
162
		       find_unique_abbrev(ce->sha1,abbrev),
163 164
		       ce_stage(ce));
	}
165
	write_name(ce->name, ce_namelen(ce));
166 167 168 169 170 171 172
	if (debug_mode) {
		printf("  ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec);
		printf("  mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec);
		printf("  dev: %d\tino: %d\n", ce->ce_dev, ce->ce_ino);
		printf("  uid: %d\tgid: %d\n", ce->ce_uid, ce->ce_gid);
		printf("  size: %d\tflags: %x\n", ce->ce_size, ce->ce_flags);
	}
173 174
}

175
static void show_ru_info(void)
J
Junio C Hamano 已提交
176
{
177 178
	struct string_list_item *item;

J
Junio C Hamano 已提交
179 180
	if (!the_index.resolve_undo)
		return;
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

	for_each_string_list_item(item, the_index.resolve_undo) {
		const char *path = item->string;
		struct resolve_undo_info *ui = item->util;
		int i, len;

		len = strlen(path);
		if (len < max_prefix_len)
			continue; /* outside of the prefix */
		if (!match_pathspec(pathspec, path, len, max_prefix_len, ps_matched))
			continue; /* uninterested */
		for (i = 0; i < 3; i++) {
			if (!ui->mode[i])
				continue;
			printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
			       find_unique_abbrev(ui->sha1[i], abbrev),
			       i + 1);
			write_name(path, len);
		}
	}
J
Junio C Hamano 已提交
201 202
}

203 204 205 206 207 208
static int ce_excluded(struct path_exclude_check *check, struct cache_entry *ce)
{
	int dtype = ce_to_dtype(ce);
	return path_excluded(check, ce->name, ce_namelen(ce), &dtype);
}

209
static void show_files(struct dir_struct *dir)
210 211
{
	int i;
212 213 214 215
	struct path_exclude_check check;

	if ((dir->flags & DIR_SHOW_IGNORED))
		path_exclude_check_init(&check, dir);
216 217

	/* For cached/deleted files we don't need to even do the readdir */
218
	if (show_others || show_killed) {
219
		fill_directory(dir, pathspec);
220
		if (show_others)
221
			show_other_files(dir);
222
		if (show_killed)
223
			show_killed_files(dir);
224
	}
225
	if (show_cached | show_stage) {
226 227
		for (i = 0; i < active_nr; i++) {
			struct cache_entry *ce = active_cache[i];
228
			if ((dir->flags & DIR_SHOW_IGNORED) &&
229
			    !ce_excluded(&check, ce))
J
Jeff King 已提交
230
				continue;
231 232
			if (show_unmerged && !ce_stage(ce))
				continue;
233
			if (ce->ce_flags & CE_UPDATE)
234
				continue;
235 236
			show_ce_entry(ce_stage(ce) ? tag_unmerged :
				(ce_skip_worktree(ce) ? tag_skip_worktree : tag_cached), ce);
237 238
		}
	}
239
	if (show_deleted | show_modified) {
240 241 242
		for (i = 0; i < active_nr; i++) {
			struct cache_entry *ce = active_cache[i];
			struct stat st;
243
			int err;
244
			if ((dir->flags & DIR_SHOW_IGNORED) &&
245
			    !ce_excluded(&check, ce))
J
Jeff King 已提交
246
				continue;
247 248
			if (ce->ce_flags & CE_UPDATE)
				continue;
249 250
			if (ce_skip_worktree(ce))
				continue;
251 252 253
			err = lstat(ce->name, &st);
			if (show_deleted && err)
				show_ce_entry(tag_removed, ce);
254
			if (show_modified && ce_modified(ce, &st, 0))
255
				show_ce_entry(tag_modified, ce);
256 257
		}
	}
258 259 260

	if ((dir->flags & DIR_SHOW_IGNORED))
		path_exclude_check_clear(&check);
261 262 263 264 265
}

/*
 * Prune the index to only contain stuff starting with "prefix"
 */
266
static void prune_cache(const char *prefix)
267
{
268
	int pos = cache_name_pos(prefix, max_prefix_len);
269 270 271 272
	unsigned int first, last;

	if (pos < 0)
		pos = -pos-1;
273 274
	memmove(active_cache, active_cache + pos,
		(active_nr - pos) * sizeof(struct cache_entry *));
275 276 277 278 279 280
	active_nr -= pos;
	first = 0;
	last = active_nr;
	while (last > first) {
		int next = (last + first) >> 1;
		struct cache_entry *ce = active_cache[next];
281
		if (!strncmp(ce->name, prefix, max_prefix_len)) {
282 283
			first = next+1;
			continue;
284
		}
285 286 287 288 289
		last = next;
	}
	active_nr = last;
}

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
static void strip_trailing_slash_from_submodules(void)
{
	const char **p;

	for (p = pathspec; *p != NULL; p++) {
		int len = strlen(*p), pos;

		if (len < 1 || (*p)[len - 1] != '/')
			continue;
		pos = cache_name_pos(*p, len - 1);
		if (pos >= 0 && S_ISGITLINK(active_cache[pos]->ce_mode))
			*p = xstrndup(*p, len - 1);
	}
}

305 306 307 308 309 310 311 312
/*
 * Read the tree specified with --with-tree option
 * (typically, HEAD) into stage #1 and then
 * squash them down to stage #0.  This is used for
 * --error-unmatch to list and check the path patterns
 * that were given from the command line.  We are not
 * going to write this index out.
 */
313
void overlay_tree_on_cache(const char *tree_name, const char *prefix)
314 315 316
{
	struct tree *tree;
	unsigned char sha1[20];
317
	struct pathspec pathspec;
318 319 320 321 322 323 324 325 326 327 328 329 330 331
	struct cache_entry *last_stage0 = NULL;
	int i;

	if (get_sha1(tree_name, sha1))
		die("tree-ish %s not found.", tree_name);
	tree = parse_tree_indirect(sha1);
	if (!tree)
		die("bad tree-ish %s", tree_name);

	/* Hoist the unmerged entries up to stage #3 to make room */
	for (i = 0; i < active_nr; i++) {
		struct cache_entry *ce = active_cache[i];
		if (!ce_stage(ce))
			continue;
332
		ce->ce_flags |= CE_STAGEMASK;
333 334 335 336 337
	}

	if (prefix) {
		static const char *(matchbuf[2]);
		matchbuf[0] = prefix;
338
		matchbuf[1] = NULL;
339
		init_pathspec(&pathspec, matchbuf);
340
		pathspec.items[0].use_wildcard = 0;
341
	} else
342 343
		init_pathspec(&pathspec, NULL);
	if (read_tree(tree, 1, &pathspec))
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
		die("unable to read tree entries %s", tree_name);

	for (i = 0; i < active_nr; i++) {
		struct cache_entry *ce = active_cache[i];
		switch (ce_stage(ce)) {
		case 0:
			last_stage0 = ce;
			/* fallthru */
		default:
			continue;
		case 1:
			/*
			 * If there is stage #0 entry for this, we do not
			 * need to show it.  We use CE_UPDATE bit to mark
			 * such an entry.
			 */
			if (last_stage0 &&
			    !strcmp(last_stage0->name, ce->name))
362
				ce->ce_flags |= CE_UPDATE;
363 364 365 366
		}
	}
}

367
int report_path_error(const char *ps_matched, const char **pathspec, const char *prefix)
368 369 370 371
{
	/*
	 * Make sure all pathspec matched; otherwise it is an error.
	 */
372 373
	struct strbuf sb = STRBUF_INIT;
	const char *name;
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
	int num, errors = 0;
	for (num = 0; pathspec[num]; num++) {
		int other, found_dup;

		if (ps_matched[num])
			continue;
		/*
		 * The caller might have fed identical pathspec
		 * twice.  Do not barf on such a mistake.
		 */
		for (found_dup = other = 0;
		     !found_dup && pathspec[other];
		     other++) {
			if (other == num || !ps_matched[other])
				continue;
			if (!strcmp(pathspec[other], pathspec[num]))
				/*
				 * Ok, we have a match already.
				 */
				found_dup = 1;
		}
		if (found_dup)
			continue;

398
		name = quote_path_relative(pathspec[num], -1, &sb, prefix);
399
		error("pathspec '%s' did not match any file(s) known to git.",
400
		      name);
401 402
		errors++;
	}
403
	strbuf_release(&sb);
404 405 406
	return errors;
}

407
static const char * const ls_files_usage[] = {
408
	N_("git ls-files [options] [<file>...]"),
409 410 411 412 413 414 415 416 417 418 419 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
	NULL
};

static int option_parse_z(const struct option *opt,
			  const char *arg, int unset)
{
	line_terminator = unset ? '\n' : '\0';

	return 0;
}

static int option_parse_exclude(const struct option *opt,
				const char *arg, int unset)
{
	struct exclude_list *list = opt->value;

	exc_given = 1;
	add_exclude(arg, "", 0, list);

	return 0;
}

static int option_parse_exclude_from(const struct option *opt,
				     const char *arg, int unset)
{
	struct dir_struct *dir = opt->value;

	exc_given = 1;
	add_excludes_from_file(dir, arg);

	return 0;
}

static int option_parse_exclude_standard(const struct option *opt,
					 const char *arg, int unset)
{
	struct dir_struct *dir = opt->value;

	exc_given = 1;
	setup_standard_excludes(dir);

	return 0;
}
452

453
int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
454
{
455
	int require_work_tree = 0, show_tag = 0;
456
	const char *max_prefix;
457
	struct dir_struct dir;
458 459
	struct option builtin_ls_files_options[] = {
		{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
460
			N_("paths are separated with NUL character"),
461 462
			PARSE_OPT_NOARG, option_parse_z },
		OPT_BOOLEAN('t', NULL, &show_tag,
463
			N_("identify the file status with tags")),
464
		OPT_BOOLEAN('v', NULL, &show_valid_bit,
465
			N_("use lowercase letters for 'assume unchanged' files")),
466
		OPT_BOOLEAN('c', "cached", &show_cached,
467
			N_("show cached files in the output (default)")),
468
		OPT_BOOLEAN('d', "deleted", &show_deleted,
469
			N_("show deleted files in the output")),
470
		OPT_BOOLEAN('m', "modified", &show_modified,
471
			N_("show modified files in the output")),
472
		OPT_BOOLEAN('o', "others", &show_others,
473
			N_("show other files in the output")),
474
		OPT_BIT('i', "ignored", &dir.flags,
475
			N_("show ignored files in the output"),
476 477
			DIR_SHOW_IGNORED),
		OPT_BOOLEAN('s', "stage", &show_stage,
478
			N_("show staged contents' object name in the output")),
479
		OPT_BOOLEAN('k', "killed", &show_killed,
480
			N_("show files on the filesystem that need to be removed")),
481
		OPT_BIT(0, "directory", &dir.flags,
482
			N_("show 'other' directories' name only"),
483
			DIR_SHOW_OTHER_DIRECTORIES),
J
Jeff King 已提交
484
		OPT_NEGBIT(0, "empty-directory", &dir.flags,
485
			N_("don't show empty directories"),
486 487
			DIR_HIDE_EMPTY_DIRECTORIES),
		OPT_BOOLEAN('u', "unmerged", &show_unmerged,
488
			N_("show unmerged files in the output")),
J
Junio C Hamano 已提交
489
		OPT_BOOLEAN(0, "resolve-undo", &show_resolve_undo,
490 491 492
			    N_("show resolve-undo information")),
		{ OPTION_CALLBACK, 'x', "exclude", &dir.exclude_list[EXC_CMDL], N_("pattern"),
			N_("skip files matching pattern"),
493
			0, option_parse_exclude },
494 495
		{ OPTION_CALLBACK, 'X', "exclude-from", &dir, N_("file"),
			N_("exclude patterns are read from <file>"),
496
			0, option_parse_exclude_from },
497 498
		OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, N_("file"),
			N_("read additional per-directory exclude patterns in <file>")),
499
		{ OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
500
			N_("add the standard git exclusions"),
501
			PARSE_OPT_NOARG, option_parse_exclude_standard },
502
		{ OPTION_SET_INT, 0, "full-name", &prefix_len, NULL,
503
			N_("make the output relative to the project top directory"),
504 505
			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
		OPT_BOOLEAN(0, "error-unmatch", &error_unmatch,
506 507 508
			N_("if any <file> is not in the index, treat this as an error")),
		OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
			N_("pretend that paths removed since <tree-ish> are still present")),
509
		OPT__ABBREV(&abbrev),
510
		OPT_BOOLEAN(0, "debug", &debug_mode, N_("show debugging data")),
511 512
		OPT_END()
	};
513

514 515 516
	if (argc == 2 && !strcmp(argv[1], "-h"))
		usage_with_options(ls_files_usage, builtin_ls_files_options);

517
	memset(&dir, 0, sizeof(dir));
518
	prefix = cmd_prefix;
519
	if (prefix)
520
		prefix_len = strlen(prefix);
521
	git_config(git_default_config, NULL);
522

523 524 525
	if (read_cache() < 0)
		die("index file corrupt");

526
	argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
527 528 529 530 531 532 533 534
			ls_files_usage, 0);
	if (show_tag || show_valid_bit) {
		tag_cached = "H ";
		tag_unmerged = "M ";
		tag_removed = "R ";
		tag_modified = "C ";
		tag_other = "? ";
		tag_killed = "K ";
535
		tag_skip_worktree = "S ";
J
Junio C Hamano 已提交
536
		tag_resolve_undo = "U ";
537
	}
538
	if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
539 540 541 542 543 544 545 546 547
		require_work_tree = 1;
	if (show_unmerged)
		/*
		 * There's no point in showing unmerged unless
		 * you also show the stage information.
		 */
		show_stage = 1;
	if (dir.exclude_per_dir)
		exc_given = 1;
548

549 550
	if (require_work_tree && !is_inside_work_tree())
		setup_work_tree();
551

552
	pathspec = get_pathspec(prefix, argv);
553

M
Mike Ralphson 已提交
554
	/* be nice with submodule paths ending in a slash */
555 556 557
	if (pathspec)
		strip_trailing_slash_from_submodules();

558
	/* Find common prefix for all pathspec's */
559
	max_prefix = common_prefix(pathspec);
560
	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
561

562 563 564 565 566 567 568 569
	/* Treat unmatching pathspec elements as errors */
	if (pathspec && error_unmatch) {
		int num;
		for (num = 0; pathspec[num]; num++)
			;
		ps_matched = xcalloc(1, num);
	}

570 571
	if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given)
		die("ls-files --ignored needs some exclude pattern");
572 573

	/* With no flags, we default to showing the cached files */
574
	if (!(show_stage | show_deleted | show_others | show_unmerged |
J
Junio C Hamano 已提交
575
	      show_killed | show_modified | show_resolve_undo))
576 577
		show_cached = 1;

578 579
	if (max_prefix)
		prune_cache(max_prefix);
580 581 582 583 584 585 586
	if (with_tree) {
		/*
		 * Basic sanity check; show-stages and show-unmerged
		 * would not make any sense with this option.
		 */
		if (show_stage || show_unmerged)
			die("ls-files --with-tree is incompatible with -s or -u");
587
		overlay_tree_on_cache(with_tree, max_prefix);
588
	}
589
	show_files(&dir);
J
Junio C Hamano 已提交
590
	if (show_resolve_undo)
591
		show_ru_info();
592 593

	if (ps_matched) {
594
		int bad;
595
		bad = report_path_error(ps_matched, pathspec, prefix);
596
		if (bad)
597 598
			fprintf(stderr, "Did you forget to 'git add'?\n");

599
		return bad ? 1 : 0;
600 601
	}

602 603
	return 0;
}