Introduction
Introduction Statistics Contact Development Disclaimer Help
toptimization: read stats once and remember it - stagit - static git page gener…
git clone git://src.adamsgaard.dk/stagit
Log
Files
Refs
README
LICENSE
---
commit 914880f31b04222fa2815f4f35543b72f881d5e4
parent 0bc47da0f7b66614cdf499755ceca1dc13ff91cd
Author: Hiltjo Posthuma <[email protected]>
Date: Sat, 30 Apr 2016 11:54:33 +0200
optimization: read stats once and remember it
for an initial run and new commits this speeds stagit up a bit:
on an initial run of sbase goes from about 4 seconds to 2.8 on my machine.
now we can't use statsbuf, so create the stats string ourselves, while at it
color the + and - using a style (can be disabled for the color-haters out
tthere ;)).
Diffstat:
M stagit.c | 186 ++++++++++++++++++++++++-----…
M style.css | 2 ++
2 files changed, 149 insertions(+), 39 deletions(-)
---
diff --git a/stagit.c b/stagit.c
t@@ -15,6 +15,13 @@
#include "compat.h"
#include "config.h"
+struct deltainfo {
+ git_patch *patch;
+
+ size_t addcount;
+ size_t delcount;
+};
+
struct commitinfo {
const git_oid *id;
t@@ -25,16 +32,18 @@ struct commitinfo {
const char *summary;
const char *msg;
- git_diff_stats *stats;
- git_diff *diff;
- git_commit *commit;
- git_commit *parent;
- git_tree *commit_tree;
- git_tree *parent_tree;
+ git_diff *diff;
+ git_commit *commit;
+ git_commit *parent;
+ git_tree *commit_tree;
+ git_tree *parent_tree;
size_t addcount;
size_t delcount;
size_t filecount;
+
+ struct deltainfo **deltas;
+ size_t ndeltas;
};
static git_repository *repo;
t@@ -49,12 +58,95 @@ static char cloneurl[1024];
static int haslicense, hasreadme, hassubmodules;
void
+deltainfo_free(struct deltainfo *di)
+{
+ if (!di)
+ return;
+ git_patch_free(di->patch);
+ di->patch = NULL;
+ free(di);
+}
+
+int
+commitinfo_getstats(struct commitinfo *ci)
+{
+ struct deltainfo *di;
+ const git_diff_delta *delta;
+ const git_diff_hunk *hunk;
+ const git_diff_line *line;
+ git_patch *patch = NULL;
+ size_t ndeltas, nhunks, nhunklines;
+ size_t i, j, k;
+
+ ndeltas = git_diff_num_deltas(ci->diff);
+ if (ndeltas && !(ci->deltas = calloc(ndeltas, sizeof(struct deltainfo …
+ err(1, "calloc");
+
+ for (i = 0; i < ndeltas; i++) {
+ if (!(di = calloc(1, sizeof(struct deltainfo))))
+ err(1, "calloc");
+ if (git_patch_from_diff(&patch, ci->diff, i)) {
+ git_patch_free(patch);
+ goto err;
+ }
+ di->patch = patch;
+ ci->deltas[i] = di;
+
+ delta = git_patch_get_delta(patch);
+
+ /* check binary data */
+ if (delta->flags & GIT_DIFF_FLAG_BINARY)
+ continue;
+
+ nhunks = git_patch_num_hunks(patch);
+ for (j = 0; j < nhunks; j++) {
+ if (git_patch_get_hunk(&hunk, &nhunklines, patch, j))
+ break;
+ for (k = 0; ; k++) {
+ if (git_patch_get_line_in_hunk(&line, patch, j…
+ break;
+ if (line->old_lineno == -1) {
+ di->addcount++;
+ ci->addcount++;
+ } else if (line->new_lineno == -1) {
+ di->delcount++;
+ ci->delcount++;
+ }
+ }
+ }
+ }
+ ci->ndeltas = i;
+ ci->filecount = i;
+
+ return 0;
+
+err:
+ if (ci->deltas)
+ for (i = 0; i < ci->ndeltas; i++)
+ deltainfo_free(ci->deltas[i]);
+ free(ci->deltas);
+ ci->deltas = NULL;
+ ci->ndeltas = 0;
+ ci->addcount = 0;
+ ci->delcount = 0;
+ ci->filecount = 0;
+
+ return -1;
+}
+
+void
commitinfo_free(struct commitinfo *ci)
{
+ size_t i;
+
if (!ci)
return;
- git_diff_stats_free(ci->stats);
+ 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);
t@@ -66,6 +158,7 @@ commitinfo_getbyoid(const git_oid *id)
{
struct commitinfo *ci;
git_diff_options opts;
+ const git_oid *oid;
int error;
if (!(ci = calloc(1, sizeof(struct commitinfo))))
t@@ -82,26 +175,24 @@ commitinfo_getbyoid(const git_oid *id)
ci->summary = git_commit_summary(ci->commit);
ci->msg = git_commit_message(ci->commit);
- if ((error = git_commit_tree(&(ci->commit_tree), ci->commit)))
+ oid = git_commit_tree_id(ci->commit);
+ if ((error = git_tree_lookup(&(ci->commit_tree), repo, oid)))
goto err;
if (!(error = git_commit_parent(&(ci->parent), ci->commit, 0))) {
- if ((error = git_commit_tree(&(ci->parent_tree), ci->parent)))
- goto err;
- } else {
- ci->parent = NULL;
- ci->parent_tree = NULL;
+ oid = git_commit_tree_id(ci->parent);
+ if ((error = git_tree_lookup(&(ci->parent_tree), repo, oid))) {
+ ci->parent = NULL;
+ ci->parent_tree = NULL;
+ }
}
git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION);
opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
if ((error = git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree,…
goto err;
- if (git_diff_get_stats(&(ci->stats), ci->diff))
- goto err;
- ci->addcount = git_diff_stats_insertions(ci->stats);
- ci->delcount = git_diff_stats_deletions(ci->stats);
- ci->filecount = git_diff_stats_files_changed(ci->stats);
+ if (commitinfo_getstats(ci) == -1)
+ goto err;
return ci;
t@@ -332,33 +423,55 @@ printshowfile(FILE *fp, struct commitinfo *ci)
const git_diff_hunk *hunk;
const git_diff_line *line;
git_patch *patch;
- git_buf statsbuf;
- size_t ndeltas, nhunks, nhunklines;
+ size_t nhunks, nhunklines, changed, add, del, total;
size_t i, j, k;
+ char linestr[80];
printcommit(fp, ci);
- memset(&statsbuf, 0, sizeof(statsbuf));
+ if (!ci->deltas)
+ return;
/* diff stat */
- if (ci->stats &&
- !git_diff_stats_to_buf(&statsbuf, ci->stats,
- GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_SHORT,…
- if (statsbuf.ptr && statsbuf.ptr[0]) {
- fputs("<b>Diffstat:</b>\n", fp);
- xmlencode(fp, statsbuf.ptr, strlen(statsbuf.ptr));
+ fputs("<b>Diffstat:</b>\n<table>", fp);
+ for (i = 0; i < ci->ndeltas; i++) {
+ delta = git_patch_get_delta(ci->deltas[i]->patch);
+ fputs("<tr><td>", fp);
+ xmlencode(fp, delta->old_file.path, strlen(delta->old_file.pat…
+ if (strcmp(delta->old_file.path, delta->new_file.path)) {
+ fputs(" -&gt; ", fp);
+ xmlencode(fp, delta->new_file.path, strlen(delta->new_…
+ }
+
+ add = ci->deltas[i]->addcount;
+ del = ci->deltas[i]->delcount;
+ changed = add + del;
+ total = sizeof(linestr) - 2;
+ if (changed > total) {
+ if (add)
+ add = ((float)total / changed * add) + 1;
+ if (del)
+ del = ((float)total / changed * del) + 1;
}
+ memset(&linestr, '+', add);
+ memset(&linestr[add], '-', del);
+
+ fprintf(fp, "</td><td> | %zu <span class=\"i\">",
+ ci->deltas[i]->addcount + ci->deltas[i]->delcount);
+ fwrite(&linestr, 1, add, fp);
+ fputs("</span><span class=\"d\">", fp);
+ fwrite(&linestr[add], 1, del, fp);
+ fputs("</span></td></tr>\n", fp);
}
+ fprintf(fp, "</table>%zu file%s changed, %zu insertion%s(+), %zu delet…
+ ci->filecount, ci->filecount == 1 ? "" : "s",
+ ci->addcount, ci->addcount == 1 ? "" : "s",
+ ci->delcount, ci->delcount == 1 ? "" : "s");
fputs("<hr/>", fp);
- ndeltas = git_diff_num_deltas(ci->diff);
- for (i = 0; i < ndeltas; i++) {
- if (git_patch_from_diff(&patch, ci->diff, i)) {
- git_patch_free(patch);
- break;
- }
-
+ for (i = 0; i < ci->ndeltas; i++) {
+ patch = ci->deltas[i]->patch;
delta = git_patch_get_delta(patch);
fprintf(fp, "<b>diff --git a/<a href=\"%sfile/%s.html\">%s</a>…
relpath, delta->old_file.path, delta->old_file.path,
t@@ -367,7 +480,6 @@ printshowfile(FILE *fp, struct commitinfo *ci)
/* check binary data */
if (delta->flags & GIT_DIFF_FLAG_BINARY) {
fputs("Binary files differ\n", fp);
- git_patch_free(patch);
continue;
}
t@@ -396,11 +508,7 @@ printshowfile(FILE *fp, struct commitinfo *ci)
fputs("</a>", fp);
}
}
- git_patch_free(patch);
}
- git_buf_free(&statsbuf);
-
- return;
}
int
diff --git a/style.css b/style.css
t@@ -79,10 +79,12 @@ pre a.h {
color: #00a;
}
+span.i,
pre a.i {
color: #070;
}
+span.d,
pre a.d {
color: #e00;
}
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.