Merge branch 'mh/retire-ref-fetch-rules'
authorJunio C Hamano <gitster@pobox.com>
Mon, 27 Jan 2014 18:44:06 +0000 (10:44 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Jan 2014 18:44:07 +0000 (10:44 -0800)
Code simplification.

* mh/retire-ref-fetch-rules:
refname_match(): always use the rules in ref_rev_parse_rules

1  2 
cache.h
refs.c
remote.c
diff --combined cache.h
index c9efe88e9ec40f94401d7a71498396edc523a7cf,aa8ce97f0d5f9ad47a43b280d1559b009d89c3dd..763c961520f93999760d8f24bdb66af2678cca04
+++ b/cache.h
@@@ -354,7 -354,6 +354,7 @@@ static inline enum object_type object_t
  #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
  #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
  #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
 +#define GIT_SHALLOW_FILE_ENVIRONMENT "GIT_SHALLOW_FILE"
  #define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR"
  #define CONFIG_ENVIRONMENT "GIT_CONFIG"
  #define CONFIG_DATA_ENVIRONMENT "GIT_CONFIG_PARAMETERS"
@@@ -761,11 -760,11 +761,11 @@@ int daemon_avoid_alias(const char *path
  int offset_1st_component(const char *path);
  
  /* object replacement */
 -#define READ_SHA1_FILE_REPLACE 1
 +#define LOOKUP_REPLACE_OBJECT 1
  extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag);
  static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
  {
 -      return read_sha1_file_extended(sha1, type, size, READ_SHA1_FILE_REPLACE);
 +      return read_sha1_file_extended(sha1, type, size, LOOKUP_REPLACE_OBJECT);
  }
  extern const unsigned char *do_lookup_replace_object(const unsigned char *sha1);
  static inline const unsigned char *lookup_replace_object(const unsigned char *sha1)
                return sha1;
        return do_lookup_replace_object(sha1);
  }
 +static inline const unsigned char *lookup_replace_object_extended(const unsigned char *sha1, unsigned flag)
 +{
 +      if (!(flag & LOOKUP_REPLACE_OBJECT))
 +              return sha1;
 +      return lookup_replace_object(sha1);
 +}
  
  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
  extern int sha1_object_info(const unsigned char *, unsigned long *);
@@@ -894,9 -887,12 +894,12 @@@ extern int dwim_log(const char *str, in
  extern int interpret_branch_name(const char *str, int len, 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
+ /*
+  * Return true iff abbrev_name is a possible abbreviation for
+  * full_name according to the rules defined by ref_rev_parse_rules in
+  * refs.c.
+  */
+ extern int refname_match(const char *abbrev_name, const char *full_name);
  
  extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg);
  extern int validate_headref(const char *ref);
@@@ -1081,7 -1077,6 +1084,7 @@@ struct object_info 
        enum object_type *typep;
        unsigned long *sizep;
        unsigned long *disk_sizep;
 +      unsigned char *delta_base_sha1;
  
        /* Response */
        enum {
                } packed;
        } u;
  };
 -extern int sha1_object_info_extended(const unsigned char *, struct object_info *);
 +extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags);
  
  /* Dumb servers support */
  extern int update_server_info(int);
