git-fetch-pack: Implement client part of the multi_ack extension
[alt-git.git] / fetch-pack.c
blob57602b9561160a3ff14b893a92d69b46c1ffa9df
1 #include "cache.h"
2 #include "refs.h"
3 #include "pkt-line.h"
4 #include "commit.h"
5 #include "tag.h"
6 #include <time.h>
7 #include <sys/wait.h>
9 static int quiet;
10 static int verbose;
11 static const char fetch_pack_usage[] =
12 "git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
13 static const char *exec = "git-upload-pack";
15 #define COMPLETE (1U << 0)
16 #define COMMON (1U << 1)
17 #define COMMON_REF (1U << 2 | COMMON)
18 #define SEEN (1U << 3)
19 #define POPPED (1U << 4)
21 static struct commit_list *rev_list = NULL;
22 static struct commit_list *rev_list_end = NULL;
23 static unsigned long non_common_revs = 0;
25 static void rev_list_append(struct commit *commit, int mark)
27 if (!(commit->object.flags & mark)) {
28 commit->object.flags |= mark;
30 if (rev_list == NULL) {
31 commit_list_insert(commit, &rev_list);
32 rev_list_end = rev_list;
33 } else {
34 commit_list_insert(commit, &(rev_list_end->next));
35 rev_list_end = rev_list_end->next;
38 if (!(commit->object.flags & COMMON))
39 non_common_revs++;
43 static int rev_list_append_sha1(const char *path, const unsigned char *sha1)
45 struct object *o = deref_tag(parse_object(sha1));
47 if (o->type == commit_type)
48 rev_list_append((struct commit *)o, SEEN);
50 return 0;
53 static void mark_common(struct commit *commit)
55 if (commit != NULL && !(commit->object.flags & COMMON)) {
56 struct object *o = (struct object *)commit;
57 o->flags |= COMMON;
58 if (!(o->flags & SEEN))
59 rev_list_append(commit, SEEN);
60 else {
61 struct commit_list *parents;
63 if (!(o->flags & POPPED))
64 non_common_revs--;
65 if (!o->parsed)
66 parse_commit(commit);
67 for (parents = commit->parents;
68 parents;
69 parents = parents->next)
70 mark_common(parents->item);
76 Get the next rev to send, ignoring the common.
79 static const unsigned char* get_rev()
81 struct commit *commit = NULL;
83 while (commit == NULL) {
84 unsigned int mark;
85 struct commit_list* parents;
87 if (rev_list == NULL || non_common_revs == 0)
88 return NULL;
90 commit = rev_list->item;
91 if (!(commit->object.parsed))
92 parse_commit(commit);
93 commit->object.flags |= POPPED;
94 if (!(commit->object.flags & COMMON))
95 non_common_revs--;
97 parents = commit->parents;
99 if (commit->object.flags & COMMON) {
100 /* do not send "have", and ignore ancestors */
101 commit = NULL;
102 mark = COMMON | SEEN;
103 } else if (commit->object.flags & COMMON_REF)
104 /* send "have", and ignore ancestors */
105 mark = COMMON | SEEN;
106 else
107 /* send "have", also for its ancestors */
108 mark = SEEN;
110 while (parents) {
111 if (mark & COMMON)
112 mark_common(parents->item);
113 else
114 rev_list_append(parents->item, mark);
115 parents = parents->next;
118 rev_list = rev_list->next;
121 return commit->object.sha1;
124 static int find_common(int fd[2], unsigned char *result_sha1,
125 struct ref *refs)
127 int fetching;
128 int count = 0, flushes = 0, multi_ack = 0, retval;
129 const unsigned char *sha1;
131 for_each_ref(rev_list_append_sha1);
133 fetching = 0;
134 for ( ; refs ; refs = refs->next) {
135 unsigned char *remote = refs->old_sha1;
136 struct object *o;
139 * If that object is complete (i.e. it is an ancestor of a
140 * local ref), we tell them we have it but do not have to
141 * tell them about its ancestors, which they already know
142 * about.
144 * We use lookup_object here because we are only
145 * interested in the case we *know* the object is
146 * reachable and we have already scanned it.
148 if (((o = lookup_object(remote)) != NULL) &&
149 (o->flags & COMPLETE)) {
150 o = deref_tag(o);
152 if (o->type == commit_type)
153 rev_list_append((struct commit *)o,
154 COMMON_REF | SEEN);
156 continue;
159 packet_write(fd[1], "want %s multi_ack\n", sha1_to_hex(remote));
160 fetching++;
162 packet_flush(fd[1]);
163 if (!fetching)
164 return 1;
166 flushes = 0;
167 retval = -1;
168 while ((sha1 = get_rev())) {
169 packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
170 if (verbose)
171 fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
172 if (!(31 & ++count)) {
173 int ack;
175 packet_flush(fd[1]);
176 flushes++;
179 * We keep one window "ahead" of the other side, and
180 * will wait for an ACK only on the next one
182 if (count == 32)
183 continue;
185 do {
186 ack = get_ack(fd[0], result_sha1);
187 if (verbose && ack)
188 fprintf(stderr, "got ack %d %s\n", ack,
189 sha1_to_hex(result_sha1));
190 if (ack == 1) {
191 if (!multi_ack)
192 flushes = 0;
193 retval = 0;
194 goto done;
195 } else if (ack == 2) {
196 multi_ack = 1;
197 mark_common((struct commit *)
198 lookup_object(result_sha1));
199 retval = 0;
201 } while(ack);
202 flushes--;
205 done:
206 if (multi_ack) {
207 packet_flush(fd[1]);
208 flushes++;
210 packet_write(fd[1], "done\n");
211 if (verbose)
212 fprintf(stderr, "done\n");
213 if (retval != 0)
214 flushes++;
215 while (flushes) {
216 if (get_ack(fd[0], result_sha1)) {
217 if (verbose)
218 fprintf(stderr, "got ack %s\n",
219 sha1_to_hex(result_sha1));
220 if (!multi_ack)
221 return 0;
222 retval = 0;
223 continue;
225 flushes--;
227 return retval;
230 static struct commit_list *complete = NULL;
232 static int mark_complete(const char *path, const unsigned char *sha1)
234 struct object *o = parse_object(sha1);
236 while (o && o->type == tag_type) {
237 struct tag *t = (struct tag *) o;
238 if (!t->tagged)
239 break; /* broken repository */
240 o->flags |= COMPLETE;
241 o = parse_object(t->tagged->sha1);
243 if (o && o->type == commit_type) {
244 struct commit *commit = (struct commit *)o;
245 commit->object.flags |= COMPLETE;
246 insert_by_date(commit, &complete);
248 return 0;
251 static void mark_recent_complete_commits(unsigned long cutoff)
253 while (complete && cutoff <= complete->item->date) {
254 if (verbose)
255 fprintf(stderr, "Marking %s as complete\n",
256 sha1_to_hex(complete->item->object.sha1));
257 pop_most_recent_commit(&complete, COMPLETE);
261 static int everything_local(struct ref *refs)
263 struct ref *ref;
264 int retval;
265 unsigned long cutoff = 0;
267 track_object_refs = 0;
268 save_commit_buffer = 0;
270 for (ref = refs; ref; ref = ref->next) {
271 struct object *o;
273 o = parse_object(ref->old_sha1);
274 if (!o)
275 continue;
277 /* We already have it -- which may mean that we were
278 * in sync with the other side at some time after
279 * that (it is OK if we guess wrong here).
281 if (o->type == commit_type) {
282 struct commit *commit = (struct commit *)o;
283 if (!cutoff || cutoff < commit->date)
284 cutoff = commit->date;
288 for_each_ref(mark_complete);
289 if (cutoff)
290 mark_recent_complete_commits(cutoff);
292 for (retval = 1; refs ; refs = refs->next) {
293 const unsigned char *remote = refs->old_sha1;
294 unsigned char local[20];
295 struct object *o;
297 o = parse_object(remote);
298 if (!o || !(o->flags & COMPLETE)) {
299 retval = 0;
300 if (!verbose)
301 continue;
302 fprintf(stderr,
303 "want %s (%s)\n", sha1_to_hex(remote),
304 refs->name);
305 continue;
308 memcpy(refs->new_sha1, local, 20);
309 if (!verbose)
310 continue;
311 fprintf(stderr,
312 "already have %s (%s)\n", sha1_to_hex(remote),
313 refs->name);
315 return retval;
318 static int fetch_pack(int fd[2], int nr_match, char **match)
320 struct ref *ref;
321 unsigned char sha1[20];
322 int status;
323 pid_t pid;
325 get_remote_heads(fd[0], &ref, nr_match, match, 1);
326 if (!ref) {
327 packet_flush(fd[1]);
328 die("no matching remote head");
330 if (everything_local(ref)) {
331 packet_flush(fd[1]);
332 goto all_done;
334 if (find_common(fd, sha1, ref) < 0)
335 fprintf(stderr, "warning: no common commits\n");
336 pid = fork();
337 if (pid < 0)
338 die("git-fetch-pack: unable to fork off git-unpack-objects");
339 if (!pid) {
340 dup2(fd[0], 0);
341 close(fd[0]);
342 close(fd[1]);
343 execlp("git-unpack-objects", "git-unpack-objects",
344 quiet ? "-q" : NULL, NULL);
345 die("git-unpack-objects exec failed");
347 close(fd[0]);
348 close(fd[1]);
349 while (waitpid(pid, &status, 0) < 0) {
350 if (errno != EINTR)
351 die("waiting for git-unpack-objects: %s", strerror(errno));
353 if (WIFEXITED(status)) {
354 int code = WEXITSTATUS(status);
355 if (code)
356 die("git-unpack-objects died with error code %d", code);
357 all_done:
358 while (ref) {
359 printf("%s %s\n",
360 sha1_to_hex(ref->old_sha1), ref->name);
361 ref = ref->next;
363 return 0;
365 if (WIFSIGNALED(status)) {
366 int sig = WTERMSIG(status);
367 die("git-unpack-objects died of signal %d", sig);
369 die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
372 int main(int argc, char **argv)
374 int i, ret, nr_heads;
375 char *dest = NULL, **heads;
376 int fd[2];
377 pid_t pid;
379 nr_heads = 0;
380 heads = NULL;
381 for (i = 1; i < argc; i++) {
382 char *arg = argv[i];
384 if (*arg == '-') {
385 if (!strncmp("--exec=", arg, 7)) {
386 exec = arg + 7;
387 continue;
389 if (!strcmp("-q", arg)) {
390 quiet = 1;
391 continue;
393 if (!strcmp("-v", arg)) {
394 verbose = 1;
395 continue;
397 usage(fetch_pack_usage);
399 dest = arg;
400 heads = argv + i + 1;
401 nr_heads = argc - i - 1;
402 break;
404 if (!dest)
405 usage(fetch_pack_usage);
406 pid = git_connect(fd, dest, exec);
407 if (pid < 0)
408 return 1;
409 ret = fetch_pack(fd, nr_heads, heads);
410 close(fd[0]);
411 close(fd[1]);
412 finish_connect(pid);
413 return ret;