Merge three separate "fetch refs" functions
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 16 Jul 2005 20:55:50 +0000 (13:55 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 16 Jul 2005 20:55:50 +0000 (13:55 -0700)
It really just boils down to one "get_remote_heads()" function, and a
common "struct ref" structure definition.

cache.h
clone-pack.c
connect.c
fetch-pack.c
send-pack.c

diff --git a/cache.h b/cache.h
index 73e05dc..150e144 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -285,10 +285,18 @@ struct pack_entry {
        struct packed_git *p;
 };
 
+struct ref {
+       struct ref *next;
+       unsigned char old_sha1[20];
+       unsigned char new_sha1[20];
+       char name[0];
+};
+
 extern int git_connect(int fd[2], char *url, const char *prog);
 extern int finish_connect(pid_t pid);
 extern int path_match(const char *path, int nr, char **match);
 extern int get_ack(int fd, unsigned char *result_sha1);
+extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match);
 
 extern void prepare_packed_git(void);
 extern int use_packed_git(struct packed_git *);
index 2aa5220..e9c20de 100644 (file)
@@ -7,50 +7,12 @@ static int quiet;
 static const char clone_pack_usage[] = "git-clone-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
 static const char *exec = "git-upload-pack";
 
-struct ref {
-       struct ref *next;
-       unsigned char sha1[20];
-       char name[0];
-};
-
-static struct ref *get_remote_refs(int fd, int nr_match, char **match)
-{
-       struct ref *ref_list = NULL, **next_ref = &ref_list;
-
-       for (;;) {
-               static char line[1000];
-               unsigned char sha1[20];
-               struct ref *ref;
-               char *refname;
-               int len;
-
-               len = packet_read_line(fd, line, sizeof(line));
-               if (!len)
-                       break;
-               if (line[len-1] == '\n')
-                       line[--len] = 0;
-               if (len < 42 || get_sha1_hex(line, sha1))
-                       die("git-clone-pack: protocol error - expected ref descriptor, got '%s'", line);
-               refname = line+41;
-               len = len-40;
-               if (nr_match && !path_match(refname, nr_match, match))
-                       continue;
-               ref = xmalloc(sizeof(struct ref) + len);
-               ref->next = NULL;
-               memcpy(ref->sha1, sha1, 20);
-               memcpy(ref->name, refname, len);
-               *next_ref = ref;
-               next_ref = &ref->next;
-       }
-       return ref_list;
-}
-
 static void clone_handshake(int fd[2], struct ref *ref)
 {
        unsigned char sha1[20];
 
        while (ref) {
-               packet_write(fd[1], "want %s\n", sha1_to_hex(ref->sha1));
+               packet_write(fd[1], "want %s\n", sha1_to_hex(ref->old_sha1));
                ref = ref->next;
        }
        packet_flush(fd[1]);
@@ -77,7 +39,7 @@ static void write_one_ref(struct ref *ref)
        fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0666);
        if (fd < 0)
                die("unable to create ref %s", ref->name);
-       hex = sha1_to_hex(ref->sha1);
+       hex = sha1_to_hex(ref->old_sha1);
        hex[40] = '\n';
        if (write(fd, hex, 41) != 41)
                die("unable to write ref %s", ref->name);
