Merge branch 'nd/transport-positive-depth-only'
authorJunio C Hamano <gitster@pobox.com>
Tue, 17 Dec 2013 20:03:29 +0000 (12:03 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 17 Dec 2013 20:03:29 +0000 (12:03 -0800)
"git fetch --depth=0" was a no-op, and was silently
ignored. Diagnose it as an error.

* nd/transport-positive-depth-only:
clone,fetch: catch non positive --depth option value

1  2 
builtin/clone.c
builtin/fetch.c
diff --combined builtin/clone.c
index ec4d1cd2bb5c4bb2c8c669924570f3492e018087,535b52f315ff4e2f0106974538b03c0739137c03..f98f52980d3b8f7a4700d37c486c4379a4dd15ed
@@@ -62,22 -62,23 +62,22 @@@ static struct option builtin_clone_opti
        OPT__VERBOSITY(&option_verbosity),
        OPT_BOOL(0, "progress", &option_progress,
                 N_("force progress reporting")),
 -      OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
 -                  N_("don't create a checkout")),
 -      OPT_BOOLEAN(0, "bare", &option_bare, N_("create a bare repository")),
 -      { OPTION_BOOLEAN, 0, "naked", &option_bare, NULL,
 -              N_("create a bare repository"),
 -              PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
 -      OPT_BOOLEAN(0, "mirror", &option_mirror,
 -                  N_("create a mirror repository (implies bare)")),
 +      OPT_BOOL('n', "no-checkout", &option_no_checkout,
 +               N_("don't create a checkout")),
 +      OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
 +      OPT_HIDDEN_BOOL(0, "naked", &option_bare,
 +                      N_("create a bare repository")),
 +      OPT_BOOL(0, "mirror", &option_mirror,
 +               N_("create a mirror repository (implies bare)")),
        OPT_BOOL('l', "local", &option_local,
                N_("to clone from a local repository")),
 -      OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks,
 +      OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
                    N_("don't use local hardlinks, always copy")),
 -      OPT_BOOLEAN('s', "shared", &option_shared,
 +      OPT_BOOL('s', "shared", &option_shared,
                    N_("setup as shared repository")),
 -      OPT_BOOLEAN(0, "recursive", &option_recursive,
 +      OPT_BOOL(0, "recursive", &option_recursive,
                    N_("initialize submodules in the clone")),
 -      OPT_BOOLEAN(0, "recurse-submodules", &option_recursive,
 +      OPT_BOOL(0, "recurse-submodules", &option_recursive,
                    N_("initialize submodules in the clone")),
        OPT_STRING(0, "template", &option_template, N_("template-directory"),
                   N_("directory from which templates will be used")),
@@@ -508,9 -509,9 +508,9 @@@ static void write_followtags(const stru
  {
        const struct ref *ref;
        for (ref = refs; ref; ref = ref->next) {
 -              if (prefixcmp(ref->name, "refs/tags/"))
 +              if (!starts_with(ref->name, "refs/tags/"))
                        continue;
 -              if (!suffixcmp(ref->name, "^{}"))
 +              if (ends_with(ref->name, "^{}"))
                        continue;
                if (!has_sha1_file(ref->old_sha1))
                        continue;
@@@ -556,7 -557,7 +556,7 @@@ static void update_remote_refs(const st
                                                              0, &rm, transport))
                        die(_("remote did not send all necessary objects"));
                if (transport->progress)
 -                      fprintf(stderr, _("done\n"));
 +                      fprintf(stderr, _("done.\n"));
        }
  
        if (refs) {
  static void update_head(const struct ref *our, const struct ref *remote,
                        const char *msg)
  {
 -      if (our && !prefixcmp(our->name, "refs/heads/")) {
 +      if (our && starts_with(our->name, "refs/heads/")) {
                /* Local default branch link */
                create_symref("HEAD", our->name, NULL);
                if (!option_bare) {
@@@ -625,7 -626,7 +625,7 @@@ static int checkout(void
                if (advice_detached_head)
                        detach_advice(sha1_to_hex(sha1));
        } else {
 -              if (prefixcmp(head, "refs/heads/"))
 +              if (!starts_with(head, "refs/heads/"))
                        die(_("HEAD not found below refs/heads!"));
        }
        free(head);
@@@ -796,6 -797,10 +796,10 @@@ int cmd_clone(int argc, const char **ar
        if (option_local > 0 && !is_local)
                warning(_("--local is ignored"));
  
+       /* no need to be strict, transport_set_option() will validate it again */
+       if (option_depth && atoi(option_depth) < 1)
+               die(_("depth %s is not a positive number"), option_depth);
        if (argc == 2)
                dir = xstrdup(argv[1]);
        else
diff --combined builtin/fetch.c
index e3ac84a0dd14612afdb1eca9f265767a701bc810,72930fcfdf65e4f2257ad77fdfb28c4b1741b428..1e7d617f4671c43f704afe912edac5f5dc6dc316
@@@ -30,11 -30,7 +30,11 @@@ enum 
        TAGS_SET = 2
  };
  
 -static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
 +static int fetch_prune_config = -1; /* unspecified */
 +static int prune = -1; /* unspecified */
 +#define PRUNE_BY_DEFAULT 0 /* do we prune by default? */
 +
 +static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
  static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
  static int tags = TAGS_DEFAULT, unshallow;
  static const char *depth;
@@@ -59,39 -55,30 +59,39 @@@ static int option_parse_recurse_submodu
        return 0;
  }
  
 +static int git_fetch_config(const char *k, const char *v, void *cb)
 +{
 +      if (!strcmp(k, "fetch.prune")) {
 +              fetch_prune_config = git_config_bool(k, v);
 +              return 0;
 +      }
 +      return 0;
 +}
 +
  static struct option builtin_fetch_options[] = {
        OPT__VERBOSITY(&verbosity),
 -      OPT_BOOLEAN(0, "all", &all,
 -                  N_("fetch from all remotes")),
 -      OPT_BOOLEAN('a', "append", &append,
 -                  N_("append to .git/FETCH_HEAD instead of overwriting")),
 +      OPT_BOOL(0, "all", &all,
 +               N_("fetch from all remotes")),
 +      OPT_BOOL('a', "append", &append,
 +               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")),
 -      OPT_BOOLEAN('m', "multiple", &multiple,
 -                  N_("fetch from multiple remotes")),
 +      OPT_BOOL('m', "multiple", &multiple,
 +               N_("fetch from multiple remotes")),
        OPT_SET_INT('t', "tags", &tags,
                    N_("fetch all tags and associated objects"), TAGS_SET),
        OPT_SET_INT('n', NULL, &tags,
                    N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
 -      OPT_BOOLEAN('p', "prune", &prune,
 -                  N_("prune remote-tracking branches no longer on remote")),
 +      OPT_BOOL('p', "prune", &prune,
 +               N_("prune remote-tracking branches no longer on remote")),
        { OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
                    N_("control recursive fetching of submodules"),
                    PARSE_OPT_OPTARG, option_parse_recurse_submodules },
 -      OPT_BOOLEAN(0, "dry-run", &dry_run,
 -                  N_("dry run")),
 -      OPT_BOOLEAN('k', "keep", &keep, N_("keep downloaded pack")),
 -      OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
 +      OPT_BOOL(0, "dry-run", &dry_run,
 +               N_("dry run")),
 +      OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
 +      OPT_BOOL('u', "update-head-ok", &update_head_ok,
                    N_("allow updating of HEAD ref")),
        OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
        OPT_STRING(0, "depth", &depth, N_("depth"),
@@@ -160,156 -147,48 +160,156 @@@ static void add_merge_config(struct re
        }
  }
  
 +static int add_existing(const char *refname, const unsigned char *sha1,
 +                      int flag, void *cbdata)
 +{
 +      struct string_list *list = (struct string_list *)cbdata;
 +      struct string_list_item *item = string_list_insert(list, refname);
 +      item->util = xmalloc(20);
 +      hashcpy(item->util, sha1);
 +      return 0;
 +}
 +
 +static int will_fetch(struct ref **head, const unsigned char *sha1)
 +{
 +      struct ref *rm = *head;
 +      while (rm) {
 +              if (!hashcmp(rm->old_sha1, sha1))
 +                      return 1;
 +              rm = rm->next;
 +      }
 +      return 0;
 +}
 +
  static void find_non_local_tags(struct transport *transport,
                        struct ref **head,
 -                      struct ref ***tail);
 +                      struct ref ***tail)
 +{
 +      struct string_list existing_refs = STRING_LIST_INIT_DUP;
 +      struct string_list remote_refs = STRING_LIST_INIT_NODUP;
 +      const struct ref *ref;
 +      struct string_list_item *item = NULL;
 +
 +      for_each_ref(add_existing, &existing_refs);
 +      for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
 +              if (!starts_with(ref->name, "refs/tags/"))
 +                      continue;
 +
 +              /*
 +               * The peeled ref always follows the matching base
 +               * ref, so if we see a peeled ref that we don't want
 +               * to fetch then we can mark the ref entry in the list
 +               * as one to ignore by setting util to NULL.
 +               */
 +              if (ends_with(ref->name, "^{}")) {
 +                      if (item && !has_sha1_file(ref->old_sha1) &&
 +                          !will_fetch(head, ref->old_sha1) &&
 +                          !has_sha1_file(item->util) &&
 +                          !will_fetch(head, item->util))
 +                              item->util = NULL;
 +                      item = NULL;
 +                      continue;
 +              }
 +
 +              /*
 +               * If item is non-NULL here, then we previously saw a
 +               * ref not followed by a peeled reference, so we need
 +               * to check if it is a lightweight tag that we want to
 +               * fetch.
 +               */
 +              if (item && !has_sha1_file(item->util) &&
 +                  !will_fetch(head, item->util))
 +                      item->util = NULL;
 +
 +              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))
 +                      continue;
 +
 +              item = string_list_insert(&remote_refs, ref->name);
 +              item->util = (void *)ref->old_sha1;
 +      }
 +      string_list_clear(&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(item->util) &&
 +          !will_fetch(head, item->util))
 +              item->util = NULL;
 +
 +      /*
 +       * For all the tags in the remote_refs string list,
 +       * add them to the list of refs to be fetched
 +       */
 +      for_each_string_list_item(item, &remote_refs) {
 +              /* 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);
 +                      hashcpy(rm->old_sha1, item->util);
 +                      **tail = rm;
 +                      *tail = &rm->next;
 +              }
 +      }
 +
 +      string_list_clear(&remote_refs, 0);
 +}
  
  static struct ref *get_ref_map(struct transport *transport,
 -                             struct refspec *refs, int ref_count, int tags,
 -                             int *autotags)
 +                             struct refspec *refspecs, int refspec_count,
 +                             int tags, int *autotags)
  {
        int i;
        struct ref *rm;
        struct ref *ref_map = NULL;
        struct ref **tail = &ref_map;
  
 -      const struct ref *remote_refs = transport_get_remote_refs(transport);
 +      /* opportunistically-updated references: */
 +      struct ref *orefs = NULL, **oref_tail = &orefs;
  
 -      if (ref_count || tags == TAGS_SET) {
 -              struct ref **old_tail;
 +      const struct ref *remote_refs = transport_get_remote_refs(transport);
  
 -              for (i = 0; i < ref_count; i++) {
 -                      get_fetch_map(remote_refs, &refs[i], &tail, 0);
 -                      if (refs[i].dst && refs[i].dst[0])
 +      if (refspec_count) {
 +              for (i = 0; i < refspec_count; i++) {
 +                      get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
 +                      if (refspecs[i].dst && refspecs[i].dst[0])
                                *autotags = 1;
                }
 -              /* Merge everything on the command line, but not --tags */
 +              /* Merge everything on the command line (but not --tags) */
                for (rm = ref_map; rm; rm = rm->next)
                        rm->fetch_head_status = FETCH_HEAD_MERGE;
 -              if (tags == TAGS_SET)
 -                      get_fetch_map(remote_refs, tag_refspec, &tail, 0);
  
                /*
 -               * For any refs that we happen to be fetching via command-line
 -               * arguments, take the opportunity to update their configured
 -               * counterparts. However, we do not want to mention these
 -               * entries in FETCH_HEAD at all, as they would simply be
 -               * duplicates of existing entries.
 +               * For any refs that we happen to be fetching via
 +               * command-line arguments, the destination ref might
 +               * have been missing or have been different than the
 +               * remote-tracking ref that would be derived from the
 +               * configured refspec.  In these cases, we want to
 +               * take the opportunity to update their configured
 +               * remote-tracking reference.  However, we do not want
 +               * to mention these entries in FETCH_HEAD at all, as
 +               * they would simply be duplicates of existing
 +               * entries, so we set them FETCH_HEAD_IGNORE below.
 +               *
 +               * We compute these entries now, based only on the
 +               * refspecs specified on the command line.  But we add
 +               * them to the list following the refspecs resulting
 +               * from the tags option so that one of the latter,
 +               * which has FETCH_HEAD_NOT_FOR_MERGE, is not removed
 +               * by ref_remove_duplicates() in favor of one of these
 +               * opportunistic entries with FETCH_HEAD_IGNORE.
                 */
 -              old_tail = tail;
                for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
                        get_fetch_map(ref_map, &transport->remote->fetch[i],
 -                                    &tail, 1);
 -              for (rm = *old_tail; rm; rm = rm->next)
 -                      rm->fetch_head_status = FETCH_HEAD_IGNORE;
 +                                    &oref_tail, 1);
 +
 +              if (tags == TAGS_SET)
 +                      get_fetch_map(remote_refs, tag_refspec, &tail, 0);
        } else {
                /* Use the defaults */
                struct remote *remote = transport->remote;
                        tail = &ref_map->next;
                }
        }
 -      if (tags == TAGS_DEFAULT && *autotags)
 +
 +      if (tags == TAGS_SET)
 +              /* 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);
 -      ref_remove_duplicates(ref_map);
  
 -      return ref_map;
 +      /* Now append any refs to be updated opportunistically: */
 +      *tail = orefs;
 +      for (rm = orefs; rm; rm = rm->next) {
 +              rm->fetch_head_status = FETCH_HEAD_IGNORE;
 +              tail = &rm->next;
 +      }
 +
 +      return ref_remove_duplicates(ref_map);
  }
  
  #define STORE_REF_ERROR_OTHER 1
@@@ -380,8 -249,7 +380,8 @@@ static int s_update_ref(const char *act
                rla = default_rla.buf;
        snprintf(msg, sizeof(msg), "%s: %s", rla, action);
        lock = lock_any_ref_for_update(ref->name,
 -                                     check_old ? ref->old_sha1 : NULL, 0);
 +                                     check_old ? ref->old_sha1 : NULL,
 +                                     0, NULL);
        if (!lock)
                return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
                                          STORE_REF_ERROR_OTHER;
@@@ -431,7 -299,7 +431,7 @@@ static int update_local_ref(struct ref 
        }
  
        if (!is_null_sha1(ref->old_sha1) &&
 -          !prefixcmp(ref->name, "refs/tags/")) {
 +          starts_with(ref->name, "refs/tags/")) {
                int r;
                r = s_update_ref("updating tag", ref, 0);
                strbuf_addf(display, "%c %-*s %-*s -> %s%s",
                 * more likely to follow a standard layout.
                 */
                const char *name = remote_ref ? remote_ref->name : "";
 -              if (!prefixcmp(name, "refs/tags/")) {
 +              if (starts_with(name, "refs/tags/")) {
                        msg = "storing tag";
                        what = _("[new tag]");
 -              } else if (!prefixcmp(name, "refs/heads/")) {
 +              } else if (starts_with(name, "refs/heads/")) {
                        msg = "storing head";
                        what = _("[new branch]");
                } else {
@@@ -589,15 -457,15 +589,15 @@@ static int store_updated_refs(const cha
                                kind = "";
                                what = "";
                        }
 -                      else if (!prefixcmp(rm->name, "refs/heads/")) {
 +                      else if (starts_with(rm->name, "refs/heads/")) {
                                kind = "branch";
                                what = rm->name + 11;
                        }
 -                      else if (!prefixcmp(rm->name, "refs/tags/")) {
 +                      else if (starts_with(rm->name, "refs/tags/")) {
                                kind = "tag";
                                what = rm->name + 10;
                        }
 -                      else if (!prefixcmp(rm->name, "refs/remotes/")) {
 +                      else if (starts_with(rm->name, "refs/remotes/")) {
                                kind = "remote-tracking branch";
                                what = rm->name + 13;
                        }
@@@ -730,6 -598,106 +730,6 @@@ static int prune_refs(struct refspec *r
        return result;
  }
  
 -static int add_existing(const char *refname, const unsigned char *sha1,
 -                      int flag, void *cbdata)
 -{
 -      struct string_list *list = (struct string_list *)cbdata;
 -      struct string_list_item *item = string_list_insert(list, refname);
 -      item->util = xmalloc(20);
 -      hashcpy(item->util, sha1);
 -      return 0;
 -}
 -
 -static int will_fetch(struct ref **head, const unsigned char *sha1)
 -{
 -      struct ref *rm = *head;
 -      while (rm) {
 -              if (!hashcmp(rm->old_sha1, sha1))
 -                      return 1;
 -              rm = rm->next;
 -      }
 -      return 0;
 -}
 -
 -static void find_non_local_tags(struct transport *transport,
 -                      struct ref **head,
 -                      struct ref ***tail)
 -{
 -      struct string_list existing_refs = STRING_LIST_INIT_DUP;
 -      struct string_list remote_refs = STRING_LIST_INIT_NODUP;
 -      const struct ref *ref;
 -      struct string_list_item *item = NULL;
 -
 -      for_each_ref(add_existing, &existing_refs);
 -      for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
 -              if (prefixcmp(ref->name, "refs/tags/"))
 -                      continue;
 -
 -              /*
 -               * The peeled ref always follows the matching base
 -               * ref, so if we see a peeled ref that we don't want
 -               * to fetch then we can mark the ref entry in the list
 -               * as one to ignore by setting util to NULL.
 -               */
 -              if (!suffixcmp(ref->name, "^{}")) {
 -                      if (item && !has_sha1_file(ref->old_sha1) &&
 -                          !will_fetch(head, ref->old_sha1) &&
 -                          !has_sha1_file(item->util) &&
 -                          !will_fetch(head, item->util))
 -                              item->util = NULL;
 -                      item = NULL;
 -                      continue;
 -              }
 -
 -              /*
 -               * If item is non-NULL here, then we previously saw a
 -               * ref not followed by a peeled reference, so we need
 -               * to check if it is a lightweight tag that we want to
 -               * fetch.
 -               */
 -              if (item && !has_sha1_file(item->util) &&
 -                  !will_fetch(head, item->util))
 -                      item->util = NULL;
 -
 -              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))
 -                      continue;
 -
 -              item = string_list_insert(&remote_refs, ref->name);
 -              item->util = (void *)ref->old_sha1;
 -      }
 -      string_list_clear(&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(item->util) &&
 -          !will_fetch(head, item->util))
 -              item->util = NULL;
 -
 -      /*
 -       * For all the tags in the remote_refs string list,
 -       * add them to the list of refs to be fetched
 -       */
 -      for_each_string_list_item(item, &remote_refs) {
 -              /* 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);
 -                      hashcpy(rm->old_sha1, item->util);
 -                      **tail = rm;
 -                      *tail = &rm->next;
 -              }
 -      }
 -
 -      string_list_clear(&remote_refs, 0);
 -}
 -
  static void check_not_current_branch(struct ref *ref_map)
  {
        struct branch *current_branch = branch_get(NULL);
@@@ -848,17 -816,28 +848,17 @@@ static int do_fetch(struct transport *t
                goto cleanup;
        }
        if (prune) {
 -              /* If --tags was specified, pretend the user gave us the canonical tags refspec */
 -              if (tags == TAGS_SET) {
 -                      const char *tags_str = "refs/tags/*:refs/tags/*";
 -                      struct refspec *tags_refspec, *refspec;
 -
 -                      /* Copy the refspec and add the tags to it */
 -                      refspec = xcalloc(ref_count + 1, sizeof(struct refspec));
 -                      tags_refspec = parse_fetch_refspec(1, &tags_str);
 -                      memcpy(refspec, refs, ref_count * sizeof(struct refspec));
 -                      memcpy(&refspec[ref_count], tags_refspec, sizeof(struct refspec));
 -                      ref_count++;
 -
 -                      prune_refs(refspec, ref_count, ref_map);
 -
 -                      ref_count--;
 -                      /* The rest of the strings belong to fetch_one */
 -                      free_refspec(1, tags_refspec);
 -                      free(refspec);
 -              } else if (ref_count) {
 +              /*
 +               * We only prune based on refspecs specified
 +               * explicitly (via command line or configuration); we
 +               * don't care whether --tags was specified.
 +               */
 +              if (ref_count) {
                        prune_refs(refs, ref_count, ref_map);
                } else {
 -                      prune_refs(transport->remote->fetch, transport->remote->fetch_refspec_nr, ref_map);
 +                      prune_refs(transport->remote->fetch,
 +                                 transport->remote->fetch_refspec_nr,
 +                                 ref_map);
                }
        }
        free_refs(ref_map);
@@@ -896,7 -875,7 +896,7 @@@ static int get_remote_group(const char 
  {
        struct remote_group_data *g = priv;
  
 -      if (!prefixcmp(key, "remotes.") &&
 +      if (starts_with(key, "remotes.") &&
                        !strcmp(key + 8, g->name)) {
                /* split list by white space */
                int space = strcspn(value, " \t\n");
@@@ -934,8 -913,8 +934,8 @@@ static void add_options_to_argv(struct 
  {
        if (dry_run)
                argv_array_push(argv, "--dry-run");
 -      if (prune)
 -              argv_array_push(argv, "--prune");
 +      if (prune != -1)
 +              argv_array_push(argv, prune ? "--prune" : "--no-prune");
        if (update_head_ok)
                argv_array_push(argv, "--update-head-ok");
        if (force)
@@@ -1002,17 -981,6 +1002,17 @@@ static int fetch_one(struct remote *rem
                    "remote name from which new revisions should be fetched."));
  
        gtransport = prepare_transport(remote);
 +
 +      if (prune < 0) {
 +              /* no command line request */
 +              if (0 <= gtransport->remote->prune)
 +                      prune = gtransport->remote->prune;
 +              else if (0 <= fetch_prune_config)
 +                      prune = fetch_prune_config;
 +              else
 +                      prune = PRUNE_BY_DEFAULT;
 +      }
 +
        if (argc > 0) {
                int j = 0;
                refs = xcalloc(argc + 1, sizeof(const char *));
@@@ -1062,8 -1030,6 +1062,8 @@@ int cmd_fetch(int argc, const char **ar
        for (i = 1; i < argc; i++)
                strbuf_addf(&default_rla, " %s", argv[i]);
  
 +      git_config(git_fetch_config, NULL);
 +
        argc = parse_options(argc, argv, prefix,
                             builtin_fetch_options, builtin_fetch_usage, 0);
  
                }
        }
  
+       /* no need to be strict, transport_set_option() will validate it again */
+       if (depth && atoi(depth) < 1)
+               die(_("depth %s is not a positive number"), depth);
        if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
                if (recurse_submodules_default) {
                        int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default);