commit-graph: add free_commit_graph
[git] / commit-graph.c
1 #include "cache.h"
2 #include "config.h"
3 #include "dir.h"
4 #include "git-compat-util.h"
5 #include "lockfile.h"
6 #include "pack.h"
7 #include "packfile.h"
8 #include "commit.h"
9 #include "object.h"
10 #include "refs.h"
11 #include "revision.h"
12 #include "sha1-lookup.h"
13 #include "commit-graph.h"
14 #include "object-store.h"
15 #include "alloc.h"
16
17 #define GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
18 #define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
19 #define GRAPH_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
20 #define GRAPH_CHUNKID_DATA 0x43444154 /* "CDAT" */
21 #define GRAPH_CHUNKID_LARGEEDGES 0x45444745 /* "EDGE" */
22
23 #define GRAPH_DATA_WIDTH 36
24
25 #define GRAPH_VERSION_1 0x1
26 #define GRAPH_VERSION GRAPH_VERSION_1
27
28 #define GRAPH_OID_VERSION_SHA1 1
29 #define GRAPH_OID_LEN_SHA1 GIT_SHA1_RAWSZ
30 #define GRAPH_OID_VERSION GRAPH_OID_VERSION_SHA1
31 #define GRAPH_OID_LEN GRAPH_OID_LEN_SHA1
32
33 #define GRAPH_OCTOPUS_EDGES_NEEDED 0x80000000
34 #define GRAPH_PARENT_MISSING 0x7fffffff
35 #define GRAPH_EDGE_LAST_MASK 0x7fffffff
36 #define GRAPH_PARENT_NONE 0x70000000
37
38 #define GRAPH_LAST_EDGE 0x80000000
39
40 #define GRAPH_HEADER_SIZE 8
41 #define GRAPH_FANOUT_SIZE (4 * 256)
42 #define GRAPH_CHUNKLOOKUP_WIDTH 12
43 #define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * GRAPH_CHUNKLOOKUP_WIDTH \
44                         + GRAPH_FANOUT_SIZE + GRAPH_OID_LEN)
45
46 char *get_commit_graph_filename(const char *obj_dir)
47 {
48         return xstrfmt("%s/info/commit-graph", obj_dir);
49 }
50
51 static struct commit_graph *alloc_commit_graph(void)
52 {
53         struct commit_graph *g = xcalloc(1, sizeof(*g));
54         g->graph_fd = -1;
55
56         return g;
57 }
58
59 struct commit_graph *load_commit_graph_one(const char *graph_file)
60 {
61         void *graph_map;
62         const unsigned char *data, *chunk_lookup;
63         size_t graph_size;
64         struct stat st;
65         uint32_t i;
66         struct commit_graph *graph;
67         int fd = git_open(graph_file);
68         uint64_t last_chunk_offset;
69         uint32_t last_chunk_id;
70         uint32_t graph_signature;
71         unsigned char graph_version, hash_version;
72
73         if (fd < 0)
74                 return NULL;
75         if (fstat(fd, &st)) {
76                 close(fd);
77                 return NULL;
78         }
79         graph_size = xsize_t(st.st_size);
80
81         if (graph_size < GRAPH_MIN_SIZE) {
82                 close(fd);
83                 die("graph file %s is too small", graph_file);
84         }
85         graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0);
86         data = (const unsigned char *)graph_map;
87
88         graph_signature = get_be32(data);
89         if (graph_signature != GRAPH_SIGNATURE) {
90                 error("graph signature %X does not match signature %X",
91                       graph_signature, GRAPH_SIGNATURE);
92                 goto cleanup_fail;
93         }
94
95         graph_version = *(unsigned char*)(data + 4);
96         if (graph_version != GRAPH_VERSION) {
97                 error("graph version %X does not match version %X",
98                       graph_version, GRAPH_VERSION);
99                 goto cleanup_fail;
100         }
101
102         hash_version = *(unsigned char*)(data + 5);
103         if (hash_version != GRAPH_OID_VERSION) {
104                 error("hash version %X does not match version %X",
105                       hash_version, GRAPH_OID_VERSION);
106                 goto cleanup_fail;
107         }
108
109         graph = alloc_commit_graph();
110
111         graph->hash_len = GRAPH_OID_LEN;
112         graph->num_chunks = *(unsigned char*)(data + 6);
113         graph->graph_fd = fd;
114         graph->data = graph_map;
115         graph->data_len = graph_size;
116
117         last_chunk_id = 0;
118         last_chunk_offset = 8;
119         chunk_lookup = data + 8;
120         for (i = 0; i < graph->num_chunks; i++) {
121                 uint32_t chunk_id = get_be32(chunk_lookup + 0);
122                 uint64_t chunk_offset = get_be64(chunk_lookup + 4);
123                 int chunk_repeated = 0;
124
125                 chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH;
126
127                 if (chunk_offset > graph_size - GIT_MAX_RAWSZ) {
128                         error("improper chunk offset %08x%08x", (uint32_t)(chunk_offset >> 32),
129                               (uint32_t)chunk_offset);
130                         goto cleanup_fail;
131                 }
132
133                 switch (chunk_id) {
134                 case GRAPH_CHUNKID_OIDFANOUT:
135                         if (graph->chunk_oid_fanout)
136                                 chunk_repeated = 1;
137                         else
138                                 graph->chunk_oid_fanout = (uint32_t*)(data + chunk_offset);
139                         break;
140
141                 case GRAPH_CHUNKID_OIDLOOKUP:
142                         if (graph->chunk_oid_lookup)
143                                 chunk_repeated = 1;
144                         else
145                                 graph->chunk_oid_lookup = data + chunk_offset;
146                         break;
147
148                 case GRAPH_CHUNKID_DATA:
149                         if (graph->chunk_commit_data)
150                                 chunk_repeated = 1;
151                         else
152                                 graph->chunk_commit_data = data + chunk_offset;
153                         break;
154
155                 case GRAPH_CHUNKID_LARGEEDGES:
156                         if (graph->chunk_large_edges)
157                                 chunk_repeated = 1;
158                         else
159                                 graph->chunk_large_edges = data + chunk_offset;
160                         break;
161                 }
162
163                 if (chunk_repeated) {
164                         error("chunk id %08x appears multiple times", chunk_id);
165                         goto cleanup_fail;
166                 }
167
168                 if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP)
169                 {
170                         graph->num_commits = (chunk_offset - last_chunk_offset)
171                                              / graph->hash_len;
172                 }
173
174                 last_chunk_id = chunk_id;
175                 last_chunk_offset = chunk_offset;
176         }
177
178         return graph;
179
180 cleanup_fail:
181         munmap(graph_map, graph_size);
182         close(fd);
183         exit(1);
184 }
185
186 /* global storage */
187 static struct commit_graph *commit_graph = NULL;
188
189 static void prepare_commit_graph_one(const char *obj_dir)
190 {
191         char *graph_name;
192
193         if (commit_graph)
194                 return;
195
196         graph_name = get_commit_graph_filename(obj_dir);
197         commit_graph = load_commit_graph_one(graph_name);
198
199         FREE_AND_NULL(graph_name);
200 }
201
202 static int prepare_commit_graph_run_once = 0;
203
204 /*
205  * Return 1 if commit_graph is non-NULL, and 0 otherwise.
206  *
207  * On the first invocation, this function attemps to load the commit
208  * graph if the_repository is configured to have one.
209  */
210 static int prepare_commit_graph(void)
211 {
212         struct alternate_object_database *alt;
213         char *obj_dir;
214
215         if (prepare_commit_graph_run_once)
216                 return !!commit_graph;
217         prepare_commit_graph_run_once = 1;
218
219         if (!core_commit_graph)
220                 return 0;
221
222         obj_dir = get_object_directory();
223         prepare_commit_graph_one(obj_dir);
224         prepare_alt_odb(the_repository);
225         for (alt = the_repository->objects->alt_odb_list;
226              !commit_graph && alt;
227              alt = alt->next)
228                 prepare_commit_graph_one(alt->path);
229         return !!commit_graph;
230 }
231
232 static void close_commit_graph(void)
233 {
234         free_commit_graph(commit_graph);
235         commit_graph = NULL;
236 }
237
238 static int bsearch_graph(struct commit_graph *g, struct object_id *oid, uint32_t *pos)
239 {
240         return bsearch_hash(oid->hash, g->chunk_oid_fanout,
241                             g->chunk_oid_lookup, g->hash_len, pos);
242 }
243
244 static struct commit_list **insert_parent_or_die(struct commit_graph *g,
245                                                  uint64_t pos,
246                                                  struct commit_list **pptr)
247 {
248         struct commit *c;
249         struct object_id oid;
250
251         if (pos >= g->num_commits)
252                 die("invalid parent position %"PRIu64, pos);
253
254         hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * pos);
255         c = lookup_commit(the_repository, &oid);
256         if (!c)
257                 die("could not find commit %s", oid_to_hex(&oid));
258         c->graph_pos = pos;
259         return &commit_list_insert(c, pptr)->next;
260 }
261
262 static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, uint32_t pos)
263 {
264         const unsigned char *commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * pos;
265         item->graph_pos = pos;
266         item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
267 }
268
269 static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t pos)
270 {
271         uint32_t edge_value;
272         uint32_t *parent_data_ptr;
273         uint64_t date_low, date_high;
274         struct commit_list **pptr;
275         const unsigned char *commit_data = g->chunk_commit_data + (g->hash_len + 16) * pos;
276
277         item->object.parsed = 1;
278         item->graph_pos = pos;
279
280         item->maybe_tree = NULL;
281
282         date_high = get_be32(commit_data + g->hash_len + 8) & 0x3;
283         date_low = get_be32(commit_data + g->hash_len + 12);
284         item->date = (timestamp_t)((date_high << 32) | date_low);
285
286         item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
287
288         pptr = &item->parents;
289
290         edge_value = get_be32(commit_data + g->hash_len);
291         if (edge_value == GRAPH_PARENT_NONE)
292                 return 1;
293         pptr = insert_parent_or_die(g, edge_value, pptr);
294
295         edge_value = get_be32(commit_data + g->hash_len + 4);
296         if (edge_value == GRAPH_PARENT_NONE)
297                 return 1;
298         if (!(edge_value & GRAPH_OCTOPUS_EDGES_NEEDED)) {
299                 pptr = insert_parent_or_die(g, edge_value, pptr);
300                 return 1;
301         }
302
303         parent_data_ptr = (uint32_t*)(g->chunk_large_edges +
304                           4 * (uint64_t)(edge_value & GRAPH_EDGE_LAST_MASK));
305         do {
306                 edge_value = get_be32(parent_data_ptr);
307                 pptr = insert_parent_or_die(g,
308                                             edge_value & GRAPH_EDGE_LAST_MASK,
309                                             pptr);
310                 parent_data_ptr++;
311         } while (!(edge_value & GRAPH_LAST_EDGE));
312
313         return 1;
314 }
315
316 static int find_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t *pos)
317 {
318         if (item->graph_pos != COMMIT_NOT_FROM_GRAPH) {
319                 *pos = item->graph_pos;
320                 return 1;
321         } else {
322                 return bsearch_graph(g, &(item->object.oid), pos);
323         }
324 }
325
326 static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item)
327 {
328         uint32_t pos;
329
330         if (!core_commit_graph)
331                 return 0;
332         if (item->object.parsed)
333                 return 1;
334
335         if (find_commit_in_graph(item, g, &pos))
336                 return fill_commit_in_graph(item, g, pos);
337
338         return 0;
339 }
340
341 int parse_commit_in_graph(struct commit *item)
342 {
343         if (!prepare_commit_graph())
344                 return 0;
345         return parse_commit_in_graph_one(commit_graph, item);
346 }
347
348 void load_commit_graph_info(struct commit *item)
349 {
350         uint32_t pos;
351         if (!prepare_commit_graph())
352                 return;
353         if (find_commit_in_graph(item, commit_graph, &pos))
354                 fill_commit_graph_info(item, commit_graph, pos);
355 }
356
357 static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c)
358 {
359         struct object_id oid;
360         const unsigned char *commit_data = g->chunk_commit_data +
361                                            GRAPH_DATA_WIDTH * (c->graph_pos);
362
363         hashcpy(oid.hash, commit_data);
364         c->maybe_tree = lookup_tree(the_repository, &oid);
365
366         return c->maybe_tree;
367 }
368
369 static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g,
370                                                  const struct commit *c)
371 {
372         if (c->maybe_tree)
373                 return c->maybe_tree;
374         if (c->graph_pos == COMMIT_NOT_FROM_GRAPH)
375                 BUG("get_commit_tree_in_graph_one called from non-commit-graph commit");
376
377         return load_tree_for_commit(g, (struct commit *)c);
378 }
379
380 struct tree *get_commit_tree_in_graph(const struct commit *c)
381 {
382         return get_commit_tree_in_graph_one(commit_graph, c);
383 }
384
385 static void write_graph_chunk_fanout(struct hashfile *f,
386                                      struct commit **commits,
387                                      int nr_commits)
388 {
389         int i, count = 0;
390         struct commit **list = commits;
391
392         /*
393          * Write the first-level table (the list is sorted,
394          * but we use a 256-entry lookup to be able to avoid
395          * having to do eight extra binary search iterations).
396          */
397         for (i = 0; i < 256; i++) {
398                 while (count < nr_commits) {
399                         if ((*list)->object.oid.hash[0] != i)
400                                 break;
401                         count++;
402                         list++;
403                 }
404
405                 hashwrite_be32(f, count);
406         }
407 }
408
409 static void write_graph_chunk_oids(struct hashfile *f, int hash_len,
410                                    struct commit **commits, int nr_commits)
411 {
412         struct commit **list = commits;
413         int count;
414         for (count = 0; count < nr_commits; count++, list++)
415                 hashwrite(f, (*list)->object.oid.hash, (int)hash_len);
416 }
417
418 static const unsigned char *commit_to_sha1(size_t index, void *table)
419 {
420         struct commit **commits = table;
421         return commits[index]->object.oid.hash;
422 }
423
424 static void write_graph_chunk_data(struct hashfile *f, int hash_len,
425                                    struct commit **commits, int nr_commits)
426 {
427         struct commit **list = commits;
428         struct commit **last = commits + nr_commits;
429         uint32_t num_extra_edges = 0;
430
431         while (list < last) {
432                 struct commit_list *parent;
433                 int edge_value;
434                 uint32_t packedDate[2];
435
436                 parse_commit(*list);
437                 hashwrite(f, get_commit_tree_oid(*list)->hash, hash_len);
438
439                 parent = (*list)->parents;
440
441                 if (!parent)
442                         edge_value = GRAPH_PARENT_NONE;
443                 else {
444                         edge_value = sha1_pos(parent->item->object.oid.hash,
445                                               commits,
446                                               nr_commits,
447                                               commit_to_sha1);
448
449                         if (edge_value < 0)
450                                 edge_value = GRAPH_PARENT_MISSING;
451                 }
452
453                 hashwrite_be32(f, edge_value);
454
455                 if (parent)
456                         parent = parent->next;
457
458                 if (!parent)
459                         edge_value = GRAPH_PARENT_NONE;
460                 else if (parent->next)
461                         edge_value = GRAPH_OCTOPUS_EDGES_NEEDED | num_extra_edges;
462                 else {
463                         edge_value = sha1_pos(parent->item->object.oid.hash,
464                                               commits,
465                                               nr_commits,
466                                               commit_to_sha1);
467                         if (edge_value < 0)
468                                 edge_value = GRAPH_PARENT_MISSING;
469                 }
470
471                 hashwrite_be32(f, edge_value);
472
473                 if (edge_value & GRAPH_OCTOPUS_EDGES_NEEDED) {
474                         do {
475                                 num_extra_edges++;
476                                 parent = parent->next;
477                         } while (parent);
478                 }
479
480                 if (sizeof((*list)->date) > 4)
481                         packedDate[0] = htonl(((*list)->date >> 32) & 0x3);
482                 else
483                         packedDate[0] = 0;
484
485                 packedDate[0] |= htonl((*list)->generation << 2);
486
487                 packedDate[1] = htonl((*list)->date);
488                 hashwrite(f, packedDate, 8);
489
490                 list++;
491         }
492 }
493
494 static void write_graph_chunk_large_edges(struct hashfile *f,
495                                           struct commit **commits,
496                                           int nr_commits)
497 {
498         struct commit **list = commits;
499         struct commit **last = commits + nr_commits;
500         struct commit_list *parent;
501
502         while (list < last) {
503                 int num_parents = 0;
504                 for (parent = (*list)->parents; num_parents < 3 && parent;
505                      parent = parent->next)
506                         num_parents++;
507
508                 if (num_parents <= 2) {
509                         list++;
510                         continue;
511                 }
512
513                 /* Since num_parents > 2, this initializer is safe. */
514                 for (parent = (*list)->parents->next; parent; parent = parent->next) {
515                         int edge_value = sha1_pos(parent->item->object.oid.hash,
516                                                   commits,
517                                                   nr_commits,
518                                                   commit_to_sha1);
519
520                         if (edge_value < 0)
521                                 edge_value = GRAPH_PARENT_MISSING;
522                         else if (!parent->next)
523                                 edge_value |= GRAPH_LAST_EDGE;
524
525                         hashwrite_be32(f, edge_value);
526                 }
527
528                 list++;
529         }
530 }
531
532 static int commit_compare(const void *_a, const void *_b)
533 {
534         const struct object_id *a = (const struct object_id *)_a;
535         const struct object_id *b = (const struct object_id *)_b;
536         return oidcmp(a, b);
537 }
538
539 struct packed_commit_list {
540         struct commit **list;
541         int nr;
542         int alloc;
543 };
544
545 struct packed_oid_list {
546         struct object_id *list;
547         int nr;
548         int alloc;
549 };
550
551 static int add_packed_commits(const struct object_id *oid,
552                               struct packed_git *pack,
553                               uint32_t pos,
554                               void *data)
555 {
556         struct packed_oid_list *list = (struct packed_oid_list*)data;
557         enum object_type type;
558         off_t offset = nth_packed_object_offset(pack, pos);
559         struct object_info oi = OBJECT_INFO_INIT;
560
561         oi.typep = &type;
562         if (packed_object_info(the_repository, pack, offset, &oi) < 0)
563                 die("unable to get type of object %s", oid_to_hex(oid));
564
565         if (type != OBJ_COMMIT)
566                 return 0;
567
568         ALLOC_GROW(list->list, list->nr + 1, list->alloc);
569         oidcpy(&(list->list[list->nr]), oid);
570         list->nr++;
571
572         return 0;
573 }
574
575 static void add_missing_parents(struct packed_oid_list *oids, struct commit *commit)
576 {
577         struct commit_list *parent;
578         for (parent = commit->parents; parent; parent = parent->next) {
579                 if (!(parent->item->object.flags & UNINTERESTING)) {
580                         ALLOC_GROW(oids->list, oids->nr + 1, oids->alloc);
581                         oidcpy(&oids->list[oids->nr], &(parent->item->object.oid));
582                         oids->nr++;
583                         parent->item->object.flags |= UNINTERESTING;
584                 }
585         }
586 }
587
588 static void close_reachable(struct packed_oid_list *oids)
589 {
590         int i;
591         struct commit *commit;
592
593         for (i = 0; i < oids->nr; i++) {
594                 commit = lookup_commit(the_repository, &oids->list[i]);
595                 if (commit)
596                         commit->object.flags |= UNINTERESTING;
597         }
598
599         /*
600          * As this loop runs, oids->nr may grow, but not more
601          * than the number of missing commits in the reachable
602          * closure.
603          */
604         for (i = 0; i < oids->nr; i++) {
605                 commit = lookup_commit(the_repository, &oids->list[i]);
606
607                 if (commit && !parse_commit(commit))
608                         add_missing_parents(oids, commit);
609         }
610
611         for (i = 0; i < oids->nr; i++) {
612                 commit = lookup_commit(the_repository, &oids->list[i]);
613
614                 if (commit)
615                         commit->object.flags &= ~UNINTERESTING;
616         }
617 }
618
619 static void compute_generation_numbers(struct packed_commit_list* commits)
620 {
621         int i;
622         struct commit_list *list = NULL;
623
624         for (i = 0; i < commits->nr; i++) {
625                 if (commits->list[i]->generation != GENERATION_NUMBER_INFINITY &&
626                     commits->list[i]->generation != GENERATION_NUMBER_ZERO)
627                         continue;
628
629                 commit_list_insert(commits->list[i], &list);
630                 while (list) {
631                         struct commit *current = list->item;
632                         struct commit_list *parent;
633                         int all_parents_computed = 1;
634                         uint32_t max_generation = 0;
635
636                         for (parent = current->parents; parent; parent = parent->next) {
637                                 if (parent->item->generation == GENERATION_NUMBER_INFINITY ||
638                                     parent->item->generation == GENERATION_NUMBER_ZERO) {
639                                         all_parents_computed = 0;
640                                         commit_list_insert(parent->item, &list);
641                                         break;
642                                 } else if (parent->item->generation > max_generation) {
643                                         max_generation = parent->item->generation;
644                                 }
645                         }
646
647                         if (all_parents_computed) {
648                                 current->generation = max_generation + 1;
649                                 pop_commit(&list);
650
651                                 if (current->generation > GENERATION_NUMBER_MAX)
652                                         current->generation = GENERATION_NUMBER_MAX;
653                         }
654                 }
655         }
656 }
657
658 static int add_ref_to_list(const char *refname,
659                            const struct object_id *oid,
660                            int flags, void *cb_data)
661 {
662         struct string_list *list = (struct string_list *)cb_data;
663
664         string_list_append(list, oid_to_hex(oid));
665         return 0;
666 }
667
668 void write_commit_graph_reachable(const char *obj_dir, int append)
669 {
670         struct string_list list;
671
672         string_list_init(&list, 1);
673         for_each_ref(add_ref_to_list, &list);
674         write_commit_graph(obj_dir, NULL, &list, append);
675 }
676
677 void write_commit_graph(const char *obj_dir,
678                         struct string_list *pack_indexes,
679                         struct string_list *commit_hex,
680                         int append)
681 {
682         struct packed_oid_list oids;
683         struct packed_commit_list commits;
684         struct hashfile *f;
685         uint32_t i, count_distinct = 0;
686         char *graph_name;
687         struct lock_file lk = LOCK_INIT;
688         uint32_t chunk_ids[5];
689         uint64_t chunk_offsets[5];
690         int num_chunks;
691         int num_extra_edges;
692         struct commit_list *parent;
693
694         oids.nr = 0;
695         oids.alloc = approximate_object_count() / 4;
696
697         if (append) {
698                 prepare_commit_graph_one(obj_dir);
699                 if (commit_graph)
700                         oids.alloc += commit_graph->num_commits;
701         }
702
703         if (oids.alloc < 1024)
704                 oids.alloc = 1024;
705         ALLOC_ARRAY(oids.list, oids.alloc);
706
707         if (append && commit_graph) {
708                 for (i = 0; i < commit_graph->num_commits; i++) {
709                         const unsigned char *hash = commit_graph->chunk_oid_lookup +
710                                 commit_graph->hash_len * i;
711                         hashcpy(oids.list[oids.nr++].hash, hash);
712                 }
713         }
714
715         if (pack_indexes) {
716                 struct strbuf packname = STRBUF_INIT;
717                 int dirlen;
718                 strbuf_addf(&packname, "%s/pack/", obj_dir);
719                 dirlen = packname.len;
720                 for (i = 0; i < pack_indexes->nr; i++) {
721                         struct packed_git *p;
722                         strbuf_setlen(&packname, dirlen);
723                         strbuf_addstr(&packname, pack_indexes->items[i].string);
724                         p = add_packed_git(packname.buf, packname.len, 1);
725                         if (!p)
726                                 die("error adding pack %s", packname.buf);
727                         if (open_pack_index(p))
728                                 die("error opening index for %s", packname.buf);
729                         for_each_object_in_pack(p, add_packed_commits, &oids);
730                         close_pack(p);
731                 }
732                 strbuf_release(&packname);
733         }
734
735         if (commit_hex) {
736                 for (i = 0; i < commit_hex->nr; i++) {
737                         const char *end;
738                         struct object_id oid;
739                         struct commit *result;
740
741                         if (commit_hex->items[i].string &&
742                             parse_oid_hex(commit_hex->items[i].string, &oid, &end))
743                                 continue;
744
745                         result = lookup_commit_reference_gently(the_repository, &oid, 1);
746
747                         if (result) {
748                                 ALLOC_GROW(oids.list, oids.nr + 1, oids.alloc);
749                                 oidcpy(&oids.list[oids.nr], &(result->object.oid));
750                                 oids.nr++;
751                         }
752                 }
753         }
754
755         if (!pack_indexes && !commit_hex)
756                 for_each_packed_object(add_packed_commits, &oids, 0);
757
758         close_reachable(&oids);
759
760         QSORT(oids.list, oids.nr, commit_compare);
761
762         count_distinct = 1;
763         for (i = 1; i < oids.nr; i++) {
764                 if (oidcmp(&oids.list[i-1], &oids.list[i]))
765                         count_distinct++;
766         }
767
768         if (count_distinct >= GRAPH_PARENT_MISSING)
769                 die(_("the commit graph format cannot write %d commits"), count_distinct);
770
771         commits.nr = 0;
772         commits.alloc = count_distinct;
773         ALLOC_ARRAY(commits.list, commits.alloc);
774
775         num_extra_edges = 0;
776         for (i = 0; i < oids.nr; i++) {
777                 int num_parents = 0;
778                 if (i > 0 && !oidcmp(&oids.list[i-1], &oids.list[i]))
779                         continue;
780
781                 commits.list[commits.nr] = lookup_commit(the_repository, &oids.list[i]);
782                 parse_commit(commits.list[commits.nr]);
783
784                 for (parent = commits.list[commits.nr]->parents;
785                      parent; parent = parent->next)
786                         num_parents++;
787
788                 if (num_parents > 2)
789                         num_extra_edges += num_parents - 1;
790
791                 commits.nr++;
792         }
793         num_chunks = num_extra_edges ? 4 : 3;
794
795         if (commits.nr >= GRAPH_PARENT_MISSING)
796                 die(_("too many commits to write graph"));
797
798         compute_generation_numbers(&commits);
799
800         graph_name = get_commit_graph_filename(obj_dir);
801         if (safe_create_leading_directories(graph_name))
802                 die_errno(_("unable to create leading directories of %s"),
803                           graph_name);
804
805         hold_lock_file_for_update(&lk, graph_name, LOCK_DIE_ON_ERROR);
806         f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
807
808         hashwrite_be32(f, GRAPH_SIGNATURE);
809
810         hashwrite_u8(f, GRAPH_VERSION);
811         hashwrite_u8(f, GRAPH_OID_VERSION);
812         hashwrite_u8(f, num_chunks);
813         hashwrite_u8(f, 0); /* unused padding byte */
814
815         chunk_ids[0] = GRAPH_CHUNKID_OIDFANOUT;
816         chunk_ids[1] = GRAPH_CHUNKID_OIDLOOKUP;
817         chunk_ids[2] = GRAPH_CHUNKID_DATA;
818         if (num_extra_edges)
819                 chunk_ids[3] = GRAPH_CHUNKID_LARGEEDGES;
820         else
821                 chunk_ids[3] = 0;
822         chunk_ids[4] = 0;
823
824         chunk_offsets[0] = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
825         chunk_offsets[1] = chunk_offsets[0] + GRAPH_FANOUT_SIZE;
826         chunk_offsets[2] = chunk_offsets[1] + GRAPH_OID_LEN * commits.nr;
827         chunk_offsets[3] = chunk_offsets[2] + (GRAPH_OID_LEN + 16) * commits.nr;
828         chunk_offsets[4] = chunk_offsets[3] + 4 * num_extra_edges;
829
830         for (i = 0; i <= num_chunks; i++) {
831                 uint32_t chunk_write[3];
832
833                 chunk_write[0] = htonl(chunk_ids[i]);
834                 chunk_write[1] = htonl(chunk_offsets[i] >> 32);
835                 chunk_write[2] = htonl(chunk_offsets[i] & 0xffffffff);
836                 hashwrite(f, chunk_write, 12);
837         }
838
839         write_graph_chunk_fanout(f, commits.list, commits.nr);
840         write_graph_chunk_oids(f, GRAPH_OID_LEN, commits.list, commits.nr);
841         write_graph_chunk_data(f, GRAPH_OID_LEN, commits.list, commits.nr);
842         write_graph_chunk_large_edges(f, commits.list, commits.nr);
843
844         close_commit_graph();
845         finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_FSYNC);
846         commit_lock_file(&lk);
847
848         free(oids.list);
849         oids.alloc = 0;
850         oids.nr = 0;
851 }
852
853 #define VERIFY_COMMIT_GRAPH_ERROR_HASH 2
854 static int verify_commit_graph_error;
855
856 static void graph_report(const char *fmt, ...)
857 {
858         va_list ap;
859
860         verify_commit_graph_error = 1;
861         va_start(ap, fmt);
862         vfprintf(stderr, fmt, ap);
863         fprintf(stderr, "\n");
864         va_end(ap);
865 }
866
867 #define GENERATION_ZERO_EXISTS 1
868 #define GENERATION_NUMBER_EXISTS 2
869
870 int verify_commit_graph(struct repository *r, struct commit_graph *g)
871 {
872         uint32_t i, cur_fanout_pos = 0;
873         struct object_id prev_oid, cur_oid, checksum;
874         int generation_zero = 0;
875         struct hashfile *f;
876         int devnull;
877
878         if (!g) {
879                 graph_report("no commit-graph file loaded");
880                 return 1;
881         }
882
883         verify_commit_graph_error = 0;
884
885         if (!g->chunk_oid_fanout)
886                 graph_report("commit-graph is missing the OID Fanout chunk");
887         if (!g->chunk_oid_lookup)
888                 graph_report("commit-graph is missing the OID Lookup chunk");
889         if (!g->chunk_commit_data)
890                 graph_report("commit-graph is missing the Commit Data chunk");
891
892         if (verify_commit_graph_error)
893                 return verify_commit_graph_error;
894
895         devnull = open("/dev/null", O_WRONLY);
896         f = hashfd(devnull, NULL);
897         hashwrite(f, g->data, g->data_len - g->hash_len);
898         finalize_hashfile(f, checksum.hash, CSUM_CLOSE);
899         if (hashcmp(checksum.hash, g->data + g->data_len - g->hash_len)) {
900                 graph_report(_("the commit-graph file has incorrect checksum and is likely corrupt"));
901                 verify_commit_graph_error = VERIFY_COMMIT_GRAPH_ERROR_HASH;
902         }
903
904         for (i = 0; i < g->num_commits; i++) {
905                 struct commit *graph_commit;
906
907                 hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
908
909                 if (i && oidcmp(&prev_oid, &cur_oid) >= 0)
910                         graph_report("commit-graph has incorrect OID order: %s then %s",
911                                      oid_to_hex(&prev_oid),
912                                      oid_to_hex(&cur_oid));
913
914                 oidcpy(&prev_oid, &cur_oid);
915
916                 while (cur_oid.hash[0] > cur_fanout_pos) {
917                         uint32_t fanout_value = get_be32(g->chunk_oid_fanout + cur_fanout_pos);
918
919                         if (i != fanout_value)
920                                 graph_report("commit-graph has incorrect fanout value: fanout[%d] = %u != %u",
921                                              cur_fanout_pos, fanout_value, i);
922                         cur_fanout_pos++;
923                 }
924
925                 graph_commit = lookup_commit(r, &cur_oid);
926                 if (!parse_commit_in_graph_one(g, graph_commit))
927                         graph_report("failed to parse %s from commit-graph",
928                                      oid_to_hex(&cur_oid));
929         }
930
931         while (cur_fanout_pos < 256) {
932                 uint32_t fanout_value = get_be32(g->chunk_oid_fanout + cur_fanout_pos);
933
934                 if (g->num_commits != fanout_value)
935                         graph_report("commit-graph has incorrect fanout value: fanout[%d] = %u != %u",
936                                      cur_fanout_pos, fanout_value, i);
937
938                 cur_fanout_pos++;
939         }
940
941         if (verify_commit_graph_error & ~VERIFY_COMMIT_GRAPH_ERROR_HASH)
942                 return verify_commit_graph_error;
943
944         for (i = 0; i < g->num_commits; i++) {
945                 struct commit *graph_commit, *odb_commit;
946                 struct commit_list *graph_parents, *odb_parents;
947                 uint32_t max_generation = 0;
948
949                 hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
950
951                 graph_commit = lookup_commit(r, &cur_oid);
952                 odb_commit = (struct commit *)create_object(r, cur_oid.hash, alloc_commit_node(r));
953                 if (parse_commit_internal(odb_commit, 0, 0)) {
954                         graph_report("failed to parse %s from object database",
955                                      oid_to_hex(&cur_oid));
956                         continue;
957                 }
958
959                 if (oidcmp(&get_commit_tree_in_graph_one(g, graph_commit)->object.oid,
960                            get_commit_tree_oid(odb_commit)))
961                         graph_report("root tree OID for commit %s in commit-graph is %s != %s",
962                                      oid_to_hex(&cur_oid),
963                                      oid_to_hex(get_commit_tree_oid(graph_commit)),
964                                      oid_to_hex(get_commit_tree_oid(odb_commit)));
965
966                 graph_parents = graph_commit->parents;
967                 odb_parents = odb_commit->parents;
968
969                 while (graph_parents) {
970                         if (odb_parents == NULL) {
971                                 graph_report("commit-graph parent list for commit %s is too long",
972                                              oid_to_hex(&cur_oid));
973                                 break;
974                         }
975
976                         if (oidcmp(&graph_parents->item->object.oid, &odb_parents->item->object.oid))
977                                 graph_report("commit-graph parent for %s is %s != %s",
978                                              oid_to_hex(&cur_oid),
979                                              oid_to_hex(&graph_parents->item->object.oid),
980                                              oid_to_hex(&odb_parents->item->object.oid));
981
982                         if (graph_parents->item->generation > max_generation)
983                                 max_generation = graph_parents->item->generation;
984
985                         graph_parents = graph_parents->next;
986                         odb_parents = odb_parents->next;
987                 }
988
989                 if (odb_parents != NULL)
990                         graph_report("commit-graph parent list for commit %s terminates early",
991                                      oid_to_hex(&cur_oid));
992
993                 if (!graph_commit->generation) {
994                         if (generation_zero == GENERATION_NUMBER_EXISTS)
995                                 graph_report("commit-graph has generation number zero for commit %s, but non-zero elsewhere",
996                                              oid_to_hex(&cur_oid));
997                         generation_zero = GENERATION_ZERO_EXISTS;
998                 } else if (generation_zero == GENERATION_ZERO_EXISTS)
999                         graph_report("commit-graph has non-zero generation number for commit %s, but zero elsewhere",
1000                                      oid_to_hex(&cur_oid));
1001
1002                 if (generation_zero == GENERATION_ZERO_EXISTS)
1003                         continue;
1004
1005                 /*
1006                  * If one of our parents has generation GENERATION_NUMBER_MAX, then
1007                  * our generation is also GENERATION_NUMBER_MAX. Decrement to avoid
1008                  * extra logic in the following condition.
1009                  */
1010                 if (max_generation == GENERATION_NUMBER_MAX)
1011                         max_generation--;
1012
1013                 if (graph_commit->generation != max_generation + 1)
1014                         graph_report("commit-graph generation for commit %s is %u != %u",
1015                                      oid_to_hex(&cur_oid),
1016                                      graph_commit->generation,
1017                                      max_generation + 1);
1018
1019                 if (graph_commit->date != odb_commit->date)
1020                         graph_report("commit date for commit %s in commit-graph is %"PRItime" != %"PRItime,
1021                                      oid_to_hex(&cur_oid),
1022                                      graph_commit->date,
1023                                      odb_commit->date);
1024         }
1025
1026         return verify_commit_graph_error;
1027 }
1028
1029 void free_commit_graph(struct commit_graph *g)
1030 {
1031         if (!g)
1032                 return;
1033         if (g->graph_fd >= 0) {
1034                 munmap((void *)g->data, g->data_len);
1035                 g->data = NULL;
1036                 close(g->graph_fd);
1037         }
1038         free(g);
1039 }