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>
8
9static int quiet;
10static int verbose;
11static const char fetch_pack_usage[] =
12"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
13static const char *exec = "git-upload-pack";
14
15#define COMPLETE (1U << 0)
16#define COMMON (1U << 1)
17#define COMMON_REF (1U << 2)
18#define SEEN (1U << 3)
19#define POPPED (1U << 4)
20
21static struct commit_list *rev_list = NULL;
22static int non_common_revs = 0;
23
24static void rev_list_push(struct commit *commit, int mark)
25{
26 if (!(commit->object.flags & mark)) {
27 commit->object.flags |= mark;
28
29 if (!(commit->object.parsed))
30 parse_commit(commit);
31
32 insert_by_date(commit, &rev_list);
33
34 if (!(commit->object.flags & COMMON))
35 non_common_revs++;
36 }
37}
38
39static int rev_list_insert_ref(const char *path, const unsigned char *sha1)
40{
41 struct object *o = deref_tag(parse_object(sha1));
42
43 if (o->type == commit_type)
44 rev_list_push((struct commit *)o, SEEN);
45
46 return 0;
47}
48
49/*
50 This function marks a rev and its ancestors as common.
51 In some cases, it is desirable to mark only the ancestors (for example
52 when only the server does not yet know that they are common).
53*/
54
55static void mark_common(struct commit *commit,
56 int ancestors_only, int dont_parse)
57{
58 if (commit != NULL && !(commit->object.flags & COMMON)) {
59 struct object *o = (struct object *)commit;
60
61 if (!ancestors_only)
62 o->flags |= COMMON;
63
64 if (!(o->flags & SEEN))
65 rev_list_push(commit, SEEN);
66 else {
67 struct commit_list *parents;
68
69 if (!ancestors_only && !(o->flags & POPPED))
70 non_common_revs--;
71 if (!o->parsed && !dont_parse)
72 parse_commit(commit);
73
74 for (parents = commit->parents;
75 parents;
76 parents = parents->next)
77 mark_common(parents->item, 0, dont_parse);
78 }
79 }
80}
81
82/*
83 Get the next rev to send, ignoring the common.
84*/
85
86static const unsigned char* get_rev()
87{
88 struct commit *commit = NULL;
89
90 while (commit == NULL) {
91 unsigned int mark;
92 struct commit_list* parents;
93
94 if (rev_list == NULL || non_common_revs == 0)
95 return NULL;
96
97 commit = rev_list->item;
98 if (!(commit->object.parsed))
99 parse_commit(commit);
100 commit->object.flags |= POPPED;
101 if (!(commit->object.flags & COMMON))
102 non_common_revs--;
103
104 parents = commit->parents;
105
106 if (commit->object.flags & COMMON) {
107 /* do not send "have", and ignore ancestors */
108 commit = NULL;
109 mark = COMMON | SEEN;
110 } else if (commit->object.flags & COMMON_REF)
111 /* send "have", and ignore ancestors */
112 mark = COMMON | SEEN;
113 else
114 /* send "have", also for its ancestors */
115 mark = SEEN;
116
117 while (parents) {
118 if (!(parents->item->object.flags & SEEN))
119 rev_list_push(parents->item, mark);
120 if (mark & COMMON)
121 mark_common(parents->item, 1, 0);
122 parents = parents->next;
123 }
124
125 rev_list = rev_list->next;
126 }
127
128 return commit->object.sha1;
129}
130
131static int find_common(int fd[2], unsigned char *result_sha1,
132 struct ref *refs)
133{
134 int fetching;
135 int count = 0, flushes = 0, retval;
136 const unsigned char *sha1;
137
138 for_each_ref(rev_list_insert_ref);
139
140 fetching = 0;
141 for ( ; refs ; refs = refs->next) {
142 unsigned char *remote = refs->old_sha1;
143 struct object *o;
144
145 /*
146 * If that object is complete (i.e. it is an ancestor of a
147 * local ref), we tell them we have it but do not have to
148 * tell them about its ancestors, which they already know
149 * about.
150 *
151 * We use lookup_object here because we are only
152 * interested in the case we *know* the object is
153 * reachable and we have already scanned it.
154 */
155 if (((o = lookup_object(remote)) != NULL) &&
156 (o->flags & COMPLETE)) {
157 continue;
158 }
159
160 packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
161 fetching++;
162 }
163 packet_flush(fd[1]);
164 if (!fetching)
165 return 1;
166
167 flushes = 0;
168 retval = -1;
169 while ((sha1 = get_rev())) {
170 packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
171 if (verbose)
172 fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
173 if (!(31 & ++count)) {
174 packet_flush(fd[1]);
175 flushes++;
176
177 /*
178 * We keep one window "ahead" of the other side, and
179 * will wait for an ACK only on the next one
180 */
181 if (count == 32)
182 continue;
183 if (get_ack(fd[0], result_sha1)) {
184 flushes = 0;
185 retval = 0;
186 if (verbose)
187 fprintf(stderr, "got ack\n");
188 break;
189 }
190 flushes--;
191 }
192 }
193
194 packet_write(fd[1], "done\n");
195 if (verbose)
196 fprintf(stderr, "done\n");
197 if (retval != 0)
198 flushes++;
199 while (flushes) {
200 flushes--;
201 if (get_ack(fd[0], result_sha1)) {
202 if (verbose)
203 fprintf(stderr, "got ack\n");
204 return 0;
205 }
206 }
207 return retval;
208}
209
210static struct commit_list *complete = NULL;
211
212static int mark_complete(const char *path, const unsigned char *sha1)
213{
214 struct object *o = parse_object(sha1);
215
216 while (o && o->type == tag_type) {
217 struct tag *t = (struct tag *) o;
218 if (!t->tagged)
219 break; /* broken repository */
220 o->flags |= COMPLETE;
221 o = parse_object(t->tagged->sha1);
222 }
223 if (o && o->type == commit_type) {
224 struct commit *commit = (struct commit *)o;
225 commit->object.flags |= COMPLETE;
226 insert_by_date(commit, &complete);
227 }
228 return 0;
229}
230
231static void mark_recent_complete_commits(unsigned long cutoff)
232{
233 while (complete && cutoff <= complete->item->date) {
234 if (verbose)
235 fprintf(stderr, "Marking %s as complete\n",
236 sha1_to_hex(complete->item->object.sha1));
237 pop_most_recent_commit(&complete, COMPLETE);
238 }
239}
240
241static void filter_refs(struct ref **refs, int nr_match, char **match)
242{
243 struct ref *prev, *current, *next;
244
245 if (!nr_match)
246 return;
247
248 for (prev = NULL, current = *refs; current; current = next) {
249 next = current->next;
250 if ((!memcmp(current->name, "refs/", 5) &&
251 check_ref_format(current->name + 5)) ||
252 !path_match(current->name, nr_match, match)) {
253 if (prev == NULL)
254 *refs = next;
255 else
256 prev->next = next;
257 free(current);
258 } else
259 prev = current;
260 }
261}
262
263static int everything_local(struct ref **refs, int nr_match, char **match)
264{
265 struct ref *ref;
266 int retval;
267 unsigned long cutoff = 0;
268
269 track_object_refs = 0;
270 save_commit_buffer = 0;
271
272 for (ref = *refs; ref; ref = ref->next) {
273 struct object *o;
274
275 o = parse_object(ref->old_sha1);
276 if (!o)
277 continue;
278
279 /* We already have it -- which may mean that we were
280 * in sync with the other side at some time after
281 * that (it is OK if we guess wrong here).
282 */
283 if (o->type == commit_type) {
284 struct commit *commit = (struct commit *)o;
285 if (!cutoff || cutoff < commit->date)
286 cutoff = commit->date;
287 }
288 }
289
290 for_each_ref(mark_complete);
291 if (cutoff)
292 mark_recent_complete_commits(cutoff);
293
294 /*
295 * Mark all complete remote refs as common refs.
296 * Don't mark them common yet; the server has to be told so first.
297 */
298 for (ref = *refs; ref; ref = ref->next) {
299 struct object *o = deref_tag(lookup_object(ref->old_sha1));
300
301 if (!o || o->type != commit_type || !(o->flags & COMPLETE))
302 continue;
303
304 if (!(o->flags & SEEN)) {
305 rev_list_push((struct commit *)o, COMMON_REF | SEEN);
306
307 mark_common((struct commit *)o, 1, 1);
308 }
309 }
310
311 filter_refs(refs, nr_match, match);
312
313 for (retval = 1, ref = *refs; ref ; ref = ref->next) {
314 const unsigned char *remote = ref->old_sha1;
315 unsigned char local[20];
316 struct object *o;
317
318 o = lookup_object(remote);
319 if (!o || !(o->flags & COMPLETE)) {
320 retval = 0;
321 if (!verbose)
322 continue;
323 fprintf(stderr,
324 "want %s (%s)\n", sha1_to_hex(remote),
325 ref->name);
326 continue;
327 }
328
329 memcpy(ref->new_sha1, local, 20);
330 if (!verbose)
331 continue;
332 fprintf(stderr,
333 "already have %s (%s)\n", sha1_to_hex(remote),
334 ref->name);
335 }
336 return retval;
337}
338
339static int fetch_pack(int fd[2], int nr_match, char **match)
340{
341 struct ref *ref;
342 unsigned char sha1[20];
343 int status;
344 pid_t pid;
345
346 get_remote_heads(fd[0], &ref, 0, NULL, 0);
347 if (!ref) {
348 packet_flush(fd[1]);
349 die("no matching remote head");
350 }
351 if (everything_local(&ref, nr_match, match)) {
352 packet_flush(fd[1]);
353 goto all_done;
354 }
355 if (find_common(fd, sha1, ref) < 0)
356 fprintf(stderr, "warning: no common commits\n");
357 pid = fork();
358 if (pid < 0)
359 die("git-fetch-pack: unable to fork off git-unpack-objects");
360 if (!pid) {
361 dup2(fd[0], 0);
362 close(fd[0]);
363 close(fd[1]);
364 execlp("git-unpack-objects", "git-unpack-objects",
365 quiet ? "-q" : NULL, NULL);
366 die("git-unpack-objects exec failed");
367 }
368 close(fd[0]);
369 close(fd[1]);
370 while (waitpid(pid, &status, 0) < 0) {
371 if (errno != EINTR)
372 die("waiting for git-unpack-objects: %s", strerror(errno));
373 }
374 if (WIFEXITED(status)) {
375 int code = WEXITSTATUS(status);
376 if (code)
377 die("git-unpack-objects died with error code %d", code);
378all_done:
379 while (ref) {
380 printf("%s %s\n",
381 sha1_to_hex(ref->old_sha1), ref->name);
382 ref = ref->next;
383 }
384 return 0;
385 }
386 if (WIFSIGNALED(status)) {
387 int sig = WTERMSIG(status);
388 die("git-unpack-objects died of signal %d", sig);
389 }
390 die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
391}
392
393int main(int argc, char **argv)
394{
395 int i, ret, nr_heads;
396 char *dest = NULL, **heads;
397 int fd[2];
398 pid_t pid;
399
400 nr_heads = 0;
401 heads = NULL;
402 for (i = 1; i < argc; i++) {
403 char *arg = argv[i];
404
405 if (*arg == '-') {
406 if (!strncmp("--exec=", arg, 7)) {
407 exec = arg + 7;
408 continue;
409 }
410 if (!strcmp("-q", arg)) {
411 quiet = 1;
412 continue;
413 }
414 if (!strcmp("-v", arg)) {
415 verbose = 1;
416 continue;
417 }
418 usage(fetch_pack_usage);
419 }
420 dest = arg;
421 heads = argv + i + 1;
422 nr_heads = argc - i - 1;
423 break;
424 }
425 if (!dest)
426 usage(fetch_pack_usage);
427 pid = git_connect(fd, dest, exec);
428 if (pid < 0)
429 return 1;
430 ret = fetch_pack(fd, nr_heads, heads);
431 close(fd[0]);
432 close(fd[1]);
433 finish_connect(pid);
434 return ret;
435}