[PATCH] Install git-verify-tag-script
[git.git] / fetch-pack.c
1 #include "cache.h"
2 #include "refs.h"
3 #include "pkt-line.h"
4 #include <sys/wait.h>
5
6 static int quiet;
7 static const char fetch_pack_usage[] = "git-fetch-pack [-q] [--exec=upload-pack] [host:]directory [heads]* < mycommitlist";
8 static const char *exec = "git-upload-pack";
9
10 static int find_common(int fd[2], unsigned char *result_sha1, unsigned char *remote)
11 {
12         static char line[1000];
13         int count = 0, flushes = 0, retval;
14         FILE *revs;
15
16         revs = popen("git-rev-list $(git-rev-parse --all)", "r");
17         if (!revs)
18                 die("unable to run 'git-rev-list'");
19         packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
20         packet_flush(fd[1]);
21         flushes = 1;
22         retval = -1;
23         while (fgets(line, sizeof(line), revs) != NULL) {
24                 unsigned char sha1[20];
25                 if (get_sha1_hex(line, sha1))
26                         die("git-fetch-pack: expected object name, got crud");
27                 packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
28                 if (!(31 & ++count)) {
29                         packet_flush(fd[1]);
30                         flushes++;
31
32                         /*
33                          * We keep one window "ahead" of the other side, and
34                          * will wait for an ACK only on the next one
35                          */
36                         if (count == 32)
37                                 continue;
38                         if (get_ack(fd[0], result_sha1)) {
39                                 flushes = 0;
40                                 retval = 0;
41                                 break;
42                         }
43                         flushes--;
44                 }
45         }
46         pclose(revs);
47         packet_write(fd[1], "done\n");
48         while (flushes) {
49                 flushes--;
50                 if (get_ack(fd[0], result_sha1))
51                         return 0;
52         }
53         return retval;
54 }
55
56 /*
57  * Eventually we'll want to be able to fetch multiple heads.
58  *
59  * Right now we'll just require a single match.
60  */
61 static int fetch_pack(int fd[2], int nr_match, char **match)
62 {
63         struct ref *ref;
64         unsigned char sha1[20];
65         int status;
66         pid_t pid;
67
68         get_remote_heads(fd[0], &ref, nr_match, match);
69         if (!ref) {
70                 packet_flush(fd[1]);
71                 die("no matching remote head");
72         }
73         if (ref->next) {
74                 packet_flush(fd[1]);
75                 die("multiple remote heads");
76         }
77         if (find_common(fd, sha1, ref->old_sha1) < 0)
78                 die("git-fetch-pack: no common commits");
79         pid = fork();
80         if (pid < 0)
81                 die("git-fetch-pack: unable to fork off git-unpack-objects");
82         if (!pid) {
83                 dup2(fd[0], 0);
84                 close(fd[0]);
85                 close(fd[1]);
86                 execlp("git-unpack-objects", "git-unpack-objects",
87                        quiet ? "-q" : NULL, NULL);
88                 die("git-unpack-objects exec failed");
89         }
90         close(fd[0]);
91         close(fd[1]);
92         while (waitpid(pid, &status, 0) < 0) {
93                 if (errno != EINTR)
94                         die("waiting for git-unpack-objects: %s", strerror(errno));
95         }
96         if (WIFEXITED(status)) {
97                 int code = WEXITSTATUS(status);
98                 if (code)
99                         die("git-unpack-objects died with error code %d", code);
100                 puts(sha1_to_hex(ref->old_sha1));
101                 return 0;
102         }
103         if (WIFSIGNALED(status)) {
104                 int sig = WTERMSIG(status);
105                 die("git-unpack-objects died of signal %d", sig);
106         }
107         die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
108 }
109
110 int main(int argc, char **argv)
111 {
112         int i, ret, nr_heads;
113         char *dest = NULL, **heads;
114         int fd[2];
115         pid_t pid;
116
117         nr_heads = 0;
118         heads = NULL;
119         for (i = 1; i < argc; i++) {
120                 char *arg = argv[i];
121
122                 if (*arg == '-') {
123                         if (!strncmp("--exec=", arg, 7)) {
124                                 exec = arg + 7;
125                                 continue;
126                         }
127                         usage(fetch_pack_usage);
128                 }
129                 dest = arg;
130                 heads = argv + i + 1;
131                 nr_heads = argc - i - 1;
132                 break;
133         }
134         if (!dest)
135                 usage(fetch_pack_usage);
136         pid = git_connect(fd, dest, exec);
137         if (pid < 0)
138                 return 1;
139         ret = fetch_pack(fd, nr_heads, heads);
140         close(fd[0]);
141         close(fd[1]);
142         finish_connect(pid);
143         return ret;
144 }