When running 'git commit-graph verify', compare the contents of the
commits that are loaded from the commit-graph file with commits that are
loaded directly from the object database. This includes checking the
root tree object ID, commit date, and parents.

Parse the commit from the graph during the initial loop through the
object IDs to guarantee we parse from the commit-graph file.

In addition, verify the generation number calculation is correct for all
commits in the commit-graph file.

Signed-off-by: Derrick Stolee <dsto...@microsoft.com>
---
 commit-graph.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/commit-graph.c b/commit-graph.c
index 8c636abba9..24f5031f3e 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -863,6 +863,8 @@ int verify_commit_graph(struct commit_graph *g)
                graph_report(_("commit-graph is missing the Commit Data 
chunk"));
 
        for (i = 0; i < g->num_commits; i++) {
+               struct commit *graph_commit;
+
                hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
 
                if (i > 0 && oidcmp(&prev_oid, &cur_oid) >= 0)
@@ -880,6 +882,10 @@ int verify_commit_graph(struct commit_graph *g)
 
                        cur_fanout_pos++;
                }
+
+               graph_commit = lookup_commit(&cur_oid);
+               if (!parse_commit_in_graph_one(g, graph_commit))
+                       graph_report(_("failed to parse %s from commit-graph"), 
oid_to_hex(&cur_oid));
        }
 
        while (cur_fanout_pos < 256) {
@@ -892,5 +898,87 @@ int verify_commit_graph(struct commit_graph *g)
                cur_fanout_pos++;
        }
 
+       for (i = 0; i < g->num_commits; i++) {
+               struct commit *graph_commit, *odb_commit;
+               struct commit_list *graph_parents, *odb_parents;
+               int num_parents = 0;
+
+               hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
+
+               graph_commit = lookup_commit(&cur_oid);
+               odb_commit = (struct commit *)create_object(cur_oid.hash, 
alloc_commit_node());
+               if (parse_commit_internal(odb_commit, 0, 0))
+                       graph_report(_("failed to parse %s from object 
database"), oid_to_hex(&cur_oid));
+
+               if (oidcmp(&get_commit_tree_in_graph_one(g, 
graph_commit)->object.oid,
+                          get_commit_tree_oid(odb_commit)))
+                       graph_report(_("root tree object ID for commit %s in 
commit-graph is %s != %s"),
+                                    oid_to_hex(&cur_oid),
+                                    
oid_to_hex(get_commit_tree_oid(graph_commit)),
+                                    
oid_to_hex(get_commit_tree_oid(odb_commit)));
+
+               if (graph_commit->date != odb_commit->date)
+                       graph_report(_("commit date for commit %s in 
commit-graph is %"PRItime" != %"PRItime""),
+                                    oid_to_hex(&cur_oid),
+                                    graph_commit->date,
+                                    odb_commit->date);
+
+
+               graph_parents = graph_commit->parents;
+               odb_parents = odb_commit->parents;
+
+               while (graph_parents) {
+                       num_parents++;
+
+                       if (odb_parents == NULL)
+                               graph_report(_("commit-graph parent list for 
commit %s is too long (%d)"),
+                                            oid_to_hex(&cur_oid),
+                                            num_parents);
+
+                       if (oidcmp(&graph_parents->item->object.oid, 
&odb_parents->item->object.oid))
+                               graph_report(_("commit-graph parent for %s is 
%s != %s"),
+                                            oid_to_hex(&cur_oid),
+                                            
oid_to_hex(&graph_parents->item->object.oid),
+                                            
oid_to_hex(&odb_parents->item->object.oid));
+
+                       graph_parents = graph_parents->next;
+                       odb_parents = odb_parents->next;
+               }
+
+               if (odb_parents != NULL)
+                       graph_report(_("commit-graph parent list for commit %s 
terminates early"),
+                                    oid_to_hex(&cur_oid));
+
+               if (graph_commit->generation) {
+                       uint32_t max_generation = 0;
+                       graph_parents = graph_commit->parents;
+
+                       while (graph_parents) {
+                               if (graph_parents->item->generation == 
GENERATION_NUMBER_ZERO ||
+                                   graph_parents->item->generation == 
GENERATION_NUMBER_INFINITY)
+                                       graph_report(_("commit-graph has valid 
generation for %s but not its parent, %s"),
+                                                    oid_to_hex(&cur_oid),
+                                                    
oid_to_hex(&graph_parents->item->object.oid));
+                               if (graph_parents->item->generation > 
max_generation)
+                                       max_generation = 
graph_parents->item->generation;
+                               graph_parents = graph_parents->next;
+                       }
+
+                       if (graph_commit->generation != max_generation + 1)
+                               graph_report(_("commit-graph has incorrect 
generation for %s"),
+                                            oid_to_hex(&cur_oid));
+               } else {
+                       graph_parents = graph_commit->parents;
+
+                       while (graph_parents) {
+                               if (graph_parents->item->generation)
+                                       graph_report(_("commit-graph has 
generation ZERO for %s but not its parent, %s"),
+                                                    oid_to_hex(&cur_oid),
+                                                    
oid_to_hex(&graph_parents->item->object.oid));
+                               graph_parents = graph_parents->next;
+                       }
+               }
+       }
+
        return verify_commit_graph_error;
 }
-- 
2.16.2.329.gfb62395de6

Reply via email to