[PATCH] Do not send "want" lines for complete objects
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>
Wed, 19 Oct 2005 23:14:34 +0000 (16:14 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 19 Oct 2005 23:14:34 +0000 (16:14 -0700)
It was all good and well to check if all remote refs are complete (local
refs or descendants thereof), but we can just as easily use the same
information to avoid sending "want" lines just for the complete objects in
the case that not all remote refs are complete (or their names differ).

Also, git-fetch-pack does not have to ask for descendants of remote refs
which are complete (for now, git-rev-list is told to ignore only the first
parent). That change also eliminates a code path where a popen()ed handle
was not pclose()ed.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
fetch-pack.c
index 969e72a7816701ed3f86ab42db1472346cab991e..9dfd072db786a62d7d971a1b98f539e68ec364fc 100644 (file)
@@ -12,31 +12,49 @@ static const char fetch_pack_usage[] =
 "git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
 static const char *exec = "git-upload-pack";
 
+#define COMPLETE       (1U << 0)
+
 static int find_common(int fd[2], unsigned char *result_sha1,
                       struct ref *refs)
 {
        int fetching;
        static char line[1000];
-       int count = 0, flushes = 0, retval;
+       static char rev_command[1024];
+       int count = 0, flushes = 0, retval, rev_command_len;
        FILE *revs;
 
-       revs = popen("git-rev-list $(git-rev-parse --all)", "r");
-       if (!revs)
-               die("unable to run 'git-rev-list'");
-
+       strcpy(rev_command, "git-rev-list $(git-rev-parse --all)");
+       rev_command_len = strlen(rev_command);
        fetching = 0;
        for ( ; refs ; refs = refs->next) {
                unsigned char *remote = refs->old_sha1;
-               unsigned char *local = refs->new_sha1;
 
-               if (!memcmp(remote, local, 20))
+               /*
+                  If that object is complete (i.e. it is a descendant of a
+                  local ref), we don't want it, nor its descendants.
+               */
+               if (has_sha1_file(remote)
+                               && parse_object(remote)->flags & COMPLETE) {
+                       if (rev_command_len + 44 < sizeof(rev_command)) {
+                               snprintf(rev_command + rev_command_len, 44,
+                                       " ^%s^", sha1_to_hex(remote));
+                               rev_command_len += 43;
+                       }
+
                        continue;
+               }
+
                packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
                fetching++;
        }
        packet_flush(fd[1]);
        if (!fetching)
                return 1;
+
+       revs = popen(rev_command, "r");
+       if (!revs)
+               die("unable to run 'git-rev-list'");
+
        flushes = 1;
        retval = -1;
        while (fgets(line, sizeof(line), revs) != NULL) {
@@ -81,7 +99,6 @@ static int find_common(int fd[2], unsigned char *result_sha1,
        return retval;
 }
 
-#define COMPLETE       (1U << 0)
 static struct commit_list *complete = NULL;
 
 static int mark_complete(const char *path, const unsigned char *sha1)