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>

Nguyễn Thái Ngọc Duy committed Jan 16, 2012 at 16:46 UTC 6f48d39fa4d3e364c81d3cbbbd656c804b9ec873
2 files changed +31 -28
builtin/clone.c
+27 -27
@@ -364,13 +364,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
364 closedir(dir);
365 }
366
367 -static const struct ref *clone_local(const char *src_repo,
368 - const char *dest_repo)
367 +static void clone_local(const char *src_repo, const char *dest_repo)
368 {
370 - const struct ref *ret;
371 - struct remote *remote;
372 - struct transport *transport;
373 -
369 if (option_shared) {
370 struct strbuf alt = STRBUF_INIT;
371 strbuf_addf(&alt, "%s/objects", src_repo);
@@ -386,13 +381,8 @@ static const struct ref *clone_local(const char *src_repo,
381 strbuf_release(&dest);
382 }
383
389 - remote = remote_get(src_repo);
390 - transport = transport_get(remote, src_repo);
391 - ret = transport_get_remote_refs(transport);
392 - transport_disconnect(transport);
384 if (0 <= option_verbosity)
385 printf(_("done.\n"));
395 - return ret;
386 }
387
388 static const char *junk_work_tree;
@@ -619,6 +609,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
609 struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
610 struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
611 struct transport *transport = NULL;
612 + struct remote *remote;
613 int err = 0;
614
615 struct refspec *refspec;
@@ -773,13 +764,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
764
765 strbuf_reset(&value);
766
776 - if (is_local) {
777 - refs = clone_local(path, git_dir);
778 - mapped_refs = wanted_peer_refs(refs, refspec);
779 - } else {
780 - struct remote *remote = remote_get(option_origin);
781 - transport = transport_get(remote, remote->url[0]);
767 + remote = remote_get(option_origin);
768 + transport = transport_get(remote, remote->url[0]);
769
770 + if (!is_local) {
771 if (!transport->get_refs_list || !transport->fetch)
772 die(_("Don't know how to clone %s"), transport->url);
773
@@ -796,14 +784,23 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
784 if (option_upload_pack)
785 transport_set_option(transport, TRANS_OPT_UPLOADPACK,
786 option_upload_pack);
799 -
800 - refs = transport_get_remote_refs(transport);
801 - if (refs) {
802 - mapped_refs = wanted_peer_refs(refs, refspec);
803 - transport_fetch_refs(transport, mapped_refs);
804 - }
787 }
788
789 + refs = transport_get_remote_refs(transport);
790 + mapped_refs = refs ? wanted_peer_refs(refs, refspec) : NULL;
791 +
792 + /*
793 + * mapped_refs may be updated if transport-helper is used so
794 + * we need fetch it early because remote_head code below
795 + * relies on it.
796 + *
797 + * for normal clones, transport_get_remote_refs() should
798 + * return reliable ref set, we can delay cloning until after
799 + * remote HEAD check.
800 + */
801 + if (!is_local && remote->foreign_vcs && refs)
802 + transport_fetch_refs(transport, mapped_refs);
803 +
804 if (refs) {
805 remote_head = find_ref_by_name(refs, "HEAD");
806 remote_head_points_at =
@@ -838,15 +835,18 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
835 "refs/heads/master");
836 }
837
838 + if (is_local)
839 + clone_local(path, git_dir);
840 + else if (refs && !remote->foreign_vcs)
841 + transport_fetch_refs(transport, mapped_refs);
842 +
843 update_remote_refs(refs, mapped_refs, remote_head_points_at,
844 branch_top.buf, reflog_msg.buf);
845
846 update_head(our_head_points_at, remote_head, reflog_msg.buf);
847
846 - if (transport) {
847 - transport_unlock_pack(transport);
848 - transport_disconnect(transport);
849 - }
848 + transport_unlock_pack(transport);
849 + transport_disconnect(transport);
850
851 err = checkout();
852
transport.c
+4 -1
@@ -895,8 +895,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
895
896 while (is_urlschemechar(p == url, *p))
897 p++;
898 - if (!prefixcmp(p, "::"))
898 + if (!prefixcmp(p, "::")) {
899 helper = xstrndup(url, p - url);
900 + remote->foreign_vcs = helper;
901 + }
902 }
903
904 if (helper) {
@@ -938,6 +940,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
940 char *handler = xmalloc(len + 1);
941 handler[len] = 0;
942 strncpy(handler, url, len);
943 + remote->foreign_vcs = handler;
944 transport_helper_init(ret, handler);
945 }
946