convert.c: mark more strings for translation
[gitweb.git] / commit-graph.c
index 3ff8c84c0e4438e5367c4e2a2911917f9cc84102..c8d521923c29fbc48d36ff3bd7cd02d5638b910e 100644 (file)
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "config.h"
+#include "dir.h"
 #include "git-compat-util.h"
 #include "lockfile.h"
 #include "pack.h"
@@ -9,6 +10,7 @@
 #include "revision.h"
 #include "sha1-lookup.h"
 #include "commit-graph.h"
+#include "object-store.h"
 
 #define GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
 #define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
@@ -75,28 +77,28 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
 
        if (graph_size < GRAPH_MIN_SIZE) {
                close(fd);
-               die("graph file %s is too small", graph_file);
+               die(_("graph file %s is too small"), graph_file);
        }
        graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0);
        data = (const unsigned char *)graph_map;
 
        graph_signature = get_be32(data);
        if (graph_signature != GRAPH_SIGNATURE) {
-               error("graph signature %X does not match signature %X",
+               error(_("graph signature %X does not match signature %X"),
                      graph_signature, GRAPH_SIGNATURE);
                goto cleanup_fail;
        }
 
        graph_version = *(unsigned char*)(data + 4);
        if (graph_version != GRAPH_VERSION) {
-               error("graph version %X does not match version %X",
+               error(_("graph version %X does not match version %X"),
                      graph_version, GRAPH_VERSION);
                goto cleanup_fail;
        }
 
        hash_version = *(unsigned char*)(data + 5);
        if (hash_version != GRAPH_OID_VERSION) {
-               error("hash version %X does not match version %X",
+               error(_("hash version %X does not match version %X"),
                      hash_version, GRAPH_OID_VERSION);
                goto cleanup_fail;
        }
@@ -120,7 +122,7 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
                chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH;
 
                if (chunk_offset > graph_size - GIT_MAX_RAWSZ) {
-                       error("improper chunk offset %08x%08x", (uint32_t)(chunk_offset >> 32),
+                       error(_("improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32),
                              (uint32_t)chunk_offset);
                        goto cleanup_fail;
                }
@@ -156,7 +158,7 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
                }
 
                if (chunk_repeated) {
-                       error("chunk id %08x appears multiple times", chunk_id);
+                       error(_("chunk id %08x appears multiple times"), chunk_id);
                        goto cleanup_fail;
                }
 
@@ -206,8 +208,10 @@ static void prepare_commit_graph(void)
 
        obj_dir = get_object_directory();
        prepare_commit_graph_one(obj_dir);
-       prepare_alt_odb();
-       for (alt = alt_odb_list; !commit_graph && alt; alt = alt->next)
+       prepare_alt_odb(the_repository);
+       for (alt = the_repository->objects->alt_odb_list;
+            !commit_graph && alt;
+            alt = alt->next)
                prepare_commit_graph_one(alt->path);
 }
 
@@ -240,14 +244,20 @@ static struct commit_list **insert_parent_or_die(struct commit_graph *g,
        hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * pos);
        c = lookup_commit(&oid);
        if (!c)
-               die("could not find commit %s", oid_to_hex(&oid));
+               die(_("could not find commit %s"), oid_to_hex(&oid));
        c->graph_pos = pos;
        return &commit_list_insert(c, pptr)->next;
 }
 
+static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, uint32_t pos)
+{
+       const unsigned char *commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * pos;
+       item->graph_pos = pos;
+       item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
+}
+
 static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t pos)
 {
-       struct object_id oid;
        uint32_t edge_value;
        uint32_t *parent_data_ptr;
        uint64_t date_low, date_high;
@@ -257,13 +267,14 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin
        item->object.parsed = 1;
        item->graph_pos = pos;
 
-       hashcpy(oid.hash, commit_data);
-       item->tree = lookup_tree(&oid);
+       item->maybe_tree = NULL;
 
        date_high = get_be32(commit_data + g->hash_len + 8) & 0x3;
        date_low = get_be32(commit_data + g->hash_len + 12);
        item->date = (timestamp_t)((date_high << 32) | date_low);
 
+       item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
+
        pptr = &item->parents;
 
        edge_value = get_be32(commit_data + g->hash_len);
@@ -292,29 +303,60 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin
        return 1;
 }
 
+static int find_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t *pos)
+{
+       if (item->graph_pos != COMMIT_NOT_FROM_GRAPH) {
+               *pos = item->graph_pos;
+               return 1;
+       } else {
+               return bsearch_graph(g, &(item->object.oid), pos);
+       }
+}
+
 int parse_commit_in_graph(struct commit *item)
 {
+       uint32_t pos;
+
        if (!core_commit_graph)
                return 0;
        if (item->object.parsed)
                return 1;
+       prepare_commit_graph();
+       if (commit_graph && find_commit_in_graph(item, commit_graph, &pos))
+               return fill_commit_in_graph(item, commit_graph, pos);
+       return 0;
+}
 
