Skip to content

Commit

Permalink
commit-graph: add repo arg to graph readers
Browse files Browse the repository at this point in the history
Add a struct repository argument to the functions in commit-graph.h that
read the commit graph. (This commit does not affect functions that write
commit graphs.)

Because the commit graph functions can now read the commit graph of any
repository, the global variable core_commit_graph has been removed.
Instead, the config option core.commitGraph is now read on the first
time in a repository that a commit is attempted to be parsed using its
commit graph.

This commit includes a test that exercises the functionality on an
arbitrary repository that is not the_repository.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
jonathantanmy authored and gitster committed Jul 17, 2018
1 parent 8527750 commit dade47c
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 42 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ TEST_BUILTINS_OBJS += test-prio-queue.o
TEST_BUILTINS_OBJS += test-read-cache.o
TEST_BUILTINS_OBJS += test-ref-store.o
TEST_BUILTINS_OBJS += test-regex.o
TEST_BUILTINS_OBJS += test-repository.o
TEST_BUILTINS_OBJS += test-revision-walking.o
TEST_BUILTINS_OBJS += test-run-command.o
TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
Expand Down
2 changes: 1 addition & 1 deletion builtin/fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)

check_connectivity();

if (core_commit_graph) {
if (!git_config_get_bool("core.commitgraph", &i) && i) {
struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
const char *verify_argv[] = { "commit-graph", "verify", NULL, NULL, NULL };

Expand Down
1 change: 0 additions & 1 deletion cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,6 @@ extern char *git_replace_ref_base;

extern int fsync_object_files;
extern int core_preload_index;
extern int core_commit_graph;
extern int core_apply_sparse_checkout;
extern int precomposed_unicode;
extern int protect_hfs;
Expand Down
60 changes: 33 additions & 27 deletions commit-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,15 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
exit(1);
}

static void prepare_commit_graph_one(const char *obj_dir)
static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
{
char *graph_name;

if (the_repository->objects->commit_graph)
if (r->objects->commit_graph)
return;

graph_name = get_commit_graph_filename(obj_dir);
the_repository->objects->commit_graph =
r->objects->commit_graph =
load_commit_graph_one(graph_name);

FREE_AND_NULL(graph_name);
Expand All @@ -203,26 +203,34 @@ static void prepare_commit_graph_one(const char *obj_dir)
* On the first invocation, this function attemps to load the commit
* graph if the_repository is configured to have one.
*/
static int prepare_commit_graph(void)
static int prepare_commit_graph(struct repository *r)
{
struct alternate_object_database *alt;
char *obj_dir;
int config_value;

if (the_repository->objects->commit_graph_attempted)
return !!the_repository->objects->commit_graph;
the_repository->objects->commit_graph_attempted = 1;
if (r->objects->commit_graph_attempted)
return !!r->objects->commit_graph;
r->objects->commit_graph_attempted = 1;

if (!core_commit_graph)
if (repo_config_get_bool(r, "core.commitgraph", &config_value) ||
!config_value)
/*
* This repository is not configured to use commit graphs, so
* do not load one. (But report commit_graph_attempted anyway
* so that commit graph loading is not attempted again for this
* repository.)
*/
return 0;

obj_dir = get_object_directory();
prepare_commit_graph_one(obj_dir);
prepare_alt_odb(the_repository);
for (alt = the_repository->objects->alt_odb_list;
!the_repository->objects->commit_graph && alt;
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(alt->path);
return !!the_repository->objects->commit_graph;
prepare_commit_graph_one(r, alt->path);
return !!r->objects->commit_graph;
}

static void close_commit_graph(void)
Expand Down Expand Up @@ -323,8 +331,6 @@ static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item
{
uint32_t pos;

if (!core_commit_graph)
return 0;
if (item->object.parsed)
return 1;

Expand All @@ -334,20 +340,20 @@ static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item
return 0;
}

int parse_commit_in_graph(struct commit *item)
int parse_commit_in_graph(struct repository *r, struct commit *item)
{
if (!prepare_commit_graph())
if (!prepare_commit_graph(r))
return 0;
return parse_commit_in_graph_one(the_repository->objects->commit_graph, item);
return parse_commit_in_graph_one(r->objects->commit_graph, item);
}

void load_commit_graph_info(struct commit *item)
void load_commit_graph_info(struct repository *r, struct commit *item)
{
uint32_t pos;
if (!prepare_commit_graph())
if (!prepare_commit_graph(r))
return;
if (find_commit_in_graph(item, the_repository->objects->commit_graph, &pos))
fill_commit_graph_info(item, the_repository->objects->commit_graph, pos);
if (find_commit_in_graph(item, r->objects->commit_graph, &pos))
fill_commit_graph_info(item, r->objects->commit_graph, pos);
}

static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c)
Expand All @@ -373,9 +379,9 @@ static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g,
return load_tree_for_commit(g, (struct commit *)c);
}

struct tree *get_commit_tree_in_graph(const struct commit *c)
struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit *c)
{
return get_commit_tree_in_graph_one(the_repository->objects->commit_graph, c);
return get_commit_tree_in_graph_one(r->objects->commit_graph, c);
}

