Commit 19ec5923 by Colin Stolley

push: Prepare pack before sending pack header.

For large pushes, preparing the pack can take a while. Currently we
send the pack header first, followed by preparing the pack and then
finally sending the pack. Unfortunately github.com will terminate
a git-receive-pack command over http if it is idle for more than 10
seconds. This is easily exceeded for a large push, and so the push is
rejected with a Broken Pipe error.

This patch moves the pack preparation ahead of sending the pack header,
so that the timeout is avoided.

prepare_pack() can be called multiple times but will only do the work
once, so the original PREPARE_PACK call inside git_packbuilder_foreach()
remains.
parent 12b53eb0
...@@ -1308,7 +1308,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, ...@@ -1308,7 +1308,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
#define ll_find_deltas(pb, l, ls, w, d) find_deltas(pb, l, &ls, w, d) #define ll_find_deltas(pb, l, ls, w, d) find_deltas(pb, l, &ls, w, d)
#endif #endif
static int prepare_pack(git_packbuilder *pb) int prepare_pack(git_packbuilder *pb)
{ {
git_pobject **delta_list; git_pobject **delta_list;
size_t i, n = 0; size_t i, n = 0;
......
...@@ -97,5 +97,7 @@ struct git_packbuilder { ...@@ -97,5 +97,7 @@ struct git_packbuilder {
}; };
int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb); int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb);
int prepare_pack(git_packbuilder *pb);
#endif #endif
...@@ -1034,6 +1034,10 @@ int git_smart__push(git_transport *transport, git_push *push, const git_remote_c ...@@ -1034,6 +1034,10 @@ int git_smart__push(git_transport *transport, git_push *push, const git_remote_c
} }
} }
/* prepare pack before sending pack header to avoid timeouts */
if (need_pack && ((error = prepare_pack(push->pb))) < 0)
goto done;
if ((error = git_smart__get_push_stream(t, &packbuilder_payload.stream)) < 0 || if ((error = git_smart__get_push_stream(t, &packbuilder_payload.stream)) < 0 ||
(error = gen_pktline(&pktline, push)) < 0 || (error = gen_pktline(&pktline, push)) < 0 ||
(error = packbuilder_payload.stream->write(packbuilder_payload.stream, git_str_cstr(&pktline), git_str_len(&pktline))) < 0) (error = packbuilder_payload.stream->write(packbuilder_payload.stream, git_str_cstr(&pktline), git_str_len(&pktline))) < 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment