From f53f481b3f02431b151ae9953998d7c7b3138585 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 18 Mar 2018 15:34:37 +0100 Subject: [PATCH] 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. --- stagit.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/stagit.c b/stagit.c index 81fdd1d..6c9b5c0 100644 --- 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: -- libgit2 1.1.1