clone: delay cloning until after remote HEAD checking

This gives us an opportunity to abort the command during remote HEAD
check without wasting much bandwidth.

Cloning with remote-helper remains before the check because the remote
helper updates mapped_refs, which is necessary for remote ref checks.
foreign_vcs field is used to indicate the transport is handled by
remote helper.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy
2012-01-16 16:46:12 +07:00
committed by Junio C Hamano
parent 960b7d1c62
commit 6f48d39fa4
2 changed files with 31 additions and 28 deletions

View File

@ -364,13 +364,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
closedir(dir); closedir(dir);
} }
static const struct ref *clone_local(const char *src_repo, static void clone_local(const char *src_repo, const char *dest_repo)
const char *dest_repo)
{ {
const struct ref *ret;
struct remote *remote;
struct transport *transport;
if (option_shared) { if (option_shared) {
struct strbuf alt = STRBUF_INIT; struct strbuf alt = STRBUF_INIT;
strbuf_addf(&alt, "%s/objects", src_repo); strbuf_addf(&alt, "%s/objects", src_repo);
@ -386,13 +381,8 @@ static const struct ref *clone_local(const char *src_repo,
strbuf_release(&dest); strbuf_release(&dest);
} }
remote = remote_get(src_repo);
transport = transport_get(remote, src_repo);
ret = transport_get_remote_refs(transport);
transport_disconnect(transport);
if (0 <= option_verbosity) if (0 <= option_verbosity)
printf(_("done.\n")); printf(_("done.\n"));
return ret;
} }
static const char *junk_work_tree; static const char *junk_work_tree;
@ -619,6 +609,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
struct strbuf key = STRBUF_INIT, value = STRBUF_INIT; struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT; struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
struct transport *transport = NULL; struct transport *transport = NULL;
struct remote *remote;
int err = 0; int err = 0;
struct refspec *refspec; struct refspec *refspec;
@ -773,13 +764,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_reset(&value); strbuf_reset(&value);
if (is_local) { remote = remote_get(option_origin);
refs = clone_local(path, git_dir);
mapped_refs = wanted_peer_refs(refs, refspec);
} else {
struct remote *remote = remote_get(option_origin);
transport = transport_get(remote, remote->url[0]); transport = transport_get(remote, remote->url[0]);
if (!is_local) {
if (!transport->get_refs_list || !transport->fetch) if (!transport->get_refs_list || !transport->fetch)
die(_("Don't know how to clone %s"), transport->url); die(_("Don't know how to clone %s"), transport->url);
@ -796,13 +784,22 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_upload_pack) if (option_upload_pack)
transport_set_option(transport, TRANS_OPT_UPLOADPACK, transport_set_option(transport, TRANS_OPT_UPLOADPACK,
option_upload_pack); option_upload_pack);
}
refs = transport_get_remote_refs(transport); refs = transport_get_remote_refs(transport);
if (refs) { mapped_refs = refs ? wanted_peer_refs(refs, refspec) : NULL;
mapped_refs = wanted_peer_refs(refs, refspec);
/*
* mapped_refs may be updated if transport-helper is used so
* we need fetch it early because remote_head code below
* relies on it.
*
* for normal clones, transport_get_remote_refs() should
* return reliable ref set, we can delay cloning until after
* remote HEAD check.
*/
if (!is_local && remote->foreign_vcs && refs)
transport_fetch_refs(transport, mapped_refs); transport_fetch_refs(transport, mapped_refs);
}
}
if (refs) { if (refs) {
remote_head = find_ref_by_name(refs, "HEAD"); remote_head = find_ref_by_name(refs, "HEAD");
@ -838,15 +835,18 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
"refs/heads/master"); "refs/heads/master");
} }
if (is_local)
clone_local(path, git_dir);
else if (refs && !remote->foreign_vcs)
transport_fetch_refs(transport, mapped_refs);
update_remote_refs(refs, mapped_refs, remote_head_points_at, update_remote_refs(refs, mapped_refs, remote_head_points_at,
branch_top.buf, reflog_msg.buf); branch_top.buf, reflog_msg.buf);
update_head(our_head_points_at, remote_head, reflog_msg.buf); update_head(our_head_points_at, remote_head, reflog_msg.buf);
if (transport) {
transport_unlock_pack(transport); transport_unlock_pack(transport);
transport_disconnect(transport); transport_disconnect(transport);
}
err = checkout(); err = checkout();

View File

@ -895,8 +895,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
while (is_urlschemechar(p == url, *p)) while (is_urlschemechar(p == url, *p))
p++; p++;
if (!prefixcmp(p, "::")) if (!prefixcmp(p, "::")) {
helper = xstrndup(url, p - url); helper = xstrndup(url, p - url);
remote->foreign_vcs = helper;
}
} }
if (helper) { if (helper) {
@ -938,6 +940,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
char *handler = xmalloc(len + 1); char *handler = xmalloc(len + 1);
handler[len] = 0; handler[len] = 0;
strncpy(handler, url, len); strncpy(handler, url, len);
remote->foreign_vcs = handler;
transport_helper_init(ret, handler); transport_helper_init(ret, handler);
} }