]> git.ipfire.org Git - thirdparty/git.git/commitdiff
ls-tree: support --object-only option for "git-ls-tree"
authorTeng Long <dyroneteng@gmail.com>
Wed, 23 Mar 2022 09:13:13 +0000 (17:13 +0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 23 Mar 2022 18:38:40 +0000 (11:38 -0700)
'--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>
Documentation/git-ls-tree.txt
builtin/ls-tree.c
t/t3103-ls-tree-misc.sh
t/t3104-ls-tree-format.sh

index 68bf1cf325f14557401fe7dcf5fed241bdd5323e..43aebb9938a0bb9332d957ef07ccc1692cf0a801 100644 (file)
@@ -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
index 8a1bf2fa4d97fa7e32121f9ae74d1f4f75dd34ac..3474f8c3d62d3d74e09fc922ac49da1e72430d70 100644 (file)
@@ -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,
index d9d7fa932f8be75870e0a1c634450b99af5a2135..d979c0df5d345807cc22eb4d3f99ef6f43f4886b 100755 (executable)
@@ -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
index 7f1eb699d3ed6ed4afadc3f682c9ae8b79aef0e5..0769a933d695e5525b08a4e39b8cc0f8370eb08b 100755 (executable)
@@ -49,6 +49,15 @@ test_ls_tree_format \
        "%(path)" \
        "--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" \