summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c130
1 files changed, 68 insertions, 62 deletions
diff --git a/refs.c b/refs.c
index 1491ae937e..d2a98e1c21 100644
--- a/refs.c
+++ b/refs.c
@@ -2,15 +2,21 @@
* The backend-independent part of the reference module.
*/
-#include "cache.h"
+#include "git-compat-util.h"
+#include "advice.h"
+#include "alloc.h"
#include "config.h"
+#include "environment.h"
#include "hashmap.h"
+#include "gettext.h"
+#include "hex.h"
#include "lockfile.h"
#include "iterator.h"
#include "refs.h"
#include "refs/refs-internal.h"
#include "run-command.h"
#include "hook.h"
+#include "object-name.h"
#include "object-store.h"
#include "object.h"
#include "tag.h"
@@ -18,9 +24,11 @@
#include "worktree.h"
#include "strvec.h"
#include "repository.h"
+#include "setup.h"
#include "sigchain.h"
#include "date.h"
#include "commit.h"
+#include "wrapper.h"
/*
* List of all available backends
@@ -1310,65 +1318,68 @@ int update_ref(const char *msg, const char *refname,
old_oid, flags, onerr);
}
+/*
+ * Check that the string refname matches a rule of the form
+ * "{prefix}%.*s{suffix}". So "foo/bar/baz" would match the rule
+ * "foo/%.*s/baz", and return the string "bar".
+ */
+static const char *match_parse_rule(const char *refname, const char *rule,
+ size_t *len)
+{
+ /*
+ * Check that rule matches refname up to the first percent in the rule.
+ * We can bail immediately if not, but otherwise we leave "rule" at the
+ * %-placeholder, and "refname" at the start of the potential matched
+ * name.
+ */
+ while (*rule != '%') {
+ if (!*rule)
+ BUG("rev-parse rule did not have percent");
+ if (*refname++ != *rule++)
+ return NULL;
+ }
+
+ /*
+ * Check that our "%" is the expected placeholder. This assumes there
+ * are no other percents (placeholder or quoted) in the string, but
+ * that is sufficient for our rev-parse rules.
+ */
+ if (!skip_prefix(rule, "%.*s", &rule))
+ return NULL;
+
+ /*
+ * And now check that our suffix (if any) matches.
+ */
+ if (!strip_suffix(refname, rule, len))
+ return NULL;
+
+ return refname; /* len set by strip_suffix() */
+}
+
char *refs_shorten_unambiguous_ref(struct ref_store *refs,
const char *refname, int strict)
{
int i;
- static char **scanf_fmts;
- static int nr_rules;
- char *short_name;
struct strbuf resolved_buf = STRBUF_INIT;
- 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(st_add(st_mult(sizeof(char *), nr_rules), 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 += xsnprintf(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) {
+ for (i = NUM_REV_PARSE_RULES - 1; i > 0 ; --i) {
int j;
int rules_to_fail = i;
- int short_name_len;
+ const char *short_name;
+ size_t short_name_len;
- if (1 != sscanf(refname, scanf_fmts[i], short_name))
+ short_name = match_parse_rule(refname, ref_rev_parse_rules[i],
+ &short_name_len);
+ if (!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;
+ rules_to_fail = NUM_REV_PARSE_RULES;
/*
* check if the short name resolves to a valid ref,
@@ -1388,7 +1399,8 @@ char *refs_shorten_unambiguous_ref(struct ref_store *refs,
*/
strbuf_reset(&resolved_buf);
strbuf_addf(&resolved_buf, rule,
- short_name_len, short_name);
+ cast_size_t_to_int(short_name_len),
+ short_name);
if (refs_ref_exists(refs, resolved_buf.buf))
break;
}
@@ -1399,12 +1411,11 @@ char *refs_shorten_unambiguous_ref(struct ref_store *refs,
*/
if (j == rules_to_fail) {
strbuf_release(&resolved_buf);
- return short_name;
+ return xmemdupz(short_name, short_name_len);
}
}
strbuf_release(&resolved_buf);
- free(short_name);
return xstrdup(refname);
}
@@ -1414,9 +1425,8 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
refname, strict);
}
-static struct string_list *hide_refs;
-
-int parse_hide_refs_config(const char *var, const char *value, const char *section)
+int parse_hide_refs_config(const char *var, const char *value, const char *section,
+ struct string_list *hide_refs)
{
const char *key;
if (!strcmp("transfer.hiderefs", var) ||
@@ -1431,21 +1441,16 @@ int parse_hide_refs_config(const char *var, const char *value, const char *secti
len = strlen(ref);
while (len && ref[len - 1] == '/')
ref[--len] = '\0';
- if (!hide_refs) {
- CALLOC_ARRAY(hide_refs, 1);
- hide_refs->strdup_strings = 1;
- }
- string_list_append(hide_refs, ref);
+ string_list_append_nodup(hide_refs, ref);
}
return 0;
}
-int ref_is_hidden(const char *refname, const char *refname_full)
+int ref_is_hidden(const char *refname, const char *refname_full,
+ const struct string_list *hide_refs)
{
int i;
- if (!hide_refs)
- return 0;
for (i = hide_refs->nr - 1; i >= 0; i--) {
const char *match = hide_refs->items[i].string;
const char *subject;
@@ -1729,9 +1734,10 @@ static void find_longest_prefixes(struct string_list *out,
strbuf_release(&prefix);
}
-int for_each_fullref_in_prefixes(const char *namespace,
- const char **patterns,
- each_ref_fn fn, void *cb_data)
+int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
+ const char *namespace,
+ const char **patterns,
+ each_ref_fn fn, void *cb_data)
{
struct string_list prefixes = STRING_LIST_INIT_DUP;
struct string_list_item *prefix;
@@ -1746,7 +1752,7 @@ int for_each_fullref_in_prefixes(const char *namespace,
for_each_string_list_item(prefix, &prefixes) {
strbuf_addstr(&buf, prefix->string);
- ret = for_each_fullref_in(buf.buf, fn, cb_data);
+ ret = refs_for_each_fullref_in(ref_store, buf.buf, fn, cb_data);
if (ret)
break;
strbuf_setlen(&buf, namespace_len);
@@ -1823,7 +1829,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
return NULL;
/*
- * dwim_ref() uses REF_ISBROKEN to distinguish between
+ * repo_dwim_ref() uses REF_ISBROKEN to distinguish between
* missing refs and refs that were present but invalid,
* to complain about the latter to stderr.
*