{"thread":{"id":"50256","subject":"cat-file ambiguity prints \"dangling\"","startedAt":"2019-01-18T03:38:47Z","lastAt":"2019-01-30T21:33:51Z","messageCount":8,"participants":["Eric Wong","David Turner","SZEDER Gábor"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"367044","messageId":"20190118033845.s2vlrb3wd3m2jfzu@dcvr","threadId":"50256","inReplyTo":null,"subject":"cat-file ambiguity prints \"dangling\"","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2019-01-18T03:38:45Z","receivedAt":"2019-01-18T03:38:47Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"Hi David,\n\nPerhaps I'm confused, the cat-file manpage seems to indicate\n\"dangling\" only gets printed if I use \"--follow-symlinks\".\n\nHowever, I'm not using \"--follow-symlinks\" and I get\n\"dangling\" when passing ambiguous object IDs:\n\nTrying to check the ambiguous \"dead\" against git.git, I get:\n\n\t$ echo dead | git cat-file --batch-check 2>/dev/null\n\tdangling 4\n\tdead\n\nIs the above intended?\n\nstderr shows the ambiguity and gives me hints, which is expected.\n\nThanks.\n"},{"id":"367045","messageId":"a7307f431e2231dd420a0190a22aa38094cd593f.camel@novalis.org","threadId":"50256","inReplyTo":"20190118033845.s2vlrb3wd3m2jfzu@dcvr","subject":"Re: cat-file ambiguity prints \"dangling\"","fromName":"David Turner","fromEmail":"novalis@novalis.org","sentAt":"2019-01-18T04:46:06Z","receivedAt":"2019-01-18T04:46:14Z","isPatch":false,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"It appears that get_oid_with_context calls into get_short_oid for that\ncase, and get_short_oid returns SHORT_NAME_AMBIGUOUS, which is -2.  We\ntreat that as DANGLING_SYMLINK, which also seems to have the value -2. \nSo, it's an ambiguity in ambiguity resolution.\n\nFix attached.  \n\nOn Fri, 2019-01-18 at 03:38 +0000, Eric Wong wrote:\n> Hi David,\n> \n> Perhaps I'm confused, the cat-file manpage seems to indicate\n> \"dangling\" only gets printed if I use \"--follow-symlinks\".\n> \n> However, I'm not using \"--follow-symlinks\" and I get\n> \"dangling\" when passing ambiguous object IDs:\n> \n> Trying to check the ambiguous \"dead\" against git.git, I get:\n> \n> \t$ echo dead | git cat-file --batch-check 2>/dev/null\n> \tdangling 4\n> \tdead\n> \n> Is the above intended?\n> \n> stderr shows the ambiguity and gives me hints, which is expected.\n> \n> Thanks.\n> \n\n\nFrom 319a4c76f1939a004775a3440d504e14f53074f3 Mon Sep 17 00:00:00 2001\nFrom: David Turner <novalis@novalis.org>\nDate: Thu, 17 Jan 2019 23:19:43 -0500\nSubject: [PATCH] Do not print 'dangling' for cat-file in case of ambiguity\n\nThe return values -1 and -2 from get_oid could mean two different\nthings, depending on whether they were from an enum returned by\nget_tree_entry_follow_symlinks, or from a different code path.  This\ncaused 'dangling' to be printed from a git cat-file in the case of an\nambiguous (-2) result.\n\nUnify the results of get_oid* and get_tree_entry_follow_symlinks to be\none common type, with unambiguous values.\n\nSigned-off-by: David Turner <novalis@novalis.org>\nReported-by: Eric Wong <e@80x24.org>\n---\n builtin/cat-file.c |  5 +++-\n cache.h            | 20 +++++++++++++++-\n sha1-name.c        | 58 ++++++++++++++++++++++++----------------------\n tree-walk.c        |  4 ++--\n tree-walk.h        | 18 +-------------\n 5 files changed, 56 insertions(+), 49 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 2ca56fd086..f2344b199f 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -380,7 +380,7 @@ static void batch_one_object(const char *obj_name,\n {\n \tstruct object_context ctx;\n \tint flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;\n-\tenum follow_symlinks_result result;\n+\tenum get_oid_result result;\n \n \tresult = get_oid_with_context(obj_name, flags, &data->oid, &ctx);\n \tif (result != FOUND) {\n@@ -388,6 +388,9 @@ static void batch_one_object(const char *obj_name,\n \t\tcase MISSING_OBJECT:\n \t\t\tprintf(\"%s missing\\n\", obj_name);\n \t\t\tbreak;\n+\t\tcase SHORT_NAME_AMBIGUOUS:\n+\t\t\t/* We've already printed the ambiguous message */\n+\t\t\tbreak;\n \t\tcase DANGLING_SYMLINK:\n \t\t\tprintf(\"dangling %\"PRIuMAX\"\\n%s\\n\",\n \t\t\t       (uintmax_t)strlen(obj_name), obj_name);\ndiff --git a/cache.h b/cache.h\nindex 49713cc5a5..70652e99dc 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1332,6 +1332,24 @@ struct object_context {\n \tGET_OID_TREE | GET_OID_TREEISH | \\\n \tGET_OID_BLOB)\n \n+enum get_oid_result {\n+\tFOUND = 0,\n+\tMISSING_OBJECT = -1, /* The requested object is missing */\n+\tSHORT_NAME_AMBIGUOUS = -2,\n+\t/* The following only apply when symlinks are followed */\n+\tDANGLING_SYMLINK = -4, /*\n+\t\t\t\t* The initial symlink is there, but\n+\t\t\t\t* (transitively) points to a missing\n+\t\t\t\t* in-tree file\n+\t\t\t\t*/\n+\tSYMLINK_LOOP = -5,\n+\tNOT_DIR = -6, /*\n+\t\t       * Somewhere along the symlink chain, a path is\n+\t\t       * requested which contains a file as a\n+\t\t       * non-final element.\n+\t\t       */\n+};\n+\n extern int get_oid(const char *str, struct object_id *oid);\n extern int get_oid_commit(const char *str, struct object_id *oid);\n extern int get_oid_committish(const char *str, struct object_id *oid);\n@@ -1339,7 +1357,7 @@ extern int get_oid_tree(const char *str, struct object_id *oid);\n extern int get_oid_treeish(const char *str, struct object_id *oid);\n extern int get_oid_blob(const char *str, struct object_id *oid);\n extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);\n-extern int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);\n+extern enum get_oid_result get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);\n \n \n typedef int each_abbrev_fn(const struct object_id *oid, void *);\ndiff --git a/sha1-name.c b/sha1-name.c\nindex b24502811b..12313165d0 100644\n--- a/sha1-name.c\n+++ b/sha1-name.c\n@@ -190,9 +190,6 @@ static void find_short_packed_object(struct disambiguate_state *ds)\n \t\tunique_in_pack(p, ds);\n }\n \n-#define SHORT_NAME_NOT_FOUND (-1)\n-#define SHORT_NAME_AMBIGUOUS (-2)\n-\n static int finish_object_disambiguation(struct disambiguate_state *ds,\n \t\t\t\t\tstruct object_id *oid)\n {\n@@ -200,7 +197,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,\n \t\treturn SHORT_NAME_AMBIGUOUS;\n \n \tif (!ds->candidate_exists)\n-\t\treturn SHORT_NAME_NOT_FOUND;\n+\t\treturn MISSING_OBJECT;\n \n \tif (!ds->candidate_checked)\n \t\t/*\n@@ -414,8 +411,9 @@ static int sort_ambiguous(const void *a, const void *b)\n \treturn a_type_sort > b_type_sort ? 1 : -1;\n }\n \n-static int get_short_oid(const char *name, int len, struct object_id *oid,\n-\t\t\t  unsigned flags)\n+static enum get_oid_result get_short_oid(const char *name, int len,\n+\t\t\t\t\t struct object_id *oid,\n+\t\t\t\t\t unsigned flags)\n {\n \tint status;\n \tstruct disambiguate_state ds;\n@@ -733,7 +731,7 @@ static inline int push_mark(const char *string, int len)\n \treturn at_mark(string, len, suffix, ARRAY_SIZE(suffix));\n }\n \n-static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);\n+static enum get_oid_result get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);\n static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);\n \n static int get_oid_basic(const char *str, int len, struct object_id *oid,\n@@ -883,11 +881,12 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,\n \treturn 0;\n }\n \n-static int get_parent(const char *name, int len,\n-\t\t      struct object_id *result, int idx)\n+static enum get_oid_result get_parent(const char *name, int len,\n+\t\t\t\t      struct object_id *result, int idx)\n {\n \tstruct object_id oid;\n-\tint ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);\n+\tenum get_oid_result ret = get_oid_1(name, len, &oid,\n+\t\t\t\t\t    GET_OID_COMMITTISH);\n \tstruct commit *commit;\n \tstruct commit_list *p;\n \n@@ -895,24 +894,25 @@ static int get_parent(const char *name, int len,\n \t\treturn ret;\n \tcommit = lookup_commit_reference(the_repository, &oid);\n \tif (parse_commit(commit))\n-\t\treturn -1;\n+\t\treturn MISSING_OBJECT;\n \tif (!idx) {\n \t\toidcpy(result, &commit->object.oid);\n-\t\treturn 0;\n+\t\treturn FOUND;\n \t}\n \tp = commit->parents;\n \twhile (p) {\n \t\tif (!--idx) {\n \t\t\toidcpy(result, &p->item->object.oid);\n-\t\t\treturn 0;\n+\t\t\treturn FOUND;\n \t\t}\n \t\tp = p->next;\n \t}\n-\treturn -1;\n+\treturn MISSING_OBJECT;\n }\n \n-static int get_nth_ancestor(const char *name, int len,\n-\t\t\t    struct object_id *result, int generation)\n+static enum get_oid_result get_nth_ancestor(const char *name, int len,\n+\t\t\t\t\t    struct object_id *result,\n+\t\t\t\t\t    int generation)\n {\n \tstruct object_id oid;\n \tstruct commit *commit;\n@@ -923,15 +923,15 @@ static int get_nth_ancestor(const char *name, int len,\n \t\treturn ret;\n \tcommit = lookup_commit_reference(the_repository, &oid);\n \tif (!commit)\n-\t\treturn -1;\n+\t\treturn MISSING_OBJECT;\n \n \twhile (generation--) {\n \t\tif (parse_commit(commit) || !commit->parents)\n-\t\t\treturn -1;\n+\t\t\treturn MISSING_OBJECT;\n \t\tcommit = commit->parents->item;\n \t}\n \toidcpy(result, &commit->object.oid);\n-\treturn 0;\n+\treturn FOUND;\n }\n \n struct object *peel_to_type(const char *name, int namelen,\n@@ -1077,7 +1077,9 @@ static int get_describe_name(const char *name, int len, struct object_id *oid)\n \treturn -1;\n }\n \n-static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags)\n+static enum get_oid_result get_oid_1(const char *name, int len,\n+\t\t\t\t     struct object_id *oid,\n+\t\t\t\t     unsigned lookup_flags)\n {\n \tint ret, has_suffix;\n \tconst char *cp;\n@@ -1111,16 +1113,16 @@ static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned\n \n \tret = peel_onion(name, len, oid, lookup_flags);\n \tif (!ret)\n-\t\treturn 0;\n+\t\treturn FOUND;\n \n \tret = get_oid_basic(name, len, oid, lookup_flags);\n \tif (!ret)\n-\t\treturn 0;\n+\t\treturn FOUND;\n \n \t/* It could be describe output that is \"SOMETHING-gXXXX\" */\n \tret = get_describe_name(name, len, oid);\n \tif (!ret)\n-\t\treturn 0;\n+\t\treturn FOUND;\n \n \treturn get_short_oid(name, len, oid, lookup_flags);\n }\n@@ -1664,11 +1666,11 @@ static char *resolve_relative_path(const char *rel)\n \t\t\t   rel);\n }\n \n-static int get_oid_with_context_1(const char *name,\n-\t\t\t\t  unsigned flags,\n-\t\t\t\t  const char *prefix,\n-\t\t\t\t  struct object_id *oid,\n-\t\t\t\t  struct object_context *oc)\n+static enum get_oid_result get_oid_with_context_1(const char *name,\n+\t\t\t\t\t\t  unsigned flags,\n+\t\t\t\t\t\t  const char *prefix,\n+\t\t\t\t\t\t  struct object_id *oid,\n+\t\t\t\t\t\t  struct object_context *oc)\n {\n \tint ret, bracket_depth;\n \tint namelen = strlen(name);\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 08210a4109..fb7959b21d 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -579,10 +579,10 @@ int get_tree_entry(const struct object_id *tree_oid, const char *name, struct ob\n  * with the sha1 of the found object, and *mode will hold the mode of\n  * the object.\n  *\n- * See the code for enum follow_symlink_result for a description of\n+ * See the code for enum get_oid_result for a description of\n  * the return values.\n  */\n-enum follow_symlinks_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode)\n+enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode)\n {\n \tint retval = MISSING_OBJECT;\n \tstruct dir_state *parents = NULL;\ndiff --git a/tree-walk.h b/tree-walk.h\nindex eefd26bb62..de6b95179d 100644\n--- a/tree-walk.h\n+++ b/tree-walk.h\n@@ -51,23 +51,7 @@ struct traverse_info;\n typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *);\n int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info);\n \n-enum follow_symlinks_result {\n-\tFOUND = 0, /* This includes out-of-tree links */\n-\tMISSING_OBJECT = -1, /* The initial symlink is missing */\n-\tDANGLING_SYMLINK = -2, /*\n-\t\t\t\t* The initial symlink is there, but\n-\t\t\t\t* (transitively) points to a missing\n-\t\t\t\t* in-tree file\n-\t\t\t\t*/\n-\tSYMLINK_LOOP = -3,\n-\tNOT_DIR = -4, /*\n-\t\t       * Somewhere along the symlink chain, a path is\n-\t\t       * requested which contains a file as a\n-\t\t       * non-final element.\n-\t\t       */\n-};\n-\n-enum follow_symlinks_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode);\n+enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode);\n \n struct traverse_info {\n \tconst char *traverse_path;\n-- \n2.19.1\n\n"},{"id":"367080","messageId":"20190118104519.fqpzirux5qulkcwa@dcvr","threadId":"50256","inReplyTo":"a7307f431e2231dd420a0190a22aa38094cd593f.camel@novalis.org","subject":"Re: cat-file ambiguity prints \"dangling\"","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2019-01-18T10:45:19Z","receivedAt":"2019-01-18T10:45:21Z","isPatch":false,"sender":{"key":"e@80x24.org","avatar":null},"body":"David Turner <novalis@novalis.org> wrote:\n> It appears that get_oid_with_context calls into get_short_oid for that\n> case, and get_short_oid returns SHORT_NAME_AMBIGUOUS, which is -2.  We\n> treat that as DANGLING_SYMLINK, which also seems to have the value -2. \n> So, it's an ambiguity in ambiguity resolution.\n> \n> Fix attached.  \n\nThanks for the quick response.  Unfortunately, the patch makes\nthe situation worse for me...\n\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index 2ca56fd086..f2344b199f 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -380,7 +380,7 @@ static void batch_one_object(const char *obj_name,\n>  {\n>  \tstruct object_context ctx;\n>  \tint flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;\n> -\tenum follow_symlinks_result result;\n> +\tenum get_oid_result result;\n>  \n>  \tresult = get_oid_with_context(obj_name, flags, &data->oid, &ctx);\n>  \tif (result != FOUND) {\n> @@ -388,6 +388,9 @@ static void batch_one_object(const char *obj_name,\n>  \t\tcase MISSING_OBJECT:\n>  \t\t\tprintf(\"%s missing\\n\", obj_name);\n>  \t\t\tbreak;\n> +\t\tcase SHORT_NAME_AMBIGUOUS:\n> +\t\t\t/* We've already printed the ambiguous message */\n> +\t\t\tbreak;\n\nBecause the message about ambiguity only goes to stderr.\nSomething needs to go to stdout, or else the reader process\nwould hang forever.\n\nI've already updated my code[1] to work around \"dangling\",\nbut maybe printing \"ambiguous\" similar to the \"missing\" message\nwould be appropriate?  Something like:\n\n\t\tcase SHORT_NAME_AMBIGUOUS:\n\t\t\tprintf(\"%s ambiguous\\n\", obj_name);\n\t\t\tbreak;\n\n(Along with a manpage update)\n\n\n[1] new stuff for public-inbox on the way :>\n"},{"id":"367108","messageId":"672a6fb9e480becbfcb5df23ae37193784811b6b.camel@novalis.org","threadId":"50256","inReplyTo":"20190118104519.fqpzirux5qulkcwa@dcvr","subject":"Re: cat-file ambiguity prints \"dangling\"","fromName":"David Turner","fromEmail":"novalis@novalis.org","sentAt":"2019-01-18T16:20:48Z","receivedAt":"2019-01-18T16:24:01Z","isPatch":false,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Let's try this version.\n\nOn Fri, 2019-01-18 at 10:45 +0000, Eric Wong wrote:\n> David Turner <novalis@novalis.org> wrote:\n> > It appears that get_oid_with_context calls into get_short_oid for\n> > that\n> > case, and get_short_oid returns SHORT_NAME_AMBIGUOUS, which is\n> > -2.  We\n> > treat that as DANGLING_SYMLINK, which also seems to have the value\n> > -2. \n> > So, it's an ambiguity in ambiguity resolution.\n> > \n> > Fix attached.  \n> \n> Thanks for the quick response.  Unfortunately, the patch makes\n> the situation worse for me...\n> \n> > diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> > index 2ca56fd086..f2344b199f 100644\n> > --- a/builtin/cat-file.c\n> > +++ b/builtin/cat-file.c\n> > @@ -380,7 +380,7 @@ static void batch_one_object(const char\n> > *obj_name,\n> >  {\n> >  \tstruct object_context ctx;\n> >  \tint flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;\n> > -\tenum follow_symlinks_result result;\n> > +\tenum get_oid_result result;\n> >  \n> >  \tresult = get_oid_with_context(obj_name, flags, &data->oid,\n> > &ctx);\n> >  \tif (result != FOUND) {\n> > @@ -388,6 +388,9 @@ static void batch_one_object(const char\n> > *obj_name,\n> >  \t\tcase MISSING_OBJECT:\n> >  \t\t\tprintf(\"%s missing\\n\", obj_name);\n> >  \t\t\tbreak;\n> > +\t\tcase SHORT_NAME_AMBIGUOUS:\n> > +\t\t\t/* We've already printed the ambiguous message\n> > */\n> > +\t\t\tbreak;\n> \n> Because the message about ambiguity only goes to stderr.\n> Something needs to go to stdout, or else the reader process\n> would hang forever.\n> \n> I've already updated my code[1] to work around \"dangling\",\n> but maybe printing \"ambiguous\" similar to the \"missing\" message\n> would be appropriate?  Something like:\n> \n> \t\tcase SHORT_NAME_AMBIGUOUS:\n> \t\t\tprintf(\"%s ambiguous\\n\", obj_name);\n> \t\t\tbreak;\n> \n> (Along with a manpage update)\n> \n> \n> [1] new stuff for public-inbox on the way :>\n> \n\n\nFrom b152b3463477a8260d2b8c0ab46ad76562feed37 Mon Sep 17 00:00:00 2001\nFrom: David Turner <novalis@novalis.org>\nDate: Thu, 17 Jan 2019 23:19:43 -0500\nSubject: [PATCH v2] Do not print 'dangling' for cat-file in case of ambiguity\n\nThe return values -1 and -2 from get_oid could mean two different\nthings, depending on whether they were from an enum returned by\nget_tree_entry_follow_symlinks, or from a different code path.  This\ncaused 'dangling' to be printed from a git cat-file in the case of an\nambiguous (-2) result.\n\nUnify the results of get_oid* and get_tree_entry_follow_symlinks to be\none common type, with unambiguous values.\n\nSigned-off-by: David Turner <novalis@novalis.org>\nReported-by: Eric Wong <e@80x24.org>\n---\n Documentation/git-cat-file.txt |  6 ++++\n builtin/cat-file.c             |  5 ++-\n cache.h                        | 20 +++++++++++-\n sha1-name.c                    | 58 ++++++++++++++++++----------------\n tree-walk.c                    |  4 +--\n tree-walk.h                    | 18 +----------\n 6 files changed, 62 insertions(+), 49 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt\nindex 74013335a1..e27a940985 100644\n--- a/Documentation/git-cat-file.txt\n+++ b/Documentation/git-cat-file.txt\n@@ -252,6 +252,12 @@ the repository, then `cat-file` will ignore any custom format and print:\n <object> SP missing LF\n ------------\n \n+If a name is specified that might refer to more than one object (an ambiguous short sha), then `cat-file` will ignore any custom format and print:\n+\n+------------\n+<object> SP ambiguous LF\n+------------\n+\n If --follow-symlinks is used, and a symlink in the repository points\n outside the repository, then `cat-file` will ignore any custom format\n and print:\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex 2ca56fd086..cebc6d7f8a 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -380,7 +380,7 @@ static void batch_one_object(const char *obj_name,\n {\n \tstruct object_context ctx;\n \tint flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;\n-\tenum follow_symlinks_result result;\n+\tenum get_oid_result result;\n \n \tresult = get_oid_with_context(obj_name, flags, &data->oid, &ctx);\n \tif (result != FOUND) {\n@@ -388,6 +388,9 @@ static void batch_one_object(const char *obj_name,\n \t\tcase MISSING_OBJECT:\n \t\t\tprintf(\"%s missing\\n\", obj_name);\n \t\t\tbreak;\n+\t\tcase SHORT_NAME_AMBIGUOUS:\n+\t\t\tprintf(\"%s ambiguous\\n\", obj_name);\n+\t\t\tbreak;\n \t\tcase DANGLING_SYMLINK:\n \t\t\tprintf(\"dangling %\"PRIuMAX\"\\n%s\\n\",\n \t\t\t       (uintmax_t)strlen(obj_name), obj_name);\ndiff --git a/cache.h b/cache.h\nindex 49713cc5a5..70652e99dc 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1332,6 +1332,24 @@ struct object_context {\n \tGET_OID_TREE | GET_OID_TREEISH | \\\n \tGET_OID_BLOB)\n \n+enum get_oid_result {\n+\tFOUND = 0,\n+\tMISSING_OBJECT = -1, /* The requested object is missing */\n+\tSHORT_NAME_AMBIGUOUS = -2,\n+\t/* The following only apply when symlinks are followed */\n+\tDANGLING_SYMLINK = -4, /*\n+\t\t\t\t* The initial symlink is there, but\n+\t\t\t\t* (transitively) points to a missing\n+\t\t\t\t* in-tree file\n+\t\t\t\t*/\n+\tSYMLINK_LOOP = -5,\n+\tNOT_DIR = -6, /*\n+\t\t       * Somewhere along the symlink chain, a path is\n+\t\t       * requested which contains a file as a\n+\t\t       * non-final element.\n+\t\t       */\n+};\n+\n extern int get_oid(const char *str, struct object_id *oid);\n extern int get_oid_commit(const char *str, struct object_id *oid);\n extern int get_oid_committish(const char *str, struct object_id *oid);\n@@ -1339,7 +1357,7 @@ extern int get_oid_tree(const char *str, struct object_id *oid);\n extern int get_oid_treeish(const char *str, struct object_id *oid);\n extern int get_oid_blob(const char *str, struct object_id *oid);\n extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);\n-extern int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);\n+extern enum get_oid_result get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);\n \n \n typedef int each_abbrev_fn(const struct object_id *oid, void *);\ndiff --git a/sha1-name.c b/sha1-name.c\nindex b24502811b..12313165d0 100644\n--- a/sha1-name.c\n+++ b/sha1-name.c\n@@ -190,9 +190,6 @@ static void find_short_packed_object(struct disambiguate_state *ds)\n \t\tunique_in_pack(p, ds);\n }\n \n-#define SHORT_NAME_NOT_FOUND (-1)\n-#define SHORT_NAME_AMBIGUOUS (-2)\n-\n static int finish_object_disambiguation(struct disambiguate_state *ds,\n \t\t\t\t\tstruct object_id *oid)\n {\n@@ -200,7 +197,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,\n \t\treturn SHORT_NAME_AMBIGUOUS;\n \n \tif (!ds->candidate_exists)\n-\t\treturn SHORT_NAME_NOT_FOUND;\n+\t\treturn MISSING_OBJECT;\n \n \tif (!ds->candidate_checked)\n \t\t/*\n@@ -414,8 +411,9 @@ static int sort_ambiguous(const void *a, const void *b)\n \treturn a_type_sort > b_type_sort ? 1 : -1;\n }\n \n-static int get_short_oid(const char *name, int len, struct object_id *oid,\n-\t\t\t  unsigned flags)\n+static enum get_oid_result get_short_oid(const char *name, int len,\n+\t\t\t\t\t struct object_id *oid,\n+\t\t\t\t\t unsigned flags)\n {\n \tint status;\n \tstruct disambiguate_state ds;\n@@ -733,7 +731,7 @@ static inline int push_mark(const char *string, int len)\n \treturn at_mark(string, len, suffix, ARRAY_SIZE(suffix));\n }\n \n-static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);\n+static enum get_oid_result get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);\n static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);\n \n static int get_oid_basic(const char *str, int len, struct object_id *oid,\n@@ -883,11 +881,12 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,\n \treturn 0;\n }\n \n-static int get_parent(const char *name, int len,\n-\t\t      struct object_id *result, int idx)\n+static enum get_oid_result get_parent(const char *name, int len,\n+\t\t\t\t      struct object_id *result, int idx)\n {\n \tstruct object_id oid;\n-\tint ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);\n+\tenum get_oid_result ret = get_oid_1(name, len, &oid,\n+\t\t\t\t\t    GET_OID_COMMITTISH);\n \tstruct commit *commit;\n \tstruct commit_list *p;\n \n@@ -895,24 +894,25 @@ static int get_parent(const char *name, int len,\n \t\treturn ret;\n \tcommit = lookup_commit_reference(the_repository, &oid);\n \tif (parse_commit(commit))\n-\t\treturn -1;\n+\t\treturn MISSING_OBJECT;\n \tif (!idx) {\n \t\toidcpy(result, &commit->object.oid);\n-\t\treturn 0;\n+\t\treturn FOUND;\n \t}\n \tp = commit->parents;\n \twhile (p) {\n \t\tif (!--idx) {\n \t\t\toidcpy(result, &p->item->object.oid);\n-\t\t\treturn 0;\n+\t\t\treturn FOUND;\n \t\t}\n \t\tp = p->next;\n \t}\n-\treturn -1;\n+\treturn MISSING_OBJECT;\n }\n \n-static int get_nth_ancestor(const char *name, int len,\n-\t\t\t    struct object_id *result, int generation)\n+static enum get_oid_result get_nth_ancestor(const char *name, int len,\n+\t\t\t\t\t    struct object_id *result,\n+\t\t\t\t\t    int generation)\n {\n \tstruct object_id oid;\n \tstruct commit *commit;\n@@ -923,15 +923,15 @@ static int get_nth_ancestor(const char *name, int len,\n \t\treturn ret;\n \tcommit = lookup_commit_reference(the_repository, &oid);\n \tif (!commit)\n-\t\treturn -1;\n+\t\treturn MISSING_OBJECT;\n \n \twhile (generation--) {\n \t\tif (parse_commit(commit) || !commit->parents)\n-\t\t\treturn -1;\n+\t\t\treturn MISSING_OBJECT;\n \t\tcommit = commit->parents->item;\n \t}\n \toidcpy(result, &commit->object.oid);\n-\treturn 0;\n+\treturn FOUND;\n }\n \n struct object *peel_to_type(const char *name, int namelen,\n@@ -1077,7 +1077,9 @@ static int get_describe_name(const char *name, int len, struct object_id *oid)\n \treturn -1;\n }\n \n-static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags)\n+static enum get_oid_result get_oid_1(const char *name, int len,\n+\t\t\t\t     struct object_id *oid,\n+\t\t\t\t     unsigned lookup_flags)\n {\n \tint ret, has_suffix;\n \tconst char *cp;\n@@ -1111,16 +1113,16 @@ static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned\n \n \tret = peel_onion(name, len, oid, lookup_flags);\n \tif (!ret)\n-\t\treturn 0;\n+\t\treturn FOUND;\n \n \tret = get_oid_basic(name, len, oid, lookup_flags);\n \tif (!ret)\n-\t\treturn 0;\n+\t\treturn FOUND;\n \n \t/* It could be describe output that is \"SOMETHING-gXXXX\" */\n \tret = get_describe_name(name, len, oid);\n \tif (!ret)\n-\t\treturn 0;\n+\t\treturn FOUND;\n \n \treturn get_short_oid(name, len, oid, lookup_flags);\n }\n@@ -1664,11 +1666,11 @@ static char *resolve_relative_path(const char *rel)\n \t\t\t   rel);\n }\n \n-static int get_oid_with_context_1(const char *name,\n-\t\t\t\t  unsigned flags,\n-\t\t\t\t  const char *prefix,\n-\t\t\t\t  struct object_id *oid,\n-\t\t\t\t  struct object_context *oc)\n+static enum get_oid_result get_oid_with_context_1(const char *name,\n+\t\t\t\t\t\t  unsigned flags,\n+\t\t\t\t\t\t  const char *prefix,\n+\t\t\t\t\t\t  struct object_id *oid,\n+\t\t\t\t\t\t  struct object_context *oc)\n {\n \tint ret, bracket_depth;\n \tint namelen = strlen(name);\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 08210a4109..fb7959b21d 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -579,10 +579,10 @@ int get_tree_entry(const struct object_id *tree_oid, const char *name, struct ob\n  * with the sha1 of the found object, and *mode will hold the mode of\n  * the object.\n  *\n- * See the code for enum follow_symlink_result for a description of\n+ * See the code for enum get_oid_result for a description of\n  * the return values.\n  */\n-enum follow_symlinks_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode)\n+enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode)\n {\n \tint retval = MISSING_OBJECT;\n \tstruct dir_state *parents = NULL;\ndiff --git a/tree-walk.h b/tree-walk.h\nindex eefd26bb62..de6b95179d 100644\n--- a/tree-walk.h\n+++ b/tree-walk.h\n@@ -51,23 +51,7 @@ struct traverse_info;\n typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *);\n int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info);\n \n-enum follow_symlinks_result {\n-\tFOUND = 0, /* This includes out-of-tree links */\n-\tMISSING_OBJECT = -1, /* The initial symlink is missing */\n-\tDANGLING_SYMLINK = -2, /*\n-\t\t\t\t* The initial symlink is there, but\n-\t\t\t\t* (transitively) points to a missing\n-\t\t\t\t* in-tree file\n-\t\t\t\t*/\n-\tSYMLINK_LOOP = -3,\n-\tNOT_DIR = -4, /*\n-\t\t       * Somewhere along the symlink chain, a path is\n-\t\t       * requested which contains a file as a\n-\t\t       * non-final element.\n-\t\t       */\n-};\n-\n-enum follow_symlinks_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode);\n+enum get_oid_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode);\n \n struct traverse_info {\n \tconst char *traverse_path;\n-- \n2.19.1\n\n"},{"id":"367153","messageId":"20190118222629.3nvcos24gmi6xe4i@dcvr","threadId":"50256","inReplyTo":"672a6fb9e480becbfcb5df23ae37193784811b6b.camel@novalis.org","subject":"[PATCH] t1512: test ambiguous cat-file --batch and --batch-output","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2019-01-18T22:26:29Z","receivedAt":"2019-01-18T22:26:33Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"David Turner <novalis@novalis.org> wrote:\n> Let's try this version.\n\nThanks!\n\nTested-by: Eric Wong <e@80x24.org>\n\nNot sure if t1512 would be the best place to put the test, but\nhaving a repo with ambiguous data already at hand was easiest.\n\n---------8<-------\nSubject: [PATCH] t1512: test ambiguous cat-file --batch and --batch-output\n\nTest the new \"ambiguous\" result from cat-file --batch and\n--batch-check.  This is in t1512 instead of t1006 since\nwe need a repo with ambiguous object_id names.\n\nSigned-off-by: Eric Wong <e@80x24.org>\n---\n t/t1512-rev-parse-disambiguation.sh | 10 ++++++++++\n 1 file changed, 10 insertions(+)\n\ndiff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh\nindex e4d5b56014..b0819630c9 100755\n--- a/t/t1512-rev-parse-disambiguation.sh\n+++ b/t/t1512-rev-parse-disambiguation.sh\n@@ -388,4 +388,14 @@ test_expect_success C_LOCALE_OUTPUT 'ambiguous commits are printed by type first\n \tdone\n '\n \n+test_expect_success 'cat-file --batch and --batch-check show ambiguous' '\n+\techo \"0000 ambiguous\" >expect &&\n+\techo 0000 | git cat-file --batch-check >actual 2>err &&\n+\ttest_cmp expect actual &&\n+\tgrep hint: err &&\n+\techo 0000 | git cat-file --batch >actual 2>err &&\n+\ttest_cmp expect actual &&\n+\tgrep hint: err\n+'\n+\n test_done\n-- \nEW\n"},{"id":"367155","messageId":"b4f859d8c414bbf0693cf26a418cc6c4769456ef.camel@novalis.org","threadId":"50256","inReplyTo":"20190118222629.3nvcos24gmi6xe4i@dcvr","subject":"Re: [PATCH] t1512: test ambiguous cat-file --batch and --batch-output","fromName":"David Turner","fromEmail":"novalis@novalis.org","sentAt":"2019-01-18T22:29:48Z","receivedAt":"2019-01-18T22:29:55Z","isPatch":true,"sender":{"key":"novalis@novalis.org","avatar":"https://avatars.githubusercontent.com/u/77003?v=4"},"body":"Thanks for adding the test. \n\nOn Fri, 2019-01-18 at 22:26 +0000, Eric Wong wrote:\n> David Turner <novalis@novalis.org> wrote:\n> > Let's try this version.\n> \n> Thanks!\n> \n> Tested-by: Eric Wong <e@80x24.org>\n> \n> Not sure if t1512 would be the best place to put the test, but\n> having a repo with ambiguous data already at hand was easiest.\n> \n> ---------8<-------\n> Subject: [PATCH] t1512: test ambiguous cat-file --batch and --batch-\n> output\n> \n> Test the new \"ambiguous\" result from cat-file --batch and\n> --batch-check.  This is in t1512 instead of t1006 since\n> we need a repo with ambiguous object_id names.\n> \n> Signed-off-by: Eric Wong <e@80x24.org>\n> ---\n>  t/t1512-rev-parse-disambiguation.sh | 10 ++++++++++\n>  1 file changed, 10 insertions(+)\n> \n> diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-\n> disambiguation.sh\n> index e4d5b56014..b0819630c9 100755\n> --- a/t/t1512-rev-parse-disambiguation.sh\n> +++ b/t/t1512-rev-parse-disambiguation.sh\n> @@ -388,4 +388,14 @@ test_expect_success C_LOCALE_OUTPUT 'ambiguous\n> commits are printed by type first\n>  \tdone\n>  '\n>  \n> +test_expect_success 'cat-file --batch and --batch-check show\n> ambiguous' '\n> +\techo \"0000 ambiguous\" >expect &&\n> +\techo 0000 | git cat-file --batch-check >actual 2>err &&\n> +\ttest_cmp expect actual &&\n> +\tgrep hint: err &&\n> +\techo 0000 | git cat-file --batch >actual 2>err &&\n> +\ttest_cmp expect actual &&\n> +\tgrep hint: err\n> +'\n> +\n>  test_done\n\n"},{"id":"367410","messageId":"20190123111117.GS840@szeder.dev","threadId":"50256","inReplyTo":"20190118222629.3nvcos24gmi6xe4i@dcvr","subject":"Re: [PATCH] t1512: test ambiguous cat-file --batch and --batch-output","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2019-01-23T11:11:17Z","receivedAt":"2019-01-23T11:11:23Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Fri, Jan 18, 2019 at 10:26:29PM +0000, Eric Wong wrote:\n> Test the new \"ambiguous\" result from cat-file --batch and\n> --batch-check.  This is in t1512 instead of t1006 since\n> we need a repo with ambiguous object_id names.\n> \n> Signed-off-by: Eric Wong <e@80x24.org>\n> ---\n>  t/t1512-rev-parse-disambiguation.sh | 10 ++++++++++\n>  1 file changed, 10 insertions(+)\n> \n> diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh\n> index e4d5b56014..b0819630c9 100755\n> --- a/t/t1512-rev-parse-disambiguation.sh\n> +++ b/t/t1512-rev-parse-disambiguation.sh\n> @@ -388,4 +388,14 @@ test_expect_success C_LOCALE_OUTPUT 'ambiguous commits are printed by type first\n>  \tdone\n>  '\n>  \n> +test_expect_success 'cat-file --batch and --batch-check show ambiguous' '\n> +\techo \"0000 ambiguous\" >expect &&\n> +\techo 0000 | git cat-file --batch-check >actual 2>err &&\n> +\ttest_cmp expect actual &&\n> +\tgrep hint: err &&\n> +\techo 0000 | git cat-file --batch >actual 2>err &&\n> +\ttest_cmp expect actual &&\n> +\tgrep hint: err\n\nThe 'git cat-file's error message and hints are translated, so they\nshould be checked by 'test_i18ngrep' instead of plain old grep.\n\n> +'\n> +\n>  test_done\n> -- \n> EW\n"},{"id":"368199","messageId":"20190130213349.h5xiujbbtw4o3i35@dcvr","threadId":"50256","inReplyTo":"20190123111117.GS840@szeder.dev","subject":"[PATCH v2] t1512: test ambiguous cat-file --batch and --batch-output","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2019-01-30T21:33:49Z","receivedAt":"2019-01-30T21:33:51Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"SZEDER Gábor <szeder.dev@gmail.com> wrote:\n> The 'git cat-file's error message and hints are translated, so they\n> should be checked by 'test_i18ngrep' instead of plain old grep.\n\nThanks, here's v2 with test_i18ngrep\n\n--------8<------\nSubject: [PATCH] t1512: test ambiguous cat-file --batch and --batch-output\n\nTest the new \"ambiguous\" result from cat-file --batch and\n--batch-check.  This is in t1512 instead of t1006 since\nwe need a repo with ambiguous object_id names.\n\nSigned-off-by: Eric Wong <e@80x24.org>\n---\n t/t1512-rev-parse-disambiguation.sh | 10 ++++++++++\n 1 file changed, 10 insertions(+)\n\ndiff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh\nindex e4d5b56014..c19fb500cb 100755\n--- a/t/t1512-rev-parse-disambiguation.sh\n+++ b/t/t1512-rev-parse-disambiguation.sh\n@@ -388,4 +388,14 @@ test_expect_success C_LOCALE_OUTPUT 'ambiguous commits are printed by type first\n \tdone\n '\n \n+test_expect_success 'cat-file --batch and --batch-check show ambiguous' '\n+\techo \"0000 ambiguous\" >expect &&\n+\techo 0000 | git cat-file --batch-check >actual 2>err &&\n+\ttest_cmp expect actual &&\n+\ttest_i18ngrep hint: err &&\n+\techo 0000 | git cat-file --batch >actual 2>err &&\n+\ttest_cmp expect actual &&\n+\ttest_i18ngrep hint: err\n+'\n+\n test_done\n-- \nEW\n"}]}