#define SEEN (1U << 3)
#define POPPED (1U << 4)
-static struct commit_list *rev_list = NULL;
-static int non_common_revs = 0, multi_ack = 0, use_thin_pack = 0;
+/*
+ * After sending this many "have"s if we do not get any new ACK , we
+ * give up traversing our history.
+ */
+#define MAX_IN_VAIN 256
+
+static struct commit_list *rev_list;
+static int non_common_revs, multi_ack, use_thin_pack, use_sideband;
static void rev_list_push(struct commit *commit, int mark)
{
}
}
-static int rev_list_insert_ref(const char *path, const unsigned char *sha1)
+static int rev_list_insert_ref(const char *path, const unsigned char *sha1, void *cb_data)
{
struct object *o = deref_tag(parse_object(sha1), path, 0);
- if (o && o->type == commit_type)
+ if (o && o->type == OBJ_COMMIT)
rev_list_push((struct commit *)o, SEEN);
return 0;
int fetching;
int count = 0, flushes = 0, retval;
const unsigned char *sha1;
+ unsigned in_vain = 0;
+ int got_continue = 0;
- for_each_ref(rev_list_insert_ref);
+ for_each_ref(rev_list_insert_ref, NULL);
fetching = 0;
for ( ; refs ; refs = refs->next) {
continue;
}
- packet_write(fd[1], "want %s%s%s\n", sha1_to_hex(remote),
- (multi_ack ? " multi_ack" : ""),
- (use_thin_pack ? " thin-pack" : ""));
+ if (!fetching)
+ packet_write(fd[1], "want %s%s%s%s%s\n",
+ sha1_to_hex(remote),
+ (multi_ack ? " multi_ack" : ""),
+ (use_sideband == 2 ? " side-band-64k" : ""),
+ (use_sideband == 1 ? " side-band" : ""),
+ (use_thin_pack ? " thin-pack" : ""));
+ else
+ packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
fetching++;
}
packet_flush(fd[1]);
packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
if (verbose)
fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
+ in_vain++;
if (!(31 & ++count)) {
int ack;
lookup_commit(result_sha1);
mark_common(commit, 0, 1);
retval = 0;
+ in_vain = 0;
+ got_continue = 1;
}
} while (ack);
flushes--;
+ if (got_continue && MAX_IN_VAIN < in_vain) {
+ if (verbose)
+ fprintf(stderr, "giving up\n");
+ break; /* give up */
+ }
}
}
done:
return retval;
}
-static struct commit_list *complete = NULL;
+static struct commit_list *complete;
-static int mark_complete(const char *path, const unsigned char *sha1)
+static int mark_complete(const char *path, const unsigned char *sha1, void *cb_data)
{
struct object *o = parse_object(sha1);
- while (o && o->type == tag_type) {
+ while (o && o->type == OBJ_TAG) {
struct tag *t = (struct tag *) o;
if (!t->tagged)
break; /* broken repository */
o->flags |= COMPLETE;
o = parse_object(t->tagged->sha1);
}
- if (o && o->type == commit_type) {
+ if (o && o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o;
commit->object.flags |= COMPLETE;
insert_by_date(commit, &complete);
* in sync with the other side at some time after
* that (it is OK if we guess wrong here).
*/
- if (o->type == commit_type) {
+ if (o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o;
if (!cutoff || cutoff < commit->date)
cutoff = commit->date;
}
}
- for_each_ref(mark_complete);
+ for_each_ref(mark_complete, NULL);
if (cutoff)
mark_recent_complete_commits(cutoff);
struct object *o = deref_tag(lookup_object(ref->old_sha1),
NULL, 0);
- if (!o || o->type != commit_type || !(o->flags & COMPLETE))
+ if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
continue;
if (!(o->flags & SEEN)) {
continue;
}
- memcpy(ref->new_sha1, local, 20);
+ hashcpy(ref->new_sha1, local);
if (!verbose)
continue;
fprintf(stderr,
fprintf(stderr, "Server supports multi_ack\n");
multi_ack = 1;
}
+ if (server_supports("side-band-64k")) {
+ if (verbose)
+ fprintf(stderr, "Server supports side-band-64k\n");
+ use_sideband = 2;
+ }
+ else if (server_supports("side-band")) {
+ if (verbose)
+ fprintf(stderr, "Server supports side-band\n");
+ use_sideband = 1;
+ }
if (!ref) {
packet_flush(fd[1]);
die("no matching remote head");
fprintf(stderr, "warning: no common commits\n");
if (keep_pack)
- status = receive_keep_pack(fd, "git-fetch-pack", quiet);
+ status = receive_keep_pack(fd, "git-fetch-pack", quiet, use_sideband);
else
- status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
+ status = receive_unpack_pack(fd, "git-fetch-pack", quiet, use_sideband);
if (status)
die("git-fetch-pack: fetch failed.");
ret = fetch_pack(fd, nr_heads, heads);
close(fd[0]);
close(fd[1]);
- finish_connect(pid);
+ ret |= finish_connect(pid);
if (!ret && nr_heads) {
/* If the heads to pull were given, we should have
}
}
- return ret;
+ return !!ret;
}