From 1a3584e2d0689aece46d9832c91f57723296807f Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 1 May 2016 17:54:14 +0200 Subject: cache support (-c option) "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.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 113 insertions(+), 38 deletions(-) (limited to 'stagit.c') diff --git a/stagit.c b/stagit.c index 7c52778..158447d 100644 --- 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("", fp); + if (ci->author) + printtimeshort(fp, &(ci->author->when)); + fputs("", fp); + if (ci->summary) { + fprintf(fp, "", relpath, ci->oid); + if ((len = strlen(ci->summary)) > summarylen) { + xmlencode(fp, ci->summary, summarylen - 1); + fputs("…", fp); + } else { + xmlencode(fp, ci->summary, len); + } + fputs("", fp); + } + fputs("", fp); + if (ci->author) + xmlencode(fp, ci->author->name, strlen(ci->author->name)); + fputs("", fp); + fprintf(fp, "%zu", ci->filecount); + fputs("", fp); + fprintf(fp, "+%zu", ci->addcount); + fputs("", fp); + fprintf(fp, "-%zu", ci->delcount); + fputs("\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("\n" - "" - "\n\n", fp); - while (!git_revwalk_next(&id, w)) { relpath = ""; + if (cachefile && !memcmp(&id, &lastoid, sizeof(id))) + break; if (!(ci = commitinfo_getbyoid(&id))) break; - fputs("\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("
DateCommit messageAuthorFiles+-
", fp); - if (ci->author) - printtimeshort(fp, &(ci->author->when)); - fputs("", fp); - if (ci->summary) { - fprintf(fp, "", relpath, ci->oid); - if ((len = strlen(ci->summary)) > summarylen) { - xmlencode(fp, ci->summary, summarylen - 1); - fputs("…", fp); - } else { - xmlencode(fp, ci->summary, len); - } - fputs("", fp); - } - fputs("", fp); - if (ci->author) - xmlencode(fp, ci->author->name, strlen(ci->author->name)); - fputs("", fp); - fprintf(fp, "%zu", ci->filecount); - fputs("", fp); - fprintf(fp, "+%zu", ci->addcount); - fputs("", fp); - fprintf(fp, "-%zu", ci->delcount); - fputs("
", 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 \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("\n" + "" + "\n\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("
DateCommit messageAuthorFiles+-
", 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(); -- cgit v1.2.3