{"thread":{"id":"12703","subject":"Re: gnulib-tool --version","startedAt":"2008-03-15T04:37:41Z","lastAt":"2008-03-15T06:08:11Z","messageCount":2,"participants":["Eric Blake","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"72160","messageId":"47DB5295.9080005@byu.net","threadId":"12703","inReplyTo":"200803150512.53166.bruno@clisp.org","subject":"Re: gnulib-tool --version","fromName":"Eric Blake","fromEmail":"ebb9@byu.net","sentAt":"2008-03-15T04:37:41Z","receivedAt":"2008-03-15T04:37:41Z","isPatch":false,"sender":{"key":"eblake@redhat.com","avatar":"https://avatars.githubusercontent.com/u/32933908?v=4"},"body":"-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA1\n\n[adding the git list]\n\nAccording to Bruno Haible on 3/14/2008 10:12 PM:\n| Take an example: Until 3 days ago,\n|   $ git log 532f\n| was equivalent to\n|   $ git log 532f4b4a94e7df8e730e433d4cba9e4119641691\n|\n| But then there was a commit 532f65ac8de5a89ea0b159fc3b76ead5a53e9fea. Since\n| then,\n|   $ git log 532f\n| gives an error message\n|   error: short SHA1 532f is ambiguous.\n|   fatal: ambiguous argument '532f': unknown revision or path not in the\nworking tree.\n|   Use '--' to separate paths from revisions\n\nThe message comes from 'git rev-parse', which is called under the hood by\nmost other git commands to resolve a SHA1 prefix into a commit.\n\n|\n| To exclude the problem of ambiguous commit ids, with a reasonable\nprobability,\n| I would therefore take the first 8 hex digits, not only the first 4.\n\n'git rev-parse', and thus 'git describe', defaults to 7 hex digits, and\nwill display no fewer than 4 (although it displays as many as are\nnecessary to have a non-ambiguous output at the time it is run).  gnulib's\ngit-version-gen script intentionally asks 'git describe' for the shortest\nprefix, on the grounds that developers don't like to type long random\nstrings, rather than sticking with the default of 7.\n\nWhat is really needed is a method in git where once a SHA1 prefix becomes\nambiguous, you can still easily choose to resolve the ambiguity in favor\nof the oldest commit that matches the prefix.  This is on the grounds that\nthere are times when the user knows that the prefix was generated by 'git\ndescribe', and was not ambiguous at the time it was abbreviated.\nUnfortunately, I don't know such a command option or special syntax to\n'git rev-parse' to make this resolution occur.  And what's worse, the\nerror message from 'git rev-parse' doesn't help - it only states that the\nprefix is either missing or ambiguous.  It would be much nicer to know\nthat the prefix is now too short (vs. never existed), to then know to try\nthe option to list all the alternative candidates and/or pick the oldest.\n\n- --\nDon't work too hard, make some time for fun as well!\n\nEric Blake             ebb9@byu.net\n-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1.4.8 (Cygwin)\nComment: Public key at home.comcast.net/~ericblake/eblake.gpg\nComment: Using GnuPG with Mozilla - http://enigmail.mozdev.org\n\niEYEARECAAYFAkfbUpUACgkQ84KuGfSFAYDsewCgrD9hRriDEYGWd/WlWIxLDRk6\nyVYAoJMIPljUvCnqS4w38Kg2ckI9g88C\n=dDhg\n-----END PGP SIGNATURE-----\n"},{"id":"72168","messageId":"7vabl0o6yc.fsf@gitster.siamese.dyndns.org","threadId":"12703","inReplyTo":"47DB5295.9080005@byu.net","subject":"Re: gnulib-tool --version","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-15T06:08:11Z","receivedAt":"2008-03-15T06:08:11Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Blake <ebb9@byu.net> writes:\n\n> What is really needed is a method in git where once a SHA1 prefix becomes\n> ambiguous, you can still easily choose to resolve the ambiguity in favor\n> of the oldest commit that matches the prefix.\n\n\"Oldest commit\" does not make much sense in a distributed environment.  In\ngit.git, I tend to have many objects in my primary repository that nobody\nelse has, and other people would probably have many objects that I do not\nhave.  \"Oldest among the ones reachable from these heads\" and specifying\nonly the ones that are publicly available may have some value, though.\n\nI agree that we would want a reverse operation of find_unique_abbrev();\nhere is a quick and dirty one.\n\n    $ git rev-parse --disamb=aba1 |\n      git name-rev --stdin\n    aba14750f47700b8923b411a9348fb251b788967 tree\n    aba15f7f592c302196401d17a42c772d744555b4 (tags/gitgui-0.9.3~5) commit\n    aba16b190c54a107521801ad77ab66586553ba69 blob\n    aba170cdb4874b72dd619e6f7bbc13c33295f831 (tags/v1.5.2^0) commit\n\nIt is very tempting to say that we should favor commits over other types,\nbut at the \"extended sha1 expression\" level, we traditionally haven't\nfavored one type over others, so it has to wait until 1.6.0 at least.\n\n---\n builtin-rev-parse.c |   13 +++++++++++++\n cache.h             |    3 +++\n sha1_name.c         |   37 +++++++++++++++++++++++++++++++++++++\n 3 files changed, 53 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex 0351d54..c64b43e 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -365,6 +365,15 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n+static void disamb_show(const unsigned char *sha1, void *cb_data)\n+{\n+\tchar *orig = cb_data;\n+\tenum object_type type;\n+\n+\ttype = sha1_object_info(sha1, NULL);\n+\tprintf(\"%s %s %s\\n\", sha1_to_hex(sha1), typename(type), orig);\n+}\n+\n int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n {\n \tint i, as_is = 0, verify = 0;\n@@ -548,6 +557,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tshow_datestring(\"--min-age=\", arg+8);\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!prefixcmp(arg, \"--disamb=\")) {\n+\t\t\t\tfor_each_sha1(arg + 9, disamb_show, NULL);\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tif (show_flag(arg) && verify)\n \t\t\t\tdie(\"Needed a single revision\");\n \t\t\tcontinue;\ndiff --git a/cache.h b/cache.h\nindex 2a1e7ec..fa15140 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -454,6 +454,9 @@ extern char *sha1_file_name(const unsigned char *sha1);\n extern char *sha1_pack_name(const unsigned char *sha1);\n extern char *sha1_pack_index_name(const unsigned char *sha1);\n extern const char *find_unique_abbrev(const unsigned char *sha1, int);\n+typedef void for_each_sha1_fn(const unsigned char *sha1, void *);\n+int for_each_sha1(const char *prefix, for_each_sha1_fn fn, void *cb_data);\n+\n extern const unsigned char null_sha1[20];\n static inline int is_null_sha1(const unsigned char *sha1)\n {\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 8b6c76f..2703831 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -213,6 +213,43 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)\n \treturn hex;\n }\n \n+static int for_each_sha1_rec(char *prefix, int len, for_each_sha1_fn fn, void *cb_data)\n+{\n+\tunsigned char sha1[20];\n+\tint status, i, found;\n+\n+\tif (40 <= len)\n+\t\treturn 0;\n+\tstatus = get_short_sha1(prefix, len, sha1, 1);\n+\tif (status == SHORT_NAME_NOT_FOUND)\n+\t\treturn 0;\n+\tif (!status) {\n+\t\tfn(sha1, cb_data);\n+\t\treturn 1;\n+\t}\n+\t/* Ambiguous */\n+\tfound = 0;\n+\tfor (i = 0; i < 16; i++) {\n+\t\tprefix[len] = \"0123456789abcdef\"[i];\n+\t\tprefix[len+1] = '\\0';\n+\t\tfound += for_each_sha1_rec(prefix, len + 1, fn, cb_data);\n+\t}\n+\treturn found;\n+}\n+\n+int for_each_sha1(const char *prefix, for_each_sha1_fn fn, void *cb_data)\n+{\n+\tint len;\n+\tchar hex[41];\n+\n+\tlen = strlen(prefix);\n+\tif (40 <= len)\n+\t\treturn 0;\n+\tmemcpy(hex, prefix, len+1);\n+\n+\treturn for_each_sha1_rec(hex, len, fn, cb_data);\n+}\n+\n static int ambiguous_path(const char *path, int len)\n {\n \tint slash = 1;\n"}]}