The commit-graph format includes a way to specify a parent is "missing" from the commit-graph (i.e. we do not have a record of that parent in our list of object IDs, and hence cannot provide a graph position). For mose cases, this does not occur due to the close_reachable() method adding all reachable commits. However, in a shallow clone, we will try to record the parents of a commit on the shallow boundary, but the parents are not in the repository. The GRAPH_PARENT_MISSING value that is stored in the format is purposeful, especially for future plans to make the commit-graph file incremental or transporting sections of a commit-graph file across the network. In the meantime, check if a commit has a missing parent while filling its details from the commit-graph. If a parent is missing, still assign the generation number and graph position for that item, but report that the commit-graph failed to fill the contents. Then the caller is responsible for filling the rest of the data from a commit buffer. Signed-off-by: Derrick Stolee <dstolee@xxxxxxxxxxxxx> --- commit-graph.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/commit-graph.c b/commit-graph.c index 80e377b90f..3e33d061fe 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -278,17 +278,44 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin struct commit_list **pptr; const unsigned char *commit_data = g->chunk_commit_data + (g->hash_len + 16) * pos; - item->object.parsed = 1; + item->generation = get_be32(commit_data + g->hash_len + 8) >> 2; item->graph_pos = pos; + /* + * If we have any edges marked as GRAPH_PARENT_MISSING, we must not parse any + * more of this object and leave it to the commit buffer to parse. + */ + edge_value = get_be32(commit_data + g->hash_len); + if (edge_value == GRAPH_PARENT_MISSING) + return 0; + if (edge_value == GRAPH_PARENT_NONE) + goto continue_parsing; + + edge_value = get_be32(commit_data + g->hash_len + 4); + if (edge_value == GRAPH_PARENT_MISSING) + return 0; + if (edge_value == GRAPH_PARENT_NONE) + goto continue_parsing; + if (!(edge_value & GRAPH_OCTOPUS_EDGES_NEEDED)) + goto continue_parsing; + + parent_data_ptr = (uint32_t*)(g->chunk_large_edges + + 4 * (uint64_t)(edge_value & GRAPH_EDGE_LAST_MASK)); + do { + edge_value = get_be32(parent_data_ptr); + if (edge_value == GRAPH_PARENT_MISSING) + return 0; + parent_data_ptr++; + } while (!(edge_value & GRAPH_LAST_EDGE)); + +continue_parsing: + item->object.parsed = 1; 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); -- 2.16.2.338.gcfe06ae955