@@ -98,7 +60,7 @@ static void write_refs(struct ref *ref)
        while (ref) {
                if (is_master(ref))
                        master_ref = ref;
-               if (head && !memcmp(ref->sha1, head->sha1, 20)) {
+               if (head && !memcmp(ref->old_sha1, head->old_sha1, 20)) {
                        if (!head_ptr || ref == master_ref)
                                head_ptr = ref;
                }
@@ -142,7 +104,7 @@ static int clone_pack(int fd[2], int nr_match, char **match)
        int status;
        pid_t pid;
 
-       refs = get_remote_refs(fd[0], nr_match, match);
+       get_remote_heads(fd[0], &refs, nr_match, match);
        if (!refs) {
                packet_flush(fd[1]);
                die("no matching remote head");
index f01b547..6bf737c 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -7,6 +7,41 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 
+/*
+ * Read all the refs from the other end
+ */
+struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match)
+{
+       *list = NULL;
+       for (;;) {
+               struct ref *ref;
+               unsigned char old_sha1[20];
+               static char buffer[1000];
+               char *name;
+               int len;
+
+               len = packet_read_line(in, buffer, sizeof(buffer));
+               if (!len)
+                       break;
+               if (buffer[len-1] == '\n')
+                       buffer[--len] = 0;
+
+               if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != ' ')
+                       die("protocol error: expected sha/ref, got '%s'", buffer);
+               name = buffer + 41;
+               if (nr_match && !path_match(name, nr_match, match))
+                       continue;
+               ref = xmalloc(sizeof(*ref) + len - 40);
+               memcpy(ref->old_sha1, old_sha1, 20);
+               memset(ref->new_sha1, 0, 20);
+               memcpy(ref->name, buffer + 41, len - 40);
+               ref->next = NULL;
+               *list = ref;
+               list = &ref->next;
+       }
+       return list;
+}
+
 int get_ack(int fd, unsigned char *result_sha1)
 {
        static char line[1000];
index 9b1bc52..65e0076 100644 (file)
@@ -53,44 +53,28 @@ static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *rem
        return retval;
 }
 
-static int get_remote_heads(int fd, int nr_match, char **match, unsigned char *result)
-{
-       int count = 0;
-
-       for (;;) {
-               static char line[1000];
-               unsigned char sha1[20];
-               char *refname;
-               int len;
-
-               len = packet_read_line(fd, line, sizeof(line));
-               if (!len)
-                       break;
-               if (line[len-1] == '\n')
-                       line[--len] = 0;
-               if (len < 42 || get_sha1_hex(line, sha1))
-                       die("git-fetch-pack: protocol error - expected ref descriptor, got '%s'", line);
-               refname = line+41;
-               if (nr_match && !path_match(refname, nr_match, match))
-                       continue;
-               count++;
-               memcpy(result, sha1, 20);
-       }
-       return count;
-}
-
+/*
+ * Eventually we'll want to be able to fetch multiple heads.
+ *
+ * Right now we'll just require a single match.
+ */
 static int fetch_pack(int fd[2], int nr_match, char **match)
 {
-       unsigned char sha1[20], remote[20];
-       int heads, status;
+       struct ref *ref;
+       unsigned char sha1[20];
+       int status;
        pid_t pid;
 
-       heads = get_remote_heads(fd[0], nr_match, match, remote);
-       if (heads != 1) {
+       get_remote_heads(fd[0], &ref, nr_match, match);
+       if (!ref) {
+               packet_flush(fd[1]);
+               die("no matching remote head");
+       }
+       if (ref->next) {
                packet_flush(fd[1]);
-               die(heads ? "multiple remote heads" : "no matching remote head");
+               die("multiple remote heads");
        }
-       if (find_common(fd, sha1, remote) < 0)
+       if (find_common(fd, sha1, ref->old_sha1) < 0)
                die("git-fetch-pack: no common commits");
        pid = fork();
        if (pid < 0)
@@ -113,7 +97,7 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
                int code = WEXITSTATUS(status);
                if (code)
                        die("git-unpack-objects died with error code %d", code);
-               puts(sha1_to_hex(remote));
+               puts(sha1_to_hex(ref->old_sha1));
                return 0;
        }
        if (WIFSIGNALED(status)) {
index abc4d1f..2994df4 100644 (file)
@@ -7,13 +7,6 @@ static const char send_pack_usage[] =
 static const char *exec = "git-receive-pack";
 static int send_all = 0;
 
-struct ref {
-       struct ref *next;
-       unsigned char old_sha1[20];
-       unsigned char new_sha1[20];
-       char name[0];
-};
-
 static int is_zero_sha1(const unsigned char *sha1)
 {
        int i;
@@ -170,36 +163,12 @@ static int try_to_match(const char *refname, const unsigned char *sha1)
 
 static int send_pack(int in, int out, int nr_match, char **match)
 {
-       struct ref *ref_list = NULL, **last_ref = &ref_list;
+       struct ref *ref_list, **last_ref;
        struct ref *ref;
        int new_refs;
 
-       /*
-        * Read all the refs from the other end
-        */
-       for (;;) {
-               unsigned char old_sha1[20];
-               static char buffer[1000];
-               char *name;
-               int len;
-
-               len = packet_read_line(in, buffer, sizeof(buffer));
-               if (!len)
-                       break;
-               if (buffer[len-1] == '\n')
-                       buffer[--len] = 0;
-
-               if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != ' ')
-                       die("protocol error: expected sha/ref, got '%s'", buffer);
-               name = buffer + 41;
-               ref = xmalloc(sizeof(*ref) + len - 40);
-               memcpy(ref->old_sha1, old_sha1, 20);
-               memset(ref->new_sha1, 0, 20);
-               memcpy(ref->name, buffer + 41, len - 40);
-               ref->next = NULL;
-               *last_ref = ref;
-               last_ref = &ref->next;
-       }
+       /* First we get all heads, whether matching or not.. */
+       last_ref = get_remote_heads(in, &ref_list, 0, NULL);
 
        /*
         * Go through the refs, see if we want to update