rework code, "cache" commit data in struct commitinfo
authorHiltjo Posthuma <hiltjo@codemadness.org>
Mon, 7 Dec 2015 22:00:07 +0000 (23:00 +0100)
committerHiltjo Posthuma <hiltjo@codemadness.org>
Mon, 7 Dec 2015 22:00:07 +0000 (23:00 +0100)
urmoms.c

index 6a7b185fea8a723980d47e6d20e0dd449dfa9d27..7d41fbbba2da8756283dc1e15b12b03051bd32fa 100644 (file)
--- a/urmoms.c
+++ b/urmoms.c
 
 #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_id(ci->commit, 0));
+
+       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, ci->commit_tree, NULL)))
+               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)) && buf[0])
+       if (ci->parentoid[0])
                fprintf(fp, "<b>parent</b> <a href=\"%scommit/%s.html\">%s</a>\n",
-                       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, " &lt;<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>&gt;\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_tree, NULL)))
-               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.path);
-
-               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.path);
-               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, commit_tree, NULL)))
-                       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, buf);
-                       xmlencode(fp, summary, strlen(summary));
+               if (ci->summary) {
+                       fprintf(fp, "<a href=\"%scommit/%s.html\">", relpath, ci->oid);
+                       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->name));
+
                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)) && buf[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, " &lt;");
-               xmlencode(fp, sig->email, strlen(sig->email));
+               xmlencode(fp, ci->author->email, strlen(ci->author->email));
                fprintf(fp, "&gt;\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>\n"
+             "</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\">Size</td></tr>\n</thead><tbody>\n", fp);
 
        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[])
 {