Unoptimize info/refs creation.
[git.git] / server-info.c
1 #include "cache.h"
2 #include "refs.h"
3 #include "object.h"
4 #include "commit.h"
5 #include "tag.h"
6
7 /* refs */
8 static FILE *info_ref_fp;
9
10 static int add_info_ref(const char *path, const unsigned char *sha1)
11 {
12         fprintf(info_ref_fp, "%s        %s\n", sha1_to_hex(sha1), path);
13         return 0;
14 }
15
16 static int update_info_refs(int force)
17 {
18         char *path0 = strdup(git_path("info/refs"));
19         int len = strlen(path0);
20         char *path1 = xmalloc(len + 2);
21
22         strcpy(path1, path0);
23         strcpy(path1 + len, "+");
24
25         safe_create_leading_directories(path0);
26         info_ref_fp = fopen(path1, "w");
27         if (!info_ref_fp)
28                 return error("unable to update %s", path0);
29         for_each_ref(add_info_ref);
30         fclose(info_ref_fp);
31         rename(path1, path0);
32         free(path0);
33         free(path1);
34         return 0;
35 }
36
37 /* packs */
38 static struct pack_info {
39         unsigned long latest;
40         struct packed_git *p;
41         int old_num;
42         int new_num;
43         int nr_alloc;
44         int nr_heads;
45         unsigned char (*head)[20];
46         char dep[0]; /* more */
47 } **info;
48 static int num_pack;
49 static const char *objdir;
50 static int objdirlen;
51
52 static struct object *parse_object_cheap(const unsigned char *sha1)
53 {
54         struct object *o;
55
56         if ((o = parse_object(sha1)) == NULL)
57                 return NULL;
58         if (o->type == commit_type) {
59                 struct commit *commit = (struct commit *)o;
60                 free(commit->buffer);
61                 commit->buffer = NULL;
62         }
63         return o;
64 }
65
66 static struct pack_info *find_pack_by_name(const char *name)
67 {
68         int i;
69         for (i = 0; i < num_pack; i++) {
70                 struct packed_git *p = info[i]->p;
71                 /* skip "/pack/" after ".git/objects" */
72                 if (!strcmp(p->pack_name + objdirlen + 6, name))
73                         return info[i];
74         }
75         return NULL;
76 }
77
78 static struct pack_info *find_pack_by_old_num(int old_num)
79 {
80         int i;
81         for (i = 0; i < num_pack; i++)
82                 if (info[i]->old_num == old_num)
83                         return info[i];
84         return NULL;
85 }
86
87 static int add_head_def(struct pack_info *this, unsigned char *sha1)
88 {
89         if (this->nr_alloc <= this->nr_heads) {
90                 this->nr_alloc = alloc_nr(this->nr_alloc);
91                 this->head = xrealloc(this->head, this->nr_alloc * 20);
92         }
93         memcpy(this->head[this->nr_heads++], sha1, 20);
94         return 0;
95 }
96
97 /* Returns non-zero when we detect that the info in the
98  * old file is useless.
99  */
100 static int parse_pack_def(const char *line, int old_cnt)
101 {
102         struct pack_info *i = find_pack_by_name(line + 2);
103         if (i) {
104                 i->old_num = old_cnt;
105                 return 0;
106         }
107         else {
108                 /* The file describes a pack that is no longer here;
109                  * dependencies between packs needs to be recalculated.
110                  */
111                 return 1;
112         }
113 }
114
115 /* Returns non-zero when we detect that the info in the
116  * old file is useless.
117  */
118 static int parse_depend_def(char *line)
119 {
120         unsigned long num;
121         char *cp, *ep;
122         struct pack_info *this, *that;
123
124         cp = line + 2;
125         num = strtoul(cp, &ep, 10);
126         if (ep == cp)
127                 return error("invalid input %s", line);
128         this = find_pack_by_old_num(num);
129         if (!this)
130                 return 0;
131         while (ep && *(cp = ep)) {
132                 num = strtoul(cp, &ep, 10);
133                 if (ep == cp)
134                         break;
135                 that = find_pack_by_old_num(num);
136                 if (!that)
137                         /* The pack this one depends on does not
138                          * exist; this should not happen because
139                          * we write out the list of packs first and
140                          * then dependency information, but it means
141                          * the file is useless anyway.
142                          */
143                         return 1;
144                 this->dep[that->new_num] = 1;
145         }
146         return 0;
147 }
148
149 /* Returns non-zero when we detect that the info in the
150  * old file is useless.
151  */
152 static int parse_head_def(char *line)
153 {
154         unsigned char sha1[20];
155         unsigned long num;
156         char *cp, *ep;
157         struct pack_info *this;
158         struct object *o;
159
160         cp = line + 2;
161         num = strtoul(cp, &ep, 10);
162         if (ep == cp || *ep++ != ' ')
163                 return error("invalid input ix %s", line);
164         this = find_pack_by_old_num(num);
165         if (!this)
166                 return 1; /* You know the drill. */
167         if (get_sha1_hex(ep, sha1) || ep[40] != ' ')
168                 return error("invalid input sha1 %s (%s)", line, ep);
169         if ((o = parse_object_cheap(sha1)) == NULL)
170                 return error("no such object: %s", line);
171         return add_head_def(this, sha1);
172 }
173
174 /* Returns non-zero when we detect that the info in the
175  * old file is useless.
176  */
177 static int read_pack_info_file(const char *infofile)
178 {
179         FILE *fp;
180         char line[1000];
181         int old_cnt = 0;
182
183         fp = fopen(infofile, "r");
184         if (!fp)
185                 return 1; /* nonexisting is not an error. */
186
187         while (fgets(line, sizeof(line), fp)) {
188                 int len = strlen(line);
189                 if (line[len-1] == '\n')
190                         line[len-1] = 0;
191
192                 switch (line[0]) {
193                 case 'P': /* P name */
194                         if (parse_pack_def(line, old_cnt++))
195                                 goto out_stale;
196                         break;
197                 case 'D': /* D ix dep-ix1 dep-ix2... */
198                         if (parse_depend_def(line))
199                                 goto out_stale;
200                         break;
201                 case 'T': /* T ix sha1 type */
202                         if (parse_head_def(line))
203                                 goto out_stale;
204                         break;
205                 default:
206                         error("unrecognized: %s", line);
207                         break;
208                 }
209         }
210         fclose(fp);
211         return 0;
212  out_stale:
213         fclose(fp);
214         return 1;
215 }
216
217 /* We sort the packs according to the date of the latest commit.  That
218  * in turn indicates how young the pack is, and in general we would
219  * want to depend on younger packs.
220  */
221 static unsigned long get_latest_commit_date(struct packed_git *p)
222 {
223         unsigned char sha1[20];
224         struct object *o;
225         int num = num_packed_objects(p);
226         int i;
227         unsigned long latest = 0;
228
229         for (i = 0; i < num; i++) {
230                 if (nth_packed_object_sha1(p, i, sha1))
231                         die("corrupt pack file %s?", p->pack_name);
232                 if ((o = parse_object_cheap(sha1)) == NULL)
233                         die("cannot parse %s", sha1_to_hex(sha1));
234                 if (o->type == commit_type) {
235                         struct commit *commit = (struct commit *)o;
236                         if (latest < commit->date)
237                                 latest = commit->date;
238                 }
239         }
240         return latest;
241 }
242
243 static int compare_info(const void *a_, const void *b_)
244 {
245         struct pack_info * const* a = a_;
246         struct pack_info * const* b = b_;
247
248         if (0 <= (*a)->old_num && 0 <= (*b)->old_num)
249                 /* Keep the order in the original */
250                 return (*a)->old_num - (*b)->old_num;
251         else if (0 <= (*a)->old_num)
252                 /* Only A existed in the original so B is obviously newer */
253                 return -1;
254         else if (0 <= (*b)->old_num)
255                 /* The other way around. */
256                 return 1;
257
258         if ((*a)->latest < (*b)->latest)
259                 return -1;
260         else if ((*a)->latest == (*b)->latest)
261                 return 0;
262         else
263                 return 1;
264 }
265
266 static void init_pack_info(const char *infofile, int force)
267 {
268         struct packed_git *p;
269         int stale;
270         int i = 0;
271         char *dep_temp;
272
273         objdir = get_object_directory();
274         objdirlen = strlen(objdir);
275
276         prepare_packed_git();
277         for (p = packed_git; p; p = p->next) {
278                 /* we ignore things on alternate path since they are
279                  * not available to the pullers in general.
280                  */
281                 if (strncmp(p->pack_name, objdir, objdirlen) ||
282                     strncmp(p->pack_name + objdirlen, "/pack/", 6))
283                         continue;
284                 i++;
285         }
286         num_pack = i;
287         info = xcalloc(num_pack, sizeof(struct pack_info *));
288         for (i = 0, p = packed_git; p; p = p->next) {
289                 if (strncmp(p->pack_name, objdir, objdirlen) ||
290                     p->pack_name[objdirlen] != '/')
291                         continue;
292                 info[i] = xcalloc(1, sizeof(struct pack_info) + num_pack);
293                 info[i]->p = p;
294                 info[i]->old_num = -1;
295                 i++;
296         }
297
298         if (infofile && !force)
299                 stale = read_pack_info_file(infofile);
300         else
301                 stale = 1;
302
303         for (i = 0; i < num_pack; i++) {
304                 if (stale) {
305                         info[i]->old_num = -1;
306                         memset(info[i]->dep, 0, num_pack);
307                         info[i]->nr_heads = 0;
308                 }
309                 if (info[i]->old_num < 0)
310                         info[i]->latest = get_latest_commit_date(info[i]->p);
311         }
312
313         qsort(info, num_pack, sizeof(info[0]), compare_info);
314         for (i = 0; i < num_pack; i++)
315                 info[i]->new_num = i;
316
317         /* we need to fix up the dependency information
318          * for the old ones.
319          */
320         dep_temp = NULL;
321         for (i = 0; i < num_pack; i++) {
322                 int old;
323
324                 if (info[i]->old_num < 0)
325                         continue;
326                 if (! dep_temp)
327                         dep_temp = xmalloc(num_pack);
328                 memset(dep_temp, 0, num_pack);
329                 for (old = 0; old < num_pack; old++) {
330                         struct pack_info *base;
331                         if (!info[i]->dep[old])
332                                 continue;
333                         base = find_pack_by_old_num(old);
334                         if (!base)
335                                 die("internal error renumbering");
336                         dep_temp[base->new_num] = 1;
337                 }
338                 memcpy(info[i]->dep, dep_temp, num_pack);
339         }
340         free(dep_temp);
341 }
342
343 static void write_pack_info_file(FILE *fp)
344 {
345         int i, j;
346         for (i = 0; i < num_pack; i++)
347                 fprintf(fp, "P %s\n", info[i]->p->pack_name + objdirlen + 6);
348
349         for (i = 0; i < num_pack; i++) {
350                 fprintf(fp, "D %1d", i);
351                 for (j = 0; j < num_pack; j++) {
352                         if ((i == j) || !(info[i]->dep[j]))
353                                 continue;
354                         fprintf(fp, " %1d", j);
355                 }
356                 fputc('\n', fp);
357         }
358
359         for (i = 0; i < num_pack; i++) {
360                 struct pack_info *this = info[i];
361                 for (j = 0; j < this->nr_heads; j++) {
362                         struct object *o = lookup_object(this->head[j]);
363                         fprintf(fp, "T %1d %s %s\n",
364                                 i, sha1_to_hex(this->head[j]), o->type);
365                 }
366         }
367
368 }
369
370 #define REFERENCED 01
371 #define INTERNAL  02
372 #define EMITTED   04
373
374 static void show(struct object *o, int pack_ix)
375 {
376         /*
377          * We are interested in objects that are not referenced,
378          * and objects that are referenced but not internal.
379          */
380         if (o->flags & EMITTED)
381                 return;
382
383         if (!(o->flags & REFERENCED))
384                 add_head_def(info[pack_ix], o->sha1);
385         else if ((o->flags & REFERENCED) && !(o->flags & INTERNAL)) {
386                 int i;
387
388                 /* Which pack contains this object?  That is what
389                  * pack_ix can depend on.  We earlier sorted info
390                  * array from youngest to oldest, so try newer packs
391                  * first to favor them here.
392                  */
393                 for (i = num_pack - 1; 0 <= i; i--) {
394                         struct packed_git *p = info[i]->p;
395                         struct pack_entry ent;
396                         if (find_pack_entry_one(o->sha1, &ent, p)) {
397                                 info[pack_ix]->dep[i] = 1;
398                                 break;
399                         }
400                 }
401         }
402         o->flags |= EMITTED;
403 }
404
405 static void find_pack_info_one(int pack_ix)
406 {
407         unsigned char sha1[20];
408         struct object *o;
409         struct object_list *ref;
410         int i;
411         struct packed_git *p = info[pack_ix]->p;
412         int num = num_packed_objects(p);
413
414         /* Scan objects, clear flags from all the edge ones and
415          * internal ones, possibly marked in the previous round.
416          */
417         for (i = 0; i < num; i++) {
418                 if (nth_packed_object_sha1(p, i, sha1))
419                         die("corrupt pack file %s?", p->pack_name);
420                 if ((o = lookup_object(sha1)) == NULL)
421                         die("cannot parse %s", sha1_to_hex(sha1));
422                 for (ref = o->refs; ref; ref = ref->next)
423                         ref->item->flags = 0;
424                 o->flags = 0;
425         }
426
427         /* Mark all the internal ones */
428         for (i = 0; i < num; i++) {
429                 if (nth_packed_object_sha1(p, i, sha1))
430                         die("corrupt pack file %s?", p->pack_name);
431                 if ((o = lookup_object(sha1)) == NULL)
432                         die("cannot find %s", sha1_to_hex(sha1));
433                 for (ref = o->refs; ref; ref = ref->next)
434                         ref->item->flags |= REFERENCED;
435                 o->flags |= INTERNAL;
436         }
437
438         for (i = 0; i < num; i++) {
439                 if (nth_packed_object_sha1(p, i, sha1))
440                         die("corrupt pack file %s?", p->pack_name);
441                 if ((o = lookup_object(sha1)) == NULL)
442                         die("cannot find %s", sha1_to_hex(sha1));
443
444                 show(o, pack_ix);
445                 for (ref = o->refs; ref; ref = ref->next)
446                         show(ref->item, pack_ix);
447         }
448
449 }
450
451 static void find_pack_info(void)
452 {
453         int i;
454         for (i = 0; i < num_pack; i++) {
455                 /* The packed objects are cast in stone, and a head
456                  * in a pack will stay as head, so is the set of missing
457                  * objects.  If the repo has been reorganized and we
458                  * are missing some packs available back then, we have
459                  * already discarded the info read from the file, so
460                  * we will find (old_num < 0) in that case.
461                  */
462                 if (0 <= info[i]->old_num)
463                         continue;
464                 find_pack_info_one(i);
465         }
466 }
467
468 static int update_info_packs(int force)
469 {
470         char infofile[PATH_MAX];
471         char name[PATH_MAX];
472         int namelen;
473         FILE *fp;
474
475         namelen = sprintf(infofile, "%s/info/packs", get_object_directory());
476         strcpy(name, infofile);
477         strcpy(name + namelen, "+");
478
479         init_pack_info(infofile, force);
480         find_pack_info();
481
482         safe_create_leading_directories(name);
483         fp = fopen(name, "w");
484         if (!fp)
485                 return error("cannot open %s", name);
486         write_pack_info_file(fp);
487         fclose(fp);
488         rename(name, infofile);
489         return 0;
490 }
491
492 /* public */
493 int update_server_info(int force)
494 {
495         /* We would add more dumb-server support files later,
496          * including index of available pack files and their
497          * intended audiences.
498          */
499         int errs = 0;
500
501         errs = errs | update_info_refs(force);
502         errs = errs | update_info_packs(force);
503
504         return errs;
505 }