diff options
Diffstat (limited to 'builtin/ls-tree.c')
-rw-r--r-- | builtin/ls-tree.c | 133 |
1 files changed, 52 insertions, 81 deletions
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 077977a461..53073d64cb 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -3,17 +3,17 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "builtin.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "object-name.h" -#include "object-store.h" +#include "object-store-ll.h" #include "blob.h" #include "tree.h" #include "commit.h" +#include "path.h" #include "quote.h" -#include "builtin.h" #include "parse-options.h" #include "pathspec.h" @@ -50,68 +50,10 @@ struct ls_tree_options { LS_SHOW_TREES = 1 << 2, } ls_options; struct pathspec pathspec; - int chomp_prefix; - const char *ls_tree_prefix; + const char *prefix; const char *format; }; -struct show_tree_data { - struct ls_tree_options *options; - unsigned mode; - enum object_type type; - const struct object_id *oid; - const char *pathname; - struct strbuf *base; -}; - -static size_t expand_show_tree(struct strbuf *sb, const char *start, - void *context) -{ - struct show_tree_data *data = context; - struct ls_tree_options *options = data->options; - const char *end; - const char *p; - unsigned int errlen; - size_t len = strbuf_expand_literal_cb(sb, start, NULL); - - if (len) - return len; - if (*start != '(') - die(_("bad ls-tree format: element '%s' does not start with '('"), start); - - end = strchr(start + 1, ')'); - if (!end) - die(_("bad ls-tree format: element '%s' does not end in ')'"), start); - - len = end - start + 1; - if (skip_prefix(start, "(objectmode)", &p)) { - strbuf_addf(sb, "%06o", data->mode); - } else if (skip_prefix(start, "(objecttype)", &p)) { - strbuf_addstr(sb, type_name(data->type)); - } else if (skip_prefix(start, "(objectsize:padded)", &p)) { - expand_objectsize(sb, data->oid, data->type, 1); - } else if (skip_prefix(start, "(objectsize)", &p)) { - expand_objectsize(sb, data->oid, data->type, 0); - } else if (skip_prefix(start, "(objectname)", &p)) { - strbuf_add_unique_abbrev(sb, data->oid, options->abbrev); - } else if (skip_prefix(start, "(path)", &p)) { - const char *name = data->base->buf; - const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; - struct strbuf sbuf = STRBUF_INIT; - size_t baselen = data->base->len; - - strbuf_addstr(data->base, data->pathname); - name = relative_path(data->base->buf, prefix, &sbuf); - quote_c_style(name, sb, NULL, 0); - strbuf_setlen(data->base, baselen); - strbuf_release(&sbuf); - } else { - errlen = (unsigned long)len; - die(_("bad ls-tree format: %%%.*s"), errlen, start); - } - return len; -} - static int show_recursive(struct ls_tree_options *options, const char *base, size_t baselen, const char *pathname) { @@ -150,14 +92,7 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, int recurse = 0; struct strbuf sb = STRBUF_INIT; enum object_type type = object_type(mode); - struct show_tree_data cb_data = { - .options = options, - .mode = mode, - .type = type, - .oid = oid, - .pathname = pathname, - .base = base, - }; + const char *format = options->format; if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname)) recurse = READ_TREE_RECURSIVE; @@ -166,7 +101,45 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, if (type == OBJ_BLOB && (options->ls_options & LS_TREE_ONLY)) return 0; - strbuf_expand(&sb, options->format, expand_show_tree, &cb_data); + while (strbuf_expand_step(&sb, &format)) { + const char *end; + size_t len; + + if (skip_prefix(format, "%", &format)) + strbuf_addch(&sb, '%'); + else if ((len = strbuf_expand_literal(&sb, format))) + format += len; + else if (*format != '(') + die(_("bad ls-tree format: element '%s' " + "does not start with '('"), format); + else if (!(end = strchr(format + 1, ')'))) + die(_("bad ls-tree format: element '%s' " + "does not end in ')'"), format); + else if (skip_prefix(format, "(objectmode)", &format)) + strbuf_addf(&sb, "%06o", mode); + else if (skip_prefix(format, "(objecttype)", &format)) + strbuf_addstr(&sb, type_name(type)); + else if (skip_prefix(format, "(objectsize:padded)", &format)) + expand_objectsize(&sb, oid, type, 1); + else if (skip_prefix(format, "(objectsize)", &format)) + expand_objectsize(&sb, oid, type, 0); + else if (skip_prefix(format, "(objectname)", &format)) + strbuf_add_unique_abbrev(&sb, oid, options->abbrev); + else if (skip_prefix(format, "(path)", &format)) { + const char *name; + const char *prefix = options->prefix; + struct strbuf sbuf = STRBUF_INIT; + size_t baselen = base->len; + + strbuf_addstr(base, pathname); + name = relative_path(base->buf, prefix, &sbuf); + quote_c_style(name, &sb, NULL, 0); + strbuf_setlen(base, baselen); + strbuf_release(&sbuf); + } else + die(_("bad ls-tree format: %%%.*s"), + (int)(end - format + 1), format); + } strbuf_addch(&sb, options->null_termination ? '\0' : '\n'); fwrite(sb.buf, sb.len, 1, stdout); strbuf_release(&sb); @@ -198,7 +171,7 @@ static void show_tree_common_default_long(struct ls_tree_options *options, const char *pathname, const size_t baselen) { - const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; + const char *prefix = options->prefix; strbuf_addstr(base, pathname); @@ -283,7 +256,7 @@ static int show_tree_name_only(const struct object_id *oid, struct strbuf *base, if (early >= 0) return early; - prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; + prefix = options->prefix; strbuf_addstr(base, pathname); if (options->null_termination) { struct strbuf sb = STRBUF_INIT; @@ -370,6 +343,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) struct object_id oid; struct tree *tree; int i, full_tree = 0; + int chomp_prefix = prefix && *prefix; read_tree_fn_t fn = NULL; enum ls_tree_cmdmode cmdmode = MODE_DEFAULT; int null_termination = 0; @@ -391,7 +365,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) MODE_NAME_STATUS), OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"), MODE_OBJECT_ONLY), - OPT_SET_INT(0, "full-name", &options.chomp_prefix, + OPT_SET_INT(0, "full-name", &chomp_prefix, N_("use full path names"), 0), OPT_BOOL(0, "full-tree", &full_tree, N_("list entire tree; not just current directory " @@ -406,18 +380,15 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) int ret; git_config(git_default_config, NULL); - options.ls_tree_prefix = prefix; - if (prefix) - options.chomp_prefix = strlen(prefix); argc = parse_options(argc, argv, prefix, ls_tree_options, ls_tree_usage, 0); options.null_termination = null_termination; - if (full_tree) { - options.ls_tree_prefix = prefix = NULL; - options.chomp_prefix = 0; - } + if (full_tree) + prefix = NULL; + options.prefix = chomp_prefix ? prefix : NULL; + /* * We wanted to detect conflicts between --name-only and * --name-status, but once we're done with that subsequent |