diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2015-02-08 16:01:35 +0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-02-09 14:29:51 -0800 |
commit | 0283d87b8890a960006bbc10ba78be4db108095d (patch) | |
tree | ebd34aa7cba439a00bcb68f006d3d65760ffcb5e | |
parent | be258d5d84244c824f5ae7d67640dd97d7500bcf (diff) | |
download | git-0283d87b8890a960006bbc10ba78be4db108095d.tar.gz |
list-files: show directories as well as files
The index does not store directories explicitly (except submodules) so
we have to figure them out from file list when output lis depth-limited.
The function show_as_directory() deliberately generates duplicate
directories and expects the previous patch to remove duplicates.
Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | builtin/ls-files.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 457d067ddd..8b5795a8f2 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -27,6 +27,8 @@ static int show_resolve_undo; static int show_modified; static int show_killed; static int show_valid_bit; +static int show_tag; +static int show_dirs; static int line_terminator = '\n'; static int debug_mode; static int use_color; @@ -179,6 +181,35 @@ static void show_killed_files(struct dir_struct *dir) } } +static int show_as_directory(const struct cache_entry *ce) +{ + struct strbuf sb = STRBUF_INIT; + const char *p; + + strbuf_add(&sb, ce->name, ce_namelen(ce)); + while (sb.len && (p = strrchr(sb.buf, '/')) != NULL) { + struct strbuf sb2 = STRBUF_INIT; + strbuf_setlen(&sb, p - sb.buf); + if (!match_pathspec(&pathspec, sb.buf, sb.len, + max_prefix_len, NULL, 1)) + continue; + write_name(&sb2, sb.buf); + if (want_color(use_color)) { + struct strbuf sb3 = STRBUF_INIT; + color_filename(&sb3, ce->name, sb2.buf, S_IFDIR, 1); + strbuf_swap(&sb2, &sb3); + strbuf_release(&sb3); + } + if (show_tag) + strbuf_insert(&sb2, 0, tag_cached, strlen(tag_cached)); + strbuf_fputs(&sb2, strbuf_detach(&sb, NULL), NULL); + strbuf_release(&sb2); + return 1; + } + strbuf_release(&sb); + return 0; +} + static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce) { struct strbuf quoted = STRBUF_INIT; @@ -191,17 +222,40 @@ static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce) strbuf_release("ed); } +static int match_pathspec_with_depth(struct pathspec *ps, + const char *name, int namelen, + int prefix, char *seen, int is_dir, + const int *custom_depth) +{ + int saved_depth = ps->max_depth; + int result; + + if (custom_depth) + ps->max_depth = *custom_depth; + result = match_pathspec(ps, name, namelen, prefix, seen, is_dir); + if (custom_depth) + ps->max_depth = saved_depth; + return result; +} + static void show_ce_entry(const char *tag, const struct cache_entry *ce) { static struct strbuf sb = STRBUF_INIT; + static const int infinite_depth = -1; int len = max_prefix_len; if (len >= ce_namelen(ce)) die("git ls-files: internal error - cache entry not superset of prefix"); - if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce), - len, ps_matched, - S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode))) + if (!match_pathspec_with_depth(&pathspec, ce->name, ce_namelen(ce), + len, ps_matched, + S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode), + show_dirs ? &infinite_depth : NULL)) + return; + + if (show_dirs && strchr(ce->name, '/') && + !match_pathspec(&pathspec, ce->name, ce_namelen(ce), prefix_len, NULL, 1) && + show_as_directory(ce)) return; if (tag && *tag && show_valid_bit && @@ -575,7 +629,7 @@ static int git_ls_config(const char *var, const char *value, void *cb) int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) { - int require_work_tree = 0, show_tag = 0, i; + int require_work_tree = 0, i; int max_depth = -1; const char *max_prefix; struct dir_struct dir; @@ -744,6 +798,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) prefix, argv); pathspec.max_depth = max_depth; pathspec.recursive = 1; + show_dirs = porcelain && max_depth != -1; + /* Find common prefix for all pathspec's */ max_prefix = common_prefix(&pathspec); |