In preparation for allowing alternative ways of expanding shorthand refs (like "master") into full refnames (like "refs/heads/master"): Expand the current ref_rev_parse_rules list into ref_expand_rules, a list of struct ref_expand_rule objects that encode both an expansion pattern (e.g. "refs/heads/%.*s") and an associated expansion function (e.g. the code that applies "master" to "refs/heads/%.*s" to produce "refs/heads/master"). This allows us to later add expansion rules that do something other than the current purely textual expansion. The current expansion behavior is encoded in the new ref_expand_txtly() helper function, which does the mksnpath() call that were previously performed by all users of ref_rev_parse_rules. The end result is identical in behavior to the existing code, but makes it easier to adjust the way ref expansion happens for remote-tracking branches in future patches Most of the existing code that uses ref_rev_parse_rules to expand shorthand refs are converted to use ref_expand_rules instead. Signed-off-by: Johan Herland <johan@xxxxxxxxxxx> --- cache.h | 4 ---- refs.c | 46 +++++++++++++++++++++++++++++++++------------- refs.h | 11 +++++++++++ remote.c | 6 +++--- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/cache.h b/cache.h index 7ce9061..6adab04 100644 --- a/cache.h +++ b/cache.h @@ -875,10 +875,6 @@ extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref); extern int interpret_branch_name(const char *str, struct strbuf *); extern int get_sha1_mb(const char *str, unsigned char *sha1); -extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules); -extern const char *ref_rev_parse_rules[]; -#define ref_fetch_rules ref_rev_parse_rules - extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg); extern int validate_headref(const char *ref); diff --git a/refs.c b/refs.c index 7231f54..8b02140 100644 --- a/refs.c +++ b/refs.c @@ -1724,7 +1724,24 @@ const char *prettify_refname(const char *name) 0); } -const char *ref_rev_parse_rules[] = { +static void ref_expand_txtly(const struct ref_expand_rule *rule, + char *dst, size_t dst_len, + const char *shortname, size_t shortname_len) +{ + mksnpath(dst, dst_len, rule->pattern, shortname_len, shortname); +} + +const struct ref_expand_rule ref_expand_rules[] = { + { ref_expand_txtly, "%.*s" }, + { ref_expand_txtly, "refs/%.*s" }, + { ref_expand_txtly, "refs/tags/%.*s" }, + { ref_expand_txtly, "refs/heads/%.*s" }, + { ref_expand_txtly, "refs/remotes/%.*s" }, + { ref_expand_txtly, "refs/remotes/%.*s/HEAD" }, + { NULL, NULL } +}; + +static const char *ref_rev_parse_rules[] = { "%.*s", "refs/%.*s", "refs/tags/%.*s", @@ -1734,15 +1751,17 @@ const char *ref_rev_parse_rules[] = { NULL }; -int refname_match(const char *abbrev_name, const char *full_name, const char **rules) +int refname_match(const char *abbrev_name, const char *full_name, + const struct ref_expand_rule *rules) { - const char **p; + const struct ref_expand_rule *p; const int abbrev_name_len = strlen(abbrev_name); + char n[PATH_MAX]; - for (p = rules; *p; p++) { - if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) { + for (p = rules; p->expand; p++) { + p->expand(p, n, sizeof(n), abbrev_name, abbrev_name_len); + if (!strcmp(full_name, n)) return 1; - } } return 0; @@ -1807,21 +1826,22 @@ static char *substitute_branch_name(const char **string, int *len) int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref) { char *last_branch = substitute_branch_name(&str, &len); - const char **p, *r; + const struct ref_expand_rule *p; + const char *r; int refs_found = 0; *ref = NULL; - for (p = ref_rev_parse_rules; *p; p++) { + for (p = ref_expand_rules; p->expand; p++) { char fullref[PATH_MAX]; unsigned char sha1_from_ref[20]; unsigned char *this_result; int flag; this_result = refs_found ? sha1_from_ref : sha1; - mksnpath(fullref, sizeof(fullref), *p, len, str); + p->expand(p, fullref, sizeof(fullref), str, len); r = resolve_ref_unsafe(fullref, this_result, 1, &flag); if (r) { - if (!refs_found++) + if ((!*ref || strcmp(*ref, r)) && !refs_found++) *ref = xstrdup(r); if (!warn_ambiguous_refs) break; @@ -1838,17 +1858,17 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref) int dwim_log(const char *str, int len, unsigned char *sha1, char **log) { char *last_branch = substitute_branch_name(&str, &len); - const char **p; + const struct ref_expand_rule *p; int logs_found = 0; *log = NULL; - for (p = ref_rev_parse_rules; *p; p++) { + for (p = ref_expand_rules; p->expand; p++) { struct stat st; unsigned char hash[20]; char path[PATH_MAX]; const char *ref, *it; - mksnpath(path, sizeof(path), *p, len, str); + p->expand(p, path, sizeof(path), str, len); ref = resolve_ref_unsafe(path, hash, 1, NULL); if (!ref) continue; diff --git a/refs.h b/refs.h index 8060ed8..85710cb 100644 --- a/refs.h +++ b/refs.h @@ -164,6 +164,17 @@ extern int for_each_reflog(each_ref_fn, void *); extern int check_refname_format(const char *refname, int flags); extern const char *prettify_refname(const char *refname); + +struct ref_expand_rule { + void (*expand)(const struct ref_expand_rule *rule, + char *dst, size_t dst_len, + const char *shortname, size_t shortname_len); + const char *pattern; +}; +extern const struct ref_expand_rule ref_expand_rules[]; +extern int refname_match(const char *abbrev_name, const char *full_name, + const struct ref_expand_rule *rules); + extern char *shorten_unambiguous_ref(const char *refname, int strict); /** rename ref, return 0 on success **/ diff --git a/remote.c b/remote.c index 68eb99b..5ef34c9 100644 --- a/remote.c +++ b/remote.c @@ -981,7 +981,7 @@ static int count_refspec_match(const char *pattern, char *name = refs->name; int namelen = strlen(name); - if (!refname_match(pattern, name, ref_rev_parse_rules)) + if (!refname_match(pattern, name, ref_expand_rules)) continue; /* A match is "weak" if it is with refs outside @@ -1499,7 +1499,7 @@ int branch_merge_matches(struct branch *branch, { if (!branch || i < 0 || i >= branch->merge_nr) return 0; - return refname_match(branch->merge[i]->src, refname, ref_fetch_rules); + return refname_match(branch->merge[i]->src, refname, ref_expand_rules); } static int ignore_symref_update(const char *refname) @@ -1545,7 +1545,7 @@ static const struct ref *find_ref_by_name_abbrev(const struct ref *refs, const c { const struct ref *ref; for (ref = refs; ref; ref = ref->next) { - if (refname_match(name, ref->name, ref_fetch_rules)) + if (refname_match(name, ref->name, ref_expand_rules)) return ref; } return NULL; -- 1.8.1.3.704.g33f7d4f -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html