--#include "cache.h"
++#include "builtin.h"
#include "refs.h"
#include "pkt-line.h"
#include "commit.h"
#include "fetch-pack.h"
#include "remote.h"
#include "run-command.h"
++#include "transport.h"
static int transfer_unpack_limit = -1;
static int fetch_unpack_limit = -1;
static int unpack_limit = 100;
static int prefer_ofs_delta = 1;
+static int no_done = 0;
static struct fetch_pack_args args = {
/* .uploadpack = */ "git-upload-pack",
};
safe_write(fd, buf->buf, buf->len);
}
++static void insert_one_alternate_ref(const struct ref *ref, void *unused)
++{
++ rev_list_insert_ref(NULL, ref->old_sha1, 0, NULL);
++}
++
++static void insert_alternate_refs(void)
++{
++ foreach_alt_odb(refs_from_alternate_cb, insert_one_alternate_ref);
++}
++
++#define INITIAL_FLUSH 16
++#define LARGE_FLUSH 1024
++
++static int next_flush(int count)
++{
++ if (count < INITIAL_FLUSH * 2)
++ count += INITIAL_FLUSH;
++ else if (count < LARGE_FLUSH)
++ count <<= 1;
++ else
++ count += LARGE_FLUSH;
++ return count;
++}
++
static int find_common(int fd[2], unsigned char *result_sha1,
struct ref *refs)
{
int fetching;
-- int count = 0, flushes = 0, retval;
++ int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval;
const unsigned char *sha1;
unsigned in_vain = 0;
int got_continue = 0;
+ int got_ready = 0;
struct strbuf req_buf = STRBUF_INIT;
size_t state_len = 0;
marked = 1;
for_each_ref(rev_list_insert_ref, NULL);
++ insert_alternate_refs();
fetching = 0;
for ( ; refs ; refs = refs->next) {
struct strbuf c = STRBUF_INIT;
if (multi_ack == 2) strbuf_addstr(&c, " multi_ack_detailed");
if (multi_ack == 1) strbuf_addstr(&c, " multi_ack");
+ if (no_done) strbuf_addstr(&c, " no-done");
if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k");
if (use_sideband == 1) strbuf_addstr(&c, " side-band");
if (args.use_thin_pack) strbuf_addstr(&c, " thin-pack");
if (args.verbose)
fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
in_vain++;
-- if (!(31 & ++count)) {
++ if (flush_at <= ++count) {
int ack;
packet_buf_flush(&req_buf);
send_request(fd[1], &req_buf);
strbuf_setlen(&req_buf, state_len);
flushes++;
++ flush_at = next_flush(count);
/*
* We keep one window "ahead" of the other side, and
* will wait for an ACK only on the next one
*/
-- if (!args.stateless_rpc && count == 32)
++ if (!args.stateless_rpc && count == INITIAL_FLUSH)
continue;
consume_shallow_list(fd[0]);
retval = 0;
in_vain = 0;
got_continue = 1;
+ if (ack == ACK_ready) {
+ rev_list = NULL;
+ got_ready = 1;
+ }
break;
}
}
}
}
done:
- packet_buf_write(&req_buf, "done\n");
- send_request(fd[1], &req_buf);
+ if (!got_ready || !no_done) {
+ packet_buf_write(&req_buf, "done\n");
+ send_request(fd[1], &req_buf);
+ }
if (args.verbose)
fprintf(stderr, "done\n");
if (retval != 0) {
if (args.verbose)
fprintf(stderr, "Server supports multi_ack_detailed\n");
multi_ack = 2;
- no_done = 1;
+ if (server_supports("no-done")) {
+ if (args.verbose)
+ fprintf(stderr, "Server supports no-done\n");
+ + if (args.stateless_rpc)
+ + no_done = 1;
+ }
}
else if (server_supports("multi_ack")) {
if (args.verbose)
char **pack_lockfile_ptr = NULL;
struct child_process *conn;
++ packet_trace_identity("fetch-pack");
++
nr_heads = 0;
heads = NULL;
for (i = 1; i < argc; i++) {
static unsigned long oldest_have;
static int multi_ack, nr_our_refs;
+ static int no_done;
static int use_thin_pack, use_ofs_delta, use_include_tag;
static int no_progress, daemon_mode;
static int shallow_nr;
static char line[1000];
unsigned char sha1[20];
char last_hex[41];
+ int got_common = 0;
+ int got_other = 0;
+ int sent_ready = 0;
save_commit_buffer = 0;
reset_timeout();
if (!len) {
+ if (multi_ack == 2 && got_common
+ && !got_other && ok_to_give_up()) {
+ sent_ready = 1;
+ packet_write(1, "ACK %s ready\n", last_hex);
+ }
if (have_obj.nr == 0 || multi_ack)
packet_write(1, "NAK\n");
+
+ if (no_done && sent_ready) {
+ packet_write(1, "ACK %s\n", last_hex);
+ return 0;
+ }
if (stateless_rpc)
exit(0);
+ got_common = 0;
+ got_other = 0;
continue;
}
strip(line, len);
if (!prefixcmp(line, "have ")) {
switch (got_sha1(line+5, sha1)) {
case -1: /* they have what we do not */
+ got_other = 1;
if (multi_ack && ok_to_give_up()) {
const char *hex = sha1_to_hex(sha1);
- if (multi_ack == 2)
+ if (multi_ack == 2) {
+ sent_ready = 1;
packet_write(1, "ACK %s ready\n", hex);
- else
+ } else
packet_write(1, "ACK %s continue\n", hex);
}
break;
default:
+ got_common = 1;
memcpy(last_hex, sha1_to_hex(sha1), 41);
if (multi_ack == 2)
packet_write(1, "ACK %s common\n", last_hex);
multi_ack = 2;
else if (strstr(line+45, "multi_ack"))
multi_ack = 1;
+ if (strstr(line+45, "no-done"))
+ no_done = 1;
if (strstr(line+45, "thin-pack"))
use_thin_pack = 1;
if (strstr(line+45, "ofs-delta"))
{
static const char *capabilities = "multi_ack thin-pack side-band"
" side-band-64k ofs-delta shallow no-progress"
- " include-tag multi_ack_detailed no-done";
+ " include-tag multi_ack_detailed";
struct object *o = parse_object(sha1);
if (!o)
die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
if (capabilities)
-- packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname,
-- 0, capabilities);
++ packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), refname,
++ 0, capabilities,
++ stateless_rpc ? " no-done" : "");
else
packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
capabilities = NULL;
int i;
int strict = 0;
++ packet_trace_identity("upload-pack");
git_extract_argv0_path(argv[0]);
read_replace_refs = 0;