commit-graph write: show progress for object search
[gitweb.git] / commit-graph.c
index 40c855f1855595fbf5b285008d3c829e6a2f41eb..3124dfae13142ef6784e81fece723f4d19633966 100644 (file)
@@ -21,7 +21,7 @@
 #define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
 #define GRAPH_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
 #define GRAPH_CHUNKID_DATA 0x43444154 /* "CDAT" */
-#define GRAPH_CHUNKID_LARGEEDGES 0x45444745 /* "EDGE" */
+#define GRAPH_CHUNKID_EXTRAEDGES 0x45444745 /* "EDGE" */
 
 #define GRAPH_DATA_WIDTH 36
 
@@ -33,7 +33,7 @@
 #define GRAPH_OID_VERSION GRAPH_OID_VERSION_SHA1
 #define GRAPH_OID_LEN GRAPH_OID_LEN_SHA1
 
-#define GRAPH_OCTOPUS_EDGES_NEEDED 0x80000000
+#define GRAPH_EXTRA_EDGES_NEEDED 0x80000000
 #define GRAPH_PARENT_MISSING 0x7fffffff
 #define GRAPH_EDGE_LAST_MASK 0x7fffffff
 #define GRAPH_PARENT_NONE 0x70000000
@@ -177,11 +177,11 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
                                graph->chunk_commit_data = data + chunk_offset;
                        break;
 
-               case GRAPH_CHUNKID_LARGEEDGES:
-                       if (graph->chunk_large_edges)
+               case GRAPH_CHUNKID_EXTRAEDGES:
+                       if (graph->chunk_extra_edges)
                                chunk_repeated = 1;
                        else
-                               graph->chunk_large_edges = data + chunk_offset;
+                               graph->chunk_extra_edges = data + chunk_offset;
                        break;
                }
 
@@ -230,8 +230,7 @@ static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
  */
 static int prepare_commit_graph(struct repository *r)
 {
-       struct alternate_object_database *alt;
-       char *obj_dir;
+       struct object_directory *odb;
        int config_value;
 
        if (r->objects->commit_graph_attempted)
@@ -252,13 +251,11 @@ static int prepare_commit_graph(struct repository *r)
        if (!commit_graph_compatible(r))
                return 0;
 
-       obj_dir = r->objects->objectdir;
-       prepare_commit_graph_one(r, obj_dir);
        prepare_alt_odb(r);
-       for (alt = r->objects->alt_odb_list;
-            !r->objects->commit_graph && alt;
-            alt = alt->next)
-               prepare_commit_graph_one(r, alt->path);
+       for (odb = r->objects->odb;
+            !r->objects->commit_graph && odb;
+            odb = odb->next)
+               prepare_commit_graph_one(r, odb->path);
        return !!r->objects->commit_graph;
 }
 
@@ -346,12 +343,12 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin
        edge_value = get_be32(commit_data + g->hash_len + 4);
        if (edge_value == GRAPH_PARENT_NONE)
                return 1;
