Junio C Hamano <[email protected]> writes:
> In order to resolve this correctly with the precedence rules, I
> think you need to make refname_match() return the precedence number
> (e.g. give 1 to "%.*s", 2 to "refs/%.*s", etc., using the index in
> ref_rev_parse_rules[] array), and make this loop keep track of the
> "best" match paying attention to the returned precedence.
That is, something like this, perhaps. The resulting behaviour
should match how "git rev-parse X" would give precedence to tag X
over branch X by going this route. What do you think?
refs.c | 8 +++-----
remote.c | 13 ++++++++++---
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/refs.c b/refs.c
index 457fb78057..fd1a7f7478 100644
--- a/refs.c
+++ b/refs.c
@@ -495,11 +495,9 @@ int refname_match(const char *abbrev_name, const char
*full_name)
const char **p;
const int abbrev_name_len = strlen(abbrev_name);
- for (p = ref_rev_parse_rules; *p; p++) {
- if (!strcmp(full_name, mkpath(*p, abbrev_name_len,
abbrev_name))) {
- return 1;
- }
- }
+ for (p = ref_rev_parse_rules; *p; p++)
+ if (!strcmp(full_name, mkpath(*p, abbrev_name_len,
abbrev_name)))
+ return (p - ref_rev_parse_rules) + 1;
return 0;
}
diff --git a/remote.c b/remote.c
index 86e6098774..ed2f80e45c 100644
--- a/remote.c
+++ b/remote.c
@@ -1689,11 +1689,18 @@ static struct ref *get_expanded_map(const struct ref
*remote_refs,
static const struct ref *find_ref_by_name_abbrev(const struct ref *refs, const
char *name)
{
const struct ref *ref;
+ const struct ref *best_match = NULL;
+ int best_score = -1;
+
for (ref = refs; ref; ref = ref->next) {
- if (refname_match(name, ref->name))
- return ref;
+ int score = refname_match(name, ref->name);
+
+ if ((score && (best_score < 0 || score < best_score))) {
+ best_match = ref;
+ best_score = score;
+ }
}
- return NULL;
+ return best_match;
}
struct ref *get_remote_ref(const struct ref *remote_refs, const char *name)