These functions do not contain any backend specific code so we can move them to the common code and share across all backends. Signed-off-by: Ronnie Sahlberg <sahlberg@xxxxxxxxxx> --- refs-common.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ refs.c | 202 ---------------------------------------------------------- 2 files changed, 202 insertions(+), 202 deletions(-) diff --git a/refs-common.c b/refs-common.c index c40fa96..ac081e1 100644 --- a/refs-common.c +++ b/refs-common.c @@ -293,3 +293,205 @@ int ref_is_hidden(const char *refname) } return 0; } + +static const char *ref_rev_parse_rules[] = { + "%.*s", + "refs/%.*s", + "refs/tags/%.*s", + "refs/heads/%.*s", + "refs/remotes/%.*s", + "refs/remotes/%.*s/HEAD", + NULL +}; + +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; + } + } + + return 0; +} + +/* + * *string and *len will only be substituted, and *string returned (for + * later free()ing) if the string passed in is a magic short-hand form + * to name a branch. + */ +static char *substitute_branch_name(const char **string, int *len) +{ + struct strbuf buf = STRBUF_INIT; + int ret = interpret_branch_name(*string, *len, &buf); + + if (ret == *len) { + size_t size; + *string = strbuf_detach(&buf, &size); + *len = size; + return (char *)*string; + } + + return NULL; +} + +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; + int refs_found = 0; + + *ref = NULL; + for (p = ref_rev_parse_rules; *p; 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); + r = resolve_ref_unsafe(fullref, this_result, + RESOLVE_REF_READING, &flag); + if (r) { + if (!refs_found++) + *ref = xstrdup(r); + if (!warn_ambiguous_refs) + break; + } else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) { + warning("ignoring dangling symref %s.", fullref); + } else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) { + warning("ignoring broken ref %s.", fullref); + } + } + free(last_branch); + return refs_found; +} + +int dwim_log(const char *str, int len, unsigned char *sha1, char **log) +{ + char *last_branch = substitute_branch_name(&str, &len); + const char **p; + int logs_found = 0; + + *log = NULL; + for (p = ref_rev_parse_rules; *p; p++) { + unsigned char hash[20]; + char path[PATH_MAX]; + const char *ref, *it; + + mksnpath(path, sizeof(path), *p, len, str); + ref = resolve_ref_unsafe(path, hash, RESOLVE_REF_READING, NULL); + if (!ref) + continue; + if (reflog_exists(path)) + it = path; + else if (strcmp(ref, path) && reflog_exists(ref)) + it = ref; + else + continue; + if (!logs_found++) { + *log = xstrdup(it); + hashcpy(sha1, hash); + } + if (!warn_ambiguous_refs) + break; + } + free(last_branch); + return logs_found; +} + +char *shorten_unambiguous_ref(const char *refname, int strict) +{ + int i; + static char **scanf_fmts; + static int nr_rules; + char *short_name; + + if (!nr_rules) { + /* + * Pre-generate scanf formats from ref_rev_parse_rules[]. + * Generate a format suitable for scanf from a + * ref_rev_parse_rules rule by interpolating "%s" at the + * location of the "%.*s". + */ + size_t total_len = 0; + size_t offset = 0; + + /* the rule list is NULL terminated, count them first */ + for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++) + /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */ + total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1; + + scanf_fmts = xmalloc(nr_rules * sizeof(char *) + total_len); + + offset = 0; + for (i = 0; i < nr_rules; i++) { + assert(offset < total_len); + scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset; + offset += snprintf(scanf_fmts[i], total_len - offset, + ref_rev_parse_rules[i], 2, "%s") + 1; + } + } + + /* bail out if there are no rules */ + if (!nr_rules) + return xstrdup(refname); + + /* buffer for scanf result, at most refname must fit */ + short_name = xstrdup(refname); + + /* skip first rule, it will always match */ + for (i = nr_rules - 1; i > 0 ; --i) { + int j; + int rules_to_fail = i; + int short_name_len; + + if (1 != sscanf(refname, scanf_fmts[i], short_name)) + continue; + + short_name_len = strlen(short_name); + + /* + * in strict mode, all (except the matched one) rules + * must fail to resolve to a valid non-ambiguous ref + */ + if (strict) + rules_to_fail = nr_rules; + + /* + * check if the short name resolves to a valid ref, + * but use only rules prior to the matched one + */ + for (j = 0; j < rules_to_fail; j++) { + const char *rule = ref_rev_parse_rules[j]; + char refname[PATH_MAX]; + + /* skip matched rule */ + if (i == j) + continue; + + /* + * the short name is ambiguous, if it resolves + * (with this previous rule) to a valid ref + * read_ref() returns 0 on success + */ + mksnpath(refname, sizeof(refname), + rule, short_name_len, short_name); + if (ref_exists(refname)) + break; + } + + /* + * short name is non-ambiguous if all previous rules + * haven't resolved to a valid ref + */ + if (j == rules_to_fail) + return short_name; + } + + free(short_name); + return xstrdup(refname); +} diff --git a/refs.c b/refs.c index 6181edf..56e146f 100644 --- a/refs.c +++ b/refs.c @@ -1956,30 +1956,6 @@ const char *prettify_refname(const char *name) 0); } -static const char *ref_rev_parse_rules[] = { - "%.*s", - "refs/%.*s", - "refs/tags/%.*s", - "refs/heads/%.*s", - "refs/remotes/%.*s", - "refs/remotes/%.*s/HEAD", - NULL -}; - -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; - } - } - - return 0; -} - static void unlock_ref(struct ref_lock *lock) { /* Do not free lock->lk -- atexit() still looks at them */ @@ -2033,91 +2009,6 @@ static int remove_empty_directories(const char *file) return result; } -/* - * *string and *len will only be substituted, and *string returned (for - * later free()ing) if the string passed in is a magic short-hand form - * to name a branch. - */ -static char *substitute_branch_name(const char **string, int *len) -{ - struct strbuf buf = STRBUF_INIT; - int ret = interpret_branch_name(*string, *len, &buf); - - if (ret == *len) { - size_t size; - *string = strbuf_detach(&buf, &size); - *len = size; - return (char *)*string; - } - - return NULL; -} - -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; - int refs_found = 0; - - *ref = NULL; - for (p = ref_rev_parse_rules; *p; 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); - r = resolve_ref_unsafe(fullref, this_result, - RESOLVE_REF_READING, &flag); - if (r) { - if (!refs_found++) - *ref = xstrdup(r); - if (!warn_ambiguous_refs) - break; - } else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) { - warning("ignoring dangling symref %s.", fullref); - } else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) { - warning("ignoring broken ref %s.", fullref); - } - } - free(last_branch); - return refs_found; -} - -int dwim_log(const char *str, int len, unsigned char *sha1, char **log) -{ - char *last_branch = substitute_branch_name(&str, &len); - const char **p; - int logs_found = 0; - - *log = NULL; - for (p = ref_rev_parse_rules; *p; p++) { - unsigned char hash[20]; - char path[PATH_MAX]; - const char *ref, *it; - - mksnpath(path, sizeof(path), *p, len, str); - ref = resolve_ref_unsafe(path, hash, RESOLVE_REF_READING, NULL); - if (!ref) - continue; - if (reflog_exists(path)) - it = path; - else if (strcmp(ref, path) && reflog_exists(ref)) - it = ref; - else - continue; - if (!logs_found++) { - *log = xstrdup(it); - hashcpy(sha1, hash); - } - if (!warn_ambiguous_refs) - break; - } - free(last_branch); - return logs_found; -} - /* This function should make sure errno is meaningful on error */ static struct ref_lock *lock_ref_sha1_basic(const char *refname, const unsigned char *old_sha1, @@ -3703,96 +3594,3 @@ cleanup: ret = -2; return ret; } - -char *shorten_unambiguous_ref(const char *refname, int strict) -{ - int i; - static char **scanf_fmts; - static int nr_rules; - char *short_name; - - if (!nr_rules) { - /* - * Pre-generate scanf formats from ref_rev_parse_rules[]. - * Generate a format suitable for scanf from a - * ref_rev_parse_rules rule by interpolating "%s" at the - * location of the "%.*s". - */ - size_t total_len = 0; - size_t offset = 0; - - /* the rule list is NULL terminated, count them first */ - for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++) - /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */ - total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1; - - scanf_fmts = xmalloc(nr_rules * sizeof(char *) + total_len); - - offset = 0; - for (i = 0; i < nr_rules; i++) { - assert(offset < total_len); - scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset; - offset += snprintf(scanf_fmts[i], total_len - offset, - ref_rev_parse_rules[i], 2, "%s") + 1; - } - } - - /* bail out if there are no rules */ - if (!nr_rules) - return xstrdup(refname); - - /* buffer for scanf result, at most refname must fit */ - short_name = xstrdup(refname); - - /* skip first rule, it will always match */ - for (i = nr_rules - 1; i > 0 ; --i) { - int j; - int rules_to_fail = i; - int short_name_len; - - if (1 != sscanf(refname, scanf_fmts[i], short_name)) - continue; - - short_name_len = strlen(short_name); - - /* - * in strict mode, all (except the matched one) rules - * must fail to resolve to a valid non-ambiguous ref - */ - if (strict) - rules_to_fail = nr_rules; - - /* - * check if the short name resolves to a valid ref, - * but use only rules prior to the matched one - */ - for (j = 0; j < rules_to_fail; j++) { - const char *rule = ref_rev_parse_rules[j]; - char refname[PATH_MAX]; - - /* skip matched rule */ - if (i == j) - continue; - - /* - * the short name is ambiguous, if it resolves - * (with this previous rule) to a valid ref - * read_ref() returns 0 on success - */ - mksnpath(refname, sizeof(refname), - rule, short_name_len, short_name); - if (ref_exists(refname)) - break; - } - - /* - * short name is non-ambiguous if all previous rules - * haven't resolved to a valid ref - */ - if (j == rules_to_fail) - return short_name; - } - - free(short_name); - return xstrdup(refname); -} -- 2.0.1.553.geee1b3e -- 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