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
#include "pathspec.h"
17

18 19 20 21 22 23
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 已提交
24
static int show_resolve_undo;
25 26 27
static int show_modified;
static int show_killed;
static int show_valid_bit;
28
static int line_terminator = '\n';
29
static int debug_mode;
30

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

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

50
static void write_name(const char *name)
51
{
52
	/*
53 54
	 * With "--full-name", prefix_len=0; this caller needs to pass
	 * an empty string in that case (a NULL is good for "").
55
	 */
56 57
	write_name_quoted_relative(name, prefix_len ? prefix : NULL,
				   stdout, line_terminator);
58 59
}

60
static void show_dir_entry(const char *tag, struct dir_entry *ent)
61
{
62
	int len = max_prefix_len;
63 64

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

67
	if (!dir_path_match(ent, &pathspec, len, ps_matched))
68 69
		return;

70
	fputs(tag, stdout);
71
	write_name(ent->name);
72 73
}

74
static void show_other_files(struct dir_struct *dir)
75 76
{
	int i;
77

78 79
	for (i = 0; i < dir->nr; i++) {
		struct dir_entry *ent = dir->entries[i];
80 81
		if (!cache_name_is_other(ent->name, ent->len))
			continue;
82 83 84 85
		show_dir_entry(tag_other, ent);
	}
}

86
static void show_killed_files(struct dir_struct *dir)
87 88
{
	int i;
89 90
	for (i = 0; i < dir->nr; i++) {
		struct dir_entry *ent = dir->entries[i];
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 125 126 127 128 129 130
		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)
131
			show_dir_entry(tag_killed, dir->entries[i]);
132
	}
133 134
}

135
static void show_ce_entry(const char *tag, const struct cache_entry *ce)
136
{
137
	int len = max_prefix_len;
138 139

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

142
	if (!match_pathspec_depth(&pathspec, ce->name, ce_namelen(ce), len, ps_matched))
143 144
		return;

145
	if (tag && *tag && show_valid_bit &&
146
	    (ce->ce_flags & CE_VALID)) {
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
		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;
	}

162 163
	if (!show_stage) {
		fputs(tag, stdout);
164
	} else {
165
		printf("%s%06o %s %d\t",
166
		       tag,
167
		       ce->ce_mode,
E
Erik Faye-Lund 已提交
168
		       find_unique_abbrev(ce->sha1,abbrev),
169 170
		       ce_stage(ce));
	}
171
	write_name(ce->name);
172
	if (debug_mode) {
173
		const struct stat_data *sd = &ce->ce_stat_data;
174 175 176 177 178 179

		printf("  ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
		printf("  mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
		printf("  dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
		printf("  uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
		printf("  size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
180
	}
181 182
}

183
static void show_ru_info(void)
J
Junio C Hamano 已提交
184
{
185 186
	struct string_list_item *item;

J
Junio C Hamano 已提交
187 188
	if (!the_index.resolve_undo)
		return;
189 190 191 192 193 194 195 196 197

	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 */
198
		if (!match_pathspec_depth(&pathspec, path, len, max_prefix_len, ps_matched))
199 200 201 202 203 204 205
			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);
206
			write_name(path);
207 208
		}
	}
J
Junio C Hamano 已提交
209 210
}

211
static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce)
212 213
{
	int dtype = ce_to_dtype(ce);
214
	return is_excluded(dir, ce->name, &dtype);
215 216
}

217
static void show_files(struct dir_struct *dir)
218 219 220 221
{
	int i;

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

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

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

293 294 295 296 297 298 299 300
/*
 * 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.
 */
301
void overlay_tree_on_cache(const char *tree_name, const char *prefix)
302 303 304
{
	struct tree *tree;
	unsigned char sha1[20];
305
	struct pathspec pathspec;
306 307 308 309 310 311 312 313 314 315 316 317 318 319
	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;
320
		ce->ce_flags |= CE_STAGEMASK;
321 322 323
	}

	if (prefix) {
324 325 326 327
		static const char *(matchbuf[1]);
		matchbuf[0] = NULL;
		parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC,
			       PATHSPEC_PREFER_CWD, prefix, matchbuf);
328
	} else
329
		memset(&pathspec, 0, sizeof(pathspec));
330
	if (read_tree(tree, 1, &pathspec))
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
		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))
349
				ce->ce_flags |= CE_UPDATE;
