{"thread":{"id":"60004","subject":"[PATCH] describe: --no-exact-match should not be the same as --exact-match","startedAt":"2023-07-18T21:23:03Z","lastAt":"2023-07-18T21:23:03Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"479608","messageId":"xmqqy1jcgbiv.fsf@gitster.g","threadId":"60004","inReplyTo":null,"subject":"[PATCH] describe: --no-exact-match should not be the same as --exact-match","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-18T21:22:48Z","receivedAt":"2023-07-18T21:23:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git describe --exact-match X\" is designed to fail when no tags are\npointing at X.  When given \"--no-exact-match\", the command line\nparser did the same thing as \"--exact-match\", which was clearly\nbogus.\n\nWhat \"--no-exact-match\" should do is not entirely clear, though.\n\nInternally, there is an integer \"max-candidates\" that specifies how\nmany possible \"describe\" names are computed (among which, the best\nname is picked), and this limit is set to 10 by default.  The\n\"--candidates=<number>\" option sets it to an arbitrary number (the\nidea being that by spending a bit more computing resource, we might\nbe able to come up with a better name).  \"--exact-match\" uses this\nmechanism to express that the user refuses to accept a name that is\nany non-zero distance away from a tag, and it does so by setting the\nlimit to 0.\n\nMaking \"--no-exact-match\" reset the counter to its default value\nwould allow \"git describe --exact-match --no-exact-match X\" to\ndefeat the earlier \"--exact-match\", and that is the solution we\nadopt here in this patch.  However, it is not clear what should\nhappen in this command:\n\n    git describe --exact-match --candidates=20 --no-exact-match X\n\nSaying --candidates=20 allows us to go inexact, but then should\n\"--no-exact-match\" become a no-op?  The implementation in this patch\nresets the counter to its default value, defeating the earlier\nsetting done by the \"--candidates\" option.  We probably could solve\nit by introducing an extra variable and combining the two after\nparse_options() returns, but let's declare that it is not worth\nsolving and use the simpler solution, i.e. \"--no-exact-match\" resets\nthe limit to its default value.\n\nThe \"--no-exact-match\" option was not covered in the tests, so let's\nadd a few.  Also add a case where --exact-match option is used on a\ncommit that cannot be described without distance from tags and make\nsure the command fails.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/describe.c  | 11 ++++++++---\n t/t6120-describe.sh |  8 ++++++++\n 2 files changed, 16 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/describe.c b/builtin/describe.c\nindex 55b4baaa22..879f8a8d45 100644\n--- a/builtin/describe.c\n+++ b/builtin/describe.c\n@@ -34,13 +34,15 @@ static const char * const describe_usage[] = {\n \tNULL\n };\n \n+#define DEFAULT_MAX_CANDIATES 10\n+\n static int debug;\t/* Display lots of verbose info */\n static int all;\t/* Any valid ref can be used */\n static int tags;\t/* Allow lightweight tags */\n static int longformat;\n static int first_parent;\n static int abbrev = -1; /* unspecified */\n-static int max_candidates = 10;\n+static int max_candidates = DEFAULT_MAX_CANDIATES;\n static struct hashmap names;\n static int have_util;\n static struct string_list patterns = STRING_LIST_INIT_NODUP;\n@@ -567,8 +569,11 @@ int cmd_describe(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"long\",       &longformat, N_(\"always use long format\")),\n \t\tOPT_BOOL(0, \"first-parent\", &first_parent, N_(\"only follow first parent\")),\n \t\tOPT__ABBREV(&abbrev),\n-\t\tOPT_SET_INT(0, \"exact-match\", &max_candidates,\n-\t\t\t    N_(\"only output exact matches\"), 0),\n+\t\tOPT_SET_INT_F(0, \"exact-match\", &max_candidates,\n+\t\t\t      N_(\"only output exact matches\"), 0, PARSE_OPT_NONEG),\n+\t\tOPT_SET_INT_F(0, \"no-exact-match\", &max_candidates,\n+\t\t\t      N_(\"only output exact matches\"), DEFAULT_MAX_CANDIATES,\n+\t\t\t      PARSE_OPT_NONEG),\n \t\tOPT_INTEGER(0, \"candidates\", &max_candidates,\n \t\t\t    N_(\"consider <n> most recent tags (default: 10)\")),\n \t\tOPT_STRING_LIST(0, \"match\", &patterns, N_(\"pattern\"),\ndiff --git a/t/t6120-describe.sh b/t/t6120-describe.sh\nindex c9afcef201..0a5c487540 100755\n--- a/t/t6120-describe.sh\n+++ b/t/t6120-describe.sh\n@@ -85,6 +85,7 @@ check_describe e-1-gHASH --tags HEAD^^\n check_describe c-2-gHASH --tags HEAD^^2\n check_describe B --tags HEAD^^2^\n check_describe e --tags HEAD^^^\n+check_describe e --tags --exact-match HEAD^^^\n \n check_describe heads/main --all HEAD\n check_describe tags/c-6-gHASH --all HEAD^\n@@ -96,6 +97,13 @@ check_describe A-3-gHASH --long HEAD^^2\n check_describe c-7-gHASH --tags\n check_describe e-3-gHASH --first-parent --tags\n \n+check_describe c-7-gHASH --tags --no-exact-match HEAD\n+check_describe e-3-gHASH --first-parent --tags --no-exact-match HEAD\n+\n+test_expect_success '--exact-match failure' '\n+\ttest_must_fail git describe --exact-match HEAD 2>err\n+'\n+\n test_expect_success 'describe --contains defaults to HEAD without commit-ish' '\n \techo \"A^0\" >expect &&\n \tgit checkout A &&\n-- \n2.41.0-376-gcba07a324d\n\n"}]}