Subject: [PATCH] git-fetch-pack: Do not use git-rev-list
[git/jrn.git] / fetch-pack.c
blob3be77c3a8e76c6bc08414e9467c1dc1d0d91c6d1
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)
18 #define SEEN (1U << 3)
19 #define POPPED (1U << 4)
21 static struct commit_list *rev_list = NULL;
22 static int non_common_revs = 0;
24 static void rev_list_push(struct commit *commit, int mark)
26 if (!(commit->object.flags & mark)) {
27 commit->object.flags |= mark;
29 if (!(commit->object.parsed))
30 parse_commit(commit);
32 insert_by_date(commit, &rev_list);
34 if (!(commit->object.flags & COMMON))
35 non_common_revs++;
39 static int rev_list_insert_ref(const char *path, const unsigned char *sha1)
41 struct object *o = deref_tag(parse_object(sha1));
43 if (o->type == commit_type)
44 rev_list_push((struct commit *)o, SEEN);
46 return 0;
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).
55 static void mark_common(struct commit *commit,
56 int ancestors_only, int dont_parse)
58 if (commit != NULL && !(commit->object.flags & COMMON)) {
59 struct object *o = (struct object *)commit;
61 if (!ancestors_only)
62 o->flags |= COMMON;
64 if (!(o->flags & SEEN))
65 rev_list_push(commit, SEEN);
66 else {
67 struct commit_list *parents;
69 if (!ancestors_only && !(o->flags & POPPED))
70 non_common_revs--;
71 if (!o->parsed && !dont_parse)
72 parse_commit(commit);
74 for (parents = commit->parents;
75 parents;
76 parents = parents->next)
77 mark_common(parents->item, 0, dont_parse);
83 Get the next rev to send, ignoring the common.
86 static const unsigned char* get_rev()
88 struct commit *commit = NULL;
90 while (commit == NULL) {
91 unsigned int mark;
92 struct commit_list* parents;
94 if (rev_list == NULL || non_common_revs == 0)
95 return NULL;
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--;
104 parents = commit->parents;
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;
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;
125 rev_list = rev_list->next;
128 return commit->object.sha1;
131 static int find_common(int fd[2], unsigned char *result_sha1,
132 struct ref *refs)
134 int fetching;
135 int count = 0, flushes = 0, retval;
136 const unsigned char *sha1;
138 for_each_ref(rev_list_insert_ref);
140 fetching = 0;
141 for ( ; refs ; refs = refs->next) {
142 unsigned char *remote = refs->old_sha1;
143 struct object *o;
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.
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.
155 if (((o = lookup_object(remote)) != NULL) &&
156 (o->flags & COMPLETE)) {
157 o = deref_tag(o);
159 if (o->type == commit_type) {
160 struct commit *commit = (struct commit *)o;
162 rev_list_push(commit, COMMON_REF | SEEN);
164 mark_common(commit, 1, 1);
166 continue;
169 packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
170 fetching++;
172 packet_flush(fd[1]);
173 if (!fetching)
174 return 1;
176 flushes = 0;
177 retval = -1;
178 while ((sha1 = get_rev())) {
179 packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
180 if (verbose)
181 fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
182 if (!(31 & ++count)) {
183 packet_flush(fd[1]);
184 flushes++;
187 * We keep one window "ahead" of the other side, and
188 * will wait for an ACK only on the next one
190 if (count == 32)
191 continue;
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;
199 flushes--;
203 packet_write(fd[1], "done\n");
204 if (verbose)
205 fprintf(stderr, "done\n");
206 if (retval != 0)
207 flushes++;
208 while (flushes) {
209 flushes--;
210 if (get_ack(fd[0], result_sha1)) {
211 if (verbose)
212 fprintf(stderr, "got ack\n");
213 return 0;
216 return retval;
219 static struct commit_list *complete = NULL;
221 static int mark_complete(const char *path, const unsigned char *sha1)
223 struct object *o = parse_object(sha1);
225 while (o && o->type == tag_type) {
226 struct tag *t = (struct tag *) o;
227 if (!t->tagged)
228 break; /* broken repository */
229 o->flags |= COMPLETE;
230 o = parse_object(t->tagged->sha1);
232 if (o && o->type == commit_type) {
233 struct commit *commit = (struct commit *)o;
234 commit->object.flags |= COMPLETE;
235 insert_by_date(commit, &complete);
237 return 0;
240 static void mark_recent_complete_commits(unsigned long cutoff)
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);
250 static int everything_local(struct ref *refs)
252 struct ref *ref;
253 int retval;
254 unsigned long cutoff = 0;
256 track_object_refs = 0;
257 save_commit_buffer = 0;
259 for (ref = refs; ref; ref = ref->next) {
260 struct object *o;
262 o = parse_object(ref->old_sha1);
263 if (!o)
264 continue;
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).
270 if (o->type == commit_type) {
271 struct commit *commit = (struct commit *)o;
272 if (!cutoff || cutoff < commit->date)
273 cutoff = commit->date;
277 for_each_ref(mark_complete);
278 if (cutoff)
279 mark_recent_complete_commits(cutoff);
281 for (retval = 1; refs ; refs = refs->next) {
282 const unsigned char *remote = refs->old_sha1;
283 unsigned char local[20];
284 struct object *o;
286 o = parse_object(remote);
287 if (!o || !(o->flags & COMPLETE)) {
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;
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);
304 return retval;
307 static int fetch_pack(int fd[2], int nr_match, char **match)
309 struct ref *ref;
310 unsigned char sha1[20];
311 int status;
312 pid_t pid;
314 get_remote_heads(fd[0], &ref, nr_match, match, 1);
315 if (!ref) {
316 packet_flush(fd[1]);
317 die("no matching remote head");
319 if (everything_local(ref)) {
320 packet_flush(fd[1]);
321 goto all_done;
323 if (find_common(fd, sha1, ref) < 0)
324 fprintf(stderr, "warning: no common commits\n");
325 pid = fork();
326 if (pid < 0)
327 die("git-fetch-pack: unable to fork off git-unpack-objects");
328 if (!pid) {
329 dup2(fd[0], 0);
330 close(fd[0]);
331 close(fd[1]);
332 execlp("git-unpack-objects", "git-unpack-objects",
333 quiet ? "-q" : NULL, NULL);
334 die("git-unpack-objects exec failed");
336 close(fd[0]);
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));
342 if (WIFEXITED(status)) {
343 int code = WEXITSTATUS(status);
344 if (code)
345 die("git-unpack-objects died with error code %d", code);
346 all_done:
347 while (ref) {
348 printf("%s %s\n",
349 sha1_to_hex(ref->old_sha1), ref->name);
350 ref = ref->next;
352 return 0;
354 if (WIFSIGNALED(status)) {
355 int sig = WTERMSIG(status);
356 die("git-unpack-objects died of signal %d", sig);
358 die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
361 int main(int argc, char **argv)
363 int i, ret, nr_heads;
364 char *dest = NULL, **heads;
365 int fd[2];
366 pid_t pid;
368 nr_heads = 0;
369 heads = NULL;
370 for (i = 1; i < argc; i++) {
371 char *arg = argv[i];
373 if (*arg == '-') {
374 if (!strncmp("--exec=", arg, 7)) {
375 exec = arg + 7;
376 continue;
378 if (!strcmp("-q", arg)) {
379 quiet = 1;
380 continue;
382 if (!strcmp("-v", arg)) {
383 verbose = 1;
384 continue;
386 usage(fetch_pack_usage);
388 dest = arg;
389 heads = argv + i + 1;
390 nr_heads = argc - i - 1;
391 break;
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;