+void load_commit_graph_info(struct commit *item)
+{
+       uint32_t pos;
+       if (!core_commit_graph)
+               return;
        prepare_commit_graph();
-       if (commit_graph) {
-               uint32_t pos;
-               int found;
-               if (item->graph_pos != COMMIT_NOT_FROM_GRAPH) {
-                       pos = item->graph_pos;
-                       found = 1;
-               } else {
-                       found = bsearch_graph(commit_graph, &(item->object.oid), &pos);
-               }
+       if (commit_graph && find_commit_in_graph(item, commit_graph, &pos))
+               fill_commit_graph_info(item, commit_graph, pos);
+}
 
-               if (found)
-                       return fill_commit_in_graph(item, commit_graph, pos);
-       }
+static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c)
+{
+       struct object_id oid;
+       const unsigned char *commit_data = g->chunk_commit_data +
+                                          GRAPH_DATA_WIDTH * (c->graph_pos);
 
-       return 0;
+       hashcpy(oid.hash, commit_data);
+       c->maybe_tree = lookup_tree(&oid);
+
+       return c->maybe_tree;
+}
+
+struct tree *get_commit_tree_in_graph(const struct commit *c)
+{
+       if (c->maybe_tree)
+               return c->maybe_tree;
+       if (c->graph_pos == COMMIT_NOT_FROM_GRAPH)
+               BUG("get_commit_tree_in_graph called from non-commit-graph commit");
+
+       return load_tree_for_commit(commit_graph, (struct commit *)c);
 }
 
 static void write_graph_chunk_fanout(struct hashfile *f,
@@ -369,7 +411,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                uint32_t packedDate[2];
 
                parse_commit(*list);
-               hashwrite(f, (*list)->tree->object.oid.hash, hash_len);
+               hashwrite(f, get_commit_tree_oid(*list)->hash, hash_len);
 
                parent = (*list)->parents;
 
@@ -417,6 +459,8 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                else
                        packedDate[0] = 0;
 
+               packedDate[0] |= htonl((*list)->generation << 2);
+
                packedDate[1] = htonl((*list)->date);
                hashwrite(f, packedDate, 8);
 
@@ -492,8 +536,8 @@ static int add_packed_commits(const struct object_id *oid,
        struct object_info oi = OBJECT_INFO_INIT;
 
        oi.typep = &type;
-       if (packed_object_info(pack, offset, &oi) < 0)
-               die("unable to get type of object %s", oid_to_hex(oid));
+       if (packed_object_info(the_repository, pack, offset, &oi) < 0)
+               die(_("unable to get type of object %s"), oid_to_hex(oid));
 
        if (type != OBJ_COMMIT)
                return 0;
@@ -549,6 +593,45 @@ static void close_reachable(struct packed_oid_list *oids)
        }
 }
 
+static void compute_generation_numbers(struct packed_commit_list* commits)
+{
+       int i;
+       struct commit_list *list = NULL;
+
+       for (i = 0; i < commits->nr; i++) {
+               if (commits->list[i]->generation != GENERATION_NUMBER_INFINITY &&
+                   commits->list[i]->generation != GENERATION_NUMBER_ZERO)
+                       continue;
+
+               commit_list_insert(commits->list[i], &list);
+               while (list) {
+                       struct commit *current = list->item;
+                       struct commit_list *parent;
+                       int all_parents_computed = 1;
+                       uint32_t max_generation = 0;
+
+                       for (parent = current->parents; parent; parent = parent->next) {
+                               if (parent->item->generation == GENERATION_NUMBER_INFINITY ||
+                                   parent->item->generation == GENERATION_NUMBER_ZERO) {
+                                       all_parents_computed = 0;
+                                       commit_list_insert(parent->item, &list);
+                                       break;
+                               } else if (parent->item->generation > max_generation) {
+                                       max_generation = parent->item->generation;
+                               }
+                       }
+
+                       if (all_parents_computed) {
+                               current->generation = max_generation + 1;
+                               pop_commit(&list);
+
+                               if (current->generation > GENERATION_NUMBER_MAX)
+                                       current->generation = GENERATION_NUMBER_MAX;
+                       }
+               }
+       }
+}
+
 void write_commit_graph(const char *obj_dir,
                        const char **pack_indexes,
                        int nr_packs,
@@ -561,7 +644,6 @@ void write_commit_graph(const char *obj_dir,
        struct hashfile *f;
        uint32_t i, count_distinct = 0;
        char *graph_name;
-       int fd;
        struct lock_file lk = LOCK_INIT;
        uint32_t chunk_ids[5];
        uint64_t chunk_offsets[5];
@@ -601,9 +683,9 @@ void write_commit_graph(const char *obj_dir,
                        strbuf_addstr(&packname, pack_indexes[i]);
                        p = add_packed_git(packname.buf, packname.len, 1);
                        if (!p)
-                               die("error adding pack %s", packname.buf);
+                               die(_("error adding pack %s"), packname.buf);
                        if (open_pack_index(p))
-                               die("error opening index for %s", packname.buf);
+                               die(_("error opening index for %s"), packname.buf);
                        for_each_object_in_pack(p, add_packed_commits, &oids);
                        close_pack(p);
                }
@@ -672,24 +754,14 @@ void write_commit_graph(const char *obj_dir,
        if (commits.nr >= GRAPH_PARENT_MISSING)
                die(_("too many commits to write graph"));
 
-       graph_name = get_commit_graph_filename(obj_dir);
-       fd = hold_lock_file_for_update(&lk, graph_name, 0);
-
-       if (fd < 0) {
-               struct strbuf folder = STRBUF_INIT;
-               strbuf_addstr(&folder, graph_name);
-               strbuf_setlen(&folder, strrchr(folder.buf, '/') - folder.buf);
-
-               if (mkdir(folder.buf, 0777) < 0)
-                       die_errno(_("cannot mkdir %s"), folder.buf);
-               strbuf_release(&folder);
+       compute_generation_numbers(&commits);
 
-               fd = hold_lock_file_for_update(&lk, graph_name, LOCK_DIE_ON_ERROR);
-
-               if (fd < 0)
-                       die_errno("unable to create '%s'", graph_name);
-       }
+       graph_name = get_commit_graph_filename(obj_dir);
+       if (safe_create_leading_directories(graph_name))
+               die_errno(_("unable to create leading directories of %s"),
+                         graph_name);
 
+       hold_lock_file_for_update(&lk, graph_name, LOCK_DIE_ON_ERROR);
        f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
 
        hashwrite_be32(f, GRAPH_SIGNATURE);