summaryrefslogtreecommitdiff
path: root/remote-curl.c
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2009-10-30 17:47:28 -0700
committerJunio C Hamano <gitster@pobox.com>2009-10-30 19:20:54 -0700
commit292ce46b60e2c12450c5c21044acf9c41bd837df (patch)
tree0db25466b9bc4f695240b1b9b0e79bfec30d9c4b /remote-curl.c
parentcff7123c11aa2b1a849a46028d60b4bc0ab54c51 (diff)
downloadgit-292ce46b60e2c12450c5c21044acf9c41bd837df.tar.gz
remote-helpers: Fetch more than one ref in a batch
Some network protocols (e.g. native git://) are able to fetch more than one ref at a time and reduce the overall transfer cost by combining the requests into a single exchange. Instead of feeding each fetch request one at a time to the helper, feed all of them at once so the helper can decide whether or not it should batch them. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> CC: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'remote-curl.c')
-rw-r--r--remote-curl.c88
1 files changed, 77 insertions, 11 deletions
diff --git a/remote-curl.c b/remote-curl.c
index 478f3ea7d3..22cd5c5fd2 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -87,6 +87,81 @@ static struct ref *get_refs(void)
return refs;
}
+static int fetch_dumb(int nr_heads, struct ref **to_fetch)
+{
+ char **targets = xmalloc(nr_heads * sizeof(char*));
+ int ret, i;
+
+ for (i = 0; i < nr_heads; i++)
+ targets[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1));
+
+ init_walker();
+ walker->get_all = 1;
+ walker->get_tree = 1;
+ walker->get_history = 1;
+ walker->get_verbosely = 0;
+ walker->get_recover = 0;
+ ret = walker_fetch(walker, nr_heads, targets, NULL, NULL);
+
+ for (i = 0; i < nr_heads; i++)
+ free(targets[i]);
+ free(targets);
+
+ return ret ? error("Fetch failed.") : 0;
+}
+
+static void parse_fetch(struct strbuf *buf)
+{
+ struct ref **to_fetch = NULL;
+ struct ref *list_head = NULL;
+ struct ref **list = &list_head;
+ int alloc_heads = 0, nr_heads = 0;
+
+ do {
+ if (!prefixcmp(buf->buf, "fetch ")) {
+ char *p = buf->buf + strlen("fetch ");
+ char *name;
+ struct ref *ref;
+ unsigned char old_sha1[20];
+
+ if (strlen(p) < 40 || get_sha1_hex(p, old_sha1))
+ die("protocol error: expected sha/ref, got %s'", p);
+ if (p[40] == ' ')
+ name = p + 41;
+ else if (!p[40])
+ name = "";
+ else
+ die("protocol error: expected sha/ref, got %s'", p);
+
+ ref = alloc_ref(name);
+ hashcpy(ref->old_sha1, old_sha1);
+
+ *list = ref;
+ list = &ref->next;
+
+ ALLOC_GROW(to_fetch, nr_heads + 1, alloc_heads);
+ to_fetch[nr_heads++] = ref;
+ }
+ else
+ die("http transport does not support %s", buf->buf);
+
+ strbuf_reset(buf);
+ if (strbuf_getline(buf, stdin, '\n') == EOF)
+ return;
+ if (!*buf->buf)
+ break;
+ } while (1);
+
+ if (fetch_dumb(nr_heads, to_fetch))
+ exit(128); /* error already reported */
+ free_refs(list_head);
+ free(to_fetch);
+
+ printf("\n");
+ fflush(stdout);
+ strbuf_reset(buf);
+}
+
int main(int argc, const char **argv)
{
struct strbuf buf = STRBUF_INIT;
@@ -110,17 +185,8 @@ int main(int argc, const char **argv)
if (strbuf_getline(&buf, stdin, '\n') == EOF)
break;
if (!prefixcmp(buf.buf, "fetch ")) {
- char *obj = buf.buf + strlen("fetch ");
- init_walker();
- walker->get_all = 1;
- walker->get_tree = 1;
- walker->get_history = 1;
- walker->get_verbosely = 0;
- walker->get_recover = 0;
- if (walker_fetch(walker, 1, &obj, NULL, NULL))
- die("Fetch failed.");
- printf("\n");
- fflush(stdout);
+ parse_fetch(&buf);
+
} else if (!strcmp(buf.buf, "list")) {
struct ref *refs = get_refs();
struct ref *posn;