350 351 352 353
		}
	}
}

354 355 356
int report_path_error(const char *ps_matched,
		      const struct pathspec *pathspec,
		      const char *prefix)
357 358 359 360
{
	/*
	 * Make sure all pathspec matched; otherwise it is an error.
	 */
361
	struct strbuf sb = STRBUF_INIT;
362
	int num, errors = 0;
363
	for (num = 0; num < pathspec->nr; num++) {
364 365 366 367 368 369 370
		int other, found_dup;

		if (ps_matched[num])
			continue;
		/*
		 * The caller might have fed identical pathspec
		 * twice.  Do not barf on such a mistake.
371 372
		 * FIXME: parse_pathspec should have eliminated
		 * duplicate pathspec.
373 374
		 */
		for (found_dup = other = 0;
375
		     !found_dup && other < pathspec->nr;
376 377 378
		     other++) {
			if (other == num || !ps_matched[other])
				continue;
379 380
			if (!strcmp(pathspec->items[other].original,
				    pathspec->items[num].original))
381 382 383 384 385 386 387 388 389
				/*
				 * Ok, we have a match already.
				 */
				found_dup = 1;
		}
		if (found_dup)
			continue;

		error("pathspec '%s' did not match any file(s) known to git.",
390
		      pathspec->items[num].original);
391 392
		errors++;
	}
393
	strbuf_release(&sb);
394 395 396
	return errors;
}

397
static const char * const ls_files_usage[] = {
398
	N_("git ls-files [options] [<file>...]"),
399 400 401 402 403 404 405 406 407 408 409 410 411 412
	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)
{
413
	struct string_list *exclude_list = opt->value;
414 415

	exc_given = 1;
416
	string_list_append(exclude_list, arg);
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

	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;
}
442

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

506 507 508
	if (argc == 2 && !strcmp(argv[1], "-h"))
		usage_with_options(ls_files_usage, builtin_ls_files_options);

509
	memset(&dir, 0, sizeof(dir));
510
	prefix = cmd_prefix;
511
	if (prefix)
512
		prefix_len = strlen(prefix);
513
	git_config(git_default_config, NULL);
514

515 516 517
	if (read_cache() < 0)
		die("index file corrupt");

518
	argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
519
			ls_files_usage, 0);
520 521 522 523
	el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
	for (i = 0; i < exclude_list.nr; i++) {
		add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args);
	}
524 525 526 527 528 529 530
	if (show_tag || show_valid_bit) {
		tag_cached = "H ";
		tag_unmerged = "M ";
		tag_removed = "R ";
		tag_modified = "C ";
		tag_other = "? ";
		tag_killed = "K ";
531
		tag_skip_worktree = "S ";
J
Junio C Hamano 已提交
532
		tag_resolve_undo = "U ";
533
	}
534
	if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
535 536 537 538 539 540 541 542 543
		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;
544

545 546
	if (require_work_tree && !is_inside_work_tree())
		setup_work_tree();
547

548 549 550 551
	parse_pathspec(&pathspec, 0,
		       PATHSPEC_PREFER_CWD |
		       PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
		       prefix, argv);
552

553
	/* Find common prefix for all pathspec's */
554
	max_prefix = common_prefix(&pathspec);
555
	max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
556

557
	/* Treat unmatching pathspec elements as errors */
558 559
	if (pathspec.nr && error_unmatch)
		ps_matched = xcalloc(1, pathspec.nr);
560

561 562
	if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given)
		die("ls-files --ignored needs some exclude pattern");
563 564

	/* With no flags, we default to showing the cached files */
565 566
	if (!(show_stage || show_deleted || show_others || show_unmerged ||
	      show_killed || show_modified || show_resolve_undo))
567 568
		show_cached = 1;

569 570
	if (max_prefix)
		prune_cache(max_prefix);
571 572 573 574 575 576 577
	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");
578
		overlay_tree_on_cache(with_tree, max_prefix);
579
	}
580
	show_files(&dir);
J
Junio C Hamano 已提交
581
	if (show_resolve_undo)
582
		show_ru_info();
583 584

	if (ps_matched) {
585
		int bad;
586
		bad = report_path_error(ps_matched, &pathspec, prefix);
587
		if (bad)
588 589
			fprintf(stderr, "Did you forget to 'git add'?\n");

590
		return bad ? 1 : 0;
591 592
	}

593 594
	return 0;
}