diff options
Diffstat (limited to 'builtin-ls-files.c')
-rw-r--r-- | builtin-ls-files.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/builtin-ls-files.c b/builtin-ls-files.c index cce17b5ced..6c1db86e80 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -9,6 +9,7 @@ #include "quote.h" #include "dir.h" #include "builtin.h" +#include "tree.h" static int abbrev; static int show_deleted; @@ -26,6 +27,7 @@ static int prefix_offset; static const char **pathspec; static int error_unmatch; static char *ps_matched; +static const char *with_tree; static const char *tag_cached = ""; static const char *tag_unmerged = ""; @@ -247,6 +249,8 @@ static void show_files(struct dir_struct *dir, const char *prefix) continue; if (show_unmerged && !ce_stage(ce)) continue; + if (ce->ce_flags & htons(CE_UPDATE)) + continue; show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce); } } @@ -332,6 +336,67 @@ static const char *verify_pathspec(const char *prefix) return real_prefix; } +/* + * 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. + */ +static void overlay_tree(const char *tree_name, const char *prefix) +{ + struct tree *tree; + unsigned char sha1[20]; + const char **match; + 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; + ce->ce_flags |= htons(CE_STAGEMASK); + } + + if (prefix) { + static const char *(matchbuf[2]); + matchbuf[0] = prefix; + matchbuf [1] = NULL; + match = matchbuf; + } else + match = NULL; + if (read_tree(tree, 1, match)) + 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)) + ce->ce_flags |= htons(CE_UPDATE); + } + } +} + static const char ls_files_usage[] = "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* " "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] " @@ -452,6 +517,10 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix) error_unmatch = 1; continue; } + if (!prefixcmp(arg, "--with-tree=")) { + with_tree = arg + 12; + continue; + } if (!prefixcmp(arg, "--abbrev=")) { abbrev = strtoul(arg+9, NULL, 10); if (abbrev && abbrev < MINIMUM_ABBREV) @@ -503,6 +572,15 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix) read_cache(); if (prefix) prune_cache(prefix); + 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"); + overlay_tree(with_tree, prefix); + } show_files(&dir, prefix); if (ps_matched) { |