@@@ -1244,8 -1239,6 +1247,8 @@@ __attribute__((format (printf, 2, 3))
  extern void trace_argv_printf(const char **argv, const char *format, ...);
  extern void trace_repo_setup(const char *prefix);
  extern int trace_want(const char *key);
 +__attribute__((format (printf, 2, 3)))
 +extern void trace_printf_key(const char *key, const char *fmt, ...);
  extern void trace_strbuf(const char *key, const struct strbuf *buf);
  
  void packet_trace_identity(const char *prog);
diff --combined refs.c
index 490b57b881d88f3f88b11327b20d19f6f3938c46,5a10c25975eaec33d6db38c6f6846fe8865f8d60..fc33ee8ffbe917659e36a801ebf7caa1b89a661d
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -637,7 -637,7 +637,7 @@@ static int do_one_ref(struct ref_entry 
        struct ref_entry *old_current_ref;
        int retval;
  
 -      if (prefixcmp(entry->name, data->base))
 +      if (!starts_with(entry->name, data->base))
                return 0;
  
        if (!(data->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
@@@ -1042,7 -1042,7 +1042,7 @@@ static void read_packed_refs(FILE *f, s
                if (refname) {
                        last = create_ref_entry(refname, sha1, REF_ISPACKED, 1);
                        if (peeled == PEELED_FULLY ||
 -                          (peeled == PEELED_TAGS && !prefixcmp(refname, "refs/tags/")))
 +                          (peeled == PEELED_TAGS && starts_with(refname, "refs/tags/")))
                                last->flag |= REF_KNOWS_PEELED;
                        add_ref(dir, last);
                        continue;
@@@ -1376,7 -1376,7 +1376,7 @@@ const char *resolve_ref_unsafe(const ch
                                        return NULL;
                        }
                        buffer[len] = 0;
 -                      if (!prefixcmp(buffer, "refs/") &&
 +                      if (starts_with(buffer, "refs/") &&
                                        !check_refname_format(buffer, 0)) {
                                strcpy(refname_buffer, buffer);
                                refname = refname_buffer;
                /*
                 * Is it a symbolic ref?
                 */
 -              if (prefixcmp(buffer, "ref:")) {
 +              if (!starts_with(buffer, "ref:")) {
                        /*
                         * Please note that FETCH_HEAD has a second
                         * line containing other data.
@@@ -1837,7 -1837,7 +1837,7 @@@ int for_each_glob_ref_in(each_ref_fn fn
        struct ref_filter filter;
        int ret;
  
 -      if (!prefix && prefixcmp(pattern, "refs/"))
 +      if (!prefix && !starts_with(pattern, "refs/"))
                strbuf_addstr(&real_pattern, "refs/");
        else if (prefix)
                strbuf_addstr(&real_pattern, prefix);
@@@ -1874,13 -1874,13 +1874,13 @@@ int for_each_rawref(each_ref_fn fn, voi
  const char *prettify_refname(const char *name)
  {
        return name + (
 -              !prefixcmp(name, "refs/heads/") ? 11 :
 -              !prefixcmp(name, "refs/tags/") ? 10 :
 -              !prefixcmp(name, "refs/remotes/") ? 13 :
 +              starts_with(name, "refs/heads/") ? 11 :
 +              starts_with(name, "refs/tags/") ? 10 :
 +              starts_with(name, "refs/remotes/") ? 13 :
                0);
  }
  
- const char *ref_rev_parse_rules[] = {
static const char *ref_rev_parse_rules[] = {
        "%.*s",
        "refs/%.*s",
        "refs/tags/%.*s",
        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 char **p;
        const int abbrev_name_len = strlen(abbrev_name);
  
-       for (p = rules; *p; p++) {
+       for (p = ref_rev_parse_rules; *p; p++) {
                if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {
                        return 1;
                }
@@@ -2244,7 -2244,7 +2244,7 @@@ static int pack_if_possible_fn(struct r
        struct pack_refs_cb_data *cb = cb_data;
        enum peel_status peel_status;
        struct ref_entry *packed_entry;
 -      int is_tag_ref = !prefixcmp(entry->name, "refs/tags/");
 +      int is_tag_ref = starts_with(entry->name, "refs/tags/");
  
        /* ALWAYS pack tags */
        if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref)
@@@ -2679,9 -2679,9 +2679,9 @@@ int log_ref_setup(const char *refname, 
  
        git_snpath(logfile, bufsize, "logs/%s", refname);
        if (log_all_ref_updates &&
 -          (!prefixcmp(refname, "refs/heads/") ||
 -           !prefixcmp(refname, "refs/remotes/") ||
 -           !prefixcmp(refname, "refs/notes/") ||
 +          (starts_with(refname, "refs/heads/") ||
 +           starts_with(refname, "refs/remotes/") ||
 +           starts_with(refname, "refs/notes/") ||
             !strcmp(refname, "HEAD"))) {
                if (safe_create_leading_directories(logfile) < 0)
                        return error("unable to create directory for %s",
@@@ -2751,7 -2751,7 +2751,7 @@@ static int log_ref_write(const char *re
  
  static int is_branch(const char *refname)
  {
 -      return !strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/");
 +      return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
  }
  
  int write_ref_sha1(struct ref_lock *lock,
@@@ -3334,6 -3334,29 +3334,6 @@@ cleanup
        return ret;
  }
  
 -/*
 - * generate a format suitable for scanf from a ref_rev_parse_rules
 - * rule, that is replace the "%.*s" spec with a "%s" spec
 - */
 -static void gen_scanf_fmt(char *scanf_fmt, const char *rule)
 -{
 -      char *spec;
 -
 -      spec = strstr(rule, "%.*s");
 -      if (!spec || strstr(spec + 4, "%.*s"))
 -              die("invalid rule in ref_rev_parse_rules: %s", rule);
 -
 -      /* copy all until spec */
 -      strncpy(scanf_fmt, rule, spec - rule);
 -      scanf_fmt[spec - rule] = '\0';
 -      /* copy new spec */
 -      strcat(scanf_fmt, "%s");
 -      /* copy remaining rule */
 -      strcat(scanf_fmt, spec + 4);
 -
 -      return;
 -}
 -
  char *shorten_unambiguous_ref(const char *refname, int strict)
  {
        int i;
        static int nr_rules;
        char *short_name;
  
 -      /* pre generate scanf formats from ref_rev_parse_rules[] */
        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++)
 -                      /* no +1 because strlen("%s") < strlen("%.*s") */
 -                      total_len += strlen(ref_rev_parse_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);
  
 -              total_len = 0;
 +              offset = 0;
                for (i = 0; i < nr_rules; i++) {
 -                      scanf_fmts[i] = (char *)&scanf_fmts[nr_rules]
 -                                      + total_len;
 -                      gen_scanf_fmt(scanf_fmts[i], ref_rev_parse_rules[i]);
 -                      total_len += strlen(ref_rev_parse_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;
                }
        }
  
@@@ -3433,7 -3450,7 +3433,7 @@@ int parse_hide_refs_config(const char *
  {
        if (!strcmp("transfer.hiderefs", var) ||
            /* NEEDSWORK: use parse_config_key() once both are merged */
 -          (!prefixcmp(var, section) && var[strlen(section)] == '.' &&
 +          (starts_with(var, section) && var[strlen(section)] == '.' &&
             !strcmp(var + strlen(section), ".hiderefs"))) {
                char *ref;
                int len;
@@@ -3461,7 -3478,7 +3461,7 @@@ int ref_is_hidden(const char *refname
                return 0;
        for_each_string_list_item(item, hide_refs) {
                int len;
 -              if (prefixcmp(refname, item->string))
 +              if (!starts_with(refname, item->string))
                        continue;
                len = strlen(item->string);
                if (!refname[len] || refname[len] == '/')
diff --combined remote.c
index a89efab5b766ba9374c3a09656b2d56593884c8e,94097b906b028d1b78ad35a891a3d7fe4542d2a0..e41251ee77af1426dd26d4b13ee61a39cffccdeb
+++ b/remote.c
@@@ -76,7 -76,7 +76,7 @@@ static const char *alias_url(const cha
                if (!r->rewrite[i])
                        continue;
                for (j = 0; j < r->rewrite[i]->instead_of_nr; j++) {
 -                      if (!prefixcmp(url, r->rewrite[i]->instead_of[j].s) &&
 +                      if (starts_with(url, r->rewrite[i]->instead_of[j].s) &&
                            (!longest ||
                             longest->len < r->rewrite[i]->instead_of[j].len)) {
                                longest = &(r->rewrite[i]->instead_of[j]);
@@@ -239,13 -239,13 +239,13 @@@ static void read_remotes_file(struct re
                int value_list;
                char *s, *p;
  
 -              if (!prefixcmp(buffer, "URL:")) {
 +              if (starts_with(buffer, "URL:")) {
                        value_list = 0;
                        s = buffer + 4;
 -              } else if (!prefixcmp(buffer, "Push:")) {
 +              } else if (starts_with(buffer, "Push:")) {
                        value_list = 1;
                        s = buffer + 5;
 -              } else if (!prefixcmp(buffer, "Pull:")) {
 +              } else if (starts_with(buffer, "Pull:")) {
                        value_list = 2;
                        s = buffer + 5;
                } else
@@@ -337,7 -337,7 +337,7 @@@ static int handle_config(const char *ke
        const char *subkey;
        struct remote *remote;
        struct branch *branch;
 -      if (!prefixcmp(key, "branch.")) {
 +      if (starts_with(key, "branch.")) {
                name = key + 7;
                subkey = strrchr(name, '.');
                if (!subkey)
                }
                return 0;
        }
 -      if (!prefixcmp(key, "url.")) {
 +      if (starts_with(key, "url.")) {
                struct rewrite *rewrite;
                name = key + 4;
                subkey = strrchr(name, '.');
                }
        }
  
 -      if (prefixcmp(key,  "remote."))
 +      if (!starts_with(key,  "remote."))
                return 0;
        name = key + 7;
  
@@@ -487,7 -487,7 +487,7 @@@ static void read_config(void
        current_branch = NULL;
        head_ref = resolve_ref_unsafe("HEAD", sha1, 0, &flag);
        if (head_ref && (flag & REF_ISSYMREF) &&
 -          !prefixcmp(head_ref, "refs/heads/")) {
 +          starts_with(head_ref, "refs/heads/")) {
                current_branch =
                        make_branch(head_ref + strlen("refs/heads/"), 0);
        }
@@@ -745,66 -745,35 +745,66 @@@ int for_each_remote(each_remote_fn fn, 
        return result;
  }
  
 -void ref_remove_duplicates(struct ref *ref_map)
 +static void handle_duplicate(struct ref *ref1, struct ref *ref2)
 +{
 +      if (strcmp(ref1->name, ref2->name)) {
 +              if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
 +                  ref2->fetch_head_status != FETCH_HEAD_IGNORE) {
 +                      die(_("Cannot fetch both %s and %s to %s"),
 +                          ref1->name, ref2->name, ref2->peer_ref->name);
 +              } else if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
 +                         ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
 +                      warning(_("%s usually tracks %s, not %s"),
 +                              ref2->peer_ref->name, ref2->name, ref1->name);
 +              } else if (ref1->fetch_head_status == FETCH_HEAD_IGNORE &&
 +                         ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
 +                      die(_("%s tracks both %s and %s"),
 +                          ref2->peer_ref->name, ref1->name, ref2->name);
 +              } else {
 +                      /*
 +                       * This last possibility doesn't occur because
 +                       * FETCH_HEAD_IGNORE entries always appear at
 +                       * the end of the list.
 +                       */
 +                      die(_("Internal error"));
 +              }
 +      }
 +      free(ref2->peer_ref);
 +      free(ref2);
 +}
 +
 +struct ref *ref_remove_duplicates(struct ref *ref_map)
  {
        struct string_list refs = STRING_LIST_INIT_NODUP;
 -      struct string_list_item *item = NULL;
 -      struct ref *prev = NULL, *next = NULL;
 -      for (; ref_map; prev = ref_map, ref_map = next) {
 -              next = ref_map->next;
 -              if (!ref_map->peer_ref)
 -                      continue;
 +      struct ref *retval = NULL;
 +      struct ref **p = &retval;
  
 -              item = string_list_lookup(&refs, ref_map->peer_ref->name);
 -              if (item) {
 -                      if (strcmp(((struct ref *)item->util)->name,
 -                                 ref_map->name))
 -                              die("%s tracks both %s and %s",
 -                                  ref_map->peer_ref->name,
 -                                  ((struct ref *)item->util)->name,
 -                                  ref_map->name);
 -                      prev->next = ref_map->next;
 -                      free(ref_map->peer_ref);
 -                      free(ref_map);
 -                      ref_map = prev; /* skip this; we freed it */
 -                      continue;
 -              }
 +      while (ref_map) {
 +              struct ref *ref = ref_map;
 +
 +              ref_map = ref_map->next;
 +              ref->next = NULL;
  
 -              item = string_list_insert(&refs, ref_map->peer_ref->name);
 -              item->util = ref_map;
 +              if (!ref->peer_ref) {
 +                      *p = ref;
 +                      p = &ref->next;
 +              } else {
 +                      struct string_list_item *item =
 +                              string_list_insert(&refs, ref->peer_ref->name);
 +
 +                      if (item->util) {
 +                              /* Entry already existed */
 +                              handle_duplicate((struct ref *)item->util, ref);
 +                      } else {
 +                              *p = ref;
 +                              p = &ref->next;
 +                              item->util = ref;
 +                      }
 +              }
        }
 +
        string_list_clear(&refs, 0);
 +      return retval;
  }
  
  int remote_has_url(struct remote *remote, const char *url)
@@@ -852,12 -821,10 +852,12 @@@ static int match_name_with_pattern(cons
        return ret;
  }
  
 -static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
 +int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
  {
        int i;
        int find_src = !query->src;
 +      const char *needle = find_src ? query->dst : query->src;
 +      char **result = find_src ? &query->src : &query->dst;
  
        if (find_src && !query->dst)
                return error("query_refspecs: need either src or dst");
                struct refspec *refspec = &refs[i];
                const char *key = find_src ? refspec->dst : refspec->src;
                const char *value = find_src ? refspec->src : refspec->dst;
 -              const char *needle = find_src ? query->dst : query->src;
 -              char **result = find_src ? &query->src : &query->dst;
  
                if (!refspec->dst)
                        continue;
@@@ -986,9 -955,9 +986,9 @@@ void sort_ref_list(struct ref **l, int 
        *l = llist_mergesort(*l, ref_list_get_next, ref_list_set_next, cmp);
  }
  
 -static int count_refspec_match(const char *pattern,
 -                             struct ref *refs,
 -                             struct ref **matched_ref)
 +int count_refspec_match(const char *pattern,
 +                      struct ref *refs,
 +                      struct ref **matched_ref)
  {
        int patlen = strlen(pattern);
        struct ref *matched_weak = NULL;
                char *name = refs->name;
                int namelen = strlen(name);
  
-               if (!refname_match(pattern, name, ref_rev_parse_rules))
+               if (!refname_match(pattern, name))
                        continue;
  
                /* A match is "weak" if it is with refs outside
                 */
                if (namelen != patlen &&
                    patlen != namelen - 5 &&
 -                  prefixcmp(name, "refs/heads/") &&
 -                  prefixcmp(name, "refs/tags/")) {
 +                  !starts_with(name, "refs/heads/") &&
 +                  !starts_with(name, "refs/tags/")) {
                        /* We want to catch the case where only weak
                         * matches are found and there are multiple
                         * matches, and where more than one strong
@@@ -1085,9 -1054,9 +1085,9 @@@ static char *guess_ref(const char *name
        if (!r)
                return NULL;
  
 -      if (!prefixcmp(r, "refs/heads/"))
 +      if (starts_with(r, "refs/heads/"))
                strbuf_addstr(&buf, "refs/heads/");
 -      else if (!prefixcmp(r, "refs/tags/"))
 +      else if (starts_with(r, "refs/tags/"))
                strbuf_addstr(&buf, "refs/tags/");
        else
                return NULL;
@@@ -1135,7 -1104,7 +1135,7 @@@ static int match_explicit(struct ref *s
                dst_value = resolve_ref_unsafe(matched_src->name, sha1, 1, &flag);
                if (!dst_value ||
                    ((flag & REF_ISSYMREF) &&
 -                   prefixcmp(dst_value, "refs/heads/")))
 +                   !starts_with(dst_value, "refs/heads/")))
                        die("%s cannot be resolved to branch.",
                            matched_src->name);
        }
@@@ -1224,7 -1193,7 +1224,7 @@@ static char *get_ref_match(const struc
                 * including refs outside refs/heads/ hierarchy, but
                 * that does not make much sense these days.
                 */
 -              if (!send_mirror && prefixcmp(ref->name, "refs/heads/"))
 +              if (!send_mirror && !starts_with(ref->name, "refs/heads/"))
                        return NULL;
                name = xstrdup(ref->name);
        }
@@@ -1279,7 -1248,7 +1279,7 @@@ static void add_missing_tags(struct re
                        add_to_tips(&sent_tips, ref->peer_ref->new_sha1);
                else
                        add_to_tips(&sent_tips, ref->old_sha1);
 -              if (!prefixcmp(ref->name, "refs/tags/"))
 +              if (starts_with(ref->name, "refs/tags/"))
                        string_list_append(&dst_tag, ref->name);
        }
        clear_commit_marks_many(sent_tips.nr, sent_tips.tip, TMP_MARK);
  
        /* Collect tags they do not have. */
        for (ref = src; ref; ref = ref->next) {
 -              if (prefixcmp(ref->name, "refs/tags/"))
 +              if (!starts_with(ref->name, "refs/tags/"))
                        continue; /* not a tag */
                if (string_list_has_string(&dst_tag, ref->name))
                        continue; /* they already have it */
@@@ -1512,7 -1481,7 +1512,7 @@@ void set_ref_status_for_push(struct re
                 */
  
                else if (!ref->deletion && !is_null_sha1(ref->old_sha1)) {
 -                      if (!prefixcmp(ref->name, "refs/tags/"))
 +                      if (starts_with(ref->name, "refs/tags/"))
                                reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
                        else if (!has_sha1_file(ref->old_sha1))
                                reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
@@@ -1571,7 -1540,7 +1571,7 @@@ int branch_merge_matches(struct 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);
  }
  
  static int ignore_symref_update(const char *refname)
        return (flag & REF_ISSYMREF);
  }
  
 +/*
 + * Create and return a list of (struct ref) consisting of copies of
 + * each remote_ref that matches refspec.  refspec must be a pattern.
 + * Fill in the copies' peer_ref to describe the local tracking refs to
 + * which they map.  Omit any references that would map to an existing
 + * local symbolic ref.
 + */
  static struct ref *get_expanded_map(const struct ref *remote_refs,
                                    const struct refspec *refspec)
  {
        struct ref *ret = NULL;
        struct ref **tail = &ret;
  
 -      char *expn_name;
 -
        for (ref = remote_refs; ref; ref = ref->next) {
 +              char *expn_name = NULL;
 +
                if (strchr(ref->name, '^'))
                        continue; /* a dereference item */
                if (match_name_with_pattern(refspec->src, ref->name,
                        struct ref *cpy = copy_ref(ref);
  
                        cpy->peer_ref = alloc_ref(expn_name);
 -                      free(expn_name);
                        if (refspec->force)
                                cpy->peer_ref->force = 1;
                        *tail = cpy;
                        tail = &cpy->next;
                }
 +              free(expn_name);
        }
  
        return ret;
@@@ -1624,7 -1586,7 +1624,7 @@@ static const struct ref *find_ref_by_na
  {
        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))
                        return ref;
        }
        return NULL;
@@@ -1645,12 -1607,12 +1645,12 @@@ static struct ref *get_local_ref(const 
        if (!name || name[0] == '\0')
                return NULL;
  
 -      if (!prefixcmp(name, "refs/"))
 +      if (starts_with(name, "refs/"))
                return alloc_ref(name);
  
 -      if (!prefixcmp(name, "heads/") ||
 -          !prefixcmp(name, "tags/") ||
 -          !prefixcmp(name, "remotes/"))
 +      if (starts_with(name, "heads/") ||
 +          starts_with(name, "tags/") ||
 +          starts_with(name, "remotes/"))
                return alloc_ref_with_prefix("refs/", 5, name);
  
        return alloc_ref_with_prefix("refs/heads/", 11, name);
@@@ -1685,7 -1647,7 +1685,7 @@@ int get_fetch_map(const struct ref *rem
  
        for (rmp = &ref_map; *rmp; ) {
                if ((*rmp)->peer_ref) {
 -                      if (prefixcmp((*rmp)->peer_ref->name, "refs/") ||
 +                      if (!starts_with((*rmp)->peer_ref->name, "refs/") ||
                            check_refname_format((*rmp)->peer_ref->name, 0)) {
                                struct ref *ignore = *rmp;
                                error("* Ignoring funny ref '%s' locally",
@@@ -1969,7 -1931,7 +1969,7 @@@ struct ref *guess_remote_head(const str
        /* Look for another ref that points there */
        for (r = refs; r; r = r->next) {
                if (r != head &&
 -                  !prefixcmp(r->name, "refs/heads/") &&
 +                  starts_with(r->name, "refs/heads/") &&
                    !hashcmp(r->old_sha1, head->old_sha1)) {
                        *tail = copy_ref(r);
                        tail = &((*tail)->next);
@@@ -2121,7 -2083,7 +2121,7 @@@ static void apply_cas(struct push_cas_o
        /* Find an explicit --<option>=<name>[:<value>] entry */
        for (i = 0; i < cas->nr; i++) {
                struct push_cas *entry = &cas->entry[i];
-               if (!refname_match(entry->refname, ref->name, ref_rev_parse_rules))
+               if (!refname_match(entry->refname, ref->name))
                        continue;
                ref->expect_old_sha1 = 1;
                if (!entry->use_tracking)