optimization: only diff the tree when it is needed for the diffstat...

... also clear all fields in the structure on failure.

This is not as big an optimization as stagit-gopher, because the diffstat is
displayed in the log, but the difference is still measurable.
This commit is contained in:
Hiltjo Posthuma 2018-03-18 15:34:37 +01:00
parent 20c37e4fe4
commit f53f481b3f

View file

@ -87,7 +87,7 @@ deltainfo_free(struct deltainfo *di)
if (!di)
return;
git_patch_free(di->patch);
di->patch = NULL;
memset(di, 0, sizeof(*di));
free(di);
}
@ -95,6 +95,7 @@ int
commitinfo_getstats(struct commitinfo *ci)
{
struct deltainfo *di;
git_diff_options opts;
const git_diff_delta *delta;
const git_diff_hunk *hunk;
const git_diff_line *line;
@ -102,6 +103,20 @@ commitinfo_getstats(struct commitinfo *ci)
size_t ndeltas, nhunks, nhunklines;
size_t i, j, k;
if (git_tree_lookup(&(ci->commit_tree), repo, git_commit_tree_id(ci->commit)))
goto err;
if (!git_commit_parent(&(ci->parent), ci->commit, 0)) {
if (git_tree_lookup(&(ci->parent_tree), repo, git_commit_tree_id(ci->parent))) {
ci->parent = NULL;
ci->parent_tree = NULL;
}
}
git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION);
opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
if (git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree, ci->commit_tree, &opts))
goto err;
ndeltas = git_diff_num_deltas(ci->diff);
if (ndeltas && !(ci->deltas = calloc(ndeltas, sizeof(struct deltainfo *))))
err(1, "calloc");
@ -143,6 +158,15 @@ commitinfo_getstats(struct commitinfo *ci)
return 0;
err:
git_diff_free(ci->diff);
ci->diff = NULL;
git_tree_free(ci->commit_tree);
ci->commit_tree = NULL;
git_tree_free(ci->parent_tree);
ci->parent_tree = NULL;
git_commit_free(ci->parent);
ci->parent = NULL;
if (ci->deltas)
for (i = 0; i < ci->ndeltas; i++)
deltainfo_free(ci->deltas[i]);
@ -166,13 +190,14 @@ commitinfo_free(struct commitinfo *ci)
if (ci->deltas)
for (i = 0; i < ci->ndeltas; i++)
deltainfo_free(ci->deltas[i]);
free(ci->deltas);
ci->deltas = NULL;
git_diff_free(ci->diff);
git_tree_free(ci->commit_tree);
git_tree_free(ci->parent_tree);
git_commit_free(ci->commit);
git_commit_free(ci->parent);
memset(ci, 0, sizeof(*ci));
free(ci);
}
@ -180,7 +205,6 @@ struct commitinfo *
commitinfo_getbyoid(const git_oid *id)
{
struct commitinfo *ci;
git_diff_options opts;
if (!(ci = calloc(1, sizeof(struct commitinfo))))
err(1, "calloc");
@ -197,20 +221,6 @@ commitinfo_getbyoid(const git_oid *id)
ci->summary = git_commit_summary(ci->commit);
ci->msg = git_commit_message(ci->commit);
if (git_tree_lookup(&(ci->commit_tree), repo, git_commit_tree_id(ci->commit)))
goto err;
if (!git_commit_parent(&(ci->parent), ci->commit, 0)) {
if (git_tree_lookup(&(ci->parent_tree), repo, git_commit_tree_id(ci->parent))) {
ci->parent = NULL;
ci->parent_tree = NULL;
}
}
git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION);
opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
if (git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree, ci->commit_tree, &opts))
goto err;
return ci;
err: