diff options
-rw-r--r-- | builtin/commit-graph.c | 9 | ||||
-rw-r--r-- | builtin/commit.c | 2 | ||||
-rw-r--r-- | builtin/merge.c | 2 | ||||
-rw-r--r-- | commit-graph.c | 283 | ||||
-rw-r--r-- | commit-graph.h | 21 | ||||
-rw-r--r-- | oss-fuzz/fuzz-commit-graph.c | 6 | ||||
-rw-r--r-- | t/helper/test-read-graph.c | 2 |
7 files changed, 157 insertions, 168 deletions
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 4992ac146e..6656187f90 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -109,7 +109,8 @@ static int graph_verify(int argc, const char **argv, const char *prefix, opened = OPENED_GRAPH; else if (errno != ENOENT) die_errno(_("Could not open commit-graph '%s'"), graph_name); - else if (open_commit_graph_chain(chain_name, &fd, &st)) + else if (open_commit_graph_chain(chain_name, &fd, &st, + the_repository->hash_algo)) opened = OPENED_CHAIN; else if (errno != ENOENT) die_errno(_("could not open commit-graph chain '%s'"), chain_name); @@ -121,15 +122,15 @@ static int graph_verify(int argc, const char **argv, const char *prefix, if (opened == OPENED_NONE) return 0; else if (opened == OPENED_GRAPH) - graph = load_commit_graph_one_fd_st(the_repository, fd, &st, source); + graph = load_commit_graph_one_fd_st(source, fd, &st); else - graph = load_commit_graph_chain_fd_st(the_repository, fd, &st, + graph = load_commit_graph_chain_fd_st(the_repository->objects, fd, &st, &incomplete_chain); if (!graph) return 1; - ret = verify_commit_graph(the_repository, graph, flags); + ret = verify_commit_graph(graph, flags); free_commit_graph(graph); if (incomplete_chain) { diff --git a/builtin/commit.c b/builtin/commit.c index b5b9608813..8a5dee384d 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1947,7 +1947,7 @@ int cmd_commit(int argc, "new index file. Check that disk is not full and quota is\n" "not exceeded, and then \"git restore --staged :/\" to recover.")); - git_test_write_commit_graph_or_die(); + git_test_write_commit_graph_or_die(the_repository->objects->sources); repo_rerere(the_repository, 0); run_auto_maintenance(quiet); diff --git a/builtin/merge.c b/builtin/merge.c index 783ca66377..b235af730a 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1863,7 +1863,7 @@ int cmd_merge(int argc, if (squash) { finish(head_commit, remoteheads, NULL, NULL); - git_test_write_commit_graph_or_die(); + git_test_write_commit_graph_or_die(the_repository->objects->sources); } else write_merge_state(remoteheads); diff --git a/commit-graph.c b/commit-graph.c index e0d92b816f..3cd9e73e2a 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -29,7 +28,7 @@ #include "tree.h" #include "chunk-format.h" -void git_test_write_commit_graph_or_die(void) +void git_test_write_commit_graph_or_die(struct odb_source *source) { int flags = 0; if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0)) @@ -38,8 +37,7 @@ void git_test_write_commit_graph_or_die(void) if (git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0)) flags = COMMIT_GRAPH_WRITE_BLOOM_FILTERS; - if (write_commit_graph_reachable(the_repository->objects->sources, - flags, NULL)) + if (write_commit_graph_reachable(source, flags, NULL)) die("failed to write commit-graph under GIT_TEST_COMMIT_GRAPH"); } @@ -54,8 +52,6 @@ void git_test_write_commit_graph_or_die(void) #define GRAPH_CHUNKID_BLOOMDATA 0x42444154 /* "BDAT" */ #define GRAPH_CHUNKID_BASE 0x42415345 /* "BASE" */ -#define GRAPH_DATA_WIDTH (the_hash_algo->rawsz + 16) - #define GRAPH_VERSION_1 0x1 #define GRAPH_VERSION GRAPH_VERSION_1 @@ -67,8 +63,6 @@ void git_test_write_commit_graph_or_die(void) #define GRAPH_HEADER_SIZE 8 #define GRAPH_FANOUT_SIZE (4 * 256) -#define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * CHUNK_TOC_ENTRY_SIZE \ - + GRAPH_FANOUT_SIZE + the_hash_algo->rawsz) #define CORRECTED_COMMIT_DATE_OFFSET_OVERFLOW (1ULL << 31) @@ -81,6 +75,16 @@ define_commit_slab(topo_level_slab, uint32_t); define_commit_slab(commit_pos, int); static struct commit_pos commit_pos = COMMIT_SLAB_INIT(1, commit_pos); +static size_t graph_data_width(const struct git_hash_algo *algop) +{ + return algop->rawsz + 16; +} + +static size_t graph_min_size(const struct git_hash_algo *algop) +{ + return GRAPH_HEADER_SIZE + 4 * CHUNK_TOC_ENTRY_SIZE + GRAPH_FANOUT_SIZE + algop->rawsz; +} + static void set_commit_pos(struct repository *r, const struct object_id *oid) { static int32_t max_pos; @@ -249,9 +253,8 @@ int open_commit_graph(const char *graph_file, int *fd, struct stat *st) return 1; } -struct commit_graph *load_commit_graph_one_fd_st(struct repository *r, - int fd, struct stat *st, - struct odb_source *source) +struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source, + int fd, struct stat *st) { void *graph_map; size_t graph_size; @@ -259,16 +262,15 @@ struct commit_graph *load_commit_graph_one_fd_st(struct repository *r, graph_size = xsize_t(st->st_size); - if (graph_size < GRAPH_MIN_SIZE) { + if (graph_size < graph_min_size(source->odb->repo->hash_algo)) { close(fd); error(_("commit-graph file is too small")); return NULL; } graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); - prepare_repo_settings(r); - ret = parse_commit_graph(&r->settings, graph_map, graph_size); + ret = parse_commit_graph(source->odb->repo, graph_map, graph_size); if (ret) ret->odb_source = source; else @@ -306,7 +308,7 @@ static int graph_read_oid_lookup(const unsigned char *chunk_start, { struct commit_graph *g = data; g->chunk_oid_lookup = chunk_start; - if (chunk_size / g->hash_len != g->num_commits) + if (chunk_size / g->hash_algo->rawsz != g->num_commits) return error(_("commit-graph OID lookup chunk is the wrong size")); return 0; } @@ -315,7 +317,7 @@ static int graph_read_commit_data(const unsigned char *chunk_start, size_t chunk_size, void *data) { struct commit_graph *g = data; - if (chunk_size / GRAPH_DATA_WIDTH != g->num_commits) + if (chunk_size / graph_data_width(g->hash_algo) != g->num_commits) return error(_("commit-graph commit data chunk is wrong size")); g->chunk_commit_data = chunk_start; return 0; @@ -368,7 +370,7 @@ static int graph_read_bloom_data(const unsigned char *chunk_start, return 0; } -struct commit_graph *parse_commit_graph(struct repo_settings *s, +struct commit_graph *parse_commit_graph(struct repository *r, void *graph_map, size_t graph_size) { const unsigned char *data; @@ -380,7 +382,7 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, if (!graph_map) return NULL; - if (graph_size < GRAPH_MIN_SIZE) + if (graph_size < graph_min_size(r->hash_algo)) return NULL; data = (const unsigned char *)graph_map; @@ -400,22 +402,22 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, } hash_version = *(unsigned char*)(data + 5); - if (hash_version != oid_version(the_hash_algo)) { + if (hash_version != oid_version(r->hash_algo)) { error(_("commit-graph hash version %X does not match version %X"), - hash_version, oid_version(the_hash_algo)); + hash_version, oid_version(r->hash_algo)); return NULL; } graph = alloc_commit_graph(); - graph->hash_len = the_hash_algo->rawsz; + graph->hash_algo = r->hash_algo; graph->num_chunks = *(unsigned char*)(data + 6); graph->data = graph_map; graph->data_len = graph_size; if (graph_size < GRAPH_HEADER_SIZE + (graph->num_chunks + 1) * CHUNK_TOC_ENTRY_SIZE + - GRAPH_FANOUT_SIZE + the_hash_algo->rawsz) { + GRAPH_FANOUT_SIZE + r->hash_algo->rawsz) { error(_("commit-graph file is too small to hold %u chunks"), graph->num_chunks); free(graph); @@ -446,7 +448,9 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, pair_chunk(cf, GRAPH_CHUNKID_BASE, &graph->chunk_base_graphs, &graph->chunk_base_graphs_size); - if (s->commit_graph_generation_version >= 2) { + prepare_repo_settings(r); + + if (r->settings.commit_graph_generation_version >= 2) { read_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA, graph_read_generation_data, graph); pair_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW, @@ -457,7 +461,7 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, graph->read_generation_data = 1; } - if (s->commit_graph_changed_paths_version) { + if (r->settings.commit_graph_changed_paths_version) { read_chunk(cf, GRAPH_CHUNKID_BLOOMINDEXES, graph_read_bloom_index, graph); read_chunk(cf, GRAPH_CHUNKID_BLOOMDATA, @@ -473,8 +477,8 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, FREE_AND_NULL(graph->bloom_filter_settings); } - oidread(&graph->oid, graph->data + graph->data_len - graph->hash_len, - the_repository->hash_algo); + oidread(&graph->oid, graph->data + graph->data_len - graph->hash_algo->rawsz, + r->hash_algo); free_chunkfile(cf); return graph; @@ -486,11 +490,9 @@ free_and_return: return NULL; } -static struct commit_graph *load_commit_graph_one(struct repository *r, - const char *graph_file, - struct odb_source *source) +static struct commit_graph *load_commit_graph_one(struct odb_source *source, + const char *graph_file) { - struct stat st; int fd; struct commit_graph *g; @@ -499,19 +501,17 @@ static struct commit_graph *load_commit_graph_one(struct repository *r, if (!open_ok) return NULL; - g = load_commit_graph_one_fd_st(r, fd, &st, source); - + g = load_commit_graph_one_fd_st(source, fd, &st); if (g) g->filename = xstrdup(graph_file); return g; } -static struct commit_graph *load_commit_graph_v1(struct repository *r, - struct odb_source *source) +static struct commit_graph *load_commit_graph_v1(struct odb_source *source) { char *graph_name = get_commit_graph_filename(source); - struct commit_graph *g = load_commit_graph_one(r, graph_name, source); + struct commit_graph *g = load_commit_graph_one(source, graph_name); free(graph_name); return g; @@ -579,7 +579,7 @@ static int add_graph_to_chain(struct commit_graph *g, return 0; } - if (g->chunk_base_graphs_size / g->hash_len < n) { + if (g->chunk_base_graphs_size / g->hash_algo->rawsz < n) { warning(_("commit-graph base graphs chunk is too small")); return 0; } @@ -589,8 +589,8 @@ static int add_graph_to_chain(struct commit_graph *g, if (!cur_g || !oideq(&oids[n], &cur_g->oid) || - !hasheq(oids[n].hash, g->chunk_base_graphs + st_mult(g->hash_len, n), - the_repository->hash_algo)) { + !hasheq(oids[n].hash, g->chunk_base_graphs + st_mult(g->hash_algo->rawsz, n), + g->hash_algo)) { warning(_("commit-graph chain does not match")); return 0; } @@ -614,7 +614,8 @@ static int add_graph_to_chain(struct commit_graph *g, } int open_commit_graph_chain(const char *chain_file, - int *fd, struct stat *st) + int *fd, struct stat *st, + const struct git_hash_algo *hash_algo) { *fd = git_open(chain_file); if (*fd < 0) @@ -623,7 +624,7 @@ int open_commit_graph_chain(const char *chain_file, close(*fd); return 0; } - if (st->st_size < the_hash_algo->hexsz) { + if (st->st_size < hash_algo->hexsz) { close(*fd); if (!st->st_size) { /* treat empty files the same as missing */ @@ -637,7 +638,7 @@ int open_commit_graph_chain(const char *chain_file, return 1; } -struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r, +struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb, int fd, struct stat *st, int *incomplete_chain) { @@ -647,10 +648,10 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r, int i = 0, valid = 1, count; FILE *fp = xfdopen(fd, "r"); - count = st->st_size / (the_hash_algo->hexsz + 1); + count = st->st_size / (odb->repo->hash_algo->hexsz + 1); CALLOC_ARRAY(oids, count); - odb_prepare_alternates(r->objects); + odb_prepare_alternates(odb); for (i = 0; i < count; i++) { struct odb_source *source; @@ -658,7 +659,7 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r, if (strbuf_getline_lf(&line, fp) == EOF) break; - if (get_oid_hex(line.buf, &oids[i])) { + if (get_oid_hex_algop(line.buf, &oids[i], odb->repo->hash_algo)) { warning(_("invalid commit-graph chain: line '%s' not a hash"), line.buf); valid = 0; @@ -666,9 +667,9 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r, } valid = 0; - for (source = r->objects->sources; source; source = source->next) { + for (source = odb->sources; source; source = source->next) { char *graph_name = get_split_graph_filename(source, line.buf); - struct commit_graph *g = load_commit_graph_one(r, graph_name, source); + struct commit_graph *g = load_commit_graph_one(source, graph_name); free(graph_name); @@ -701,50 +702,38 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r, return graph_chain; } -static struct commit_graph *load_commit_graph_chain(struct repository *r, - struct odb_source *source) +static struct commit_graph *load_commit_graph_chain(struct odb_source *source) { char *chain_file = get_commit_graph_chain_filename(source); struct stat st; int fd; struct commit_graph *g = NULL; - if (open_commit_graph_chain(chain_file, &fd, &st)) { + if (open_commit_graph_chain(chain_file, &fd, &st, source->odb->repo->hash_algo)) { int incomplete; /* ownership of fd is taken over by load function */ - g = load_commit_graph_chain_fd_st(r, fd, &st, &incomplete); + g = load_commit_graph_chain_fd_st(source->odb, fd, &st, &incomplete); } free(chain_file); return g; } -struct commit_graph *read_commit_graph_one(struct repository *r, - struct odb_source *source) +struct commit_graph *read_commit_graph_one(struct odb_source *source) { - struct commit_graph *g = load_commit_graph_v1(r, source); + struct commit_graph *g = load_commit_graph_v1(source); if (!g) - g = load_commit_graph_chain(r, source); + g = load_commit_graph_chain(source); return g; } -static void prepare_commit_graph_one(struct repository *r, - struct odb_source *source) -{ - - if (r->objects->commit_graph) - return; - - r->objects->commit_graph = read_commit_graph_one(r, source); -} - /* * Return 1 if commit_graph is non-NULL, and 0 otherwise. * * On the first invocation, this function attempts to load the commit - * graph if the_repository is configured to have one. + * graph if the repository is configured to have one. */ static int prepare_commit_graph(struct repository *r) { @@ -780,10 +769,12 @@ static int prepare_commit_graph(struct repository *r) return 0; odb_prepare_alternates(r->objects); - for (source = r->objects->sources; - !r->objects->commit_graph && source; - source = source->next) - prepare_commit_graph_one(r, source); + for (source = r->objects->sources; source; source = source->next) { + r->objects->commit_graph = read_commit_graph_one(source); + if (r->objects->commit_graph) + break; + } + return !!r->objects->commit_graph; } @@ -800,7 +791,7 @@ int generation_numbers_enabled(struct repository *r) return 0; first_generation = get_be32(g->chunk_commit_data + - g->hash_len + 8) >> 2; + g->hash_algo->rawsz + 8) >> 2; return !!first_generation; } @@ -844,7 +835,7 @@ void close_commit_graph(struct object_database *o) static int bsearch_graph(struct commit_graph *g, const struct object_id *oid, uint32_t *pos) { return bsearch_hash(oid->hash, g->chunk_oid_fanout, - g->chunk_oid_lookup, g->hash_len, pos); + g->chunk_oid_lookup, g->hash_algo->rawsz, pos); } static void load_oid_from_graph(struct commit_graph *g, @@ -864,12 +855,11 @@ static void load_oid_from_graph(struct commit_graph *g, lex_index = pos - g->num_commits_in_base; - oidread(oid, g->chunk_oid_lookup + st_mult(g->hash_len, lex_index), - the_repository->hash_algo); + oidread(oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, lex_index), + g->hash_algo); } -static struct commit_list **insert_parent_or_die(struct repository *r, - struct commit_graph *g, +static struct commit_list **insert_parent_or_die(struct commit_graph *g, uint32_t pos, struct commit_list **pptr) { @@ -880,7 +870,7 @@ static struct commit_list **insert_parent_or_die(struct repository *r, die("invalid parent position %"PRIu32, pos); load_oid_from_graph(g, pos, &oid); - c = lookup_commit(r, &oid); + c = lookup_commit(g->odb_source->odb->repo, &oid); if (!c) die(_("could not find commit %s"), oid_to_hex(&oid)); commit_graph_data_at(c)->graph_pos = pos; @@ -901,13 +891,13 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, die(_("invalid commit position. commit-graph is likely corrupt")); lex_index = pos - g->num_commits_in_base; - commit_data = g->chunk_commit_data + st_mult(GRAPH_DATA_WIDTH, lex_index); + commit_data = g->chunk_commit_data + st_mult(graph_data_width(g->hash_algo), lex_index); graph_data = commit_graph_data_at(item); graph_data->graph_pos = pos; - date_high = get_be32(commit_data + g->hash_len + 8) & 0x3; - date_low = get_be32(commit_data + g->hash_len + 12); + date_high = get_be32(commit_data + g->hash_algo->rawsz + 8) & 0x3; + date_low = get_be32(commit_data + g->hash_algo->rawsz + 12); item->date = (timestamp_t)((date_high << 32) | date_low); if (g->read_generation_data) { @@ -925,10 +915,10 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, } else graph_data->generation = item->date + offset; } else - graph_data->generation = get_be32(commit_data + g->hash_len + 8) >> 2; + graph_data->generation = get_be32(commit_data + g->hash_algo->rawsz + 8) >> 2; if (g->topo_levels) - *topo_level_slab_at(g->topo_levels, item) = get_be32(commit_data + g->hash_len + 8) >> 2; + *topo_level_slab_at(g->topo_levels, item) = get_be32(commit_data + g->hash_algo->rawsz + 8) >> 2; } static inline void set_commit_tree(struct commit *c, struct tree *t) @@ -936,8 +926,7 @@ static inline void set_commit_tree(struct commit *c, struct tree *t) c->maybe_tree = t; } -static int fill_commit_in_graph(struct repository *r, - struct commit *item, +static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t pos) { uint32_t edge_value; @@ -952,7 +941,7 @@ static int fill_commit_in_graph(struct repository *r, fill_commit_graph_info(item, g, pos); lex_index = pos - g->num_commits_in_base; - commit_data = g->chunk_commit_data + st_mult(g->hash_len + 16, lex_index); + commit_data = g->chunk_commit_data + st_mult(g->hash_algo->rawsz + 16, lex_index); item->object.parsed = 1; @@ -960,16 +949,16 @@ static int fill_commit_in_graph(struct repository *r, pptr = &item->parents; - edge_value = get_be32(commit_data + g->hash_len); + edge_value = get_be32(commit_data + g->hash_algo->rawsz); if (edge_value == GRAPH_PARENT_NONE) return 1; - pptr = insert_parent_or_die(r, g, edge_value, pptr); + pptr = insert_parent_or_die(g, edge_value, pptr); - edge_value = get_be32(commit_data + g->hash_len + 4); + edge_value = get_be32(commit_data + g->hash_algo->rawsz + 4); if (edge_value == GRAPH_PARENT_NONE) return 1; if (!(edge_value & GRAPH_EXTRA_EDGES_NEEDED)) { - pptr = insert_parent_or_die(r, g, edge_value, pptr); + pptr = insert_parent_or_die(g, edge_value, pptr); return 1; } @@ -984,7 +973,7 @@ static int fill_commit_in_graph(struct repository *r, } edge_value = get_be32(g->chunk_extra_edges + sizeof(uint32_t) * parent_data_pos); - pptr = insert_parent_or_die(r, g, + pptr = insert_parent_or_die(g, edge_value & GRAPH_EDGE_LAST_MASK, pptr); parent_data_pos++; @@ -1050,14 +1039,13 @@ struct commit *lookup_commit_in_graph(struct repository *repo, const struct obje if (commit->object.parsed) return commit; - if (!fill_commit_in_graph(repo, commit, repo->objects->commit_graph, pos)) + if (!fill_commit_in_graph(commit, repo->objects->commit_graph, pos)) return NULL; return commit; } -static int parse_commit_in_graph_one(struct repository *r, - struct commit_graph *g, +static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item) { uint32_t pos; @@ -1066,7 +1054,7 @@ static int parse_commit_in_graph_one(struct repository *r, return 1; if (find_commit_pos_in_graph(item, g, &pos)) - return fill_commit_in_graph(r, item, g, pos); + return fill_commit_in_graph(item, g, pos); return 0; } @@ -1083,7 +1071,7 @@ int parse_commit_in_graph(struct repository *r, struct commit *item) if (!prepare_commit_graph(r)) return 0; - return parse_commit_in_graph_one(r, r->objects->commit_graph, item); + return parse_commit_in_graph_one(r->objects->commit_graph, item); } void load_commit_graph_info(struct repository *r, struct commit *item) @@ -1093,8 +1081,7 @@ void load_commit_graph_info(struct repository *r, struct commit *item) fill_commit_graph_info(item, r->objects->commit_graph, pos); } -static struct tree *load_tree_for_commit(struct repository *r, - struct commit_graph *g, +static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c) { struct object_id oid; @@ -1105,16 +1092,16 @@ static struct tree *load_tree_for_commit(struct repository *r, g = g->base_graph; commit_data = g->chunk_commit_data + - st_mult(GRAPH_DATA_WIDTH, graph_pos - g->num_commits_in_base); + st_mult(graph_data_width(g->hash_algo), + graph_pos - g->num_commits_in_base); - oidread(&oid, commit_data, the_repository->hash_algo); - set_commit_tree(c, lookup_tree(r, &oid)); + oidread(&oid, commit_data, g->hash_algo); + set_commit_tree(c, lookup_tree(g->odb_source->odb->repo, &oid)); return c->maybe_tree; } -static struct tree *get_commit_tree_in_graph_one(struct repository *r, - struct commit_graph *g, +static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g, const struct commit *c) { if (c->maybe_tree) @@ -1122,12 +1109,12 @@ static struct tree *get_commit_tree_in_graph_one(struct repository *r, if (commit_graph_position(c) == COMMIT_NOT_FROM_GRAPH) BUG("get_commit_tree_in_graph_one called from non-commit-graph commit"); - return load_tree_for_commit(r, g, (struct commit *)c); + return load_tree_for_commit(g, (struct commit *)c); } struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit *c) { - return get_commit_tree_in_graph_one(r, r->objects->commit_graph, c); + return get_commit_tree_in_graph_one(r->objects->commit_graph, c); } struct packed_commit_list { @@ -1213,7 +1200,7 @@ static int write_graph_chunk_oids(struct hashfile *f, int count; for (count = 0; count < ctx->commits.nr; count++, list++) { display_progress(ctx->progress, ++ctx->progress_cnt); - hashwrite(f, (*list)->object.oid.hash, the_hash_algo->rawsz); + hashwrite(f, (*list)->object.oid.hash, f->algop->rawsz); } return 0; @@ -1244,7 +1231,7 @@ static int write_graph_chunk_data(struct hashfile *f, die(_("unable to parse commit %s"), oid_to_hex(&(*list)->object.oid)); tree = get_commit_tree_oid(*list); - hashwrite(f, tree->hash, the_hash_algo->rawsz); + hashwrite(f, tree->hash, ctx->r->hash_algo->rawsz); parent = (*list)->parents; @@ -1534,7 +1521,7 @@ static void close_reachable(struct write_commit_graph_context *ctx) if (ctx->report_progress) ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Loading known commits in commit graph"), ctx->oids.nr); for (i = 0; i < ctx->oids.nr; i++) { @@ -1552,7 +1539,7 @@ static void close_reachable(struct write_commit_graph_context *ctx) */ if (ctx->report_progress) ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Expanding reachable commits in commit graph"), 0); for (i = 0; i < ctx->oids.nr; i++) { @@ -1573,7 +1560,7 @@ static void close_reachable(struct write_commit_graph_context *ctx) if (ctx->report_progress) ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Clearing commit marks in commit graph"), ctx->oids.nr); for (i = 0; i < ctx->oids.nr; i++) { @@ -1691,7 +1678,7 @@ static void compute_topological_levels(struct write_commit_graph_context *ctx) if (ctx->report_progress) info.progress = ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Computing commit graph topological levels"), ctx->commits.nr); @@ -1726,7 +1713,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx) if (ctx->report_progress) info.progress = ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Computing commit graph generation numbers"), ctx->commits.nr); @@ -1803,7 +1790,7 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx) if (ctx->report_progress) progress = start_delayed_progress( - the_repository, + ctx->r, _("Computing commit changed paths Bloom filters"), ctx->commits.nr); @@ -1849,6 +1836,7 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx) } struct refs_cb_data { + struct repository *repo; struct oidset *commits; struct progress *progress; }; @@ -1861,9 +1849,9 @@ static int add_ref_to_set(const char *refname UNUSED, struct object_id peeled; struct refs_cb_data *data = (struct refs_cb_data *)cb_data; - if (!peel_iterated_oid(the_repository, oid, &peeled)) + if (!peel_iterated_oid(data->repo, oid, &peeled)) oid = &peeled; - if (odb_read_object_info(the_repository->objects, oid, NULL) == OBJ_COMMIT) + if (odb_read_object_info(data->repo->objects, oid, NULL) == OBJ_COMMIT) oidset_insert(data->commits, oid); display_progress(data->progress, oidset_size(data->commits)); @@ -1880,13 +1868,15 @@ int write_commit_graph_reachable(struct odb_source *source, int result; memset(&data, 0, sizeof(data)); + data.repo = source->odb->repo; data.commits = &commits; + if (flags & COMMIT_GRAPH_WRITE_PROGRESS) data.progress = start_delayed_progress( - the_repository, + source->odb->repo, _("Collecting referenced commits"), 0); - refs_for_each_ref(get_main_ref_store(the_repository), add_ref_to_set, + refs_for_each_ref(get_main_ref_store(source->odb->repo), add_ref_to_set, &data); stop_progress(&data.progress); @@ -1915,7 +1905,7 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx, "Finding commits for commit graph in %"PRIuMAX" packs", pack_indexes->nr), (uintmax_t)pack_indexes->nr); - ctx->progress = start_delayed_progress(the_repository, + ctx->progress = start_delayed_progress(ctx->r, progress_title.buf, 0); ctx->progress_done = 0; } @@ -1969,7 +1959,7 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx) { if (ctx->report_progress) ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Finding commits for commit graph among packed objects"), ctx->approx_nr_objects); for_each_packed_object(ctx->r, add_packed_commits, ctx, @@ -1988,7 +1978,7 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx) ctx->num_extra_edges = 0; if (ctx->report_progress) ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Finding extra edges in commit graph"), ctx->oids.nr); oid_array_sort(&ctx->oids); @@ -2027,7 +2017,7 @@ static int write_graph_chunk_base_1(struct hashfile *f, return 0; num = write_graph_chunk_base_1(f, g->base_graph); - hashwrite(f, g->oid.hash, the_hash_algo->rawsz); + hashwrite(f, g->oid.hash, g->hash_algo->rawsz); return num + 1; } @@ -2051,7 +2041,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) struct hashfile *f; struct tempfile *graph_layer; /* when ctx->split is non-zero */ struct lock_file lk = LOCK_INIT; - const unsigned hashsz = the_hash_algo->rawsz; + const unsigned hashsz = ctx->r->hash_algo->rawsz; struct strbuf progress_title = STRBUF_INIT; struct chunkfile *cf; unsigned char file_hash[GIT_MAX_RAWSZ]; @@ -2067,7 +2057,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) ctx->graph_name = get_commit_graph_filename(ctx->odb_source); } - if (safe_create_leading_directories(the_repository, ctx->graph_name)) { + if (safe_create_leading_directories(ctx->r, ctx->graph_name)) { error(_("unable to create leading directories of %s"), ctx->graph_name); return -1; @@ -2086,18 +2076,18 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) return -1; } - if (adjust_shared_perm(the_repository, get_tempfile_path(graph_layer))) { + if (adjust_shared_perm(ctx->r, get_tempfile_path(graph_layer))) { error(_("unable to adjust shared permissions for '%s'"), get_tempfile_path(graph_layer)); return -1; } - f = hashfd(the_repository->hash_algo, + f = hashfd(ctx->r->hash_algo, get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer)); } else { hold_lock_file_for_update_mode(&lk, ctx->graph_name, LOCK_DIE_ON_ERROR, 0444); - f = hashfd(the_repository->hash_algo, + f = hashfd(ctx->r->hash_algo, get_lock_file_fd(&lk), get_lock_file_path(&lk)); } @@ -2139,7 +2129,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) hashwrite_be32(f, GRAPH_SIGNATURE); hashwrite_u8(f, GRAPH_VERSION); - hashwrite_u8(f, oid_version(the_hash_algo)); + hashwrite_u8(f, oid_version(ctx->r->hash_algo)); hashwrite_u8(f, get_num_chunks(cf)); hashwrite_u8(f, ctx->num_commit_graphs_after - 1); @@ -2150,7 +2140,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) get_num_chunks(cf)), get_num_chunks(cf)); ctx->progress = start_delayed_progress( - the_repository, + ctx->r, progress_title.buf, st_mult(get_num_chunks(cf), ctx->commits.nr)); } @@ -2208,7 +2198,8 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) } free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]); - ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] = xstrdup(hash_to_hex(file_hash)); + ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] = + xstrdup(hash_to_hex_algop(file_hash, ctx->r->hash_algo)); final_graph_name = get_split_graph_filename(ctx->odb_source, ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]); free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1]); @@ -2363,7 +2354,7 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx) if (ctx->report_progress) ctx->progress = start_delayed_progress( - the_repository, + ctx->r, _("Scanning merged commits"), ctx->commits.nr); @@ -2408,7 +2399,7 @@ static void merge_commit_graphs(struct write_commit_graph_context *ctx) current_graph_number--; if (ctx->report_progress) - ctx->progress = start_delayed_progress(the_repository, + ctx->progress = start_delayed_progress(ctx->r, _("Merging commit-graph"), 0); merge_commit_graph(ctx, g); @@ -2511,7 +2502,7 @@ int write_commit_graph(struct odb_source *source, enum commit_graph_write_flags flags, const struct commit_graph_opts *opts) { - struct repository *r = the_repository; + struct repository *r = source->odb->repo; struct write_commit_graph_context ctx = { .r = r, .odb_source = source, @@ -2611,14 +2602,14 @@ int write_commit_graph(struct odb_source *source, replace = ctx.opts->split_flags & COMMIT_GRAPH_SPLIT_REPLACE; } - ctx.approx_nr_objects = repo_approximate_object_count(the_repository); + ctx.approx_nr_objects = repo_approximate_object_count(r); if (ctx.append && ctx.r->objects->commit_graph) { struct commit_graph *g = ctx.r->objects->commit_graph; for (i = 0; i < g->num_commits; i++) { struct object_id oid; - oidread(&oid, g->chunk_oid_lookup + st_mult(g->hash_len, i), - the_repository->hash_algo); + oidread(&oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, i), + r->hash_algo); oid_array_append(&ctx.oids, &oid); } } @@ -2726,15 +2717,15 @@ static void graph_report(const char *fmt, ...) static int commit_graph_checksum_valid(struct commit_graph *g) { - return hashfile_checksum_valid(the_repository->hash_algo, + return hashfile_checksum_valid(g->hash_algo, g->data, g->data_len); } -static int verify_one_commit_graph(struct repository *r, - struct commit_graph *g, +static int verify_one_commit_graph(struct commit_graph *g, struct progress *progress, uint64_t *seen) { + struct repository *r = g->odb_source->odb->repo; uint32_t i, cur_fanout_pos = 0; struct object_id prev_oid, cur_oid; struct commit *seen_gen_zero = NULL; @@ -2748,8 +2739,8 @@ static int verify_one_commit_graph(struct repository *r, for (i = 0; i < g->num_commits; i++) { struct commit *graph_commit; - oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_len, i), - the_repository->hash_algo); + oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, i), + g->hash_algo); if (i && oidcmp(&prev_oid, &cur_oid) >= 0) graph_report(_("commit-graph has incorrect OID order: %s then %s"), @@ -2768,7 +2759,7 @@ static int verify_one_commit_graph(struct repository *r, } graph_commit = lookup_commit(r, &cur_oid); - if (!parse_commit_in_graph_one(r, g, graph_commit)) + if (!parse_commit_in_graph_one(g, graph_commit)) graph_report(_("failed to parse commit %s from commit-graph"), oid_to_hex(&cur_oid)); } @@ -2793,8 +2784,8 @@ static int verify_one_commit_graph(struct repository *r, timestamp_t generation; display_progress(progress, ++(*seen)); - oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_len, i), - the_repository->hash_algo); + oidread(&cur_oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, i), + g->hash_algo); graph_commit = lookup_commit(r, &cur_oid); odb_commit = (struct commit *)create_object(r, &cur_oid, alloc_commit_node(r)); @@ -2804,7 +2795,7 @@ static int verify_one_commit_graph(struct repository *r, continue; } - if (!oideq(&get_commit_tree_in_graph_one(r, g, graph_commit)->object.oid, + if (!oideq(&get_commit_tree_in_graph_one(g, graph_commit)->object.oid, get_commit_tree_oid(odb_commit))) graph_report(_("root tree OID for commit %s in commit-graph is %s != %s"), oid_to_hex(&cur_oid), @@ -2822,7 +2813,7 @@ static int verify_one_commit_graph(struct repository *r, } /* parse parent in case it is in a base graph */ - parse_commit_in_graph_one(r, g, graph_parents->item); + parse_commit_in_graph_one(g, graph_parents->item); if (!oideq(&graph_parents->item->object.oid, &odb_parents->item->object.oid)) graph_report(_("commit-graph parent for %s is %s != %s"), @@ -2882,7 +2873,7 @@ static int verify_one_commit_graph(struct repository *r, return verify_commit_graph_error; } -int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) +int verify_commit_graph(struct commit_graph *g, int flags) { struct progress *progress = NULL; int local_error = 0; @@ -2898,13 +2889,13 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) if (!(flags & COMMIT_GRAPH_VERIFY_SHALLOW)) total += g->num_commits_in_base; - progress = start_progress(the_repository, + progress = start_progress(g->odb_source->odb->repo, _("Verifying commits in commit graph"), total); } for (; g; g = g->base_graph) { - local_error |= verify_one_commit_graph(r, g, progress, &seen); + local_error |= verify_one_commit_graph(g, progress, &seen); if (flags & COMMIT_GRAPH_VERIFY_SHALLOW) break; } diff --git a/commit-graph.h b/commit-graph.h index 78ab7b875b..4899b54ef8 100644 --- a/commit-graph.h +++ b/commit-graph.h @@ -21,7 +21,7 @@ * call this method oustide of a builtin, and only if you know what * you are doing! */ -void git_test_write_commit_graph_or_die(void); +void git_test_write_commit_graph_or_die(struct odb_source *source); struct commit; struct bloom_filter_settings; @@ -32,7 +32,8 @@ struct string_list; char *get_commit_graph_filename(struct odb_source *source); char *get_commit_graph_chain_filename(struct odb_source *source); int open_commit_graph(const char *graph_file, int *fd, struct stat *st); -int open_commit_graph_chain(const char *chain_file, int *fd, struct stat *st); +int open_commit_graph_chain(const char *chain_file, int *fd, struct stat *st, + const struct git_hash_algo *hash_algo); /* * Given a commit struct, try to fill the commit struct info, including: @@ -84,7 +85,7 @@ struct commit_graph { const unsigned char *data; size_t data_len; - unsigned char hash_len; + const struct git_hash_algo *hash_algo; unsigned char num_chunks; uint32_t num_commits; struct object_id oid; @@ -113,14 +114,12 @@ struct commit_graph { struct bloom_filter_settings *bloom_filter_settings; }; -struct commit_graph *load_commit_graph_one_fd_st(struct repository *r, - int fd, struct stat *st, - struct odb_source *source); -struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r, +struct commit_graph *load_commit_graph_one_fd_st(struct odb_source *source, + int fd, struct stat *st); +struct commit_graph *load_commit_graph_chain_fd_st(struct object_database *odb, int fd, struct stat *st, int *incomplete_chain); -struct commit_graph *read_commit_graph_one(struct repository *r, - struct odb_source *source); +struct commit_graph *read_commit_graph_one(struct odb_source *source); struct repo_settings; @@ -128,7 +127,7 @@ struct repo_settings; * Callers should initialize the repo_settings with prepare_repo_settings() * prior to calling parse_commit_graph(). */ -struct commit_graph *parse_commit_graph(struct repo_settings *s, +struct commit_graph *parse_commit_graph(struct repository *r, void *graph_map, size_t graph_size); /* @@ -184,7 +183,7 @@ int write_commit_graph(struct odb_source *source, #define COMMIT_GRAPH_VERIFY_SHALLOW (1 << 0) -int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags); +int verify_commit_graph(struct commit_graph *g, int flags); void close_commit_graph(struct object_database *); void free_commit_graph(struct commit_graph *); diff --git a/oss-fuzz/fuzz-commit-graph.c b/oss-fuzz/fuzz-commit-graph.c index fbb77fec19..fb8b8787a4 100644 --- a/oss-fuzz/fuzz-commit-graph.c +++ b/oss-fuzz/fuzz-commit-graph.c @@ -4,9 +4,6 @@ #include "commit-graph.h" #include "repository.h" -struct commit_graph *parse_commit_graph(struct repo_settings *s, - void *graph_map, size_t graph_size); - int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) @@ -22,9 +19,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) * possible. */ repo_set_hash_algo(the_repository, GIT_HASH_SHA1); + the_repository->settings.initialized = 1; the_repository->settings.commit_graph_generation_version = 2; the_repository->settings.commit_graph_changed_paths_version = 1; - g = parse_commit_graph(&the_repository->settings, (void *)data, size); + g = parse_commit_graph(the_repository, (void *)data, size); repo_clear(the_repository); free_commit_graph(g); diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index ef5339bbee..6a5f64e473 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -81,7 +81,7 @@ int cmd__read_graph(int argc, const char **argv) prepare_repo_settings(the_repository); - graph = read_commit_graph_one(the_repository, source); + graph = read_commit_graph_one(source); if (!graph) { ret = 1; goto done; |