diff options
author | Teng Long <dyroneteng@gmail.com> | 2022-03-23 17:13:13 +0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2022-03-23 11:38:40 -0700 |
commit | cab851c2f8c190bed93719ca8c712fdfcc3c7182 (patch) | |
tree | c16ec0ab0e594ed42a555c6c5a79e8dab04e49ae | |
parent | ls-tree: introduce "--format" option (diff) | |
download | tgif-cab851c2f8c190bed93719ca8c712fdfcc3c7182.tar.xz |
ls-tree: support --object-only option for "git-ls-tree"
'--object-only' is an alias for '--format=%(objectname)'. It cannot
be used together other format-altering options like '--name-only',
'--long' or '--format', they are mutually exclusive.
The "--name-only" option outputs <filepath> only. Likewise, <objectName>
is another high frequency used field, so implement '--object-only' option
will bring intuitive and clear semantics for this scenario. Using
'--format=%(objectname)' we can achieve a similar effect, but the former
is with a lower learning cost(without knowing the format requirement
of '--format' option).
Even so, if a user is prefer to use "--format=%(objectname)", this is entirely
welcome because they are not only equivalent in function, but also have almost
identical performance. The reason is this commit also add the specific of
"--format=%(objectname)" to the current fast-pathes (builtin formats) to
avoid running unnecessary parsing mechanisms.
The following performance benchmarks are based on torvalds/linux.git:
When hit the fast-path:
Benchmark 1: /opt/git/ls-tree-oid-only/bin/git ls-tree -r --object-only HEAD
Time (mean ± σ): 83.6 ms ± 2.0 ms [User: 59.4 ms, System: 24.1 ms]
Range (min … max): 80.4 ms … 87.2 ms 35 runs
Benchmark 1: /opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(objectname)' HEAD
Time (mean ± σ): 84.1 ms ± 1.8 ms [User: 61.7 ms, System: 22.3 ms]
Range (min … max): 80.9 ms … 87.5 ms 35 runs
But for a customized format, it will be slower:
Benchmark 1: /opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='oid: %(objectname)' HEAD
Time (mean ± σ): 96.5 ms ± 2.5 ms [User: 72.9 ms, System: 23.5 ms]
Range (min … max): 93.1 ms … 104.1 ms 31 runs
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Teng Long <dyroneteng@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | Documentation/git-ls-tree.txt | 11 | ||||
-rw-r--r-- | builtin/ls-tree.c | 13 | ||||
-rwxr-xr-x | t/t3103-ls-tree-misc.sh | 7 | ||||
-rwxr-xr-x | t/t3104-ls-tree-format.sh | 9 |
4 files changed, 36 insertions, 4 deletions
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt index 68bf1cf325..43aebb9938 100644 --- a/Documentation/git-ls-tree.txt +++ b/Documentation/git-ls-tree.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git ls-tree' [-d] [-r] [-t] [-l] [-z] - [--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev[=<n>]] [--format=<format>] + [--name-only] [--name-status] [--object-only] [--full-name] [--full-tree] [--abbrev[=<n>]] [--format=<format>] <tree-ish> [<path>...] DESCRIPTION @@ -59,6 +59,15 @@ OPTIONS --name-only:: --name-status:: List only filenames (instead of the "long" output), one per line. + Cannot be combined with `--object-only`. + +--object-only:: + List only names of the objects, one per line. Cannot be combined + with `--name-only` or `--name-status`. + This is equivalent to specifying `--format='%(objectname)'`, but + for both this option and that exact format the command takes a + hand-optimized codepath instead of going through the generic + formatting mechanism. --abbrev[=<n>]:: Instead of showing the full 40-byte hexadecimal object diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 8a1bf2fa4d..3474f8c3d6 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -24,7 +24,6 @@ static struct pathspec pathspec; static int chomp_prefix; static const char *ls_tree_prefix; static const char *format; - struct show_tree_data { unsigned mode; enum object_type type; @@ -42,6 +41,7 @@ static enum ls_tree_cmdmode { MODE_DEFAULT = 0, MODE_LONG, MODE_NAME_ONLY, + MODE_OBJECT_ONLY, } cmdmode; static void expand_objectsize(struct strbuf *line, const struct object_id *oid, @@ -227,6 +227,11 @@ static int show_tree(const struct object_id *oid, struct strbuf *base, return recurse; } + if (cmdmode == MODE_OBJECT_ONLY) { + printf("%s%c", find_unique_abbrev(oid, abbrev), line_termination); + return recurse; + } + if (cmdmode == MODE_NAME_ONLY) { baselen = base->len; strbuf_addstr(base, pathname); @@ -264,6 +269,10 @@ static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format[] = { .mode = MODE_NAME_ONLY, /* And MODE_NAME_STATUS */ .fmt = "%(path)", }, + { + .mode = MODE_OBJECT_ONLY, + .fmt = "%(objectname)", + }, { 0 }, }; @@ -288,6 +297,8 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) MODE_NAME_ONLY), OPT_CMDMODE(0, "name-status", &cmdmode, N_("list only filenames"), MODE_NAME_ONLY), + OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"), + MODE_OBJECT_ONLY), OPT_SET_INT(0, "full-name", &chomp_prefix, N_("use full path names"), 0), OPT_BOOL(0, "full-tree", &full_tree, diff --git a/t/t3103-ls-tree-misc.sh b/t/t3103-ls-tree-misc.sh index d9d7fa932f..d979c0df5d 100755 --- a/t/t3103-ls-tree-misc.sh +++ b/t/t3103-ls-tree-misc.sh @@ -25,11 +25,14 @@ test_expect_success 'ls-tree fails with non-zero exit code on broken tree' ' for opts in \ "--name-only --long" \ - "--name-status --long" + "--name-status --long" \ + "--name-only --object-only" \ + "--name-status --object-only" \ + "--object-only --long" \ + "--object-only --format" do test_expect_success "usage: incompatible options: $opts" ' test_expect_code 129 git ls-tree $opts $tree ' done - test_done diff --git a/t/t3104-ls-tree-format.sh b/t/t3104-ls-tree-format.sh index 7f1eb699d3..0769a933d6 100755 --- a/t/t3104-ls-tree-format.sh +++ b/t/t3104-ls-tree-format.sh @@ -50,6 +50,15 @@ test_ls_tree_format \ "--name-only" test_ls_tree_format \ + "%(objectname)" \ + "--object-only" + +test_ls_tree_format \ + "%(objectname)" \ + "--object-only --abbrev" \ + "--abbrev" + +test_ls_tree_format \ "%(objectmode) %(objecttype) %(objectname)%x09%(path)" \ "-t" \ "-t" |