-       if (!(edge_value & GRAPH_OCTOPUS_EDGES_NEEDED)) {
+       if (!(edge_value & GRAPH_EXTRA_EDGES_NEEDED)) {
                pptr = insert_parent_or_die(g, edge_value, pptr);
                return 1;
        }
 
-       parent_data_ptr = (uint32_t*)(g->chunk_large_edges +
+       parent_data_ptr = (uint32_t*)(g->chunk_extra_edges +
                          4 * (uint64_t)(edge_value & GRAPH_EDGE_LAST_MASK));
        do {
                edge_value = get_be32(parent_data_ptr);
@@ -433,7 +430,9 @@ struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit
 
 static void write_graph_chunk_fanout(struct hashfile *f,
                                     struct commit **commits,
-                                    int nr_commits)
+                                    int nr_commits,
+                                    struct progress *progress,
+                                    uint64_t *progress_cnt)
 {
        int i, count = 0;
        struct commit **list = commits;
@@ -447,6 +446,7 @@ static void write_graph_chunk_fanout(struct hashfile *f,
                while (count < nr_commits) {
                        if ((*list)->object.oid.hash[0] != i)
                                break;
+                       display_progress(progress, ++*progress_cnt);
                        count++;
                        list++;
                }
@@ -456,12 +456,16 @@ static void write_graph_chunk_fanout(struct hashfile *f,
 }
 
 static void write_graph_chunk_oids(struct hashfile *f, int hash_len,
-                                  struct commit **commits, int nr_commits)
+                                  struct commit **commits, int nr_commits,
+                                  struct progress *progress,
+                                  uint64_t *progress_cnt)
 {
        struct commit **list = commits;
        int count;
-       for (count = 0; count < nr_commits; count++, list++)
+       for (count = 0; count < nr_commits; count++, list++) {
+               display_progress(progress, ++*progress_cnt);
                hashwrite(f, (*list)->object.oid.hash, (int)hash_len);
+       }
 }
 
 static const unsigned char *commit_to_sha1(size_t index, void *table)
@@ -471,7 +475,9 @@ static const unsigned char *commit_to_sha1(size_t index, void *table)
 }
 
 static void write_graph_chunk_data(struct hashfile *f, int hash_len,
-                                  struct commit **commits, int nr_commits)
+                                  struct commit **commits, int nr_commits,
+                                  struct progress *progress,
+                                  uint64_t *progress_cnt)
 {
        struct commit **list = commits;
        struct commit **last = commits + nr_commits;
@@ -481,6 +487,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                struct commit_list *parent;
                int edge_value;
                uint32_t packedDate[2];
+               display_progress(progress, ++*progress_cnt);
 
                parse_commit(*list);
                hashwrite(f, get_commit_tree_oid(*list)->hash, hash_len);
@@ -507,7 +514,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                if (!parent)
                        edge_value = GRAPH_PARENT_NONE;
                else if (parent->next)
-                       edge_value = GRAPH_OCTOPUS_EDGES_NEEDED | num_extra_edges;
+                       edge_value = GRAPH_EXTRA_EDGES_NEEDED | num_extra_edges;
                else {
                        edge_value = sha1_pos(parent->item->object.oid.hash,
                                              commits,
@@ -519,7 +526,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
 
                hashwrite_be32(f, edge_value);
 
-               if (edge_value & GRAPH_OCTOPUS_EDGES_NEEDED) {
+               if (edge_value & GRAPH_EXTRA_EDGES_NEEDED) {
                        do {
                                num_extra_edges++;
                                parent = parent->next;
@@ -540,9 +547,11 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
        }
 }
 
-static void write_graph_chunk_large_edges(struct hashfile *f,
+static void write_graph_chunk_extra_edges(struct hashfile *f,
                                          struct commit **commits,
-                                         int nr_commits)
+                                         int nr_commits,
+                                         struct progress *progress,
+                                         uint64_t *progress_cnt)
 {
        struct commit **list = commits;
        struct commit **last = commits + nr_commits;
@@ -550,6 +559,9 @@ static void write_graph_chunk_large_edges(struct hashfile *f,
 
        while (list < last) {
                int num_parents = 0;
+
+               display_progress(progress, ++*progress_cnt);
+
                for (parent = (*list)->parents; num_parents < 3 && parent;
                     parent = parent->next)
                        num_parents++;
@@ -641,26 +653,29 @@ static void add_missing_parents(struct packed_oid_list *oids, struct commit *com
 
 static void close_reachable(struct packed_oid_list *oids, int report_progress)
 {
-       int i;
+       int i, j;
        struct commit *commit;
        struct progress *progress = NULL;
-       int j = 0;
 
        if (report_progress)
                progress = start_delayed_progress(
-                       _("Annotating commits in commit graph"), 0);
+                       _("Loading known commits in commit graph"), j = 0);
        for (i = 0; i < oids->nr; i++) {
                display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
                if (commit)
                        commit->object.flags |= UNINTERESTING;
        }
+       stop_progress(&progress);
 
        /*
         * As this loop runs, oids->nr may grow, but not more
         * than the number of missing commits in the reachable
         * closure.
         */
+       if (report_progress)
+               progress = start_delayed_progress(
+                       _("Expanding reachable commits in commit graph"), j = 0);
        for (i = 0; i < oids->nr; i++) {
                display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
@@ -668,7 +683,11 @@ static void close_reachable(struct packed_oid_list *oids, int report_progress)
                if (commit && !parse_commit(commit))
                        add_missing_parents(oids, commit);
        }
+       stop_progress(&progress);
 
+       if (report_progress)
+               progress = start_delayed_progress(
+                       _("Clearing commit marks in commit graph"), j = 0);
        for (i = 0; i < oids->nr; i++) {
                display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
@@ -764,12 +783,16 @@ void write_commit_graph(const char *obj_dir,
        int num_extra_edges;
        struct commit_list *parent;
        struct progress *progress = NULL;
+       uint64_t progress_cnt = 0;
+       struct strbuf progress_title = STRBUF_INIT;
+       unsigned long approx_nr_objects;
 
        if (!commit_graph_compatible(the_repository))
                return;
 
        oids.nr = 0;
-       oids.alloc = approximate_object_count() / 32;
+       approx_nr_objects = approximate_object_count();
+       oids.alloc = approx_nr_objects / 32;
        oids.progress = NULL;
        oids.progress_done = 0;
 
@@ -812,7 +835,8 @@ void write_commit_graph(const char *obj_dir,
                                die(_("error adding pack %s"), packname.buf);
                        if (open_pack_index(p))
                                die(_("error opening index for %s"), packname.buf);
-                       for_each_object_in_pack(p, add_packed_commits, &oids, 0);
+                       for_each_object_in_pack(p, add_packed_commits, &oids,
+                                               FOR_EACH_OBJECT_PACK_ORDER);
                        close_pack(p);
                        free(p);
                }
@@ -849,8 +873,12 @@ void write_commit_graph(const char *obj_dir,
        if (!pack_indexes && !commit_hex) {
                if (report_progress)
                        oids.progress = start_delayed_progress(
-                               _("Finding commits for commit graph"), 0);
-               for_each_packed_object(add_packed_commits, &oids, 0);
+                               _("Finding commits for commit graph"),
+                               approx_nr_objects);
+               for_each_packed_object(add_packed_commits, &oids,
+                                      FOR_EACH_OBJECT_PACK_ORDER);
+               if (oids.progress_done < approx_nr_objects)
+                       display_progress(oids.progress, approx_nr_objects);
                stop_progress(&oids.progress);
        }
 
@@ -917,7 +945,7 @@ void write_commit_graph(const char *obj_dir,
        chunk_ids[1] = GRAPH_CHUNKID_OIDLOOKUP;
        chunk_ids[2] = GRAPH_CHUNKID_DATA;
        if (num_extra_edges)
-               chunk_ids[3] = GRAPH_CHUNKID_LARGEEDGES;
+               chunk_ids[3] = GRAPH_CHUNKID_EXTRAEDGES;
        else
                chunk_ids[3] = 0;
        chunk_ids[4] = 0;
@@ -937,10 +965,23 @@ void write_commit_graph(const char *obj_dir,
                hashwrite(f, chunk_write, 12);
        }
 
-       write_graph_chunk_fanout(f, commits.list, commits.nr);
-       write_graph_chunk_oids(f, GRAPH_OID_LEN, commits.list, commits.nr);
-       write_graph_chunk_data(f, GRAPH_OID_LEN, commits.list, commits.nr);
-       write_graph_chunk_large_edges(f, commits.list, commits.nr);
+       if (report_progress) {
+               strbuf_addf(&progress_title,
+                           Q_("Writing out commit graph in %d pass",
+                              "Writing out commit graph in %d passes",
+                              num_chunks),
+                           num_chunks);
+               progress = start_delayed_progress(
+                       progress_title.buf,
+                       num_chunks * commits.nr);
+       }
+       write_graph_chunk_fanout(f, commits.list, commits.nr, progress, &progress_cnt);
+       write_graph_chunk_oids(f, GRAPH_OID_LEN, commits.list, commits.nr, progress, &progress_cnt);
+       write_graph_chunk_data(f, GRAPH_OID_LEN, commits.list, commits.nr, progress, &progress_cnt);
+       if (num_extra_edges)
+               write_graph_chunk_extra_edges(f, commits.list, commits.nr, progress, &progress_cnt);
+       stop_progress(&progress);
+       strbuf_release(&progress_title);
 
        close_commit_graph(the_repository);
        finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_FSYNC);