If a remote repo has too many tags (or branches), cloning it over the smart HTTP transport can fail because remote-curl.c puts all the refs from the remote repo on the fetch-pack command line. This can make the command line longer than the global OS command line limit, causing fetch-pack to fail. This is especially a problem on Windows where the command line limit is orders of magnitude shorter than Linux. There are already real repos out there that msysGit cannot clone over smart HTTP due to this problem. To solve this problem we teach remote-curl.c to pipe the refs to fetch-pack using the new --stdin option, instead of on the fetch-pack command line. For a more detailed discussion of the problem see the parent of this commit, titled "fetch-pack: new --stdin option to read refs from stdin". --- remote-curl.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/remote-curl.c b/remote-curl.c index d159fe7f34..52c21433c7 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -290,6 +290,7 @@ static void output_refs(struct ref *refs) struct rpc_state { const char *service_name; const char **argv; + struct strbuf *stdin_preamble; char *service_url; char *hdr_content_type; char *hdr_accept; @@ -535,6 +536,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads) { const char *svc = rpc->service_name; struct strbuf buf = STRBUF_INIT; + struct strbuf *preamble = rpc->stdin_preamble; struct child_process client; int err = 0; @@ -545,6 +547,8 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads) client.argv = rpc->argv; if (start_command(&client)) exit(1); + if (preamble) + write_or_die(client.in, preamble->buf, preamble->len); if (heads) write_or_die(client.in, heads->buf, heads->len); @@ -626,6 +630,7 @@ static int fetch_git(struct discovery *heads, int nr_heads, struct ref **to_fetch) { struct rpc_state rpc; + struct strbuf preamble; char *depth_arg = NULL; const char **argv; int argc = 0, i, err; @@ -633,6 +638,7 @@ static int fetch_git(struct discovery *heads, argv = xmalloc((15 + nr_heads) * sizeof(char*)); argv[argc++] = "fetch-pack"; argv[argc++] = "--stateless-rpc"; + argv[argc++] = "--stdin"; argv[argc++] = "--lock-pack"; if (options.followtags) argv[argc++] = "--include-tag"; @@ -651,23 +657,28 @@ static int fetch_git(struct discovery *heads, argv[argc++] = depth_arg; } argv[argc++] = url; + argv[argc++] = NULL; + + strbuf_init(&preamble, 4); for (i = 0; i < nr_heads; i++) { struct ref *ref = to_fetch[i]; if (!ref->name || !*ref->name) die("cannot fetch by sha1 over smart http"); - argv[argc++] = ref->name; + packet_buf_write(&preamble, "%s\n", ref->name); } - argv[argc++] = NULL; + packet_buf_flush(&preamble); memset(&rpc, 0, sizeof(rpc)); rpc.service_name = "git-upload-pack", rpc.argv = argv; + rpc.stdin_preamble = &preamble; rpc.gzip_request = 1; err = rpc_service(&rpc, heads); if (rpc.result.len) safe_write(1, rpc.result.buf, rpc.result.len); strbuf_release(&rpc.result); + strbuf_release(&preamble); free(argv); free(depth_arg); return err; -- 1.7.9.5.4.g4f508 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html