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>maint
							parent
							
								
									16a465bc01
								
							
						
					
					
						commit
						d1dd94b308
					
				|  | @ -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); | ||||
|  |  | |||
							
								
								
									
										20
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										20
									
								
								cache.h
								
								
								
								
							|  | @ -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 *); | ||||
|  |  | |||
							
								
								
									
										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); | ||||
| } | ||||
|  | ||||
| #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; | ||||
|  |  | |||
							
								
								
									
										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 *); | ||||
| 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…
	
		Reference in New Issue
	
	 David Turner
						David Turner