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)
69779a56
JS
16#define COMMON (1U << 1)
17#define COMMON_REF (1U << 2 | COMMON)
18#define SEEN (1U << 3)
19#define POPPED (1U << 4)
20
21static struct commit_list *rev_list = NULL;
22static struct commit_list *rev_list_end = NULL;
23static unsigned long non_common_revs = 0;
24
25static void rev_list_append(struct commit *commit, int mark)
26{
27 if (!(commit->object.flags & mark)) {
28 commit->object.flags |= mark;
29
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;
36 }
37
38 if (!(commit->object.flags & COMMON))
39 non_common_revs++;
40 }
41}
42
43static int rev_list_append_sha1(const char *path, const unsigned char *sha1)
44{
45 struct object *o = deref_tag(parse_object(sha1));
46
47 if (o->type == commit_type)
48 rev_list_append((struct commit *)o, SEEN);
49
50 return 0;
51}
52
53static void mark_common(struct commit *commit)
54{
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;
62
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);
71 }
72 }
73}
74
75/*
76 Get the next rev to send, ignoring the common.
77*/
78
79static const unsigned char* get_rev()
80{
81 struct commit *commit = NULL;
82
83 while (commit == NULL) {
84 unsigned int mark;
85 struct commit_list* parents;
86
87 if (rev_list == NULL || non_common_revs == 0)
88 return NULL;
89
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--;
96
97 parents = commit->parents;
98
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;
109
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;
116 }
117
118 rev_list = rev_list->next;
119 }
120
121 return commit->object.sha1;
122}
0a8944dd 123
33b83034
JH
124static int find_common(int fd[2], unsigned char *result_sha1,
125 struct ref *refs)
def88e9a 126{
2759cbc7 127 int fetching;
69779a56
JS
128 int count = 0, flushes = 0, retval;
129 const unsigned char *sha1;
130
131 for_each_ref(rev_list_append_sha1);
def88e9a 132
2759cbc7
LT
133 fetching = 0;
134 for ( ; refs ; refs = refs->next) {
33b83034 135 unsigned char *remote = refs->old_sha1;
4dab94d5 136 struct object *o;
2759cbc7 137
0a8944dd 138 /*
4dab94d5
JH
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.
f1f0a2be
JH
143 *
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.
4dab94d5 147 */
f1f0a2be 148 if (((o = lookup_object(remote)) != NULL) &&
4dab94d5 149 (o->flags & COMPLETE)) {
69779a56
JS
150 o = deref_tag(o);
151
152 if (o->type == commit_type)
153 rev_list_append((struct commit *)o,
154 COMMON_REF | SEEN);
155
2759cbc7 156 continue;
0a8944dd 157 }
69779a56 158
33b83034 159 packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
2759cbc7 160 fetching++;
33b83034 161 }
fb9040cc 162 packet_flush(fd[1]);
2759cbc7
LT
163 if (!fetching)
164 return 1;
0a8944dd 165
75bfc6c2
LT
166 flushes = 1;
167 retval = -1;
69779a56 168 while ((sha1 = get_rev())) {
def88e9a 169 packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
33b83034
JH
170 if (verbose)
171 fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
def88e9a
LT
172 if (!(31 & ++count)) {
173 packet_flush(fd[1]);
174 flushes++;
175
176 /*
177 * We keep one window "ahead" of the other side, and
178 * will wait for an ACK only on the next one
179 */
180 if (count == 32)
181 continue;
75bfc6c2
LT
182 if (get_ack(fd[0], result_sha1)) {
183 flushes = 0;
184 retval = 0;
33b83034
JH
185 if (verbose)
186 fprintf(stderr, "got ack\n");
75bfc6c2
LT
187 break;
188 }
def88e9a
LT
189 flushes--;
190 }
191 }
75bfc6c2 192 packet_write(fd[1], "done\n");
33b83034
JH
193 if (verbose)
194 fprintf(stderr, "done\n");
def88e9a
LT
195 while (flushes) {
196 flushes--;
33b83034
JH
197 if (get_ack(fd[0], result_sha1)) {
198 if (verbose)
199 fprintf(stderr, "got ack\n");
def88e9a 200 return 0;
33b83034 201 }
def88e9a 202 }
75bfc6c2 203 return retval;
def88e9a
LT
204}
205
49bb805e
JH
206static struct commit_list *complete = NULL;
207
208static int mark_complete(const char *path, const unsigned char *sha1)
209{
210 struct object *o = parse_object(sha1);
211
212 while (o && o->type == tag_type) {
f1f0a2be
JH
213 struct tag *t = (struct tag *) o;
214 if (!t->tagged)
215 break; /* broken repository */
49bb805e 216 o->flags |= COMPLETE;
f1f0a2be 217 o = parse_object(t->tagged->sha1);
49bb805e 218 }
f1f0a2be 219 if (o && o->type == commit_type) {
49bb805e
JH
220 struct commit *commit = (struct commit *)o;
221 commit->object.flags |= COMPLETE;
222 insert_by_date(commit, &complete);
223 }
224 return 0;
225}
226
227static void mark_recent_complete_commits(unsigned long cutoff)
228{
229 while (complete && cutoff <= complete->item->date) {
230 if (verbose)
231 fprintf(stderr, "Marking %s as complete\n",
232 sha1_to_hex(complete->item->object.sha1));
233 pop_most_recent_commit(&complete, COMPLETE);
234 }
235}
236
2759cbc7
LT
237static int everything_local(struct ref *refs)
238{
49bb805e 239 struct ref *ref;
2759cbc7 240 int retval;
49bb805e
JH
241 unsigned long cutoff = 0;
242
243 track_object_refs = 0;
244 save_commit_buffer = 0;
245
246 for (ref = refs; ref; ref = ref->next) {
247 struct object *o;
248
249 o = parse_object(ref->old_sha1);
250 if (!o)
251 continue;
252
253 /* We already have it -- which may mean that we were
254 * in sync with the other side at some time after
255 * that (it is OK if we guess wrong here).
256 */
257 if (o->type == commit_type) {
258 struct commit *commit = (struct commit *)o;
259 if (!cutoff || cutoff < commit->date)
260 cutoff = commit->date;
261 }
262 }
263
264 for_each_ref(mark_complete);
265 if (cutoff)
266 mark_recent_complete_commits(cutoff);
2759cbc7
LT
267
268 for (retval = 1; refs ; refs = refs->next) {
269 const unsigned char *remote = refs->old_sha1;
270 unsigned char local[20];
49bb805e 271 struct object *o;
2759cbc7 272
49bb805e
JH
273 o = parse_object(remote);
274 if (!o || !(o->flags & COMPLETE)) {
2759cbc7
LT
275 retval = 0;
276 if (!verbose)
277 continue;
278 fprintf(stderr,
279 "want %s (%s)\n", sha1_to_hex(remote),
280 refs->name);
281 continue;
282 }
283
284 memcpy(refs->new_sha1, local, 20);
285 if (!verbose)
286 continue;
287 fprintf(stderr,
288 "already have %s (%s)\n", sha1_to_hex(remote),
289 refs->name);
290 }
291 return retval;
292}
293
def88e9a
LT
294static int fetch_pack(int fd[2], int nr_match, char **match)
295{
d1c133f5
LT
296 struct ref *ref;
297 unsigned char sha1[20];
298 int status;
75bfc6c2 299 pid_t pid;
def88e9a 300
1a7141ff 301 get_remote_heads(fd[0], &ref, nr_match, match, 1);
d1c133f5
LT
302 if (!ref) {
303 packet_flush(fd[1]);
304 die("no matching remote head");
305 }
2759cbc7
LT
306 if (everything_local(ref)) {
307 packet_flush(fd[1]);
308 goto all_done;
309 }
33b83034
JH
310 if (find_common(fd, sha1, ref) < 0)
311 fprintf(stderr, "warning: no common commits\n");
75bfc6c2
LT
312 pid = fork();
313 if (pid < 0)
314 die("git-fetch-pack: unable to fork off git-unpack-objects");
315 if (!pid) {
75bfc6c2
LT
316 dup2(fd[0], 0);
317 close(fd[0]);
85c414b5 318 close(fd[1]);
8b3d9dc0
JH
319 execlp("git-unpack-objects", "git-unpack-objects",
320 quiet ? "-q" : NULL, NULL);
75bfc6c2
LT
321 die("git-unpack-objects exec failed");
322 }
fb9040cc 323 close(fd[0]);
75bfc6c2
LT
324 close(fd[1]);
325 while (waitpid(pid, &status, 0) < 0) {
326 if (errno != EINTR)
327 die("waiting for git-unpack-objects: %s", strerror(errno));
328 }
329 if (WIFEXITED(status)) {
330 int code = WEXITSTATUS(status);
331 if (code)
332 die("git-unpack-objects died with error code %d", code);
2759cbc7 333all_done:
33b83034
JH
334 while (ref) {
335 printf("%s %s\n",
336 sha1_to_hex(ref->old_sha1), ref->name);
337 ref = ref->next;
338 }
75bfc6c2
LT
339 return 0;
340 }
341 if (WIFSIGNALED(status)) {
342 int sig = WTERMSIG(status);
343 die("git-unpack-objects died of signal %d", sig);
344 }
345 die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
def88e9a
LT
346}
347
348int main(int argc, char **argv)
349{
350 int i, ret, nr_heads;
351 char *dest = NULL, **heads;
352 int fd[2];
353 pid_t pid;
354
355 nr_heads = 0;
356 heads = NULL;
357 for (i = 1; i < argc; i++) {
358 char *arg = argv[i];
359
360 if (*arg == '-') {
8b3d9dc0
JH
361 if (!strncmp("--exec=", arg, 7)) {
362 exec = arg + 7;
363 continue;
364 }
33b83034
JH
365 if (!strcmp("-q", arg)) {
366 quiet = 1;
367 continue;
368 }
369 if (!strcmp("-v", arg)) {
370 verbose = 1;
371 continue;
372 }
def88e9a
LT
373 usage(fetch_pack_usage);
374 }
375 dest = arg;
376 heads = argv + i + 1;
377 nr_heads = argc - i - 1;
378 break;
379 }
380 if (!dest)
381 usage(fetch_pack_usage);
382 pid = git_connect(fd, dest, exec);
383 if (pid < 0)
384 return 1;
385 ret = fetch_pack(fd, nr_heads, heads);
386 close(fd[0]);
387 close(fd[1]);
388 finish_connect(pid);
389 return ret;
390}