Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/ls-tree.c')
-rw-r--r--builtin/ls-tree.c133
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