static void write_graph_chunk_fanout(struct hashfile *f,
Expand Down Expand Up @@ -691,7 +697,7 @@ void write_commit_graph(const char *obj_dir,
oids.alloc = approximate_object_count() / 4;

if (append) {
prepare_commit_graph_one(obj_dir);
prepare_commit_graph_one(the_repository, obj_dir);
if (the_repository->objects->commit_graph)
oids.alloc += the_repository->objects->commit_graph->num_commits;
}
Expand Down
7 changes: 4 additions & 3 deletions commit-graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@ char *get_commit_graph_filename(const char *obj_dir);
*
* See parse_commit_buffer() for the fallback after this call.
*/
int parse_commit_in_graph(struct commit *item);
int parse_commit_in_graph(struct repository *r, struct commit *item);

/*
* It is possible that we loaded commit contents from the commit buffer,
* but we also want to ensure the commit-graph content is correctly
* checked and filled. Fill the graph_pos and generation members of
* the given commit.
*/
void load_commit_graph_info(struct commit *item);
void load_commit_graph_info(struct repository *r, struct commit *item);

struct tree *get_commit_tree_in_graph(const struct commit *c);
struct tree *get_commit_tree_in_graph(struct repository *r,
const struct commit *c);

struct commit_graph {
int graph_fd;
Expand Down
6 changes: 3 additions & 3 deletions commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ struct tree *get_commit_tree(const struct commit *commit)
if (commit->graph_pos == COMMIT_NOT_FROM_GRAPH)
BUG("commit has NULL tree, but was not loaded from commit-graph");

return get_commit_tree_in_graph(commit);
return get_commit_tree_in_graph(the_repository, commit);
}

struct object_id *get_commit_tree_oid(const struct commit *commit)
Expand Down Expand Up @@ -438,7 +438,7 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
item->date = parse_commit_date(bufptr, tail);

if (check_graph)
load_commit_graph_info(item);
load_commit_graph_info(the_repository, item);

return 0;
}
Expand All @@ -454,7 +454,7 @@ int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_com
return -1;
if (item->object.parsed)
return 0;
if (use_commit_graph && parse_commit_in_graph(item))
if (use_commit_graph && parse_commit_in_graph(the_repository, item))
return 0;
buffer = read_object_file(&item->object.oid, &type, &size);
if (!buffer)
Expand Down
5 changes: 0 additions & 5 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1309,11 +1309,6 @@ static int git_default_core_config(const char *var, const char *value)
return 0;
}

if (!strcmp(var, "core.commitgraph")) {
core_commit_graph = git_config_bool(var, value);
return 0;
}

