]> git.armaanb.net Git - stagit.git/commitdiff
cache support (-c option)
authorHiltjo Posthuma <hiltjo@codemadness.org>
Sun, 1 May 2016 15:54:14 +0000 (17:54 +0200)
committerHiltjo Posthuma <hiltjo@codemadness.org>
Mon, 2 May 2016 19:17:52 +0000 (21:17 +0200)
"Optionally the -c cachefile option can be used to cache the entries of
the log page up to the point of the last commit. The cachefile will store
the last commit id and the entries in the HTML table."

this caches the diffstat and commits, it is an expensive operation (twss).

stagit.1
stagit.c

index 7ee1249544cc7a8a4b35f64fb356e581ccda62b4..d3cbb7e543553cf582ce29246c281bdac280318f 100644 (file)
--- a/stagit.1
+++ b/stagit.1
@@ -1,4 +1,4 @@
-.Dd December 26, 2015
+.Dd May 1, 2016
 .Dt STAGIT 1
 .Os
 .Sh NAME
@@ -6,12 +6,26 @@
 .Nd static git page generator
 .Sh SYNOPSIS
 .Nm
-.Op Ar repodir
+.Op Fl c Ar cachefile
+.Ar repodir
 .Sh DESCRIPTION
 .Nm
 writes HTML pages for the repository
 .Ar repodir
-to the current directory. The following files will be written:
+to the current directory.
+.Pp
+Optionally the
+.Fl c Ar cachefile
+option can be used to cache the entries of the log page up to the point of
+the last commit. The
+.Ar cachefile
+will store the last commit id and the entries in the HTML table. It is up
+to the user to make sure the state of the
+.Ar cachefile
+is in sync with the history of the repository, for example a
+git push \-\-force can screw this up.
+.Pp
+The following files will be written:
 .Bl -tag -width Ds
 .It atom.xml
 Atom XML feed
index 7c527785c69d4c4a74fb91254ec75c3e04362a86..158447d871c41ae6498a961fdfe39e6765584fa7 100644 (file)
--- a/stagit.c
+++ b/stagit.c
@@ -58,6 +58,12 @@ static char description[255];
 static char cloneurl[1024];
 static int haslicense, hasreadme, hassubmodules;
 
+/* cache */
+static git_oid lastoid;
+static char lastoidstr[GIT_OID_HEXSZ + 2]; /* id + newline + nul byte */
+static FILE *rcachefp, *wcachefp;
+static const char *cachefile;
+
 void
 deltainfo_free(struct deltainfo *di)
 {
@@ -530,13 +536,43 @@ printshowfile(FILE *fp, struct commitinfo *ci)
        }
 }
 
+void
+writelogline(FILE *fp, struct commitinfo *ci)
+{
+       size_t len;
+
+       fputs("<tr><td>", fp);
+       if (ci->author)
+               printtimeshort(fp, &(ci->author->when));
+       fputs("</td><td>", fp);
+       if (ci->summary) {
+               fprintf(fp, "<a href=\"%scommit/%s.html\">", relpath, ci->oid);
+               if ((len = strlen(ci->summary)) > summarylen) {
+                       xmlencode(fp, ci->summary, summarylen - 1);
+                       fputs("…", fp);
+               } else {
+                       xmlencode(fp, ci->summary, len);
+               }
+               fputs("</a>", fp);
+       }
+       fputs("</td><td>", fp);
+       if (ci->author)
+               xmlencode(fp, ci->author->name, strlen(ci->author->name));
+       fputs("</td><td class=\"num\">", fp);
+       fprintf(fp, "%zu", ci->filecount);
+       fputs("</td><td class=\"num\">", fp);
+       fprintf(fp, "+%zu", ci->addcount);
+       fputs("</td><td class=\"num\">", fp);
+       fprintf(fp, "-%zu", ci->delcount);
+       fputs("</td></tr>\n", fp);
+}
+
 int
 writelog(FILE *fp, const git_oid *oid)
 {
        struct commitinfo *ci;
        git_revwalk *w = NULL;
        git_oid id;
-       size_t len;
        char path[PATH_MAX];
        FILE *fpfile;
        int r;
@@ -546,40 +582,17 @@ writelog(FILE *fp, const git_oid *oid)
        git_revwalk_sorting(w, GIT_SORT_TIME);
        git_revwalk_simplify_first_parent(w);
 
-       fputs("<table id=\"log\"><thead>\n<tr><td>Date</td><td>Commit message</td>"
-                 "<td>Author</td><td class=\"num\">Files</td><td class=\"num\">+</td>"
-                 "<td class=\"num\">-</td></tr>\n</thead><tbody>\n", fp);
-
        while (!git_revwalk_next(&id, w)) {
                relpath = "";
 
+               if (cachefile && !memcmp(&id, &lastoid, sizeof(id)))
+                       break;
                if (!(ci = commitinfo_getbyoid(&id)))
                        break;
 
-               fputs("<tr><td>", fp);
-               if (ci->author)
-                       printtimeshort(fp, &(ci->author->when));
-               fputs("</td><td>", fp);
-               if (ci->summary) {
-                       fprintf(fp, "<a href=\"%scommit/%s.html\">", relpath, ci->oid);
-                       if ((len = strlen(ci->summary)) > summarylen) {
-                               xmlencode(fp, ci->summary, summarylen - 1);
-                               fputs("…", fp);
-                       } else {
-                               xmlencode(fp, ci->summary, len);
-                       }
-                       fputs("</a>", fp);
-               }
-               fputs("</td><td>", fp);
-               if (ci->author)
-                       xmlencode(fp, ci->author->name, strlen(ci->author->name));
-               fputs("</td><td class=\"num\">", fp);
-               fprintf(fp, "%zu", ci->filecount);
-               fputs("</td><td class=\"num\">", fp);
-               fprintf(fp, "+%zu", ci->addcount);
-               fputs("</td><td class=\"num\">", fp);
-               fprintf(fp, "-%zu", ci->delcount);
-               fputs("</td></tr>\n", fp);
+               writelogline(fp, ci);
+               if (cachefile)
+                       writelogline(wcachefp, ci);
 
                relpath = "../";
 
@@ -599,8 +612,6 @@ writelog(FILE *fp, const git_oid *oid)
                }
                commitinfo_free(ci);
        }
