send-pack: take refspecs over stdin
Pushing a large number of refs works over most transports,
because we implement send-pack as an internal function.
However, it can sometimes fail when pushing over http,
because we have to spawn "git send-pack --stateless-rpc" to
do the heavy lifting, and we pass each refspec on the
command line. This can cause us to overflow the OS limits on
the size of the command line for a large push.
We can solve this by giving send-pack a --stdin option and
using it from remote-curl. We already dealt with this on
the fetch-pack side in 078b895
(fetch-pack: new --stdin
option to read refs from stdin, 2012-04-02). The stdin
option (and in particular, its use of packet-lines for
stateless-rpc input) is modeled after that solution.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
4109c28e05
commit
26be19ba8d
@ -110,6 +110,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
int flags;
|
||||
unsigned int reject_reasons;
|
||||
int progress = -1;
|
||||
int from_stdin = 0;
|
||||
struct push_cas_option cas = {0};
|
||||
|
||||
argv++;
|
||||
@ -169,6 +170,10 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
args.stateless_rpc = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--stdin")) {
|
||||
from_stdin = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--helper-status")) {
|
||||
helper_status = 1;
|
||||
continue;
|
||||
@ -201,6 +206,28 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
if (!dest)
|
||||
usage(send_pack_usage);
|
||||
|
||||
if (from_stdin) {
|
||||
struct argv_array all_refspecs = ARGV_ARRAY_INIT;
|
||||
|
||||
for (i = 0; i < nr_refspecs; i++)
|
||||
argv_array_push(&all_refspecs, refspecs[i]);
|
||||
|
||||
if (args.stateless_rpc) {
|
||||
const char *buf;
|
||||
while ((buf = packet_read_line(0, NULL)))
|
||||
argv_array_push(&all_refspecs, buf);
|
||||
} else {
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
while (strbuf_getline(&line, stdin, '\n') != EOF)
|
||||
argv_array_push(&all_refspecs, line.buf);
|
||||
strbuf_release(&line);
|
||||
}
|
||||
|
||||
refspecs = all_refspecs.argv;
|
||||
nr_refspecs = all_refspecs.argc;
|
||||
}
|
||||
|
||||
/*
|
||||
* --all and --mirror are incompatible; neither makes sense
|
||||
* with any refspecs.
|
||||
|
Reference in New Issue
Block a user