[PATCH] Update the list of diagnostics for git-commit-tree
[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 static int get_remote_heads(int fd, int nr_match, char **match, unsigned char *result)
57 {
58         int count = 0;
59
60         for (;;) {
61                 static char line[1000];
62                 unsigned char sha1[20];
63                 char *refname;
64                 int len;
65
66                 len = packet_read_line(fd, line, sizeof(line));
67                 if (!len)
68                         break;
69                 if (line[len-1] == '\n')
70                         line[--len] = 0;
71                 if (len < 42 || get_sha1_hex(line, sha1))
72                         die("git-fetch-pack: protocol error - expected ref descriptor, got '%s'", line);
73                 refname = line+41;
74                 if (nr_match && !path_match(refname, nr_match, match))
75                         continue;
76                 count++;
77                 memcpy(result, sha1, 20);
78         }
79         return count;
80 }
81
82 static int fetch_pack(int fd[2], int nr_match, char **match)
83 {
84         unsigned char sha1[20], remote[20];
85         int heads, status;
86         pid_t pid;
87
88         heads = get_remote_heads(fd[0], nr_match, match, remote);
89         if (heads != 1) {
90                 packet_flush(fd[1]);
91                 die(heads ? "multiple remote heads" : "no matching remote head");
92         }
93         if (find_common(fd, sha1, remote) < 0)
94                 die("git-fetch-pack: no common commits");
95         pid = fork();
96         if (pid < 0)
97                 die("git-fetch-pack: unable to fork off git-unpack-objects");
98         if (!pid) {
99                 dup2(fd[0], 0);
100                 close(fd[0]);
101                 close(fd[1]);
102                 execlp("git-unpack-objects", "git-unpack-objects",
103                        quiet ? "-q" : NULL, NULL);
104                 die("git-unpack-objects exec failed");
105         }
106         close(fd[0]);
107         close(fd[1]);
108         while (waitpid(pid, &status, 0) < 0) {
109                 if (errno != EINTR)
110                         die("waiting for git-unpack-objects: %s", strerror(errno));
111         }
112         if (WIFEXITED(status)) {
113                 int code = WEXITSTATUS(status);
114                 if (code)
115                         die("git-unpack-objects died with error code %d", code);
116                 puts(sha1_to_hex(remote));
117                 return 0;
118         }
119         if (WIFSIGNALED(status)) {
120                 int sig = WTERMSIG(status);
121                 die("git-unpack-objects died of signal %d", sig);
122         }
123         die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
124 }
125
126 int main(int argc, char **argv)
127 {
128         int i, ret, nr_heads;
129         char *dest = NULL, **heads;
130         int fd[2];
131         pid_t pid;
132
133         nr_heads = 0;
134         heads = NULL;
135         for (i = 1; i < argc; i++) {
136                 char *arg = argv[i];
137
138                 if (*arg == '-') {
139                         if (!strncmp("--exec=", arg, 7)) {
140                                 exec = arg + 7;
141                                 continue;
142                         }
143                         usage(fetch_pack_usage);
144                 }
145                 dest = arg;
146                 heads = argv + i + 1;
147                 nr_heads = argc - i - 1;
148                 break;
149         }
150         if (!dest)
151                 usage(fetch_pack_usage);
152         pid = git_connect(fd, dest, exec);
153         if (pid < 0)
154                 return 1;
155         ret = fetch_pack(fd, nr_heads, heads);
156         close(fd[0]);
157         close(fd[1]);
158         finish_connect(pid);
159         return ret;
160 }