зеркало из https://github.com/microsoft/git.git
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
This commit is contained in:
Коммит
cfd9167c15
|
@ -252,6 +252,12 @@ the repository, then `cat-file` will ignore any custom format and print:
|
||||||
<object> SP missing LF
|
<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
|
If --follow-symlinks is used, and a symlink in the repository points
|
||||||
outside the repository, then `cat-file` will ignore any custom format
|
outside the repository, then `cat-file` will ignore any custom format
|
||||||
and print:
|
and print:
|
||||||
|
|
|
@ -380,7 +380,7 @@ static void batch_one_object(const char *obj_name,
|
||||||
{
|
{
|
||||||
struct object_context ctx;
|
struct object_context ctx;
|
||||||
int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
|
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);
|
result = get_oid_with_context(obj_name, flags, &data->oid, &ctx);
|
||||||
if (result != FOUND) {
|
if (result != FOUND) {
|
||||||
|
@ -388,6 +388,9 @@ static void batch_one_object(const char *obj_name,
|
||||||
case MISSING_OBJECT:
|
case MISSING_OBJECT:
|
||||||
printf("%s missing\n", obj_name);
|
printf("%s missing\n", obj_name);
|
||||||
break;
|
break;
|
||||||
|
case SHORT_NAME_AMBIGUOUS:
|
||||||
|
printf("%s ambiguous\n", obj_name);
|
||||||
|
break;
|
||||||
case DANGLING_SYMLINK:
|
case DANGLING_SYMLINK:
|
||||||
printf("dangling %"PRIuMAX"\n%s\n",
|
printf("dangling %"PRIuMAX"\n%s\n",
|
||||||
(uintmax_t)strlen(obj_name), obj_name);
|
(uintmax_t)strlen(obj_name), obj_name);
|
||||||
|
|
20
cache.h
20
cache.h
|
@ -1345,6 +1345,24 @@ struct object_context {
|
||||||
GET_OID_TREE | GET_OID_TREEISH | \
|
GET_OID_TREE | GET_OID_TREEISH | \
|
||||||
GET_OID_BLOB)
|
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(const char *str, struct object_id *oid);
|
||||||
extern int get_oid_commit(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);
|
extern int get_oid_committish(const char *str, struct object_id *oid);
|
||||||
|
@ -1352,7 +1370,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_treeish(const char *str, struct object_id *oid);
|
||||||
extern int get_oid_blob(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 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 *);
|
typedef int each_abbrev_fn(const struct object_id *oid, void *);
|
||||||
|
|
58
sha1-name.c
58
sha1-name.c
|
@ -190,9 +190,6 @@ static void find_short_packed_object(struct disambiguate_state *ds)
|
||||||
unique_in_pack(p, 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,
|
static int finish_object_disambiguation(struct disambiguate_state *ds,
|
||||||
struct object_id *oid)
|
struct object_id *oid)
|
||||||
{
|
{
|
||||||
|
@ -200,7 +197,7 @@ static int finish_object_disambiguation(struct disambiguate_state *ds,
|
||||||
return SHORT_NAME_AMBIGUOUS;
|
return SHORT_NAME_AMBIGUOUS;
|
||||||
|
|
||||||
if (!ds->candidate_exists)
|
if (!ds->candidate_exists)
|
||||||
return SHORT_NAME_NOT_FOUND;
|
return MISSING_OBJECT;
|
||||||
|
|
||||||
if (!ds->candidate_checked)
|
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;
|
return a_type_sort > b_type_sort ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_short_oid(const char *name, int len, struct object_id *oid,
|
static enum get_oid_result get_short_oid(const char *name, int len,
|
||||||
unsigned flags)
|
struct object_id *oid,
|
||||||
|
unsigned flags)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
struct disambiguate_state ds;
|
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));
|
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 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,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_parent(const char *name, int len,
|
static enum get_oid_result get_parent(const char *name, int len,
|
||||||
struct object_id *result, int idx)
|
struct object_id *result, int idx)
|
||||||
{
|
{
|
||||||
struct object_id oid;
|
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 *commit;
|
||||||
struct commit_list *p;
|
struct commit_list *p;
|
||||||
|
|
||||||
|
@ -895,24 +894,25 @@ static int get_parent(const char *name, int len,
|
||||||
return ret;
|
return ret;
|
||||||
commit = lookup_commit_reference(the_repository, &oid);
|
commit = lookup_commit_reference(the_repository, &oid);
|
||||||
if (parse_commit(commit))
|
if (parse_commit(commit))
|
||||||
return -1;
|
return MISSING_OBJECT;
|
||||||
if (!idx) {
|
if (!idx) {
|
||||||
oidcpy(result, &commit->object.oid);
|
oidcpy(result, &commit->object.oid);
|
||||||
return 0;
|
return FOUND;
|
||||||
}
|
}
|
||||||
p = commit->parents;
|
p = commit->parents;
|
||||||
while (p) {
|
while (p) {
|
||||||
if (!--idx) {
|
if (!--idx) {
|
||||||
oidcpy(result, &p->item->object.oid);
|
oidcpy(result, &p->item->object.oid);
|
||||||
return 0;
|
return FOUND;
|
||||||
}
|
}
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
return -1;
|
return MISSING_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_nth_ancestor(const char *name, int len,
|
static enum get_oid_result get_nth_ancestor(const char *name, int len,
|
||||||
struct object_id *result, int generation)
|
struct object_id *result,
|
||||||
|
int generation)
|
||||||
{
|
{
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
|
@ -923,15 +923,15 @@ static int get_nth_ancestor(const char *name, int len,
|
||||||
return ret;
|
return ret;
|
||||||
commit = lookup_commit_reference(the_repository, &oid);
|
commit = lookup_commit_reference(the_repository, &oid);
|
||||||
if (!commit)
|
if (!commit)
|
||||||
return -1;
|
return MISSING_OBJECT;
|
||||||
|
|
||||||
while (generation--) {
|
while (generation--) {
|
||||||
if (parse_commit(commit) || !commit->parents)
|
if (parse_commit(commit) || !commit->parents)
|
||||||
return -1;
|
return MISSING_OBJECT;
|
||||||
commit = commit->parents->item;
|
commit = commit->parents->item;
|
||||||
}
|
}
|
||||||
oidcpy(result, &commit->object.oid);
|
oidcpy(result, &commit->object.oid);
|
||||||
return 0;
|
return FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct object *peel_to_type(const char *name, int namelen,
|
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;
|
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;
|
int ret, has_suffix;
|
||||||
const char *cp;
|
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);
|
ret = peel_onion(name, len, oid, lookup_flags);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return FOUND;
|
||||||
|
|
||||||
ret = get_oid_basic(name, len, oid, lookup_flags);
|
ret = get_oid_basic(name, len, oid, lookup_flags);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return FOUND;
|
||||||
|
|
||||||
/* It could be describe output that is "SOMETHING-gXXXX" */
|
/* It could be describe output that is "SOMETHING-gXXXX" */
|
||||||
ret = get_describe_name(name, len, oid);
|
ret = get_describe_name(name, len, oid);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return FOUND;
|
||||||
|
|
||||||
return get_short_oid(name, len, oid, lookup_flags);
|
return get_short_oid(name, len, oid, lookup_flags);
|
||||||
}
|
}
|
||||||
|
@ -1664,11 +1666,11 @@ static char *resolve_relative_path(const char *rel)
|
||||||
rel);
|
rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_oid_with_context_1(const char *name,
|
static enum get_oid_result get_oid_with_context_1(const char *name,
|
||||||
unsigned flags,
|
unsigned flags,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
struct object_id *oid,
|
struct object_id *oid,
|
||||||
struct object_context *oc)
|
struct object_context *oc)
|
||||||
{
|
{
|
||||||
int ret, bracket_depth;
|
int ret, bracket_depth;
|
||||||
int namelen = strlen(name);
|
int namelen = strlen(name);
|
||||||
|
|
|
@ -388,4 +388,14 @@ test_expect_success C_LOCALE_OUTPUT 'ambiguous commits are printed by type first
|
||||||
done
|
done
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cat-file --batch and --batch-check show ambiguous' '
|
||||||
|
echo "0000 ambiguous" >expect &&
|
||||||
|
echo 0000 | git cat-file --batch-check >actual 2>err &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_i18ngrep hint: err &&
|
||||||
|
echo 0000 | git cat-file --batch >actual 2>err &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_i18ngrep hint: err
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -582,10 +582,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
|
* with the sha1 of the found object, and *mode will hold the mode of
|
||||||
* the object.
|
* 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.
|
* 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;
|
int retval = MISSING_OBJECT;
|
||||||
struct dir_state *parents = NULL;
|
struct dir_state *parents = NULL;
|
||||||
|
|
18
tree-walk.h
18
tree-walk.h
|
@ -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 *);
|
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);
|
int traverse_trees(struct index_state *istate, int n, struct tree_desc *t, struct traverse_info *info);
|
||||||
|
|
||||||
enum follow_symlinks_result {
|
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);
|
||||||
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);
|
|
||||||
|
|
||||||
struct traverse_info {
|
struct traverse_info {
|
||||||
const char *traverse_path;
|
const char *traverse_path;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче