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