Subject: [PATCH] git-fetch-pack: Do not use git-rev-list
[git.git] / fetch-pack.c
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
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";
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
21 static struct commit_list *rev_list = NULL;
22 static int non_common_revs = 0;
23
24 static 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
39 static 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
55 static 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
86 static 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
131 static 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                         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);
165                         }
166                         continue;
167                 }
168
169                 packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
170                 fetching++;
171         }
172         packet_flush(fd[1]);
173         if (!fetching)
174                 return 1;
175
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++;
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;
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                         }
199                         flushes--;
200                 }
201         }
202
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;
214                 }
215         }
216         return retval;
217 }
218
219 static struct commit_list *complete = NULL;
220
221 static 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) {
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);
231         }
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);
236         }
237         return 0;
238 }
239
240 static 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
250 static int everything_local(struct ref *refs)
251 {
252         struct ref *ref;
253         int retval;
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);
280
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;
285
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;
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
307 static int fetch_pack(int fd[2], int nr_match, char **match)
308 {
309         struct ref *ref;
310         unsigned char sha1[20];
311         int status;
312         pid_t pid;
313
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");
318         }
319         if (everything_local(ref)) {
320                 packet_flush(fd[1]);
321                 goto all_done;
322         }
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");
335         }
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));
341         }
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;
351                 }
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);
359 }
360
361 int 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 == '-') {
374                         if (!strncmp("--exec=", arg, 7)) {
375                                 exec = arg + 7;
376                                 continue;
377                         }
378                         if (!strcmp("-q", arg)) {
379                                 quiet = 1;
380                                 continue;
381                         }
382                         if (!strcmp("-v", arg)) {
383                                 verbose = 1;
384                                 continue;
385                         }
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 }