rework code, "cache" commit data in struct commitinfo - stagit-gopher - A git g… | |
git clone git://bitreich.org/stagit-gopher/ git://enlrupgkhuxnvlhsf6lc3fziv5h2h… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit 9c1862ccdacddee9b8a324a8d4a67d18c5ab7d93 | |
parent 1b4f30ba2e66133139f225cb536ba2c6ed62ff36 | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Mon, 7 Dec 2015 23:00:07 +0100 | |
rework code, "cache" commit data in struct commitinfo | |
Diffstat: | |
M urmoms.c | 353 +++++++++++++++--------------… | |
1 file changed, 175 insertions(+), 178 deletions(-) | |
--- | |
diff --git a/urmoms.c b/urmoms.c | |
@@ -11,6 +11,28 @@ | |
#include "git2.h" | |
+struct commitinfo { | |
+ const git_oid *id; | |
+ | |
+ char oid[GIT_OID_HEXSZ + 1]; | |
+ char parentoid[GIT_OID_HEXSZ + 1]; | |
+ | |
+ const git_signature *author; | |
+ 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; | |
+ | |
+ size_t addcount; | |
+ size_t delcount; | |
+ size_t filecount; | |
+}; | |
+ | |
static git_repository *repo; | |
static const char *relpath = ""; | |
@@ -20,6 +42,69 @@ static char name[255]; | |
static char description[255]; | |
static int hasreadme, haslicense; | |
+void | |
+commitinfo_free(struct commitinfo *ci) | |
+{ | |
+ if (!ci) | |
+ return; | |
+ | |
+ /* TODO: print error ? */ | |
+ git_diff_stats_free(ci->stats); | |
+ git_diff_free(ci->diff); | |
+ git_commit_free(ci->commit); | |
+} | |
+ | |
+struct commitinfo * | |
+commitinfo_getbyoid(const git_oid *id) | |
+{ | |
+ struct commitinfo *ci; | |
+ int error; | |
+ | |
+ if (!(ci = calloc(1, sizeof(struct commitinfo)))) | |
+ err(1, "calloc"); | |
+ | |
+ ci->id = id; | |
+ if (git_commit_lookup(&(ci->commit), repo, id)) | |
+ goto err; | |
+ | |
+ /* TODO: show tags when commit has it */ | |
+ git_oid_tostr(ci->oid, sizeof(ci->oid), git_commit_id(ci->commit)); | |
+ git_oid_tostr(ci->parentoid, sizeof(ci->parentoid), git_commit_parent_… | |
+ | |
+ ci->author = git_commit_author(ci->commit); | |
+ ci->summary = git_commit_summary(ci->commit); | |
+ ci->msg = git_commit_message(ci->commit); | |
+ | |
+ if ((error = git_commit_tree(&(ci->commit_tree), ci->commit))) | |
+ goto err; /* TODO: handle error */ | |
+ 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; | |
+ } | |
+ | |
+ 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); | |
+ | |
+ /* TODO: show tag when commit has it */ | |
+ | |
+ return ci; | |
+ | |
+err: | |
+ commitinfo_free(ci); | |
+ free(ci); | |
+ | |
+ return NULL; | |
+} | |
+ | |
int | |
writeheader(FILE *fp) | |
{ | |
@@ -156,22 +241,23 @@ printtime(FILE *fp, const git_time *intime) | |
} | |
void | |
-printcommit(FILE *fp, git_commit *commit) | |
+writeblobhtml(FILE *fp, const git_blob *blob) | |
{ | |
- const git_signature *sig; | |
- char buf[GIT_OID_HEXSZ + 1]; | |
- int i, count; | |
- const char *msg; | |
+ xmlencode(fp, git_blob_rawcontent(blob), (size_t)git_blob_rawsize(blob… | |
+} | |
+void | |
+printcommit(FILE *fp, struct commitinfo *ci) | |
+{ | |
/* TODO: show tag when commit has it */ | |
- git_oid_tostr(buf, sizeof(buf), git_commit_id(commit)); | |
fprintf(fp, "<b>commit</b> <a href=\"%scommit/%s.html\">%s</a>\n", | |
- relpath, buf, buf); | |
+ relpath, ci->oid, ci->oid); | |
- if (git_oid_tostr(buf, sizeof(buf), git_commit_parent_id(commit, 0)) &… | |
+ if (ci->parentoid[0]) | |
fprintf(fp, "<b>parent</b> <a href=\"%scommit/%s.html\">%s</a>… | |
- relpath, buf, buf); | |
+ relpath, ci->parentoid, ci->parentoid); | |
+#if 0 | |
if ((count = (int)git_commit_parentcount(commit)) > 1) { | |
fprintf(fp, "<b>Merge:</b>"); | |
for (i = 0; i < count; i++) { | |
@@ -181,81 +267,66 @@ printcommit(FILE *fp, git_commit *commit) | |
} | |
fputc('\n', fp); | |
} | |
- if ((sig = git_commit_author(commit)) != NULL) { | |
+#endif | |
+ if (ci->author) { | |
fprintf(fp, "<b>Author:</b> "); | |
- xmlencode(fp, sig->name, strlen(sig->name)); | |
+ xmlencode(fp, ci->author->name, strlen(ci->author->name)); | |
fprintf(fp, " <<a href=\"mailto:"); | |
- xmlencode(fp, sig->email, strlen(sig->email)); | |
+ xmlencode(fp, ci->author->email, strlen(ci->author->email)); | |
fputs("\">", fp); | |
- xmlencode(fp, sig->email, strlen(sig->email)); | |
+ xmlencode(fp, ci->author->email, strlen(ci->author->email)); | |
fputs("</a>>\n<b>Date:</b> ", fp); | |
- printtime(fp, &sig->when); | |
+ printtime(fp, &(ci->author->when)); | |
fputc('\n', fp); | |
} | |
fputc('\n', fp); | |
- if ((msg = git_commit_message(commit))) | |
- xmlencode(fp, msg, strlen(msg)); | |
+ if (ci->msg) | |
+ xmlencode(fp, ci->msg, strlen(ci->msg)); | |
+ | |
fputc('\n', fp); | |
} | |
void | |
-printshowfile(git_commit *commit) | |
+printshowfile(struct commitinfo *ci) | |
{ | |
- const git_diff_delta *delta = NULL; | |
- const git_diff_hunk *hunk = NULL; | |
- const git_diff_line *line = NULL; | |
- git_commit *parent = NULL; | |
- git_tree *commit_tree = NULL, *parent_tree = NULL; | |
- git_patch *patch = NULL; | |
- git_diff *diff = NULL; | |
- git_diff_stats *diffstats = NULL; | |
- git_buf diffstatsbuf; | |
+ const git_diff_delta *delta; | |
+ const git_diff_hunk *hunk; | |
+ const git_diff_line *line; | |
+ git_patch *patch; | |
+ git_buf statsbuf; | |
+ size_t ndeltas, nhunks, nhunklines; | |
FILE *fp; | |
- size_t i, j, k, ndeltas, nhunks = 0, nhunklines = 0; | |
- char buf[GIT_OID_HEXSZ + 1], path[PATH_MAX]; | |
- int error; | |
+ size_t i, j, k; | |
+ char path[PATH_MAX]; | |
- git_oid_tostr(buf, sizeof(buf), git_commit_id(commit)); | |
- if (!buf[0]) | |
- return; | |
- snprintf(path, sizeof(path), "commit/%s.html", buf); | |
+ snprintf(path, sizeof(path), "commit/%s.html", ci->oid); | |
/* check if file exists if so skip it */ | |
if (!access(path, F_OK)) | |
return; | |
- memset(&diffstatsbuf, 0, sizeof(diffstatsbuf)); | |
- | |
fp = efopen(path, "w+b"); | |
writeheader(fp); | |
- printcommit(fp, commit); | |
+ printcommit(fp, ci); | |
- if ((error = git_commit_tree(&commit_tree, commit))) | |
- goto err; | |
- if (!(error = git_commit_parent(&parent, commit, 0))) { | |
- if ((error = git_commit_tree(&parent_tree, parent))) | |
- goto err; /* TODO: handle error */ | |
- } else { | |
- parent = NULL; | |
- parent_tree = NULL; | |
- } | |
- if ((error = git_diff_tree_to_tree(&diff, repo, parent_tree, commit_tr… | |
- goto err; | |
+ memset(&statsbuf, 0, sizeof(statsbuf)); | |
/* diff stat */ | |
- if (!git_diff_get_stats(&diffstats, diff)) { | |
- if (!git_diff_stats_to_buf(&diffstatsbuf, diffstats, | |
+ if (ci->stats) { | |
+ if (!git_diff_stats_to_buf(&statsbuf, ci->stats, | |
GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_SHORT, 80)) { | |
- fprintf(fp, "<b>Diffstat:</b>\n"); | |
- fputs(diffstatsbuf.ptr, fp); | |
+ if (statsbuf.ptr && statsbuf.ptr[0]) { | |
+ fprintf(fp, "<b>Diffstat:</b>\n"); | |
+ fputs(statsbuf.ptr, fp); | |
+ } | |
} | |
- git_diff_stats_free(diffstats); | |
} | |
+ | |
fputs("<hr/>", fp); | |
- ndeltas = git_diff_num_deltas(diff); | |
+ ndeltas = git_diff_num_deltas(ci->diff); | |
for (i = 0; i < ndeltas; i++) { | |
- if (git_patch_from_diff(&patch, diff, i)) { | |
+ if (git_patch_from_diff(&patch, ci->diff, i)) { | |
git_patch_free(patch); | |
break; /* TODO: handle error */ | |
} | |
@@ -265,26 +336,6 @@ printshowfile(git_commit *commit) | |
relpath, delta->old_file.path, delta->old_file.path, | |
relpath, delta->new_file.path, delta->new_file.path); | |
- /* TODO: "new file mode <mode>". */ | |
- /* TODO: add indexfrom...indexto + flags */ | |
- | |
-#if 0 | |
- fputs("<b>--- ", fp); | |
- if (delta->status & GIT_DELTA_ADDED) | |
- fputs("/dev/null", fp); | |
- else | |
- fprintf(fp, "a/<a href=\"%sfile/%s\">%s</a>", | |
- relpath, delta->old_file.path, delta->old_file… | |
- | |
- fputs("\n+++ ", fp); | |
- if (delta->status & GIT_DELTA_DELETED) | |
- fputs("/dev/null", fp); | |
- else | |
- fprintf(fp, "b/<a href=\"%sfile/%s\">%s</a>", | |
- relpath, delta->new_file.path, delta->new_file… | |
- fputs("</b>\n", fp); | |
-#endif | |
- | |
/* check binary data */ | |
if (delta->flags & GIT_DIFF_FLAG_BINARY) { | |
fputs("Binary files differ\n", fp); | |
@@ -317,32 +368,20 @@ printshowfile(git_commit *commit) | |
} | |
git_patch_free(patch); | |
} | |
- git_diff_free(diff); | |
+ git_buf_free(&statsbuf); | |
writefooter(fp); | |
fclose(fp); | |
return; | |
- | |
-err: | |
- git_buf_free(&diffstatsbuf); | |
- fclose(fp); | |
} | |
int | |
writelog(FILE *fp) | |
{ | |
+ struct commitinfo *ci; | |
git_revwalk *w = NULL; | |
git_oid id; | |
- git_commit *commit = NULL; | |
- const git_signature *author; | |
- git_diff_stats *stats = NULL; | |
- git_tree *commit_tree = NULL, *parent_tree = NULL; | |
- git_commit *parent = NULL; | |
- git_diff *diff = NULL; | |
- size_t nfiles, ndel, nadd; | |
- const char *summary; | |
- char buf[GIT_OID_HEXSZ + 1]; | |
- int error, ret = 0; | |
+ int ret = 0; | |
mkdir("commit", 0755); | |
@@ -355,67 +394,37 @@ writelog(FILE *fp) | |
while (!git_revwalk_next(&id, w)) { | |
relpath = ""; | |
- if (git_commit_lookup(&commit, repo, &id)) { | |
- ret = 1; | |
- goto err; | |
- } | |
- if ((error = git_commit_tree(&commit_tree, commit))) | |
- goto errdiff; /* TODO: handle error */ | |
- if (!(error = git_commit_parent(&parent, commit, 0))) { | |
- if ((error = git_commit_tree(&parent_tree, parent))) | |
- goto errdiff; | |
- } else { | |
- parent = NULL; | |
- parent_tree = NULL; | |
- } | |
- | |
- if ((error = git_diff_tree_to_tree(&diff, repo, parent_tree, c… | |
- goto errdiff; | |
- if (git_diff_get_stats(&stats, diff)) | |
- goto errdiff; | |
- | |
- git_oid_tostr(buf, sizeof(buf), git_commit_id(commit)); | |
- | |
- ndel = git_diff_stats_deletions(stats); | |
- nadd = git_diff_stats_insertions(stats); | |
- nfiles = git_diff_stats_files_changed(stats); | |
- | |
- /* TODO: show tag when commit has it */ | |
- | |
- /* TODO: collect stats per author and make stats.html page */ | |
- author = git_commit_author(commit); | |
- summary = git_commit_summary(commit); | |
+ if (!(ci = commitinfo_getbyoid(&id))) | |
+ break; | |
fputs("<tr><td>", fp); | |
- if (summary) { | |
- fprintf(fp, "<a href=\"%scommit/%s.html\">", relpath, … | |
- xmlencode(fp, summary, strlen(summary)); | |
+ if (ci->summary) { | |
+ fprintf(fp, "<a href=\"%scommit/%s.html\">", relpath, … | |
+ xmlencode(fp, ci->summary, strlen(ci->summary)); | |
fputs("</a>", fp); | |
} | |
fputs("</td><td>", fp); | |
- if (author) | |
- xmlencode(fp, author->name, strlen(author->name)); | |
+ if (ci->author) | |
+ xmlencode(fp, ci->author->name, strlen(ci->author->nam… | |
+ | |
fputs("</td><td align=\"right\">", fp); | |
- printtime(fp, &author->when); | |
+ if (ci->author) | |
+ printtime(fp, &(ci->author->when)); | |
fputs("</td><td align=\"right\">", fp); | |
- fprintf(fp, "%zu", nfiles); | |
+ fprintf(fp, "%zu", ci->filecount); | |
fputs("</td><td align=\"right\">", fp); | |
- fprintf(fp, "+%zu", nadd); | |
+ fprintf(fp, "+%zu", ci->addcount); | |
fputs("</td><td align=\"right\">", fp); | |
- fprintf(fp, "-%zu", ndel); | |
+ fprintf(fp, "-%zu", ci->delcount); | |
fputs("</td></tr>\n", fp); | |
relpath = "../"; | |
- printshowfile(commit); | |
+ printshowfile(ci); | |
-errdiff: | |
- /* TODO: print error ? */ | |
- git_diff_stats_free(stats); | |
- git_diff_free(diff); | |
- git_commit_free(commit); | |
+ commitinfo_free(ci); | |
} | |
fprintf(fp, "</tbody></table>"); | |
-err: | |
+ | |
git_revwalk_free(w); | |
relpath = ""; | |
@@ -423,38 +432,28 @@ err: | |
} | |
void | |
-printcommitatom(FILE *fp, git_commit *commit) | |
+printcommitatom(FILE *fp, struct commitinfo *ci) | |
{ | |
- const git_signature *sig; | |
- char buf[GIT_OID_HEXSZ + 1]; | |
- int i, count; | |
- const char *msg, *summary; | |
- | |
fputs("<entry>\n", fp); | |
- /* TODO: show tag when commit has it */ | |
- git_oid_tostr(buf, sizeof(buf), git_commit_id(commit)); | |
- fprintf(fp, "<id>%s</id>\n", buf); | |
- | |
- sig = git_commit_author(commit); | |
- | |
- if (sig) { | |
+ fprintf(fp, "<id>%s</id>\n", ci->oid); | |
+ if (ci->author) { | |
fputs("<updated>", fp); | |
- printtimez(fp, &sig->when); | |
+ printtimez(fp, &(ci->author->when)); | |
fputs("</updated>\n", fp); | |
} | |
- | |
- if ((summary = git_commit_summary(commit))) { | |
+ if (ci->summary) { | |
fputs("<title type=\"text\">", fp); | |
- xmlencode(fp, summary, strlen(summary)); | |
+ xmlencode(fp, ci->summary, strlen(ci->summary)); | |
fputs("</title>\n", fp); | |
} | |
fputs("<content type=\"text\">", fp); | |
- fprintf(fp, "commit %s\n", buf); | |
- if (git_oid_tostr(buf, sizeof(buf), git_commit_parent_id(commit, 0)) &… | |
- fprintf(fp, "parent %s\n", buf); | |
+ fprintf(fp, "commit %s\n", ci->oid); | |
+ if (ci->parentoid[0]) | |
+ fprintf(fp, "parent %s\n", ci->parentoid); | |
+#if 0 | |
if ((count = (int)git_commit_parentcount(commit)) > 1) { | |
fprintf(fp, "Merge:"); | |
for (i = 0; i < count; i++) { | |
@@ -463,25 +462,26 @@ printcommitatom(FILE *fp, git_commit *commit) | |
} | |
fputc('\n', fp); | |
} | |
+#endif | |
- if (sig) { | |
+ if (ci->author) { | |
fprintf(fp, "Author: "); | |
- xmlencode(fp, sig->name, strlen(sig->name)); | |
+ xmlencode(fp, ci->author->name, strlen(ci->author->name)); | |
fprintf(fp, " <"); | |
- xmlencode(fp, sig->email, strlen(sig->email)); | |
+ xmlencode(fp, ci->author->email, strlen(ci->author->email)); | |
fprintf(fp, ">\nDate: "); | |
- printtime(fp, &sig->when); | |
+ printtime(fp, &(ci->author->when)); | |
} | |
fputc('\n', fp); | |
- if ((msg = git_commit_message(commit))) | |
- xmlencode(fp, msg, strlen(msg)); | |
+ if (ci->msg) | |
+ xmlencode(fp, ci->msg, strlen(ci->msg)); | |
fputs("\n</content>\n", fp); | |
- if (sig) { | |
+ if (ci->author) { | |
fputs("<author><name>", fp); | |
- xmlencode(fp, sig->name, strlen(sig->name)); | |
+ xmlencode(fp, ci->author->name, strlen(ci->author->name)); | |
fputs("</name>\n<email>", fp); | |
- xmlencode(fp, sig->email, strlen(sig->email)); | |
+ xmlencode(fp, ci->author->email, strlen(ci->author->email)); | |
fputs("</email>\n</author>\n", fp); | |
} | |
fputs("</entry>\n", fp); | |
@@ -490,9 +490,9 @@ printcommitatom(FILE *fp, git_commit *commit) | |
int | |
writeatom(FILE *fp) | |
{ | |
+ struct commitinfo *ci; | |
git_revwalk *w = NULL; | |
git_oid id; | |
- git_commit *c = NULL; | |
size_t i, m = 100; /* max */ | |
fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp); | |
@@ -507,10 +507,10 @@ writeatom(FILE *fp) | |
git_revwalk_push_head(w); | |
for (i = 0; i < m && !git_revwalk_next(&id, w); i++) { | |
- if (git_commit_lookup(&c, repo, &id)) | |
- return 1; /* TODO: error */ | |
- printcommitatom(fp, c); | |
- git_commit_free(c); | |
+ if (!(ci = commitinfo_getbyoid(&id))) | |
+ break; | |
+ printcommitatom(fp, ci); | |
+ commitinfo_free(ci); | |
} | |
git_revwalk_free(w); | |
@@ -522,14 +522,16 @@ writeatom(FILE *fp) | |
int | |
writefiles(FILE *fp) | |
{ | |
- git_index *index; | |
const git_index_entry *entry; | |
+ git_index *index; | |
size_t count, i; | |
- git_repository_index(&index, repo); | |
+ fputs("<table><thead>\n" | |
+ "<tr><td>Mode</td><td>Name</td><td align=\"right\">Size</td></tr… | |
+ "</thead><tbody>\n", fp); | |
+ git_repository_index(&index, repo); | |
count = git_index_entrycount(index); | |
- fputs("<table><thead>\n<tr><td>Mode</td><td>Name</td><td align=\"right… | |
for (i = 0; i < count; i++) { | |
entry = git_index_get_byindex(index, i); | |
@@ -543,17 +545,12 @@ writefiles(FILE *fp) | |
fprintf(fp, "%" PRIu64, entry->file_size); | |
fputs("</td></tr>\n", fp); | |
} | |
+ | |
fputs("</tbody></table>", fp); | |
return 0; | |
} | |
-void | |
-writeblobhtml(FILE *fp, const git_blob *blob) | |
-{ | |
- xmlencode(fp, git_blob_rawcontent(blob), (size_t)git_blob_rawsize(blob… | |
-} | |
- | |
int | |
main(int argc, char *argv[]) | |
{ |