if (!strcmp(var, "core.sparsecheckout")) {
core_apply_sparse_checkout = git_config_bool(var, value);
return 0;
Expand Down
1 change: 0 additions & 1 deletion environment.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
char *notes_ref_name;
int grafts_replace_parents = 1;
int core_commit_graph;
int core_apply_sparse_checkout;
int merge_log_config = -1;
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
Expand Down
2 changes: 1 addition & 1 deletion ref-filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1713,7 +1713,7 @@ static enum contains_result contains_tag_algo(struct commit *candidate,

for (p = want; p; p = p->next) {
struct commit *c = p->item;
load_commit_graph_info(c);
load_commit_graph_info(the_repository, c);
if (c->generation < cutoff)
cutoff = c->generation;
}
Expand Down
82 changes: 82 additions & 0 deletions t/helper/test-repository.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "test-tool.h"
#include "cache.h"
#include "commit-graph.h"
#include "commit.h"
#include "config.h"
#include "object-store.h"
#include "object.h"
#include "repository.h"
#include "tree.h"

static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
const struct object_id *commit_oid)
{
struct repository r;
struct commit *c;
struct commit_list *parent;

repo_init(&r, gitdir, worktree);

c = lookup_commit(&r, commit_oid);

if (!parse_commit_in_graph(&r, c))
die("Couldn't parse commit");

printf("%"PRItime, c->date);
for (parent = c->parents; parent; parent = parent->next)
printf(" %s", oid_to_hex(&parent->item->object.oid));
printf("\n");

repo_clear(&r);
}

static void test_get_commit_tree_in_graph(const char *gitdir,
const char *worktree,
const struct object_id *commit_oid)
{
struct repository r;
struct commit *c;
struct tree *tree;

repo_init(&r, gitdir, worktree);

c = lookup_commit(&r, commit_oid);

/*
* get_commit_tree_in_graph does not automatically parse the commit, so
* parse it first.
*/
if (!parse_commit_in_graph(&r, c))
die("Couldn't parse commit");
tree = get_commit_tree_in_graph(&r, c);
if (!tree)
die("Couldn't get commit tree");

printf("%s\n", oid_to_hex(&tree->object.oid));

repo_clear(&r);
}

int cmd__repository(int argc, const char **argv)
{
if (argc < 2)
die("must have at least 2 arguments");
if (!strcmp(argv[1], "parse_commit_in_graph")) {
struct object_id oid;
if (argc < 5)
die("not enough arguments");
if (parse_oid_hex(argv[4], &oid, &argv[4]))
die("cannot parse oid '%s'", argv[4]);
test_parse_commit_in_graph(argv[2], argv[3], &oid);
} else if (!strcmp(argv[1], "get_commit_tree_in_graph")) {
struct object_id oid;
if (argc < 5)
die("not enough arguments");
if (parse_oid_hex(argv[4], &oid, &argv[4]))
die("cannot parse oid '%s'", argv[4]);
test_get_commit_tree_in_graph(argv[2], argv[3], &oid);
} else {
die("unrecognized '%s'", argv[1]);
}
return 0;
}
1 change: 1 addition & 0 deletions t/helper/test-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static struct test_cmd cmds[] = {
{ "read-cache", cmd__read_cache },
{ "ref-store", cmd__ref_store },
{ "regex", cmd__regex },
{ "repository", cmd__repository },
{ "revision-walking", cmd__revision_walking },
{ "run-command", cmd__run_command },
{ "scrap-cache-tree", cmd__scrap_cache_tree },
Expand Down
1 change: 1 addition & 0 deletions t/helper/test-tool.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ int cmd__prio_queue(int argc, const char **argv);
int cmd__read_cache(int argc, const char **argv);
int cmd__ref_store(int argc, const char **argv);
int cmd__regex(int argc, const char **argv);
int cmd__repository(int argc, const char **argv);
int cmd__revision_walking(int argc, const char **argv);
int cmd__run_command(int argc, const char **argv);
int cmd__scrap_cache_tree(int argc, const char **argv);
Expand Down
35 changes: 35 additions & 0 deletions t/t5318-commit-graph.sh
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,39 @@ test_expect_success 'git fsck (checks commit-graph)' '
test_must_fail git fsck
'

test_expect_success 'setup non-the_repository tests' '
rm -rf repo &&
git init repo &&
test_commit -C repo one &&
test_commit -C repo two &&
git -C repo config core.commitGraph true &&
git -C repo rev-parse two | \
git -C repo commit-graph write --stdin-commits
'

test_expect_success 'parse_commit_in_graph works for non-the_repository' '
test-tool repository parse_commit_in_graph \
repo/.git repo "$(git -C repo rev-parse two)" >actual &&
echo $(git -C repo log --pretty="%ct" -1) \
$(git -C repo rev-parse one) >expect &&
test_cmp expect actual &&
test-tool repository parse_commit_in_graph \
repo/.git repo "$(git -C repo rev-parse one)" >actual &&
echo $(git -C repo log --pretty="%ct" -1 one) >expect &&
test_cmp expect actual
'

test_expect_success 'get_commit_tree_in_graph works for non-the_repository' '
test-tool repository get_commit_tree_in_graph \
repo/.git repo "$(git -C repo rev-parse two)" >actual &&
echo $(git -C repo rev-parse two^{tree}) >expect &&
test_cmp expect actual &&
test-tool repository get_commit_tree_in_graph \
repo/.git repo "$(git -C repo rev-parse one)" >actual &&
echo $(git -C repo rev-parse one^{tree}) >expect &&
test_cmp expect actual
'

test_done

0 comments on commit dade47c

Please sign in to comment.