Code

git-fetch-pack: Implement client part of the multi_ack extension
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>
Sun, 23 Oct 2005 01:40:13 +0000 (03:40 +0200)
committerJunio C Hamano <junkio@cox.net>
Mon, 24 Oct 2005 22:13:37 +0000 (15:13 -0700)
This patch concludes the series, which makes
git-fetch-pack/git-upload-pack negotiate a potentially better set of
common revs. It should make a difference when fetching from a repository
with a few branches.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
connect.c
fetch-pack.c

index b171c5dbc8c9ecc32f6738d17c339858cbbf76f1..57e25a34bcd7cfc8aa0f2694286c5e9cb3b145ae 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -59,8 +59,11 @@ int get_ack(int fd, unsigned char *result_sha1)
        if (!strcmp(line, "NAK"))
                return 0;
        if (!strncmp(line, "ACK ", 3)) {
-               if (!get_sha1_hex(line+4, result_sha1))
+               if (!get_sha1_hex(line+4, result_sha1)) {
+                       if (strstr(line+45, "continue"))
+                               return 2;
                        return 1;
+               }
        }
        die("git-fetch_pack: expected ACK/NAK, got '%s'", line);
 }
index 3a903c4f9092d914aaa754067eed74ff7efd09e6..57602b9561160a3ff14b893a92d69b46c1ffa9df 100644 (file)
@@ -125,7 +125,7 @@ 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, multi_ack = 0, retval;
        const unsigned char *sha1;
 
        for_each_ref(rev_list_append_sha1);
@@ -156,20 +156,22 @@ static int find_common(int fd[2], unsigned char *result_sha1,
                        continue;
                }
 
-               packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
+               packet_write(fd[1], "want %s multi_ack\n", sha1_to_hex(remote));
                fetching++;
        }
        packet_flush(fd[1]);
        if (!fetching)
                return 1;
 
-       flushes = 1;
+       flushes = 0;
        retval = -1;
        while ((sha1 = get_rev())) {
                packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
                if (verbose)
                        fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
                if (!(31 & ++count)) {
+                       int ack;
+
                        packet_flush(fd[1]);
                        flushes++;
 
@@ -179,26 +181,48 @@ static int find_common(int fd[2], unsigned char *result_sha1,
                         */
                        if (count == 32)
                                continue;
-                       if (get_ack(fd[0], result_sha1)) {
-                               flushes = 0;
-                               retval = 0;
-                               if (verbose)
-                                       fprintf(stderr, "got ack\n");
-                               break;
-                       }
+
+                       do {
+                               ack = get_ack(fd[0], result_sha1);
+                               if (verbose && ack)
+                                       fprintf(stderr, "got ack %d %s\n", ack,
+                                                       sha1_to_hex(result_sha1));
+                               if (ack == 1) {
+                                       if (!multi_ack)
+                                               flushes = 0;
+                                       retval = 0;
+                                       goto done;
+                               } else if (ack == 2) {
+                                       multi_ack = 1;
+                                       mark_common((struct commit *)
+                                                       lookup_object(result_sha1));
+                                       retval = 0;
+                               }
+                       } while(ack);
                        flushes--;
                }
        }
+done:
+       if (multi_ack) {
+               packet_flush(fd[1]);
+               flushes++;
+       }
        packet_write(fd[1], "done\n");
        if (verbose)
                fprintf(stderr, "done\n");
+       if (retval != 0)
+               flushes++;
        while (flushes) {
-               flushes--;
                if (get_ack(fd[0], result_sha1)) {
                        if (verbose)
-                               fprintf(stderr, "got ack\n");
-                       return 0;
+                               fprintf(stderr, "got ack %s\n",
+                                       sha1_to_hex(result_sha1));
+                       if (!multi_ack)
+                               return 0;
+                       retval = 0;
+                       continue;
                }
+               flushes--;
        }
        return retval;
 }