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