stagit

custom fork of stagit
Index Commits Files Refs README LICENSE
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:
Mstagit.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: