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