-       fputs("</tbody></table>", fp);
-
        git_revwalk_free(w);
 
        relpath = "";
@@ -1005,6 +1016,13 @@ joinpath(char *buf, size_t bufsiz, const char *path, const char *path2)
                        path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2);
 }
 
+void
+usage(char *argv0)
+{
+       fprintf(stderr, "%s [-c cachefile] repodir\n", argv0);
+       exit(1);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -1013,12 +1031,23 @@ main(int argc, char *argv[])
        const git_error *e = NULL;
        FILE *fp, *fpread;
        char path[PATH_MAX], repodirabs[PATH_MAX + 1], *p;
-
-       if (argc != 2) {
-               fprintf(stderr, "%s <repodir>\n", argv[0]);
-               return 1;
+       char tmppath[64] = "cache.XXXXXXXXXXXX", buf[BUFSIZ];
+       size_t n;
+       int i, fd;
+
+       for (i = 1; i < argc; i++) {
+               if (argv[i][0] != '-') {
+                       if (repodir)
+                               usage(argv[0]);
+                       repodir = argv[i];
+               } else if (argv[i][1] == 'c') {
+                       if (i + 1 >= argc)
+                               usage(argv[0]);
+                       cachefile = argv[++i];
+               }
        }
-       repodir = argv[1];
+       if (!repodir)
+               usage(argv[0]);
 
        if (!realpath(repodir, repodirabs))
                err(1, "realpath");
@@ -1088,9 +1117,51 @@ main(int argc, char *argv[])
        /* log for HEAD */
        fp = efopen("log.html", "w");
        relpath = "";
-       writeheader(fp, "Log");
        mkdir("commit", 0755);
-       writelog(fp, head);
+       writeheader(fp, "Log");
+       fputs("<table id=\"log\"><thead>\n<tr><td>Date</td><td>Commit message</td>"
+                 "<td>Author</td><td class=\"num\">Files</td><td class=\"num\">+</td>"
+                 "<td class=\"num\">-</td></tr>\n</thead><tbody>\n", fp);
+
+       if (cachefile) {
+               /* read from cache file (does not need to exist) */
+               if ((rcachefp = fopen(cachefile, "r"))) {
+                       if (!fgets(lastoidstr, sizeof(lastoidstr), rcachefp))
+                               errx(1, "%s: no object id", cachefile);
+                       if (git_oid_fromstr(&lastoid, lastoidstr))
+                               errx(1, "%s: invalid object id", cachefile);
+               }
+
+               /* write log to (temporary) cache */
+               if ((fd = mkstemp(tmppath)) == -1)
+                       err(1, "mkstemp");
+               if (!(wcachefp = fdopen(fd, "w")))
+                       err(1, "fdopen");
+               /* write last commit id (HEAD) */
+               git_oid_tostr(buf, sizeof(buf), head);
+               fprintf(wcachefp, "%s\n", buf);
+
+               writelog(fp, head);
+
+               if (rcachefp) {
+                       /* append previous log to log.html and the new cache */
+                       while (!feof(rcachefp)) {
+                               n = fread(buf, 1, sizeof(buf), rcachefp);
+                               if (ferror(rcachefp))
+                                       err(1, "fread");
+                               if (fwrite(buf, 1, n, fp) != n)
+                                       err(1, "fwrite");
+                               if (fwrite(buf, 1, n, wcachefp) != n)
+                                       err(1, "fwrite");
+                       }
+                       fclose(rcachefp);
+               }
+               fclose(wcachefp);
+       } else {
+               writelog(fp, head);
+       }
+
+       fputs("</tbody></table>", fp);
        writefooter(fp);
        fclose(fp);
 
@@ -1113,6 +1184,10 @@ main(int argc, char *argv[])
        writeatom(fp);
        fclose(fp);
 
+       /* rename new cache file on success */
+       if (cachefile && rename(tmppath, cachefile))
+               err(1, "rename: '%s' to '%s'", tmppath, cachefile);
+
        /* cleanup */
        git_repository_free(repo);
        git_libgit2_shutdown();