commit-graph: add repo arg to graph readers
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>
Jonathan Tan committed
Jul 11, 2018 at 15:42 UTC
dade47c06cf849b0ca180a8e6383b55ea6f75812
13 files changed
+162
-42
Makefile
+1
@@ -719,6 +719,7 @@ TEST_BUILTINS_OBJS += test-prio-queue.o
719
TEST_BUILTINS_OBJS += test-read-cache.o
720
TEST_BUILTINS_OBJS += test-ref-store.o
721
TEST_BUILTINS_OBJS += test-regex.o
722
+TEST_BUILTINS_OBJS += test-repository.o
723
TEST_BUILTINS_OBJS += test-revision-walking.o
724
TEST_BUILTINS_OBJS += test-run-command.o
725
TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
builtin/fsck.c
+1
-1
@@ -830,7 +830,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
830
831
check_connectivity();
832
833
- if (core_commit_graph) {
833
+ if (!git_config_get_bool("core.commitgraph", &i) && i) {
834
struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
835
const char *verify_argv[] = { "commit-graph", "verify", NULL, NULL, NULL };
836
cache.h
-1
@@ -813,7 +813,6 @@ extern char *git_replace_ref_base;
813
814
extern int fsync_object_files;
815
extern int core_preload_index;
816
-extern int core_commit_graph;
816
extern int core_apply_sparse_checkout;
817
extern int precomposed_unicode;
818
extern int protect_hfs;
commit-graph.c
+33
-27
@@ -183,15 +183,15 @@ cleanup_fail:
183
exit(1);
184
}
185
186
-static void prepare_commit_graph_one(const char *obj_dir)
186
+static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
187
{
188
char *graph_name;
189
190
- if (the_repository->objects->commit_graph)
190
+ if (r->objects->commit_graph)
191
return;
192
193
graph_name = get_commit_graph_filename(obj_dir);
194
- the_repository->objects->commit_graph =
194
+ r->objects->commit_graph =
195
load_commit_graph_one(graph_name);
196
197
FREE_AND_NULL(graph_name);
@@ -203,26 +203,34 @@ static void prepare_commit_graph_one(const char *obj_dir)
203
* On the first invocation, this function attemps to load the commit
204
* graph if the_repository is configured to have one.
205
*/
206
-static int prepare_commit_graph(void)
206
+static int prepare_commit_graph(struct repository *r)
207
{
208
struct alternate_object_database *alt;
209
char *obj_dir;
210
+ int config_value;
211
211
- if (the_repository->objects->commit_graph_attempted)
212
- return !!the_repository->objects->commit_graph;
213
- the_repository->objects->commit_graph_attempted = 1;
212
+ if (r->objects->commit_graph_attempted)
213
+ return !!r->objects->commit_graph;
214
+ r->objects->commit_graph_attempted = 1;
215
215
- if (!core_commit_graph)
216
+ if (repo_config_get_bool(r, "core.commitgraph", &config_value) ||
217
+ !config_value)
218
+ /*
219
+ * This repository is not configured to use commit graphs, so
220
+ * do not load one. (But report commit_graph_attempted anyway
221
+ * so that commit graph loading is not attempted again for this
222
+ * repository.)
223
+ */
224
return 0;
225
218
- obj_dir = get_object_directory();
219
- prepare_commit_graph_one(obj_dir);
220
- prepare_alt_odb(the_repository);
221
- for (alt = the_repository->objects->alt_odb_list;
222
- !the_repository->objects->commit_graph && alt;
226
+ obj_dir = r->objects->objectdir;
227
+ prepare_commit_graph_one(r, obj_dir);
228
+ prepare_alt_odb(r);
229
+ for (alt = r->objects->alt_odb_list;
230
+ !r->objects->commit_graph && alt;
231
alt = alt->next)
224
- prepare_commit_graph_one(alt->path);
225
- return !!the_repository->objects->commit_graph;
232
+ prepare_commit_graph_one(r, alt->path);
233
+ return !!r->objects->commit_graph;
234
}
235
236
static void close_commit_graph(void)
@@ -323,8 +331,6 @@ static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item
331
{
332
uint32_t pos;
333
326
- if (!core_commit_graph)
327
- return 0;
334
if (item->object.parsed)
335
return 1;
336
@@ -334,20 +340,20 @@ static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item
340
return 0;
341
}
342
337
-int parse_commit_in_graph(struct commit *item)
343
+int parse_commit_in_graph(struct repository *r, struct commit *item)
344
{
339
- if (!prepare_commit_graph())
345
+ if (!prepare_commit_graph(r))
346
return 0;
341
- return parse_commit_in_graph_one(the_repository->objects->commit_graph, item);
347
+ return parse_commit_in_graph_one(r->objects->commit_graph, item);
348
}
349
344
-void load_commit_graph_info(struct commit *item)
350
+void load_commit_graph_info(struct repository *r, struct commit *item)
351
{
352
uint32_t pos;
347
- if (!prepare_commit_graph())
353
+ if (!prepare_commit_graph(r))
354
return;
349
- if (find_commit_in_graph(item, the_repository->objects->commit_graph, &pos))
350
- fill_commit_graph_info(item, the_repository->objects->commit_graph, pos);
355
+ if (find_commit_in_graph(item, r->objects->commit_graph, &pos))
356
+ fill_commit_graph_info(item, r->objects->commit_graph, pos);
357
}
358
359
static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c)
@@ -373,9 +379,9 @@ static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g,
379
return load_tree_for_commit(g, (struct commit *)c);
380
}
381
376
-struct tree *get_commit_tree_in_graph(const struct commit *c)
382
+struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit *c)
383
{
378
- return get_commit_tree_in_graph_one(the_repository->objects->commit_graph, c);
384
+ return get_commit_tree_in_graph_one(r->objects->commit_graph, c);
385
}
386
387
static void write_graph_chunk_fanout(struct hashfile *f,
@@ -691,7 +697,7 @@ void write_commit_graph(const char *obj_dir,
697
oids.alloc = approximate_object_count() / 4;
698
699
if (append) {
694
- prepare_commit_graph_one(obj_dir);
700
+ prepare_commit_graph_one(the_repository, obj_dir);
701
if (the_repository->objects->commit_graph)
702
oids.alloc += the_repository->objects->commit_graph->num_commits;
703
}
commit-graph.h
+4
-3
@@ -19,7 +19,7 @@ char *get_commit_graph_filename(const char *obj_dir);
19
*
20
* See parse_commit_buffer() for the fallback after this call.
21
*/
22
-int parse_commit_in_graph(struct commit *item);
22
+int parse_commit_in_graph(struct repository *r, struct commit *item);
23
24
/*
25
* It is possible that we loaded commit contents from the commit buffer,
@@ -27,9 +27,10 @@ int parse_commit_in_graph(struct commit *item);
27
* checked and filled. Fill the graph_pos and generation members of
28
* the given commit.
29
*/
30
-void load_commit_graph_info(struct commit *item);
30
+void load_commit_graph_info(struct repository *r, struct commit *item);
31
32
-struct tree *get_commit_tree_in_graph(const struct commit *c);
32
+struct tree *get_commit_tree_in_graph(struct repository *r,
33
+ const struct commit *c);
34
35
struct commit_graph {
36
int graph_fd;
commit.c
+3
-3
@@ -342,7 +342,7 @@ struct tree *get_commit_tree(const struct commit *commit)
342
if (commit->graph_pos == COMMIT_NOT_FROM_GRAPH)
343
BUG("commit has NULL tree, but was not loaded from commit-graph");
344
345
- return get_commit_tree_in_graph(commit);
345
+ return get_commit_tree_in_graph(the_repository, commit);
346
}
347
348
struct object_id *get_commit_tree_oid(const struct commit *commit)
@@ -438,7 +438,7 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
438
item->date = parse_commit_date(bufptr, tail);
439
440
if (check_graph)
441
- load_commit_graph_info(item);
441
+ load_commit_graph_info(the_repository, item);
442
443
return 0;
444
}
@@ -454,7 +454,7 @@ int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_com
454
return -1;
455
if (item->object.parsed)
456
return 0;
457
- if (use_commit_graph && parse_commit_in_graph(item))
457
+ if (use_commit_graph && parse_commit_in_graph(the_repository, item))
458
return 0;
459
buffer = read_object_file(&item->object.oid, &type, &size);
460
if (!buffer)
config.c
-5
@@ -1309,11 +1309,6 @@ static int git_default_core_config(const char *var, const char *value)
1309
return 0;
1310
}
1311
1312
- if (!strcmp(var, "core.commitgraph")) {
1313
- core_commit_graph = git_config_bool(var, value);
1314
- return 0;
1315
- }
1316
-
1312
if (!strcmp(var, "core.sparsecheckout")) {
1313
core_apply_sparse_checkout = git_config_bool(var, value);
1314
return 0;
environment.c
-1
@@ -66,7 +66,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
66
enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
67
char *notes_ref_name;
68
int grafts_replace_parents = 1;
69
-int core_commit_graph;
69
int core_apply_sparse_checkout;
70
int merge_log_config = -1;
71
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
ref-filter.c
+1
-1
@@ -1713,7 +1713,7 @@ static enum contains_result contains_tag_algo(struct commit *candidate,
1713
1714
for (p = want; p; p = p->next) {
1715
struct commit *c = p->item;
1716
- load_commit_graph_info(c);
1716
+ load_commit_graph_info(the_repository, c);
1717
if (c->generation < cutoff)
1718
cutoff = c->generation;
1719
}
t/helper/test-repository.c
new
+82
@@ -0,0 +1,82 @@
1
+#include "test-tool.h"
2
+#include "cache.h"
3
+#include "commit-graph.h"
4
+#include "commit.h"
5
+#include "config.h"
6
+#include "object-store.h"
7
+#include "object.h"
8
+#include "repository.h"
9
+#include "tree.h"
10
+
11
+static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
12
+ const struct object_id *commit_oid)
13
+{
14
+ struct repository r;
15
+ struct commit *c;
16
+ struct commit_list *parent;
17
+
18
+ repo_init(&r, gitdir, worktree);
19
+
20
+ c = lookup_commit(&r, commit_oid);
21
+
22
+ if (!parse_commit_in_graph(&r, c))
23
+ die("Couldn't parse commit");
24
+
25
+ printf("%"PRItime, c->date);
26
+ for (parent = c->parents; parent; parent = parent->next)
27
+ printf(" %s", oid_to_hex(&parent->item->object.oid));
28
+ printf("\n");
29
+
30
+ repo_clear(&r);
31
+}
32
+
33
+static void test_get_commit_tree_in_graph(const char *gitdir,
34
+ const char *worktree,
35
+ const struct object_id *commit_oid)
36
+{
37
+ struct repository r;
38
+ struct commit *c;
39
+ struct tree *tree;
40
+
41
+ repo_init(&r, gitdir, worktree);
42
+
43
+ c = lookup_commit(&r, commit_oid);
44
+
45
+ /*
46
+ * get_commit_tree_in_graph does not automatically parse the commit, so
47
+ * parse it first.
48
+ */
49
+ if (!parse_commit_in_graph(&r, c))
50
+ die("Couldn't parse commit");
51
+ tree = get_commit_tree_in_graph(&r, c);
52
+ if (!tree)
53
+ die("Couldn't get commit tree");
54
+
55
+ printf("%s\n", oid_to_hex(&tree->object.oid));
56
+
57
+ repo_clear(&r);
58
+}
59
+
60
+int cmd__repository(int argc, const char **argv)
61
+{
62
+ if (argc < 2)
63
+ die("must have at least 2 arguments");
64
+ if (!strcmp(argv[1], "parse_commit_in_graph")) {
65
+ struct object_id oid;
66
+ if (argc < 5)
67
+ die("not enough arguments");
68
+ if (parse_oid_hex(argv[4], &oid, &argv[4]))
69
+ die("cannot parse oid '%s'", argv[4]);
70
+ test_parse_commit_in_graph(argv[2], argv[3], &oid);
71
+ } else if (!strcmp(argv[1], "get_commit_tree_in_graph")) {
72
+ struct object_id oid;
73
+ if (argc < 5)
74
+ die("not enough arguments");
75
+ if (parse_oid_hex(argv[4], &oid, &argv[4]))
76
+ die("cannot parse oid '%s'", argv[4]);
77
+ test_get_commit_tree_in_graph(argv[2], argv[3], &oid);
78
+ } else {
79
+ die("unrecognized '%s'", argv[1]);
80
+ }
81
+ return 0;
82
+}
t/helper/test-tool.c
+1
@@ -29,6 +29,7 @@ static struct test_cmd cmds[] = {
29
{ "read-cache", cmd__read_cache },
30
{ "ref-store", cmd__ref_store },
31
{ "regex", cmd__regex },
32
+ { "repository", cmd__repository },
33
{ "revision-walking", cmd__revision_walking },
34
{ "run-command", cmd__run_command },
35
{ "scrap-cache-tree", cmd__scrap_cache_tree },
t/helper/test-tool.h
+1
@@ -23,6 +23,7 @@ int cmd__prio_queue(int argc, const char **argv);
23
int cmd__read_cache(int argc, const char **argv);
24
int cmd__ref_store(int argc, const char **argv);
25
int cmd__regex(int argc, const char **argv);
26
+int cmd__repository(int argc, const char **argv);
27
int cmd__revision_walking(int argc, const char **argv);
28
int cmd__run_command(int argc, const char **argv);
29
int cmd__scrap_cache_tree(int argc, const char **argv);
t/t5318-commit-graph.sh
+35
@@ -431,4 +431,39 @@ test_expect_success 'git fsck (checks commit-graph)' '
431
test_must_fail git fsck
432
'
433
434
+test_expect_success 'setup non-the_repository tests' '
435
+ rm -rf repo &&
436
+ git init repo &&
437
+ test_commit -C repo one &&
438
+ test_commit -C repo two &&
439
+ git -C repo config core.commitGraph true &&
440
+ git -C repo rev-parse two | \
441
+ git -C repo commit-graph write --stdin-commits
442
+'
443
+
444
+test_expect_success 'parse_commit_in_graph works for non-the_repository' '
445
+ test-tool repository parse_commit_in_graph \
446
+ repo/.git repo "$(git -C repo rev-parse two)" >actual &&
447
+ echo $(git -C repo log --pretty="%ct" -1) \
448
+ $(git -C repo rev-parse one) >expect &&
449
+ test_cmp expect actual &&
450
+
451
+ test-tool repository parse_commit_in_graph \
452
+ repo/.git repo "$(git -C repo rev-parse one)" >actual &&
453
+ echo $(git -C repo log --pretty="%ct" -1 one) >expect &&
454
+ test_cmp expect actual
455
+'
456
+
457
+test_expect_success 'get_commit_tree_in_graph works for non-the_repository' '
458
+ test-tool repository get_commit_tree_in_graph \
459
+ repo/.git repo "$(git -C repo rev-parse two)" >actual &&
460
+ echo $(git -C repo rev-parse two^{tree}) >expect &&
461
+ test_cmp expect actual &&
462
+
463
+ test-tool repository get_commit_tree_in_graph \
464
+ repo/.git repo "$(git -C repo rev-parse one)" >actual &&
465
+ echo $(git -C repo rev-parse one^{tree}) >expect &&
466
+ test_cmp expect actual
467
+'
468
+
469
test_done