Merge branch 'jk/commit-graph-lazy-load-fallback'
The logic to lazy-load trees from the commit-graph has been made more robust by falling back to reading the commit object when the commit-graph is no longer available. * jk/commit-graph-lazy-load-fallback: commit: fall back to full read when maybe_tree is NULLmain
commit
f6c8fe189b
33
commit.c
33
commit.c
|
|
@ -434,6 +434,27 @@ static inline void set_commit_tree(struct commit *c, struct tree *t)
|
|||
c->maybe_tree = t;
|
||||
}
|
||||
|
||||
static void load_tree_from_commit_contents(struct repository *r, struct commit *commit)
|
||||
{
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
char *buf;
|
||||
const char *p;
|
||||
struct object_id tree_oid;
|
||||
|
||||
buf = odb_read_object(r->objects, &commit->object.oid, &type, &size);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
if (type == OBJ_COMMIT &&
|
||||
skip_prefix(buf, "tree ", &p) &&
|
||||
!parse_oid_hex_algop(p, &tree_oid, &p, r->hash_algo) &&
|
||||
*p == '\n')
|
||||
set_commit_tree(commit, lookup_tree(r, &tree_oid));
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
struct tree *repo_get_commit_tree(struct repository *r,
|
||||
const struct commit *commit)
|
||||
{
|
||||
|
|
@ -443,7 +464,17 @@ struct tree *repo_get_commit_tree(struct repository *r,
|
|||
if (commit_graph_position(commit) != COMMIT_NOT_FROM_GRAPH)
|
||||
return get_commit_tree_in_graph(r, commit);
|
||||
|
||||
return NULL;
|
||||
/*
|
||||
* This is either a corrupt commit, or one which we partially loaded
|
||||
* from a graph file but then subsequently threw away the graph data.
|
||||
*
|
||||
* Optimistically assume it's the latter and try to reload from
|
||||
* scratch. This gives a performance penalty if it really is a corrupt
|
||||
* commit, but presumably that happens rarely (and only once per
|
||||
* process).
|
||||
*/
|
||||
load_tree_from_commit_contents(r, (struct commit *)commit);
|
||||
return commit->maybe_tree;
|
||||
}
|
||||
|
||||
struct object_id *get_commit_tree_oid(const struct commit *commit)
|
||||
|
|
|
|||
|
|
@ -360,4 +360,27 @@ test_expect_success SYMLINKS 'clone repo with symlinked objects directory' '
|
|||
grep "is a symlink, refusing to clone with --local" err
|
||||
'
|
||||
|
||||
test_expect_success 'dissociate from repo with commit graph' '
|
||||
git init orig &&
|
||||
# We are trying to make sure the dissociated repo can
|
||||
# find the tree of the tip commit, so the test could still
|
||||
# serve its purpose with an empty tree. But having actual
|
||||
# content future-proofs us against any kind of internal
|
||||
# empty-tree optimizations.
|
||||
echo content >orig/file &&
|
||||
git -C orig add . &&
|
||||
git -C orig commit -m foo &&
|
||||
|
||||
# We will use graph.git as our "local" source to dissociate
|
||||
# from.
|
||||
git clone --bare orig graph.git &&
|
||||
git -C graph.git commit-graph write --reachable &&
|
||||
|
||||
# And then finally clone orig, using graph.git to get our objects. This
|
||||
# must be non-bare so that we perform the checkout step, which will
|
||||
# need to access the tree of HEAD, which we will have originally loaded
|
||||
# via the commit graph.
|
||||
git clone --no-local --reference graph.git --dissociate orig clone
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
|||
Loading…
Reference in New Issue