Skip to content

Commit cfd9167

Browse files
committed
Merge branch 'dt/cat-file-batch-ambiguous'
"git cat-file --batch" reported a dangling symbolic link by mistake, when it wanted to report that a given name is ambiguous. * dt/cat-file-batch-ambiguous: t1512: test ambiguous cat-file --batch and --batch-output Do not print 'dangling' for cat-file in case of ambiguity
2 parents a3d4173 + df799f5 commit cfd9167

File tree

7 files changed

+72
-49
lines changed

7 files changed

+72
-49
lines changed

Documentation/git-cat-file.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ the repository, then `cat-file` will ignore any custom format and print:
252252
<object> SP missing LF
253253
------------
254254

255+
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:
256+
257+
------------
258+
<object> SP ambiguous LF
259+
------------
260+
255261
If --follow-symlinks is used, and a symlink in the repository points
256262
outside the repository, then `cat-file` will ignore any custom format
257263
and print:

builtin/cat-file.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,17 @@ static void batch_one_object(const char *obj_name,
380380
{
381381
struct object_context ctx;
382382
int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
383-
enum follow_symlinks_result result;
383+
enum get_oid_result result;
384384

385385
result = get_oid_with_context(obj_name, flags, &data->oid, &ctx);
386386
if (result != FOUND) {
387387
switch (result) {
388388
case MISSING_OBJECT:
389389
printf("%s missing\n", obj_name);
390390
break;
391+
case SHORT_NAME_AMBIGUOUS:
392+
printf("%s ambiguous\n", obj_name);
393+
break;
391394
case DANGLING_SYMLINK:
392395
printf("dangling %"PRIuMAX"\n%s\n",
393396
(uintmax_t)strlen(obj_name), obj_name);

cache.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1345,14 +1345,32 @@ struct object_context {
13451345
GET_OID_TREE | GET_OID_TREEISH | \
13461346
GET_OID_BLOB)
13471347

1348+
enum get_oid_result {
1349+
FOUND = 0,
1350+
MISSING_OBJECT = -1, /* The requested object is missing */
1351+
SHORT_NAME_AMBIGUOUS = -2,
1352+
/* The following only apply when symlinks are followed */
1353+
DANGLING_SYMLINK = -4, /*
1354+
* The initial symlink is there, but
1355+
* (transitively) points to a missing
1356+
* in-tree file
1357+
*/
1358+
SYMLINK_LOOP = -5,
1359+
NOT_DIR = -6, /*
1360+
* Somewhere along the symlink chain, a path is
1361+
* requested which contains a file as a
1362+
* non-final element.
1363+
*/
1364+
};
1365+
13481366
extern int get_oid(const char *str, struct object_id *oid);
13491367
extern int get_oid_commit(const char *str, struct object_id *oid);
13501368
extern int get_oid_committish(const char *str, struct object_id *oid);
13511369
extern int get_oid_tree(const char *str, struct object_id *oid);
13521370
extern int get_oid_treeish(const char *str, struct object_id *oid);
13531371
extern int get_oid_blob(const char *str, struct object_id *oid);
13541372
extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
1355-
extern int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
1373+
extern enum get_oid_result get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
13561374

13571375

13581376
typedef int each_abbrev_fn(const struct object_id *oid, void *);

sha1-name.c

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -190,17 +190,14 @@ static void find_short_packed_object(struct disambiguate_state *ds)
190190
unique_in_pack(p, ds);
191191
}
192192

193-
#define SHORT_NAME_NOT_FOUND (-1)
194-
#define SHORT_NAME_AMBIGUOUS (-2)
195-
196193
static int finish_object_disambiguation(struct disambiguate_state *ds,
197194
struct object_id *oid)
198195
{
199196
if (ds->ambiguous)
200197
return SHORT_NAME_AMBIGUOUS;
201198

202199
if (!ds->candidate_exists)
203-
return SHORT_NAME_NOT_FOUND;
200+
return MISSING_OBJECT;
204201

205202
if (!ds->candidate_checked)
206203
/*
@@ -414,8 +411,9 @@ static int sort_ambiguous(const void *a, const void *b)
414411
return a_type_sort > b_type_sort ? 1 : -1;
415412
}
416413

417-
static int get_short_oid(const char *name, int len, struct object_id *oid,
418-
unsigned flags)
414+
static enum get_oid_result get_short_oid(const char *name, int len,
415+
struct object_id *oid,
416+
unsigned flags)
419417
{
420418
int status;
421419
struct disambiguate_state ds;
@@ -733,7 +731,7 @@ static inline int push_mark(const char *string, int len)
733731
return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
734732
}
735733

736-
static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);
734+
static enum get_oid_result get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags);
737735
static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
738736

739737
static int get_oid_basic(const char *str, int len, struct object_id *oid,
@@ -883,36 +881,38 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid,
883881
return 0;
884882
}
885883

886-
static int get_parent(const char *name, int len,
887-
struct object_id *result, int idx)
884+
static enum get_oid_result get_parent(const char *name, int len,
885+
struct object_id *result, int idx)
888886
{
889887
struct object_id oid;
890-
int ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH);
888+
enum get_oid_result ret = get_oid_1(name, len, &oid,
889+
GET_OID_COMMITTISH);
891890
struct commit *commit;
892891
struct commit_list *p;
893892

894893
if (ret)
895894
return ret;
896895
commit = lookup_commit_reference(the_repository, &oid);
897896
if (parse_commit(commit))
898-
return -1;
897+
return MISSING_OBJECT;
899898
if (!idx) {
900899
oidcpy(result, &commit->object.oid);
901-
return 0;
900+
return FOUND;
902901
}
903902
p = commit->parents;
904903
while (p) {
905904
if (!--idx) {
906905
oidcpy(result, &p->item->object.oid);
907-
return 0;
906+
return FOUND;
908907
}
909908
p = p->next;
910909
}
911-
return -1;
910+
return MISSING_OBJECT;
912911
}
913912

914-
static int get_nth_ancestor(const char *name, int len,
915-
struct object_id *result, int generation)
913+
static enum get_oid_result get_nth_ancestor(const char *name, int len,
914+
struct object_id *result,
915+
int generation)
916916
{
917917
struct object_id oid;
918918
struct commit *commit;
@@ -923,15 +923,15 @@ static int get_nth_ancestor(const char *name, int len,
923923
return ret;
924924
commit = lookup_commit_reference(the_repository, &oid);
925925
if (!commit)
926-
return -1;
926+
return MISSING_OBJECT;
927927

928928
while (generation--) {
929929
if (parse_commit(commit) || !commit->parents)
930-
return -1;
930+
return MISSING_OBJECT;
931931
commit = commit->parents->item;
932932
}
933933
oidcpy(result, &commit->object.oid);
934-
return 0;
934+
return FOUND;
935935
}
936936

937937
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)
10771077
return -1;
10781078
}
10791079

1080-
static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned lookup_flags)
1080+
static enum get_oid_result get_oid_1(const char *name, int len,
1081+
struct object_id *oid,
1082+
unsigned lookup_flags)
10811083
{
10821084
int ret, has_suffix;
10831085
const char *cp;
@@ -1111,16 +1113,16 @@ static int get_oid_1(const char *name, int len, struct object_id *oid, unsigned
11111113

11121114
ret = peel_onion(name, len, oid, lookup_flags);
11131115
if (!ret)
1114-
return 0;
1116+
return FOUND;
11151117

11161118
ret = get_oid_basic(name, len, oid, lookup_flags);
11171119
if (!ret)
1118-
return 0;
1120+
return FOUND;
11191121

11201122
/* It could be describe output that is "SOMETHING-gXXXX" */
11211123
ret = get_describe_name(name, len, oid);
11221124
if (!ret)
1123-
return 0;
1125+
return FOUND;
11241126

11251127
return get_short_oid(name, len, oid, lookup_flags);
11261128
}
@@ -1664,11 +1666,11 @@ static char *resolve_relative_path(const char *rel)
16641666
rel);
16651667
}
16661668

1667-
static int get_oid_with_context_1(const char *name,
1668-
unsigned flags,
1669-
const char *prefix,
1670-
struct object_id *oid,
1671-
struct object_context *oc)
1669+
static enum get_oid_result get_oid_with_context_1(const char *name,
1670+
unsigned flags,
1671+
const char *prefix,
1672+
struct object_id *oid,
1673+
struct object_context *oc)
16721674
{
16731675
int ret, bracket_depth;
16741676
int namelen = strlen(name);

t/t1512-rev-parse-disambiguation.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,4 +388,14 @@ test_expect_success C_LOCALE_OUTPUT 'ambiguous commits are printed by type first
388388
done
389389
'
390390

391+
test_expect_success 'cat-file --batch and --batch-check show ambiguous' '
392+
echo "0000 ambiguous" >expect &&
393+
echo 0000 | git cat-file --batch-check >actual 2>err &&
394+
test_cmp expect actual &&
395+
test_i18ngrep hint: err &&
396+
echo 0000 | git cat-file --batch >actual 2>err &&
397+
test_cmp expect actual &&
398+
test_i18ngrep hint: err
399+
'
400+
391401
test_done

tree-walk.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,10 +582,10 @@ int get_tree_entry(const struct object_id *tree_oid, const char *name, struct ob
582582
* with the sha1 of the found object, and *mode will hold the mode of
583583
* the object.
584584
*
585-
* See the code for enum follow_symlink_result for a description of
585+
* See the code for enum get_oid_result for a description of
586586
* the return values.
587587
*/
588-
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)
588+
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)
589589
{
590590
int retval = MISSING_OBJECT;
591591
struct dir_state *parents = NULL;

tree-walk.h

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,23 +51,7 @@ struct traverse_info;
5151
typedef int (*traverse_callback_t)(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *);
5252
int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info);
5353

54-
enum follow_symlinks_result {
55-
FOUND = 0, /* This includes out-of-tree links */
56-
MISSING_OBJECT = -1, /* The initial symlink is missing */
57-
DANGLING_SYMLINK = -2, /*
58-
* The initial symlink is there, but
59-
* (transitively) points to a missing
60-
* in-tree file
61-
*/
62-
SYMLINK_LOOP = -3,
63-
NOT_DIR = -4, /*
64-
* Somewhere along the symlink chain, a path is
65-
* requested which contains a file as a
66-
* non-final element.
67-
*/
68-
};
69-
70-
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);
54+
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);
7155

7256
struct traverse_info {
7357
const char *traverse_path;

0 commit comments

Comments
 (0)