commit: f53f481b3f02431b151ae9953998d7c7b3138585
parent 20c37e4fe4bfef13642542f3fa15aa73c92a037c
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Sun, 18 Mar 2018 15:34:37 +0100
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.
Diffstat:
M | stagit.c | 44 | +++++++++++++++++++++++++++----------------- |
1 file changed, 27 insertions(+), 17 deletions(-)
diff --git a/stagit.c b/stagit.c
@@ -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: