Subject: [PATCH] git-fetch-pack: Do not use git-rev-list
[git/git.git] / fetch-pack.c
CommitLineData
def88e9a 1#include "cache.h"
fb9040cc 2#include "refs.h"
def88e9a 3#include "pkt-line.h"
49bb805e
JH
4#include "commit.h"
5#include "tag.h"
6#include <time.h>
75bfc6c2 7#include <sys/wait.h>
def88e9a 8
8b3d9dc0 9static int quiet;
33b83034
JH
10static int verbose;
11static const char fetch_pack_usage[] =
12"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
def88e9a
LT
13static const char *exec = "git-upload-pack";
14
0a8944dd 15#define COMPLETE (1U << 0)
23d61f83
JS
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}
0a8944dd 130
33b83034
JH
131static int find_common(int fd[2], unsigned char *result_sha1,
132 struct ref *refs)
def88e9a 133{
2759cbc7 134 int fetching;
23d61f83
JS
135 int count = 0, flushes = 0, retval;
136 const unsigned char *sha1;
137
138 for_each_ref(rev_list_insert_ref);
def88e9a 139
2759cbc7
LT
140 fetching = 0;
141 for ( ; refs ; refs = refs->next) {
33b83034 142 unsigned char *remote = refs->old_sha1;
4dab94d5 143 struct object *o;
2759cbc7 144
0a8944dd 145 /*
4dab94d5
JH
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.
f1f0a2be
JH
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.
4dab94d5 154 */
f1f0a2be 155 if (((o = lookup_object(remote)) != NULL) &&
4dab94d5 156 (o->flags & COMPLETE)) {
23d61f83
JS
157 o = deref_tag(o);
158
159 if (o->type == commit_type) {
160 struct commit *commit = (struct commit *)o;
161
162 rev_list_push(commit, COMMON_REF | SEEN);
163
164 mark_common(commit, 1, 1);
af2d3aa4 165 }
2759cbc7 166 continue;
0a8944dd 167 }
23d61f83 168
af2d3aa4 169 packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
2759cbc7 170 fetching++;
33b83034 171 }
fb9040cc 172 packet_flush(fd[1]);
2759cbc7
LT
173 if (!fetching)
174 return 1;
0a8944dd 175
23d61f83 176 flushes = 0;
75bfc6c2 177 retval = -1;
23d61f83 178 while ((sha1 = get_rev())) {
def88e9a 179 packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
33b83034
JH
180 if (verbose)
181 fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
def88e9a
LT
182 if (!(31 & ++count)) {
183 packet_flush(fd[1]);
184 flushes++;
185
186 /*
187 * We keep one window "ahead" of the other side, and
188 * will wait for an ACK only on the next one
189 */
190 if (count == 32)
191 continue;
af2d3aa4
JH
192 if (get_ack(fd[0], result_sha1)) {
193 flushes = 0;
194 retval = 0;
195 if (verbose)
196 fprintf(stderr, "got ack\n");
197 break;
198 }
def88e9a
LT
199 flushes--;
200 }
201 }
23d61f83 202
75bfc6c2 203 packet_write(fd[1], "done\n");
33b83034
JH
204 if (verbose)
205 fprintf(stderr, "done\n");
23d61f83
JS
206 if (retval != 0)
207 flushes++;
def88e9a 208 while (flushes) {
af2d3aa4 209 flushes--;
33b83034
JH
210 if (get_ack(fd[0], result_sha1)) {
211 if (verbose)
af2d3aa4
JH
212 fprintf(stderr, "got ack\n");
213 return 0;
33b83034 214 }
def88e9a 215 }
75bfc6c2 216 return retval;
def88e9a
LT
217}
218
49bb805e
JH
219static struct commit_list *complete = NULL;
220
221static int mark_complete(const char *path, const unsigned char *sha1)
222{
223 struct object *o = parse_object(sha1);
224
225 while (o && o->type == tag_type) {
f1f0a2be
JH
226 struct tag *t = (struct tag *) o;
227 if (!t->tagged)
228 break; /* broken repository */
49bb805e 229 o->flags |= COMPLETE;
f1f0a2be 230 o = parse_object(t->tagged->sha1);
49bb805e 231 }
f1f0a2be 232 if (o && o->type == commit_type) {
49bb805e
JH
233 struct commit *commit = (struct commit *)o;
234 commit->object.flags |= COMPLETE;
235 insert_by_date(commit, &complete);
236 }
237 return 0;
238}
239
240static void mark_recent_complete_commits(unsigned long cutoff)
241{
242 while (complete && cutoff <= complete->item->date) {
243 if (verbose)
244 fprintf(stderr, "Marking %s as complete\n",
245 sha1_to_hex(complete->item->object.sha1));
246 pop_most_recent_commit(&complete, COMPLETE);
247 }
248}
249
2759cbc7
LT
250static int everything_local(struct ref *refs)
251{
49bb805e 252 struct ref *ref;
2759cbc7 253 int retval;
49bb805e
JH
254 unsigned long cutoff = 0;
255
256 track_object_refs = 0;
257 save_commit_buffer = 0;
258
259 for (ref = refs; ref; ref = ref->next) {
260 struct object *o;
261
262 o = parse_object(ref->old_sha1);
263 if (!o)
264 continue;
265
266 /* We already have it -- which may mean that we were
267 * in sync with the other side at some time after
268 * that (it is OK if we guess wrong here).
269 */
270 if (o->type == commit_type) {
271 struct commit *commit = (struct commit *)o;
272 if (!cutoff || cutoff < commit->date)
273 cutoff = commit->date;
274 }
275 }
276
277 for_each_ref(mark_complete);
278 if (cutoff)
279 mark_recent_complete_commits(cutoff);
2759cbc7
LT
280
281 for (retval = 1; refs ; refs = refs->next) {
282 const unsigned char *remote = refs->old_sha1;
283 unsigned char local[20];
49bb805e 284 struct object *o;
2759cbc7 285
49bb805e
JH
286 o = parse_object(remote);
287 if (!o || !(o->flags & COMPLETE)) {
2759cbc7
LT
288 retval = 0;
289 if (!verbose)
290 continue;
291 fprintf(stderr,
292 "want %s (%s)\n", sha1_to_hex(remote),
293 refs->name);
294 continue;
295 }
296
297 memcpy(refs->new_sha1, local, 20);
298 if (!verbose)
299 continue;
300 fprintf(stderr,
301 "already have %s (%s)\n", sha1_to_hex(remote),
302 refs->name);
303 }
304 return retval;
305}
306
def88e9a
LT
307static int fetch_pack(int fd[2], int nr_match, char **match)
308{
d1c133f5
LT
309 struct ref *ref;
310 unsigned char sha1[20];
311 int status;
75bfc6c2 312 pid_t pid;
def88e9a 313
1a7141ff 314 get_remote_heads(fd[0], &ref, nr_match, match, 1);
d1c133f5
LT
315 if (!ref) {
316 packet_flush(fd[1]);
317 die("no matching remote head");
318 }
2759cbc7
LT
319 if (everything_local(ref)) {
320 packet_flush(fd[1]);
321 goto all_done;
322 }
33b83034
JH
323 if (find_common(fd, sha1, ref) < 0)
324 fprintf(stderr, "warning: no common commits\n");
75bfc6c2
LT
325 pid = fork();
326 if (pid < 0)
327 die("git-fetch-pack: unable to fork off git-unpack-objects");
328 if (!pid) {
75bfc6c2
LT
329 dup2(fd[0], 0);
330 close(fd[0]);
85c414b5 331 close(fd[1]);
8b3d9dc0
JH
332 execlp("git-unpack-objects", "git-unpack-objects",
333 quiet ? "-q" : NULL, NULL);
75bfc6c2
LT
334 die("git-unpack-objects exec failed");
335 }
fb9040cc 336 close(fd[0]);
75bfc6c2
LT
337 close(fd[1]);
338 while (waitpid(pid, &status, 0) < 0) {
339 if (errno != EINTR)
340 die("waiting for git-unpack-objects: %s", strerror(errno));
341 }
342 if (WIFEXITED(status)) {
343 int code = WEXITSTATUS(status);
344 if (code)
345 die("git-unpack-objects died with error code %d", code);
2759cbc7 346all_done:
33b83034
JH
347 while (ref) {
348 printf("%s %s\n",
349 sha1_to_hex(ref->old_sha1), ref->name);
350 ref = ref->next;
351 }
75bfc6c2
LT
352 return 0;
353 }
354 if (WIFSIGNALED(status)) {
355 int sig = WTERMSIG(status);
356 die("git-unpack-objects died of signal %d", sig);
357 }
358 die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
def88e9a
LT
359}
360
361int main(int argc, char **argv)
362{
363 int i, ret, nr_heads;
364 char *dest = NULL, **heads;
365 int fd[2];
366 pid_t pid;
367
368 nr_heads = 0;
369 heads = NULL;
370 for (i = 1; i < argc; i++) {
371 char *arg = argv[i];
372
373 if (*arg == '-') {
8b3d9dc0
JH
374 if (!strncmp("--exec=", arg, 7)) {
375 exec = arg + 7;
376 continue;
377 }
33b83034
JH
378 if (!strcmp("-q", arg)) {
379 quiet = 1;
380 continue;
381 }
382 if (!strcmp("-v", arg)) {
383 verbose = 1;
384 continue;
385 }
def88e9a
LT
386 usage(fetch_pack_usage);
387 }
388 dest = arg;
389 heads = argv + i + 1;
390 nr_heads = argc - i - 1;
391 break;
392 }
393 if (!dest)
394 usage(fetch_pack_usage);
395 pid = git_connect(fd, dest, exec);
396 if (pid < 0)
397 return 1;
398 ret = fetch_pack(fd, nr_heads, heads);
399 close(fd[0]);
400 close(fd[1]);
401 finish_connect(pid);
402 return ret;
403}