use syntax similar to `git-checkout` to make <tree-ish> optional for
`ls-tree`. if <tree-ish> is omitted, default to HEAD. infer arguments as
follows:

1. if args start with --
        assume <tree-ish> to be HEAD
2. if exactly one arg precedes --, treat the argument as <tree-ish>
3. if more than one arg precedes --, exit with an error
4. if -- is not in args
        a) if args[0] is a valid <tree-ish> object, treat is as such
        b) else, assume <tree-ish> to be HEAD

in all cases, every argument besides <tree-ish> is treated as a <path>
---
 builtin/ls-tree.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git builtin/ls-tree.c builtin/ls-tree.c
index 409da4e83..14102b052 100644
--- builtin/ls-tree.c
+++ builtin/ls-tree.c
@@ -153,7 +153,7 @@ int cmd_ls_tree(int argc, const char **argv, const char 
*prefix)
                chomp_prefix = strlen(prefix);
 
        argc = parse_options(argc, argv, prefix, ls_tree_options,
-                            ls_tree_usage, 0);
+                            ls_tree_usage, PARSE_OPT_KEEP_DASHDASH);
        if (full_tree) {
                ls_tree_prefix = prefix = NULL;
                chomp_prefix = 0;
@@ -163,10 +163,39 @@ int cmd_ls_tree(int argc, const char **argv, const char 
*prefix)
            ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options))
                ls_options |= LS_SHOW_TREES;
 
+       const char *object;
+       short initialized = 0;
        if (argc < 1)
-               usage_with_options(ls_tree_usage, ls_tree_options);
-       if (get_oid(argv[0], &oid))
-               die("Not a valid object name %s", argv[0]);
+               object = "HEAD";
+       else {
+               /* taken from checkout.c;
+                * we have a simpler case because we never create a branch */
+               short dash_dash_pos = -1, i = 0;
+               for (; i < argc; i++) {
+                       if (!strcmp(argv[i], "--")) {
+                               dash_dash_pos = i;
+                               break;
+                       }
+               }
+               if (dash_dash_pos == 0) {
+                       object = "HEAD";
+                       argv++, argc++;
+               } else if (dash_dash_pos == 1) {
+                       object = argv[0];
+                       argv += 2, argc += 2;
+               } else if (dash_dash_pos >= 2)
+                       die(_("only one reference expected, %d given."), 
dash_dash_pos);
+               else if (get_oid(argv[0], &oid)) // not a valid object
+                       object = "HEAD";
+               else {
+                       argv++, argc++;
+                       initialized = 1;
+               }
+       }
+
+       if (!initialized) // if we've already run get_oid, don't run it again
+               if (get_oid(object, &oid))
+                       die("Not a valid object name %s", object);
 
        /*
         * show_recursive() rolls its own matching code and is
@@ -177,7 +206,7 @@ int cmd_ls_tree(int argc, const char **argv, const char 
*prefix)
        parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC &
                                  ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
                       PATHSPEC_PREFER_CWD,
-                      prefix, argv + 1);
+                      prefix, argv);
        for (i = 0; i < pathspec.nr; i++)
                pathspec.items[i].nowildcard_len = pathspec.items[i].len;
        pathspec.has_wildcard = 0;
-- 
2.18.GIT

Reply via email to