Do not print 'dangling' for cat-file in case of ambiguity

The return values -1 and -2 from get_oid could mean two different
things, depending on whether they were from an enum returned by
get_tree_entry_follow_symlinks, or from a different code path.  This
caused 'dangling' to be printed from a git cat-file in the case of an
ambiguous (-2) result.

Unify the results of get_oid* and get_tree_entry_follow_symlinks to be
one common type, with unambiguous values.

Signed-off-by: David Turner <novalis@novalis.org>
Reported-by: Eric Wong <e@80x24.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
pull/573/head
David Turner 4 years ago committed by Junio C Hamano
parent 16a465bc01
commit d1dd94b308
  1. 6
      Documentation/git-cat-file.txt
  2. 5
      builtin/cat-file.c
  3. 20
      cache.h
  4. 58
      sha1-name.c
  5. 4
      tree-walk.c
  6. 18
      tree-walk.h

@ -252,6 +252,12 @@ the repository, then `cat-file` will ignore any custom format and print:
<object> SP missing LF
------------
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:
------------
<object> SP ambiguous LF
------------
If --follow-symlinks is used, and a symlink in the repository points
outside the repository, then `cat-file` will ignore any custom format
and print:

@ -380,7 +380,7 @@ static void batch_one_object(const char *obj_name,
{
struct object_context ctx;
int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
enum follow_symlinks_result result;
enum get_oid_result result;
result = get_oid_with_context(obj_name, flags, &data->oid, &ctx);
if (result != FOUND) {
@ -388,6 +388,9 @@ static void batch_one_object(const char *obj_name,
case MISSING_OBJECT:
printf("%s missing\n", obj_name);
break;
case SHORT_NAME_AMBIGUOUS:
printf("%s ambiguous\n", obj_name);
break;
case DANGLING_SYMLINK:
printf("dangling %"PRIuMAX"\n%s\n",
(uintmax_t)strlen(obj_name), obj_name);

@ -1332,6 +1332,24 @@ struct object_context {
GET_OID_TREE | GET_OID_TREEISH | \
GET_OID_BLOB)
enum get_oid_result {
FOUND = 0,
MISSING_OBJECT = -1, /* The requested object is missing */
SHORT_NAME_AMBIGUOUS = -2,
/* The following only apply when symlinks are followed */
DANGLING_SYMLINK = -4, /*
* The initial symlink is there, but
* (transitively) points to a missing
* in-tree file
*/
SYMLINK_LOOP = -5,
NOT_DIR = -6, /*
* Somewhere along the symlink chain, a path is
* requested which contains a file as a
* non-final element.
*/
};
extern int get_oid(const char *str, struct object_id *oid);
extern int get_oid_commit(const char *str, struct object_id *oid);
extern int get_oid_committish(const char *str, struct object_id *oid);
@ -1339,7 +1357,7 @@ extern int get_oid_tree(const char *str, struct object_id *oid);
extern int get_oid_treeish(const char *str, struct object_id *oid);
extern int get_oid_blob(const char *str, struct object_id *oid);
extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
extern int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
extern enum get_oid_result get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
typedef int each_abbrev_fn(const struct object_id *oid, void *);

@ -190,9 +190,6 @@ static void find_short_packed_object(struct disambiguate_state *ds)
unique_in_pack(p, ds);
}
#define SHORT_NAME_NOT_FOUND (-1)
#define SHORT_NAME_AMBIGUOUS (-2)
static int finish_object_disambiguation(struct disambiguate_state *ds,
struct object_id *oid)
{
@ -200,7 +197,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
return SHORT_NAME_AMBIGUOUS;
if (!ds->candidate_exists)
return SHORT_NAME_NOT_FOUND;
return MISSING_OBJECT;
if (!ds->candidate_checked)
/*
@ -414,8 +411,9 @@ static int sort_ambiguous(const void *a, const void *b)
return a_type_sort > b_type_sort ? 1 : -1;
}
static int get_short_oid(const char *name, int len, struct object_id *oid,
unsigned flags)
static enum get_oid_result get_short_oid(const char *name, int len,
struct object_id *oid,
unsigned flags)
{
int status;
struct disambiguate_state ds;
@ -733,7 +731,7 @@ static inline int push_mark(const char *string, int len)
return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
}
static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);
static enum get_oid_result get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);
static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
static int get_oid_basic(const char *str, int len, struct object_id *oid,
@ -883,11 +881,12 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
return 0;
}
static int get_parent(const char *name, int len,
struct object_id *result, int idx)
static enum get_oid_result get_parent(const char *name, int len,
struct object_id *result, int idx)
{
struct object_id oid;
int ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);
enum get_oid_result ret = get_oid_1(name, len, &oid,
GET_OID_COMMITTISH);
struct commit *commit;
struct commit_list *p;
@ -895,24 +894,25 @@ static int get_parent(const char *name, int len,
return ret;
commit = lookup_commit_reference(the_repository, &oid);
if (parse_commit(commit))
return -1;
return MISSING_OBJECT;
if (!idx) {
oidcpy(result, &commit->object.oid);
return 0;
return FOUND;
}
p = commit->parents;
while (p) {
if (!--idx) {
oidcpy(result, &p->item->object.oid);
return 0;
return FOUND;
}
p = p->next;
}
return -1;
return MISSING_OBJECT;
}
static int get_nth_ancestor(const char *name, int len,
struct object_id *result, int generation)
static enum get_oid_result get_nth_ancestor(const char *name, int len,
struct object_id *result,
int generation)
{
struct object_id oid;
struct commit *commit;
@ -923,15 +923,15 @@ static int get_nth_ancestor(const char *name, int len,
return ret;
commit = lookup_commit_reference(the_repository, &oid);
if (!commit)
return -1;
return MISSING_OBJECT;
while (generation--) {
if (parse_commit(commit) || !commit->parents)
return -1;
return MISSING_OBJECT;
commit = commit->parents->item;
}
oidcpy(result, &commit->object.oid);
return 0;
return FOUND;
}
struct object *peel_to_type(const char *name, int namelen,
@ -1077,7 +1077,9 @@ static int get_describe_name(const char *name, int len, struct object_id *oid)
return -1;
}
static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags)
static enum get_oid_result get_oid_1(const char *name, int len,
struct object_id *oid,
unsigned lookup_flags)
{
int ret, has_suffix;
const char *cp;
@ -1111,16 +1113,16 @@ static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned
ret = peel_onion(name, len, oid, lookup_flags);
if (!ret)
return 0;
return FOUND;
ret = get_oid_basic(name, len, oid, lookup_flags);
if (!ret)
return 0;
return FOUND;
/* It could be describe output that is "SOMETHING-gXXXX" */
ret = get_describe_name(name, len, oid);
if (!ret)
return 0;
return FOUND;
return get_short_oid(name, len, oid, lookup_flags);
}
@ -1664,11 +1666,11 @@ static char *resolve_relative_path(const char *rel)
rel);
}
static int get_oid_with_context_1(const char *name,
unsigned flags,
const char *prefix,
struct object_id *oid,
struct object_context *oc)
static enum get_oid_result get_oid_with_context_1(const char *name,
unsigned flags,
const char *prefix,
struct object_id *oid,
struct object_context *oc)
{
int ret, bracket_depth;
int namelen = strlen(name);

@ -579,10 +579,10 @@ int get_tree_entry(const struct object_id *tree_oid, const char *name, struct ob
* with the sha1 of the found object, and *mode will hold the mode of
* the object.
*
* See the code for enum follow_symlink_result for a description of
* See the code for enum get_oid_result for a description of
* the return values.
*/
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)
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)
{
int retval = MISSING_OBJECT;
struct dir_state *parents = NULL;

@ -51,23 +51,7 @@ struct traverse_info;
typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *);
int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info);
enum follow_symlinks_result {
FOUND = 0, /* This includes out-of-tree links */
MISSING_OBJECT = -1, /* The initial symlink is missing */
DANGLING_SYMLINK = -2, /*
* The initial symlink is there, but
* (transitively) points to a missing
* in-tree file
*/
SYMLINK_LOOP = -3,
NOT_DIR = -4, /*
* Somewhere along the symlink chain, a path is
* requested which contains a file as a
* non-final element.
*/
};
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);
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);
struct traverse_info {
const char *traverse_path;

Loading…
Cancel
Save