Merge branch 'sg/clone-initial-fetch-configuration'

Refspecs configured with "git -c var=val clone" did not propagate
to the resulting repository, which has been corrected.

* sg/clone-initial-fetch-configuration:
  Documentation/clone: document ignored configuration variables
  clone: respect additional configured fetch refspecs during initial fetch
  clone: use a more appropriate variable name for the default refspec
This commit is contained in:
Junio C Hamano 2019-01-04 13:33:34 -08:00
commit 84d178316f
3 changed files with 73 additions and 15 deletions

View File

@ -189,6 +189,12 @@ objects from the source repository into a pack in the cloned repository.
values are given for the same key, each value will be written to
the config file. This makes it safe, for example, to add
additional fetch refspecs to the origin remote.
+
Due to limitations of the current implementation, some configuration
variables do not take effect until after the initial fetch and checkout.
Configuration variables known to not take effect are:
`remote.<name>.mirror` and `remote.<name>.tagOpt`. Use the
corresponding `--mirror` and `--no-tags` options instead.
--depth <depth>::
Create a 'shallow' clone with a history truncated to the

View File

@ -548,7 +548,7 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
}
static struct ref *wanted_peer_refs(const struct ref *refs,
struct refspec_item *refspec)
struct refspec *refspec)
{
struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
struct ref *local_refs = head;
@ -569,13 +569,19 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
warning(_("Could not find remote branch %s to clone."),
option_branch);
else {
get_fetch_map(remote_head, refspec, &tail, 0);
int i;
for (i = 0; i < refspec->nr; i++)
get_fetch_map(remote_head, &refspec->items[i],
&tail, 0);
/* if --branch=tag, pull the requested tag explicitly */
get_fetch_map(remote_head, tag_refspec, &tail, 0);
}
} else
get_fetch_map(refs, refspec, &tail, 0);
} else {
int i;
for (i = 0; i < refspec->nr; i++)
get_fetch_map(refs, &refspec->items[i], &tail, 0);
}
if (!option_mirror && !option_single_branch && !option_no_tags)
get_fetch_map(refs, tag_refspec, &tail, 0);
@ -890,7 +896,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
const struct ref *our_head_points_at;
struct ref *mapped_refs;
const struct ref *ref;
struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
struct strbuf key = STRBUF_INIT;
struct strbuf default_refspec = STRBUF_INIT;
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
struct transport *transport = NULL;
const char *src_ref_prefix = "refs/heads/";
@ -898,7 +905,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
int err = 0, complete_refs_before_fetch = 1;
int submodule_progress;
struct refspec rs = REFSPEC_INIT_FETCH;
struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
fetch_if_missing = 0;
@ -1067,7 +1073,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
}
strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
strbuf_addf(&key, "remote.%s.url", option_origin);
git_config_set(key.buf, repo);
strbuf_reset(&key);
@ -1081,11 +1086,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_required_reference.nr || option_optional_reference.nr)
setup_reference();
refspec_append(&rs, value.buf);
strbuf_reset(&value);
remote = remote_get(option_origin);
strbuf_addf(&default_refspec, "+%s*:%s*", src_ref_prefix,
branch_top.buf);
refspec_append(&remote->fetch, default_refspec.buf);
transport = transport_get(remote, remote->url[0]);
transport_set_verbosity(transport, option_verbosity, option_progress);
transport->family = family;
@ -1140,7 +1146,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
argv_array_push(&ref_prefixes, "HEAD");
refspec_ref_prefixes(&rs, &ref_prefixes);
refspec_ref_prefixes(&remote->fetch, &ref_prefixes);
if (option_branch)
expand_ref_prefix(&ref_prefixes, option_branch);
if (!option_no_tags)
@ -1149,7 +1155,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
refs = transport_get_remote_refs(transport, &ref_prefixes);
if (refs) {
mapped_refs = wanted_peer_refs(refs, &rs.items[0]);
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
/*
* transport_get_remote_refs() may return refs with null sha-1
* in mapped_refs (see struct transport->get_refs_list
@ -1240,10 +1246,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_release(&reflog_msg);
strbuf_release(&branch_top);
strbuf_release(&key);
strbuf_release(&value);
strbuf_release(&default_refspec);
junk_mode = JUNK_LEAVE_ALL;
refspec_clear(&rs);
argv_array_clear(&ref_prefixes);
return err;
}

View File

@ -45,6 +45,53 @@ test_expect_success 'clone -c config is available during clone' '
test_cmp expect child/file
'
test_expect_success 'clone -c remote.origin.fetch=<refspec> works' '
rm -rf child &&
git update-ref refs/grab/it refs/heads/master &&
git update-ref refs/leave/out refs/heads/master &&
git clone -c "remote.origin.fetch=+refs/grab/*:refs/grab/*" . child &&
git -C child for-each-ref --format="%(refname)" >actual &&
cat >expect <<-\EOF &&
refs/grab/it
refs/heads/master
refs/remotes/origin/HEAD
refs/remotes/origin/master
EOF
test_cmp expect actual
'
test_expect_success 'git -c remote.origin.fetch=<refspec> clone works' '
rm -rf child &&
git -c "remote.origin.fetch=+refs/grab/*:refs/grab/*" clone . child &&
git -C child for-each-ref --format="%(refname)" >actual &&
cat >expect <<-\EOF &&
refs/grab/it
refs/heads/master
refs/remotes/origin/HEAD
refs/remotes/origin/master
EOF
test_cmp expect actual
'
test_expect_success 'clone -c remote.<remote>.fetch=<refspec> --origin=<name>' '
rm -rf child &&
git clone --origin=upstream \
-c "remote.upstream.fetch=+refs/grab/*:refs/grab/*" \
-c "remote.origin.fetch=+refs/leave/*:refs/leave/*" \
. child &&
git -C child for-each-ref --format="%(refname)" >actual &&
cat >expect <<-\EOF &&
refs/grab/it
refs/heads/master
refs/remotes/upstream/HEAD
refs/remotes/upstream/master
EOF
test_cmp expect actual
'
# Tests for the hidden file attribute on windows
is_hidden () {
# Use the output of `attrib`, ignore the absolute path