Merge branch 'cc/fetch-error-message-fix'
authorJunio C Hamano <gitster@pobox.com>
Tue, 29 Jan 2019 20:47:53 +0000 (12:47 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 29 Jan 2019 20:47:53 +0000 (12:47 -0800)
Error message fix.

* cc/fetch-error-message-fix:
fetch: fix extensions.partialclone name in error message

1  2 
builtin/fetch.c
diff --combined builtin/fetch.c
index e0140327aab23654c69e7388c23a07b98b8ff913,b930ade2e08f15a73162ce7ea0c4c0390d339ab7..c0ade48f5d68bef87d85c478ec63b3212a2f4940
@@@ -6,7 -6,6 +6,7 @@@
  #include "repository.h"
  #include "refs.h"
  #include "refspec.h"
 +#include "object-store.h"
  #include "commit.h"
  #include "builtin.h"
  #include "string-list.h"
@@@ -22,7 -21,6 +22,7 @@@
  #include "utf8.h"
  #include "packfile.h"
  #include "list-objects-filter-options.h"
 +#include "commit-reach.h"
  
  static const char * const builtin_fetch_usage[] = {
        N_("git fetch [<options>] [<repository> [<refspec>...]]"),
@@@ -65,7 -63,6 +65,7 @@@ static int shown_url = 0
  static struct refspec refmap = REFSPEC_INIT_FETCH;
  static struct list_objects_filter_options filter_options;
  static struct string_list server_options = STRING_LIST_INIT_DUP;
 +static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
  
  static int git_fetch_config(const char *k, const char *v, void *cb)
  {
        return git_default_config(k, v, cb);
  }
  
 -static int gitmodules_fetch_config(const char *var, const char *value, void *cb)
 -{
 -      if (!strcmp(var, "submodule.fetchjobs")) {
 -              max_children = parse_submodule_fetchjobs(var, value);
 -              return 0;
 -      } else if (!strcmp(var, "fetch.recursesubmodules")) {
 -              recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
 -              return 0;
 -      }
 -
 -      return 0;
 -}
 -
  static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
  {
 +      BUG_ON_OPT_NEG(unset);
 +
        /*
         * "git fetch --refmap='' origin foo"
         * can be used to tell the command not to store anywhere
@@@ -117,7 -125,7 +117,7 @@@ static struct option builtin_fetch_opti
                 N_("append to .git/FETCH_HEAD instead of overwriting")),
        OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
                   N_("path to upload pack on remote end")),
 -      OPT__FORCE(&force, N_("force overwrite of local branch"), 0),
 +      OPT__FORCE(&force, N_("force overwrite of local reference"), 0),
        OPT_BOOL('m', "multiple", &multiple,
                 N_("fetch from multiple remotes")),
        OPT_SET_INT('t', "tags", &tags,
                        TRANSPORT_FAMILY_IPV4),
        OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
                        TRANSPORT_FAMILY_IPV6),
 +      OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"),
 +                      N_("report that we have only objects reachable from this object")),
        OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
        OPT_END()
  };
@@@ -225,84 -231,40 +225,84 @@@ static void add_merge_config(struct re
        }
  }
  
 -static int add_existing(const char *refname, const struct object_id *oid,
 -                      int flag, void *cbdata)
 -{
 -      struct string_list *list = (struct string_list *)cbdata;
 -      struct string_list_item *item = string_list_insert(list, refname);
 -      struct object_id *old_oid = xmalloc(sizeof(*old_oid));
 -
 -      oidcpy(old_oid, oid);
 -      item->util = old_oid;
 -      return 0;
 -}
 -
  static int will_fetch(struct ref **head, const unsigned char *sha1)
  {
        struct ref *rm = *head;
        while (rm) {
 -              if (!hashcmp(rm->old_oid.hash, sha1))
 +              if (hasheq(rm->old_oid.hash, sha1))
                        return 1;
                rm = rm->next;
        }
        return 0;
  }
  
 -static void find_non_local_tags(struct transport *transport,
 -                      struct ref **head,
 -                      struct ref ***tail)
 +struct refname_hash_entry {
 +      struct hashmap_entry ent; /* must be the first member */
 +      struct object_id oid;
 +      char refname[FLEX_ARRAY];
 +};
 +
 +static int refname_hash_entry_cmp(const void *hashmap_cmp_fn_data,
 +                                const void *e1_,
 +                                const void *e2_,
 +                                const void *keydata)
 +{
 +      const struct refname_hash_entry *e1 = e1_;
 +      const struct refname_hash_entry *e2 = e2_;
 +
 +      return strcmp(e1->refname, keydata ? keydata : e2->refname);
 +}
 +
 +static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
 +                                                 const char *refname,
 +                                                 const struct object_id *oid)
 +{
 +      struct refname_hash_entry *ent;
 +      size_t len = strlen(refname);
 +
 +      FLEX_ALLOC_MEM(ent, refname, refname, len);
 +      hashmap_entry_init(ent, strhash(refname));
 +      oidcpy(&ent->oid, oid);
 +      hashmap_add(map, ent);
 +      return ent;
 +}
 +
 +static int add_one_refname(const char *refname,
 +                         const struct object_id *oid,
 +                         int flag, void *cbdata)
 +{
 +      struct hashmap *refname_map = cbdata;
 +
 +      (void) refname_hash_add(refname_map, refname, oid);
 +      return 0;
 +}
 +
 +static void refname_hash_init(struct hashmap *map)
 +{
 +      hashmap_init(map, refname_hash_entry_cmp, NULL, 0);
 +}
 +
 +static int refname_hash_exists(struct hashmap *map, const char *refname)
  {
 -      struct string_list existing_refs = STRING_LIST_INIT_DUP;
 -      struct string_list remote_refs = STRING_LIST_INIT_NODUP;
 +      return !!hashmap_get_from_hash(map, strhash(refname), refname);
 +}
 +
 +static void find_non_local_tags(const struct ref *refs,
 +                              struct ref **head,
 +                              struct ref ***tail)
 +{
 +      struct hashmap existing_refs;
 +      struct hashmap remote_refs;
 +      struct string_list remote_refs_list = STRING_LIST_INIT_NODUP;
 +      struct string_list_item *remote_ref_item;
        const struct ref *ref;
 -      struct string_list_item *item = NULL;
 +      struct refname_hash_entry *item = NULL;
 +
 +      refname_hash_init(&existing_refs);
 +      refname_hash_init(&remote_refs);
  
 -      for_each_ref(add_existing, &existing_refs);
 -      for (ref = transport_get_remote_refs(transport, NULL); ref; ref = ref->next) {
 +      for_each_ref(add_one_refname, &existing_refs);
 +      for (ref = refs; ref; ref = ref->next) {
                if (!starts_with(ref->name, "refs/tags/"))
                        continue;
  
                            !has_object_file_with_flags(&ref->old_oid,
                                                        OBJECT_INFO_QUICK) &&
                            !will_fetch(head, ref->old_oid.hash) &&
 -                          !has_sha1_file_with_flags(item->util,
 +                          !has_sha1_file_with_flags(item->oid.hash,
                                                      OBJECT_INFO_QUICK) &&
 -                          !will_fetch(head, item->util))
 -                              item->util = NULL;
 +                          !will_fetch(head, item->oid.hash))
 +                              oidclr(&item->oid);
                        item = NULL;
                        continue;
                }
                 * fetch.
                 */
                if (item &&
 -                  !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) &&
 -                  !will_fetch(head, item->util))
 -                      item->util = NULL;
 +                  !has_sha1_file_with_flags(item->oid.hash, OBJECT_INFO_QUICK) &&
 +                  !will_fetch(head, item->oid.hash))
 +                      oidclr(&item->oid);
  
                item = NULL;
  
                /* skip duplicates and refs that we already have */
 -              if (string_list_has_string(&remote_refs, ref->name) ||
 -                  string_list_has_string(&existing_refs, ref->name))
 +              if (refname_hash_exists(&remote_refs, ref->name) ||
 +                  refname_hash_exists(&existing_refs, ref->name))
                        continue;
  
 -              item = string_list_insert(&remote_refs, ref->name);
 -              item->util = (void *)&ref->old_oid;
 +              item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
 +              string_list_insert(&remote_refs_list, ref->name);
        }
 -      string_list_clear(&existing_refs, 1);
 +      hashmap_free(&existing_refs, 1);
  
        /*
         * We may have a final lightweight tag that needs to be
         * checked to see if it needs fetching.
         */
        if (item &&
 -          !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) &&
 -          !will_fetch(head, item->util))
 -              item->util = NULL;
 +          !has_sha1_file_with_flags(item->oid.hash, OBJECT_INFO_QUICK) &&
 +          !will_fetch(head, item->oid.hash))
 +              oidclr(&item->oid);
  
        /*
 -       * For all the tags in the remote_refs string list,
 +       * For all the tags in the remote_refs_list,
         * add them to the list of refs to be fetched
         */
 -      for_each_string_list_item(item, &remote_refs) {
 +      for_each_string_list_item(remote_ref_item, &remote_refs_list) {
 +              const char *refname = remote_ref_item->string;
 +
 +              item = hashmap_get_from_hash(&remote_refs, strhash(refname), refname);
 +              if (!item)
 +                      BUG("unseen remote ref?");
 +
                /* Unless we have already decided to ignore this item... */
 -              if (item->util)
 -              {
 -                      struct ref *rm = alloc_ref(item->string);
 -                      rm->peer_ref = alloc_ref(item->string);
 -                      oidcpy(&rm->old_oid, item->util);
 +              if (!is_null_oid(&item->oid)) {
 +                      struct ref *rm = alloc_ref(item->refname);
 +                      rm->peer_ref = alloc_ref(item->refname);
 +                      oidcpy(&rm->old_oid, &item->oid);
                        **tail = rm;
                        *tail = &rm->next;
                }
        }
 -
 -      string_list_clear(&remote_refs, 0);
 +      hashmap_free(&remote_refs, 1);
 +      string_list_clear(&remote_refs_list, 0);
  }
  
 -static struct ref *get_ref_map(struct transport *transport,
 +static struct ref *get_ref_map(struct remote *remote,
 +                             const struct ref *remote_refs,
                               struct refspec *rs,
                               int tags, int *autotags)
  {
        struct ref *rm;
        struct ref *ref_map = NULL;
        struct ref **tail = &ref_map;
 -      struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
  
        /* opportunistically-updated references: */
        struct ref *orefs = NULL, **oref_tail = &orefs;
  
 -      const struct ref *remote_refs;
 -
 -      if (rs->nr)
 -              refspec_ref_prefixes(rs, &ref_prefixes);
 -      else if (transport->remote && transport->remote->fetch.nr)
 -              refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
 -
 -      if (ref_prefixes.argc &&
 -          (tags == TAGS_SET || (tags == TAGS_DEFAULT && !rs->nr))) {
 -              argv_array_push(&ref_prefixes, "refs/tags/");
 -      }
 -
 -      remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
 -
 -      argv_array_clear(&ref_prefixes);
 +      struct hashmap existing_refs;
  
        if (rs->nr) {
                struct refspec *fetch_refspec;
                if (refmap.nr)
                        fetch_refspec = &refmap;
                else
 -                      fetch_refspec = &transport->remote->fetch;
 +                      fetch_refspec = &remote->fetch;
  
                for (i = 0; i < fetch_refspec->nr; i++)
                        get_fetch_map(ref_map, &fetch_refspec->items[i], &oref_tail, 1);
                die("--refmap option is only meaningful with command-line refspec(s).");
        } else {
                /* Use the defaults */
 -              struct remote *remote = transport->remote;
                struct branch *branch = branch_get(NULL);
                int has_merge = branch_has_merge_config(branch);
                if (remote &&
                /* also fetch all tags */
                get_fetch_map(remote_refs, tag_refspec, &tail, 0);
        else if (tags == TAGS_DEFAULT && *autotags)
 -              find_non_local_tags(transport, &ref_map, &tail);
 +              find_non_local_tags(remote_refs, &ref_map, &tail);
  
        /* Now append any refs to be updated opportunistically: */
        *tail = orefs;
                tail = &rm->next;
        }
  
 -      return ref_remove_duplicates(ref_map);
 +      ref_map = ref_remove_duplicates(ref_map);
 +
 +      refname_hash_init(&existing_refs);
 +      for_each_ref(add_one_refname, &existing_refs);
 +
 +      for (rm = ref_map; rm; rm = rm->next) {
 +              if (rm->peer_ref) {
 +                      const char *refname = rm->peer_ref->name;
 +                      struct refname_hash_entry *peer_item;
 +
 +                      peer_item = hashmap_get_from_hash(&existing_refs,
 +                                                        strhash(refname),
 +                                                        refname);
 +                      if (peer_item) {
 +                              struct object_id *old_oid = &peer_item->oid;
 +                              oidcpy(&rm->peer_ref->old_oid, old_oid);
 +                      }
 +              }
 +      }
 +      hashmap_free(&existing_refs, 1);
 +
 +      return ref_map;
  }
  
  #define STORE_REF_ERROR_OTHER 1
@@@ -564,7 -515,7 +564,7 @@@ static void adjust_refcol_width(const s
        int max, rlen, llen, len;
  
        /* uptodate lines are only shown on high verbosity level */
 -      if (!verbosity && !oidcmp(&ref->peer_ref->old_oid, &ref->old_oid))
 +      if (!verbosity && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
                return;
  
        max    = term_columns();
@@@ -701,7 -652,7 +701,7 @@@ static int update_local_ref(struct ref 
        if (type < 0)
                die(_("object %s not found"), oid_to_hex(&ref->new_oid));
  
 -      if (!oidcmp(&ref->old_oid, &ref->new_oid)) {
 +      if (oideq(&ref->old_oid, &ref->new_oid)) {
                if (verbosity > 0)
                        format_display(display, '=', _("[up to date]"), NULL,
                                       remote, pretty_ref, summary_width);
  
        if (!is_null_oid(&ref->old_oid) &&
            starts_with(ref->name, "refs/tags/")) {
 -              int r;
 -              r = s_update_ref("updating tag", ref, 0);
 -              format_display(display, r ? '!' : 't', _("[tag update]"),
 -                             r ? _("unable to update local ref") : NULL,
 -                             remote, pretty_ref, summary_width);
 -              return r;
 +              if (force || ref->force) {
 +                      int r;
 +                      r = s_update_ref("updating tag", ref, 0);
 +                      format_display(display, r ? '!' : 't', _("[tag update]"),
 +                                     r ? _("unable to update local ref") : NULL,
 +                                     remote, pretty_ref, summary_width);
 +                      return r;
 +              } else {
 +                      format_display(display, '!', _("[rejected]"), _("would clobber existing tag"),
 +                                     remote, pretty_ref, summary_width);
 +                      return 1;
 +              }
        }
  
 -      current = lookup_commit_reference_gently(&ref->old_oid, 1);
 -      updated = lookup_commit_reference_gently(&ref->new_oid, 1);
 +      current = lookup_commit_reference_gently(the_repository,
 +                                               &ref->old_oid, 1);
 +      updated = lookup_commit_reference_gently(the_repository,
 +                                               &ref->new_oid, 1);
        if (!current || !updated) {
                const char *msg;
                const char *what;
@@@ -825,7 -768,7 +825,7 @@@ static int iterate_ref_map(void *cb_dat
  }
  
  static int store_updated_refs(const char *raw_url, const char *remote_name,
 -              struct ref *ref_map)
 +                            int connectivity_checked, struct ref *ref_map)
  {
        FILE *fp;
        struct commit *commit;
        const char *what, *kind;
        struct ref *rm;
        char *url;
 -      const char *filename = dry_run ? "/dev/null" : git_path_fetch_head();
 +      const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(the_repository);
        int want_status;
        int summary_width = transport_summary_width(ref_map);
  
        else
                url = xstrdup("foreign");
  
 -      rm = ref_map;
 -      if (check_connected(iterate_ref_map, &rm, NULL)) {
 -              rc = error(_("%s did not send all necessary objects\n"), url);
 -              goto abort;
 +      if (!connectivity_checked) {
 +              rm = ref_map;
 +              if (check_connected(iterate_ref_map, &rm, NULL)) {
 +                      rc = error(_("%s did not send all necessary objects\n"), url);
 +                      goto abort;
 +              }
        }
  
        prepare_format_display(ref_map);
                                continue;
                        }
  
 -                      commit = lookup_commit_reference_gently(&rm->old_oid,
 +                      commit = lookup_commit_reference_gently(the_repository,
 +                                                              &rm->old_oid,
                                                                1);
                        if (!commit)
                                rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
   * everything we are going to fetch already exists and is connected
   * locally.
   */
 -static int quickfetch(struct ref *ref_map)
 +static int check_exist_and_connected(struct ref *ref_map)
  {
        struct ref *rm = ref_map;
        struct check_connected_options opt = CHECK_CONNECTED_INIT;
 +      struct ref *r;
  
        /*
         * If we are deepening a shallow clone we already have these
         */
        if (deepen)
                return -1;
 +
 +      /*
 +       * check_connected() allows objects to merely be promised, but
 +       * we need all direct targets to exist.
 +       */
 +      for (r = rm; r; r = r->next) {
 +              if (!has_object_file(&r->old_oid))
 +                      return -1;
 +      }
 +
        opt.quiet = 1;
        return check_connected(iterate_ref_map, &rm, &opt);
  }
  
  static int fetch_refs(struct transport *transport, struct ref *ref_map)
  {
 -      int ret = quickfetch(ref_map);
 +      int ret = check_exist_and_connected(ref_map);
        if (ret)
                ret = transport_fetch_refs(transport, ref_map);
        if (!ret)
 -              ret |= store_updated_refs(transport->url,
 -                              transport->remote->name,
 -                              ref_map);
 +              /*
 +               * Keep the new pack's ".keep" file around to allow the caller
 +               * time to update refs to reference the new objects.
 +               */
 +              return 0;
 +      transport_unlock_pack(transport);
 +      return ret;
 +}
 +
 +/* Update local refs based on the ref values fetched from a remote */
 +static int consume_refs(struct transport *transport, struct ref *ref_map)
 +{
 +      int connectivity_checked = transport->smart_options
 +              ? transport->smart_options->connectivity_checked : 0;
 +      int ret = store_updated_refs(transport->url,
 +                                   transport->remote->name,
 +                                   connectivity_checked,
 +                                   ref_map);
        transport_unlock_pack(transport);
        return ret;
  }
@@@ -1115,7 -1029,7 +1115,7 @@@ static void check_not_current_branch(st
  
  static int truncate_fetch_head(void)
  {
 -      const char *filename = git_path_fetch_head();
 +      const char *filename = git_path_fetch_head(the_repository);
        FILE *fp = fopen_for_writing(filename);
  
        if (!fp)
@@@ -1135,40 -1049,6 +1135,40 @@@ static void set_option(struct transpor
                        name, transport->url);
  }
  
 +
 +static int add_oid(const char *refname, const struct object_id *oid, int flags,
 +                 void *cb_data)
 +{
 +      struct oid_array *oids = cb_data;
 +
 +      oid_array_append(oids, oid);
 +      return 0;
 +}
 +
 +static void add_negotiation_tips(struct git_transport_options *smart_options)
 +{
 +      struct oid_array *oids = xcalloc(1, sizeof(*oids));
 +      int i;
 +
 +      for (i = 0; i < negotiation_tip.nr; i++) {
 +              const char *s = negotiation_tip.items[i].string;
 +              int old_nr;
 +              if (!has_glob_specials(s)) {
 +                      struct object_id oid;
 +                      if (get_oid(s, &oid))
 +                              die("%s is not a valid object", s);
 +                      oid_array_append(oids, &oid);
 +                      continue;
 +              }
 +              old_nr = oids->nr;
 +              for_each_glob_ref(add_oid, s, oids);
 +              if (old_nr == oids->nr)
 +                      warning("Ignoring --negotiation-tip=%s because it does not match any refs",
 +                              s);
 +      }
 +      smart_options->negotiation_tips = oids;
 +}
 +
  static struct transport *prepare_transport(struct remote *remote, int deepen)
  {
        struct transport *transport;
                           filter_options.filter_spec);
                set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
        }
 +      if (negotiation_tip.nr) {
 +              if (transport->smart_options)
 +                      add_negotiation_tips(transport->smart_options);
 +              else
 +                      warning("Ignoring --negotiation-tip because the protocol does not support it.");
 +      }
        return transport;
  }
  
@@@ -1225,8 -1099,7 +1225,8 @@@ static void backfill_tags(struct transp
        transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
        transport_set_option(transport, TRANS_OPT_DEPTH, "0");
        transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
 -      fetch_refs(transport, ref_map);
 +      if (!fetch_refs(transport, ref_map))
 +              consume_refs(transport, ref_map);
  
        if (gsecondary) {
                transport_disconnect(gsecondary);
  static int do_fetch(struct transport *transport,
                    struct refspec *rs)
  {
 -      struct string_list existing_refs = STRING_LIST_INIT_DUP;
        struct ref *ref_map;
 -      struct ref *rm;
        int autotags = (transport->remote->fetch_tags == 1);
        int retcode = 0;
 -
 -      for_each_ref(add_existing, &existing_refs);
 +      const struct ref *remote_refs;
 +      struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
 +      int must_list_refs = 1;
  
        if (tags == TAGS_DEFAULT) {
                if (transport->remote->fetch_tags == 2)
                        goto cleanup;
        }
  
 -      ref_map = get_ref_map(transport, rs, tags, &autotags);
 -      if (!update_head_ok)
 -              check_not_current_branch(ref_map);
 +      if (rs->nr) {
 +              int i;
  
 -      for (rm = ref_map; rm; rm = rm->next) {
 -              if (rm->peer_ref) {
 -                      struct string_list_item *peer_item =
 -                              string_list_lookup(&existing_refs,
 -                                                 rm->peer_ref->name);
 -                      if (peer_item) {
 -                              struct object_id *old_oid = peer_item->util;
 -                              oidcpy(&rm->peer_ref->old_oid, old_oid);
 +              refspec_ref_prefixes(rs, &ref_prefixes);
 +
 +              /*
 +               * We can avoid listing refs if all of them are exact
 +               * OIDs
 +               */
 +              must_list_refs = 0;
 +              for (i = 0; i < rs->nr; i++) {
 +                      if (!rs->items[i].exact_sha1) {
 +                              must_list_refs = 1;
 +                              break;
                        }
                }
 +      } else if (transport->remote && transport->remote->fetch.nr)
 +              refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
 +
 +      if (tags == TAGS_SET || tags == TAGS_DEFAULT) {
 +              must_list_refs = 1;
 +              if (ref_prefixes.argc)
 +                      argv_array_push(&ref_prefixes, "refs/tags/");
        }
  
 +      if (must_list_refs)
 +              remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
 +      else
 +              remote_refs = NULL;
 +
 +      argv_array_clear(&ref_prefixes);
 +
 +      ref_map = get_ref_map(transport->remote, remote_refs, rs,
 +                            tags, &autotags);
 +      if (!update_head_ok)
 +              check_not_current_branch(ref_map);
 +
        if (tags == TAGS_DEFAULT && autotags)
                transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
        if (prune) {
                                   transport->url);
                }
        }
 -      if (fetch_refs(transport, ref_map)) {
 +      if (fetch_refs(transport, ref_map) || consume_refs(transport, ref_map)) {
                free_refs(ref_map);
                retcode = 1;
                goto cleanup;
        if (tags == TAGS_DEFAULT && autotags) {
                struct ref **tail = &ref_map;
                ref_map = NULL;
 -              find_non_local_tags(transport, &ref_map, &tail);
 +              find_non_local_tags(remote_refs, &ref_map, &tail);
                if (ref_map)
                        backfill_tags(transport, ref_map);
                free_refs(ref_map);
        }
  
   cleanup:
 -      string_list_clear(&existing_refs, 1);
        return retcode;
  }
  
@@@ -1478,7 -1332,8 +1478,8 @@@ static inline void fetch_one_setup_part
         */
        if (strcmp(remote->name, repository_format_partial_clone)) {
                if (filter_options.choice)
-                       die(_("--filter can only be used with the remote configured in core.partialClone"));
+                       die(_("--filter can only be used with the remote "
+                             "configured in extensions.partialclone"));
                return;
        }
  
@@@ -1579,7 -1434,7 +1580,7 @@@ int cmd_fetch(int argc, const char **ar
        for (i = 1; i < argc; i++)
                strbuf_addf(&default_rla, " %s", argv[i]);
  
 -      config_from_gitmodules(gitmodules_fetch_config, NULL);
 +      fetch_config_from_gitmodules(&max_children, &recurse_submodules);
        git_config(git_fetch_config, NULL);
  
        argc = parse_options(argc, argv, prefix,
        if (unshallow) {
                if (depth)
                        die(_("--depth and --unshallow cannot be used together"));
 -              else if (!is_repository_shallow())
 +              else if (!is_repository_shallow(the_repository))
                        die(_("--unshallow on a complete repository does not make sense"));
                else
                        depth = xstrfmt("%d", INFINITE_DEPTH);
                result = fetch_one(remote, argc, argv, prune_tags_ok);
        } else {
                if (filter_options.choice)
-                       die(_("--filter can only be used with the remote configured in core.partialClone"));
+                       die(_("--filter can only be used with the remote "
+                             "configured in extensions.partialclone"));
                /* TODO should this also die if we have a previous partial-clone? */
                result = fetch_multiple(&list);
        }