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.
1 files changed, 27 insertions(+), 17 deletions(-) | |||
---|---|---|---|
M | stagit.c | +27 | -17 |
1@@ -87,7 +87,7 @@ deltainfo_free(struct deltainfo *di)
2 if (!di)
3 return;
4 git_patch_free(di->patch);
5- di->patch = NULL;
6+ memset(di, 0, sizeof(*di));
7 free(di);
8 }
9
10@@ -95,6 +95,7 @@ int
11 commitinfo_getstats(struct commitinfo *ci)
12 {
13 struct deltainfo *di;
14+ git_diff_options opts;
15 const git_diff_delta *delta;
16 const git_diff_hunk *hunk;
17 const git_diff_line *line;
18@@ -102,6 +103,20 @@ commitinfo_getstats(struct commitinfo *ci)
19 size_t ndeltas, nhunks, nhunklines;
20 size_t i, j, k;
21
22+ if (git_tree_lookup(&(ci->commit_tree), repo, git_commit_tree_id(ci->commit)))
23+ goto err;
24+ if (!git_commit_parent(&(ci->parent), ci->commit, 0)) {
25+ if (git_tree_lookup(&(ci->parent_tree), repo, git_commit_tree_id(ci->parent))) {
26+ ci->parent = NULL;
27+ ci->parent_tree = NULL;
28+ }
29+ }
30+
31+ git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION);
32+ opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
33+ if (git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree, ci->commit_tree, &opts))
34+ goto err;
35+
36 ndeltas = git_diff_num_deltas(ci->diff);
37 if (ndeltas && !(ci->deltas = calloc(ndeltas, sizeof(struct deltainfo *))))
38 err(1, "calloc");
39@@ -143,6 +158,15 @@ commitinfo_getstats(struct commitinfo *ci)
40 return 0;
41
42 err:
43+ git_diff_free(ci->diff);
44+ ci->diff = NULL;
45+ git_tree_free(ci->commit_tree);
46+ ci->commit_tree = NULL;
47+ git_tree_free(ci->parent_tree);
48+ ci->parent_tree = NULL;
49+ git_commit_free(ci->parent);
50+ ci->parent = NULL;
51+
52 if (ci->deltas)
53 for (i = 0; i < ci->ndeltas; i++)
54 deltainfo_free(ci->deltas[i]);
55@@ -166,13 +190,14 @@ commitinfo_free(struct commitinfo *ci)
56 if (ci->deltas)
57 for (i = 0; i < ci->ndeltas; i++)
58 deltainfo_free(ci->deltas[i]);
59+
60 free(ci->deltas);
61- ci->deltas = NULL;
62 git_diff_free(ci->diff);
63 git_tree_free(ci->commit_tree);
64 git_tree_free(ci->parent_tree);
65 git_commit_free(ci->commit);
66 git_commit_free(ci->parent);
67+ memset(ci, 0, sizeof(*ci));
68 free(ci);
69 }
70
71@@ -180,7 +205,6 @@ struct commitinfo *
72 commitinfo_getbyoid(const git_oid *id)
73 {
74 struct commitinfo *ci;
75- git_diff_options opts;
76
77 if (!(ci = calloc(1, sizeof(struct commitinfo))))
78 err(1, "calloc");
79@@ -197,20 +221,6 @@ commitinfo_getbyoid(const git_oid *id)
80 ci->summary = git_commit_summary(ci->commit);
81 ci->msg = git_commit_message(ci->commit);
82
83- if (git_tree_lookup(&(ci->commit_tree), repo, git_commit_tree_id(ci->commit)))
84- goto err;
85- if (!git_commit_parent(&(ci->parent), ci->commit, 0)) {
86- if (git_tree_lookup(&(ci->parent_tree), repo, git_commit_tree_id(ci->parent))) {
87- ci->parent = NULL;
88- ci->parent_tree = NULL;
89- }
90- }
91-
92- git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION);
93- opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
94- if (git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree, ci->commit_tree, &opts))
95- goto err;
96-
97 return ci;
98
99 err: