diff mbox series

[1/3] ls-tree.c: support `--oid-only` option for "git-ls-tree"

Message ID 20211115115153.48307-2-dyroneteng@gmail.com (mailing list archive)
State Superseded
Headers show
Series support `--oid-only` in `ls-tree` | expand

Commit Message

Teng Long Nov. 15, 2021, 11:51 a.m. UTC
This commit supply an option names `--oid-only` to let `git ls-tree`
only print out the OID of the object. `--oid-only` and `--name-only`
are mutually exclusive in use.

Signed-off-by: Teng Long <dyroneteng@gmail.com>
---
 builtin/ls-tree.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

Comments

Ævar Arnfjörð Bjarmason Nov. 15, 2021, 3:12 p.m. UTC | #1
lorn Mon, Nov 15 2021, Teng Long wrote:

> This commit supply an option names `--oid-only` to let `git ls-tree`
> only print out the OID of the object. `--oid-only` and `--name-only`
> are mutually exclusive in use.
>
> Signed-off-by: Teng Long <dyroneteng@gmail.com>
> ---
>  builtin/ls-tree.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
> index 3a442631c7..1f82229649 100644
> --- a/builtin/ls-tree.c
> +++ b/builtin/ls-tree.c
> @@ -20,6 +20,7 @@ static int line_termination = '\n';
>  #define LS_SHOW_TREES 4
>  #define LS_NAME_ONLY 8
>  #define LS_SHOW_SIZE 16
> +#define LS_OID_ONLY 32
>  static int abbrev;
>  static int ls_options;
>  static struct pathspec pathspec;
> @@ -90,6 +91,14 @@ static int show_tree(const struct object_id *oid, struct strbuf *base,
>  	else if (ls_options & LS_TREE_ONLY)
>  		return 0;
>  
> +	if ((ls_options & LS_NAME_ONLY) && (ls_options & LS_OID_ONLY))
> +		die(_("cannot specify --oid-only and --name-only at the same time"));

If you make these an OPT_CMDMODE you get this behavior for free. See
e.g. my
https://lore.kernel.org/git/patch-v2-06.10-d945fc94774-20211112T221506Z-avarab@gmail.com/
Jeff King Nov. 15, 2021, 7:16 p.m. UTC | #2
On Mon, Nov 15, 2021 at 07:51:51PM +0800, Teng Long wrote:

> diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
> index 3a442631c7..1f82229649 100644
> --- a/builtin/ls-tree.c
> +++ b/builtin/ls-tree.c
> @@ -20,6 +20,7 @@ static int line_termination = '\n';
>  #define LS_SHOW_TREES 4
>  #define LS_NAME_ONLY 8
>  #define LS_SHOW_SIZE 16
> +#define LS_OID_ONLY 32
>  static int abbrev;
>  static int ls_options;
>  static struct pathspec pathspec;
> @@ -90,6 +91,14 @@ static int show_tree(const struct object_id *oid, struct strbuf *base,
>  	else if (ls_options & LS_TREE_ONLY)
>  		return 0;
>  
> +	if ((ls_options & LS_NAME_ONLY) && (ls_options & LS_OID_ONLY))
> +		die(_("cannot specify --oid-only and --name-only at the same time"));

This seems reasonable to me. Letting them overwrite each other (i.e.,
"last one wins") would also be fine, but we can always loosen to that
behavior later if we choose.

This is a somewhat funny place to put the check, though. It will be run
for every entry in the tree (so is a tiny bit less efficient, but also
would not trigger for an empty tree). It probably should go in
cmd_ls_tree(), perhaps here:

diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 1f82229649..3c9ea00489 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -91,9 +91,6 @@ static int show_tree(const struct object_id *oid, struct strbuf *base,
 	else if (ls_options & LS_TREE_ONLY)
 		return 0;
 
-	if ((ls_options & LS_NAME_ONLY) && (ls_options & LS_OID_ONLY))
-		die(_("cannot specify --oid-only and --name-only at the same time"));
-
 	if (ls_options & LS_OID_ONLY) {
 		printf("%s\n", find_unique_abbrev(oid, abbrev));
 		return 0;
@@ -175,6 +172,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 	    ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options))
 		ls_options |= LS_SHOW_TREES;
 
+	if ((ls_options & LS_NAME_ONLY) && (ls_options & LS_OID_ONLY))
+		die(_("cannot specify --oid-only and --name-only at the same time"));
+
 	if (argc < 1)
 		usage_with_options(ls_tree_usage, ls_tree_options);
 	if (get_oid(argv[0], &oid))

Ævar also mentioned using OPT_CMDMODE(), which I think would naturally
move the logic in a similar way.

-Peff
Jeff King Nov. 15, 2021, 7:25 p.m. UTC | #3
On Mon, Nov 15, 2021 at 02:16:27PM -0500, Jeff King wrote:

> On Mon, Nov 15, 2021 at 07:51:51PM +0800, Teng Long wrote:
> 
> > diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
> > index 3a442631c7..1f82229649 100644
> > --- a/builtin/ls-tree.c
> > +++ b/builtin/ls-tree.c
> > @@ -20,6 +20,7 @@ static int line_termination = '\n';
> >  #define LS_SHOW_TREES 4
> >  #define LS_NAME_ONLY 8
> >  #define LS_SHOW_SIZE 16
> > +#define LS_OID_ONLY 32
> >  static int abbrev;
> >  static int ls_options;
> >  static struct pathspec pathspec;
> > @@ -90,6 +91,14 @@ static int show_tree(const struct object_id *oid, struct strbuf *base,
> >  	else if (ls_options & LS_TREE_ONLY)
> >  		return 0;
> >  
> > +	if ((ls_options & LS_NAME_ONLY) && (ls_options & LS_OID_ONLY))
> > +		die(_("cannot specify --oid-only and --name-only at the same time"));
> 
> This seems reasonable to me. Letting them overwrite each other (i.e.,
> "last one wins") would also be fine, but we can always loosen to that
> behavior later if we choose.

Oh, and whichever direction we go, it would probably make sense for
--long to be handled in the same way. I.e.:

  git ls-tree --long --oid-only

does not really make sense. Though we currently just ignore --long for:

  git ls-tree --long --name-only

which is arguably a bug.

-Peff
Teng Long Nov. 18, 2021, 9:28 a.m. UTC | #4
> If you make these an OPT_CMDMODE you get this behavior for free. See
> e.g. my
> https://lore.kernel.org/git/patch-v2-06.10-d945fc94774-20211112T221506Z-avarab@gmail.com/	   

Thank you very much for providing this input.

So I try to read this patch your mentioned and try to repeat the idea in my understanding.

First, OPT_CMDMODE() can be used for:

       1. Easy for checking the combined command options, such as "mutually exclusive" conditions.

       2. Die and output the error message consistently when the incompatible options are found.

       3. Brings better extensibilites, no need to change a lot of if/elses.

Then, you suggest to consider about to use OPT_CMDMODE instead of the current implementations.

Did I understand your suggestion right and comprehensive?
Ævar Arnfjörð Bjarmason Nov. 18, 2021, 11 a.m. UTC | #5
On Thu, Nov 18 2021, Teng Long wrote:

>> If you make these an OPT_CMDMODE you get this behavior for free. See
>> e.g. my
>> https://lore.kernel.org/git/patch-v2-06.10-d945fc94774-20211112T221506Z-avarab@gmail.com/	   
>
> Thank you very much for providing this input.
>
> So I try to read this patch your mentioned and try to repeat the idea in my understanding.
>
> First, OPT_CMDMODE() can be used for:
>
>        1. Easy for checking the combined command options, such as "mutually exclusive" conditions.
>
>        2. Die and output the error message consistently when the incompatible options are found.
>
>        3. Brings better extensibilites, no need to change a lot of if/elses.
>
> Then, you suggest to consider about to use OPT_CMDMODE instead of the current implementations.
>
> Did I understand your suggestion right and comprehensive?

Yes, all of that is correct.

It's a way of defining N options, --foo, --bar, --baz, where combining
any of them is an error.

We usually use it for a "command mode" (hence the name), but it can be
used when the command has flags that are mutually exclusive.

I think (but am not sure, and didn't check) that you can even use it for
--foo AND --bar that are exclusive, and --other --flags that are also
mutually exclusive (but could be combined with one of --foo or --bar),
you just need to provide another variable for it to set.

But I haven't tested that or used it like that, maybe it doesn't work
for some reason I'm forgetting...
Teng Long Nov. 18, 2021, 11:23 a.m. UTC | #6
On Mon, 15 Nov 2021 14:16:27 -0500, Jeff King wrote:

> This is a somewhat funny place to put the check, though. It will be run
> for every entry in the tree (so is a tiny bit less efficient, but also
> would not trigger for an empty tree). It probably should go in
> cmd_ls_tree(), perhaps here:

Yes, it's better here as a fail-fast case.

According to the suggestion of the new location I think why not put the logic
further head, after the parse_options() return, like:

diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 1f82229649..003a9ade54 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -166,6 +166,10 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 
        argc = parse_options(argc, argv, prefix, ls_tree_options,
                             ls_tree_usage, 0);
+
+       if ((ls_options & LS_NAME_ONLY) && (ls_options & LS_OID_ONLY))
+               die(_("cannot specify --oid-only and --name-only at the same time"));
+
        if (full_tree) {
                ls_tree_prefix = prefix = NULL;
                chomp_prefix = 0;

Will it bring other new problems?

Thank you.
diff mbox series

Patch

diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 3a442631c7..1f82229649 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -20,6 +20,7 @@  static int line_termination = '\n';
 #define LS_SHOW_TREES 4
 #define LS_NAME_ONLY 8
 #define LS_SHOW_SIZE 16
+#define LS_OID_ONLY 32
 static int abbrev;
 static int ls_options;
 static struct pathspec pathspec;
@@ -90,6 +91,14 @@  static int show_tree(const struct object_id *oid, struct strbuf *base,
 	else if (ls_options & LS_TREE_ONLY)
 		return 0;
 
+	if ((ls_options & LS_NAME_ONLY) && (ls_options & LS_OID_ONLY))
+		die(_("cannot specify --oid-only and --name-only at the same time"));
+
+	if (ls_options & LS_OID_ONLY) {
+		printf("%s\n", find_unique_abbrev(oid, abbrev));
+		return 0;
+	}
+
 	if (!(ls_options & LS_NAME_ONLY)) {
 		if (ls_options & LS_SHOW_SIZE) {
 			char size_text[24];
@@ -139,6 +148,8 @@  int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 			LS_NAME_ONLY),
 		OPT_BIT(0, "name-status", &ls_options, N_("list only filenames"),
 			LS_NAME_ONLY),
+		OPT_BIT(0, "oid-only", &ls_options, N_("list only oids"),
+			LS_OID_ONLY),
 		OPT_SET_INT(0, "full-name", &chomp_prefix,
 			    N_("use full path names"), 0),
 		OPT_BOOL(0, "full-tree", &full_tree,