[PATCH v2 12/14] commit-graph: read only from specific pack-indexes
From: Derrick Stolee <hidden>
Date: 2018-01-30 21:40:38
Subsystem:
documentation, the rest · Maintainers:
Jonathan Corbet, Linus Torvalds
Teach git-commit-graph to inspect the objects only in a certain list of pack-indexes within the given pack directory. This allows updating the commit graph iteratively, since we add all commits stored in a previous commit graph. Signed-off-by: Derrick Stolee <redacted> --- Documentation/git-commit-graph.txt | 13 +++++++++++++ builtin/commit-graph.c | 25 ++++++++++++++++++++++--- commit-graph.c | 25 +++++++++++++++++++++++-- commit-graph.h | 4 +++- packfile.c | 4 ++-- packfile.h | 2 ++ t/t5318-commit-graph.sh | 6 ++++-- 7 files changed, 69 insertions(+), 10 deletions(-)
diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt
index 7b376e9212..d0571cd896 100644
--- a/Documentation/git-commit-graph.txt
+++ b/Documentation/git-commit-graph.txt@@ -43,6 +43,11 @@ OPTIONS When used with --write and --update-head, delete the graph file previously referenced by graph-head. +--stdin-packs:: + When used with --write, generate the new graph by walking objects + only in the specified packfiles and any commits in the + existing graph-head. + EXAMPLES --------
@@ -65,6 +70,14 @@ $ git commit-graph --write $ git commit-graph --write --update-head --delete-expired ------------------------------------------------ +* Write a graph file, extending the current graph file using commits +* in <pack-index>, update graph-head, and delete the old graph-<hash>.graph +* file. ++ +------------------------------------------------ +$ echo <pack-index> | git commit-graph --write --update-head --delete-expired --stdin-packs +------------------------------------------------ + * Read basic information from a graph file. + ------------------------------------------------
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 766f09e6fc..80a409e784 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c@@ -12,7 +12,7 @@ static char const * const builtin_commit_graph_usage[] = { N_("git commit-graph [--pack-dir <packdir>]"), N_("git commit-graph --clear [--pack-dir <packdir>]"), N_("git commit-graph --read [--graph-hash=<hash>]"), - N_("git commit-graph --write [--pack-dir <packdir>] [--update-head] [--delete-expired]"), + N_("git commit-graph --write [--pack-dir <packdir>] [--update-head] [--delete-expired] [--stdin-packs]"), NULL };
@@ -24,6 +24,7 @@ static struct opts_commit_graph { int write; int update_head; int delete_expired; + int stdin_packs; int has_existing; struct object_id old_graph_hash; } opts;
@@ -114,7 +115,24 @@ static void update_head_file(const char *pack_dir, const struct object_id *graph static int graph_write(void) { - struct object_id *graph_hash = construct_commit_graph(opts.pack_dir); + struct object_id *graph_hash; + char **pack_indexes = NULL; + int num_packs = 0; + int size_packs = 0; + + if (opts.stdin_packs) { + struct strbuf buf = STRBUF_INIT; + size_packs = 128; + ALLOC_ARRAY(pack_indexes, size_packs); + + while (strbuf_getline(&buf, stdin) != EOF) { + ALLOC_GROW(pack_indexes, num_packs + 1, size_packs); + pack_indexes[num_packs++] = buf.buf; + strbuf_detach(&buf, NULL); + } + } + + graph_hash = construct_commit_graph(opts.pack_dir, pack_indexes, num_packs); if (opts.update_head) update_head_file(opts.pack_dir, graph_hash);
@@ -122,7 +140,6 @@ static int graph_write(void) if (graph_hash) printf("%s\n", oid_to_hex(graph_hash)); - if (opts.delete_expired && opts.update_head && opts.has_existing && oidcmp(graph_hash, &opts.old_graph_hash)) { char *old_path = get_commit_graph_filename_hash(opts.pack_dir,
@@ -153,6 +170,8 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix) N_("update graph-head to written graph file")), OPT_BOOL('d', "delete-expired", &opts.delete_expired, N_("delete expired head graph file")), + OPT_BOOL('s', "stdin-packs", &opts.stdin_packs, + N_("only scan packfiles listed by stdin")), { OPTION_STRING, 'H', "graph-hash", &opts.graph_hash, N_("hash"), N_("A hash for a specific graph file in the pack-dir."),
diff --git a/commit-graph.c b/commit-graph.c
index fc816533c6..e5a1d9ee8b 100644
--- a/commit-graph.c
+++ b/commit-graph.c@@ -638,7 +638,9 @@ static int if_packed_commit_add_to_list(const struct object_id *oid, return 0; } -struct object_id *construct_commit_graph(const char *pack_dir) +struct object_id *construct_commit_graph(const char *pack_dir, + char **pack_indexes, + int nr_packs) { struct packed_oid_list oids; struct packed_commit_list commits;
@@ -674,7 +676,26 @@ struct object_id *construct_commit_graph(const char *pack_dir) oids.num = commit_graph->num_commits; } - for_each_packed_object(if_packed_commit_add_to_list, &oids, 0); + if (pack_indexes) { + int pack_dir_len = strlen(pack_dir) + 1; + struct strbuf packname = STRBUF_INIT; + strbuf_add(&packname, pack_dir, pack_dir_len - 1); + strbuf_addch(&packname, '/'); + for (i = 0; i < nr_packs; i++) { + struct packed_git *p; + strbuf_setlen(&packname, pack_dir_len); + strbuf_addstr(&packname, pack_indexes[i]); + p = add_packed_git(packname.buf, packname.len, 1); + if (!p) + die("error adding pack %s", packname.buf); + if (open_pack_index(p)) + die("error opening index for %s", packname.buf); + for_each_object_in_pack(p, if_packed_commit_add_to_list, &oids); + close_pack(p); + } + } else { + for_each_packed_object(if_packed_commit_add_to_list, &oids, 0); + } QSORT(oids.list, oids.num, commit_compare); count_distinct = 1;
diff --git a/commit-graph.h b/commit-graph.h
index 05ddbbe165..3ae1eadce0 100644
--- a/commit-graph.h
+++ b/commit-graph.h@@ -60,6 +60,8 @@ extern struct object_id *get_nth_commit_oid(struct commit_graph *g, uint32_t n, struct object_id *oid); -extern struct object_id *construct_commit_graph(const char *pack_dir); +extern struct object_id *construct_commit_graph(const char *pack_dir, + char **pack_indexes, + int nr_packs); #endif
diff --git a/packfile.c b/packfile.c
index 4a5fe7ab18..48133bd669 100644
--- a/packfile.c
+++ b/packfile.c@@ -299,7 +299,7 @@ void close_pack_index(struct packed_git *p) } } -static void close_pack(struct packed_git *p) +void close_pack(struct packed_git *p) { close_pack_windows(p); close_pack_fd(p);
@@ -1860,7 +1860,7 @@ int has_pack_index(const unsigned char *sha1) return 1; } -static int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn cb, void *data) +int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn cb, void *data) { uint32_t i; int r = 0;
diff --git a/packfile.h b/packfile.h
index 0cdeb54dcd..cde868feb6 100644
--- a/packfile.h
+++ b/packfile.h@@ -61,6 +61,7 @@ extern void close_pack_index(struct packed_git *); extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *); extern void close_pack_windows(struct packed_git *); +extern void close_pack(struct packed_git *); extern void close_all_packs(void); extern void unuse_pack(struct pack_window **); extern void clear_delta_base_cache(void);
@@ -133,6 +134,7 @@ typedef int each_packed_object_fn(const struct object_id *oid, struct packed_git *pack, uint32_t pos, void *data); +extern int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn cb, void *data); extern int for_each_packed_object(each_packed_object_fn, void *, unsigned flags); #endif
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 93b0d4f51b..b9a73f398c 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh@@ -137,7 +137,9 @@ test_expect_success 'Add more commits' \ git commit -m "commit $i" && git branch commits/$i done && - git repack' + ls ${packdir} | grep idx >existing-idx && + git repack && + ls ${packdir} | grep idx | grep -v --file=existing-idx >new-idx' # Current graph structure: #
@@ -174,7 +176,7 @@ _graph_git_behavior commits/20 merge/1 _graph_git_behavior commits/20 merge/2 test_expect_success 'write graph with merges' \ - 'graph3=$(git commit-graph --write --update-head --delete-expired) && + 'graph3=$(cat new-idx | git commit-graph --write --update-head --delete-expired --stdin-packs) && test_path_is_file ${packdir}/graph-${graph3}.graph && test_path_is_missing ${packdir}/graph-${graph2}.graph && test_path_is_file ${packdir}/graph-${graph1}.graph &&
--
2.16.0.15.g9c3cf44.dirty