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. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/ls-files.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 1a1c9c8..29b5c2e 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_release(&sb2); + sb2 = 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; @@ -194,16 +225,31 @@ static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce) static void show_ce_entry(const char *tag, const struct cache_entry *ce) { static struct strbuf sb = STRBUF_INIT; - int len = max_prefix_len; + int len = max_prefix_len, saved_max_depth; if (len >= ce_namelen(ce)) die("git ls-files: internal error - cache entry not superset of prefix"); + if (show_dirs) { + /* ignore depth to catch dirs that contain matched entries */ + saved_max_depth = pathspec.max_depth; + pathspec.max_depth = -1; + } + if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce), len, ps_matched, S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode))) return; + if (show_dirs) { + pathspec.max_depth = saved_max_depth; + if (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 && (ce->ce_flags & CE_VALID)) { static char alttag[4]; @@ -575,7 +621,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 +790,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); -- 2.2.0.84.ge9c7a8a -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html