summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerrick Stolee <dstolee@microsoft.com>2018-04-10 12:56:04 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-04-11 01:43:02 (GMT)
commit4f2542b49e1525ebde595a5254743579a28a7382 (patch)
treeecba6a331d4f8fabeec0f71207da6913401a5628
parent1b70dfd5946f76e40516f2229afbf249f185bc7a (diff)
downloadgit-4f2542b49e1525ebde595a5254743579a28a7382.zip
git-4f2542b49e1525ebde595a5254743579a28a7382.tar.gz
git-4f2542b49e1525ebde595a5254743579a28a7382.tar.bz2
commit-graph: close under reachability
Teach write_commit_graph() to walk all parents from the commits discovered in packfiles. This prevents gaps given by loose objects or previously-missed packfiles. Also automatically add commits from the existing graph file, if it exists. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--commit-graph.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/commit-graph.c b/commit-graph.c
index b1bd3a8..ea29c5c 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -367,6 +367,50 @@ static int add_packed_commits(const struct object_id *oid,
return 0;
}
+static void add_missing_parents(struct packed_oid_list *oids, struct commit *commit)
+{
+ struct commit_list *parent;
+ for (parent = commit->parents; parent; parent = parent->next) {
+ if (!(parent->item->object.flags & UNINTERESTING)) {
+ ALLOC_GROW(oids->list, oids->nr + 1, oids->alloc);
+ oidcpy(&oids->list[oids->nr], &(parent->item->object.oid));
+ oids->nr++;
+ parent->item->object.flags |= UNINTERESTING;
+ }
+ }
+}
+
+static void close_reachable(struct packed_oid_list *oids)
+{
+ int i;
+ struct commit *commit;
+
+ for (i = 0; i < oids->nr; i++) {
+ commit = lookup_commit(&oids->list[i]);
+ if (commit)
+ commit->object.flags |= UNINTERESTING;
+ }
+
+ /*
+ * As this loop runs, oids->nr may grow, but not more
+ * than the number of missing commits in the reachable
+ * closure.
+ */
+ for (i = 0; i < oids->nr; i++) {
+ commit = lookup_commit(&oids->list[i]);
+
+ if (commit && !parse_commit(commit))
+ add_missing_parents(oids, commit);
+ }
+
+ for (i = 0; i < oids->nr; i++) {
+ commit = lookup_commit(&oids->list[i]);
+
+ if (commit)
+ commit->object.flags &= ~UNINTERESTING;
+ }
+}
+
void write_commit_graph(const char *obj_dir)
{
struct packed_oid_list oids;
@@ -390,6 +434,7 @@ void write_commit_graph(const char *obj_dir)
ALLOC_ARRAY(oids.list, oids.alloc);
for_each_packed_object(add_packed_commits, &oids, 0);
+ close_reachable(&oids);
QSORT(oids.list, oids.nr, commit_compare);