diff options
Diffstat (limited to 'builtin/clone.c')
-rw-r--r-- | builtin/clone.c | 88 |
1 files changed, 68 insertions, 20 deletions
diff --git a/builtin/clone.c b/builtin/clone.c index 391aa41075..e335734b4c 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -53,6 +53,7 @@ static int option_shallow_submodules; static int deepen; static char *option_template, *option_depth, *option_since; static char *option_origin = NULL; +static char *remote_name = NULL; static char *option_branch = NULL; static struct string_list option_not = STRING_LIST_INIT_NODUP; static const char *real_git_dir; @@ -721,7 +722,7 @@ static void update_head(const struct ref *our, const struct ref *remote, if (!option_bare) { update_ref(msg, "HEAD", &our->old_oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR); - install_branch_config(0, head, option_origin, our->name); + install_branch_config(0, head, remote_name, our->name); } } else if (our) { struct commit *c = lookup_commit_reference(the_repository, @@ -851,8 +852,26 @@ static int checkout(int submodule_progress) return err; } +static int git_clone_config(const char *k, const char *v, void *cb) +{ + if (!strcmp(k, "clone.defaultremotename")) { + free(remote_name); + remote_name = xstrdup(v); + } + return git_default_config(k, v, cb); +} + static int write_one_config(const char *key, const char *value, void *data) { + /* + * give git_clone_config a chance to write config values back to the + * environment, since git_config_set_multivar_gently only deals with + * config-file writes + */ + int apply_failed = git_clone_config(key, value, data); + if (apply_failed) + return apply_failed; + return git_config_set_multivar_gently(key, value ? value : "true", CONFIG_REGEX_NONE, 0); @@ -905,12 +924,12 @@ static void write_refspec_config(const char *src_ref_prefix, } /* Configure the remote */ if (value.len) { - strbuf_addf(&key, "remote.%s.fetch", option_origin); + strbuf_addf(&key, "remote.%s.fetch", remote_name); git_config_set_multivar(key.buf, value.buf, "^$", 0); strbuf_reset(&key); if (option_mirror) { - strbuf_addf(&key, "remote.%s.mirror", option_origin); + strbuf_addf(&key, "remote.%s.mirror", remote_name); git_config_set(key.buf, "true"); strbuf_reset(&key); } @@ -963,6 +982,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix) struct strvec ref_prefixes = STRVEC_INIT; packet_trace_identity("clone"); + + git_config(git_clone_config, NULL); + argc = parse_options(argc, argv, prefix, builtin_clone_options, builtin_clone_usage, 0); @@ -991,9 +1013,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) option_no_checkout = 1; } - if (!option_origin) - option_origin = "origin"; - repo_name = argv[0]; path = get_repo_path(repo_name, &is_bundle); @@ -1124,9 +1143,30 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (real_git_dir) git_dir = real_git_dir; + /* + * additional config can be injected with -c, make sure it's included + * after init_db, which clears the entire config environment. + */ write_config(&option_config); - git_config(git_default_config, NULL); + /* + * re-read config after init_db and write_config to pick up any config + * injected by --template and --config, respectively. + */ + git_config(git_clone_config, NULL); + + /* + * apply the remote name provided by --origin only after this second + * call to git_config, to ensure it overrides all config-based values. + */ + if (option_origin != NULL) + remote_name = xstrdup(option_origin); + + if (remote_name == NULL) + remote_name = xstrdup("origin"); + + if (!valid_remote_name(remote_name)) + die(_("'%s' is not a valid remote name"), remote_name); if (option_bare) { if (option_mirror) @@ -1135,15 +1175,15 @@ int cmd_clone(int argc, const char **argv, const char *prefix) git_config_set("core.bare", "true"); } else { - strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin); + strbuf_addf(&branch_top, "refs/remotes/%s/", remote_name); } - strbuf_addf(&key, "remote.%s.url", option_origin); + strbuf_addf(&key, "remote.%s.url", remote_name); git_config_set(key.buf, repo); strbuf_reset(&key); if (option_no_tags) { - strbuf_addf(&key, "remote.%s.tagOpt", option_origin); + strbuf_addf(&key, "remote.%s.tagOpt", remote_name); git_config_set(key.buf, "--no-tags"); strbuf_reset(&key); } @@ -1154,7 +1194,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_sparse_checkout && git_sparse_checkout_init(dir)) return 1; - remote = remote_get(option_origin); + remote = remote_get(remote_name); refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix, branch_top.buf); @@ -1253,8 +1293,11 @@ int cmd_clone(int argc, const char **argv, const char *prefix) break; } - if (!is_local && !complete_refs_before_fetch) - transport_fetch_refs(transport, mapped_refs); + if (!is_local && !complete_refs_before_fetch) { + err = transport_fetch_refs(transport, mapped_refs); + if (err) + goto cleanup; + } remote_head = find_ref_by_name(refs, "HEAD"); remote_head_points_at = @@ -1266,7 +1309,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (!our_head_points_at) die(_("Remote branch %s not found in upstream %s"), - option_branch, option_origin); + option_branch, remote_name); } else our_head_points_at = remote_head_points_at; @@ -1274,7 +1317,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) else { if (option_branch) die(_("Remote branch %s not found in upstream %s"), - option_branch, option_origin); + option_branch, remote_name); warning(_("You appear to have cloned an empty repository.")); mapped_refs = NULL; @@ -1283,10 +1326,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) remote_head = NULL; option_no_checkout = 1; if (!option_bare) { - const char *branch = git_default_branch_name(); + const char *branch = git_default_branch_name(0); char *ref = xstrfmt("refs/heads/%s", branch); - install_branch_config(0, branch, option_origin, ref); + install_branch_config(0, branch, remote_name, ref); free(ref); } } @@ -1295,12 +1338,15 @@ int cmd_clone(int argc, const char **argv, const char *prefix) remote_head_points_at, &branch_top); if (filter_options.choice) - partial_clone_register(option_origin, &filter_options); + partial_clone_register(remote_name, &filter_options); if (is_local) clone_local(path, git_dir); - else if (refs && complete_refs_before_fetch) - transport_fetch_refs(transport, mapped_refs); + else if (refs && complete_refs_before_fetch) { + err = transport_fetch_refs(transport, mapped_refs); + if (err) + goto cleanup; + } update_remote_refs(refs, mapped_refs, remote_head_points_at, branch_top.buf, reflog_msg.buf, transport, @@ -1327,6 +1373,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) junk_mode = JUNK_LEAVE_REPO; err = checkout(submodule_progress); +cleanup: + free(remote_name); strbuf_release(&reflog_msg); strbuf_release(&branch_top); strbuf_release(&key); |