7c6f58351f5c3321627e7c4020b2c5f9d8336c7b galt Wed Mar 3 17:34:20 2010 -0800 fixed colors, fixed counts on new files when there is no context line to finish the block, fixed bug in output of git show in diff part where odd and variable extra context appeared after @@ .* @@, currently just using sed to trim the diff file so html file inherits automatically diff --git git-reports.c git-reports.c index 4cdd62f..07e56ee 100644 --- git-reports.c +++ git-reports.c @@ -1,520 +1,557 @@ /* git-reports.c for creating git equivalent of cvs-reports. */ #include "common.h" #include "options.h" #include "dystring.h" #include "errabort.h" #include "hash.h" #include "linefile.h" #include "htmshell.h" static char const rcsid[] = "$Id: git-reports.c,v 1.1 2010/03/02 08:43:07 galt Exp $"; struct hash *userHash = NULL; struct slName *users = NULL; char *startTag = NULL; char *endTag = NULL; char *startDate = NULL; char *endDate = NULL; char *title = NULL; char *repoDir = NULL; char *outDir = NULL; char *outPrefix = NULL; char gitCmd[1024]; struct files { struct files *next; char type; char *path; int linesChanged; }; struct commit { struct commit *next; char *commitId; char *author; char *date; char *comment; struct files *files; }; void usage(char *msg) /* Explain usage and exit. */ { errAbort( "%s\n\n" "git-reports - produce source code reports useful for code-review on git repository \n" "\n" "Usage:\n" " git-reports startTag endTag startDate endDate title repoDir outDir outPrefix\n" "where " " startTag and endTag are repository tags marking the beginning and end of the git range\n" " startDate and endDate and title are just strings that get printed on the report\n" " title is usually the branch number, e.g. v225\n" " repoDir is where the git repository (use absolute path)\n" " outDir is the output directory (use absolute path).\n" " outPrefix is typically \"branch\" or \"review\" directory.\n" " --help - this help screen\n", msg); } static struct optionSpec options[] = { {"-help", OPTION_BOOLEAN}, {NULL, 0}, }; struct commit* getCommits() /* get all commits from startTag to endTag */ { safef(gitCmd,sizeof(gitCmd), "" "git log origin/%s..origin/%s --name-status > commits.tmp" , startTag, endTag); system(gitCmd); // TODO error handling struct lineFile *lf = lineFileOpen("commits.tmp", TRUE); int lineSize; char *line; struct commit *commits = NULL, *commit = NULL; struct files *files = NULL, *f = NULL; char *sep = ""; while (lineFileNext(lf, &line, &lineSize)) { boolean isMerge = FALSE; char *w = nextWord(&line); AllocVar(commit); if (!sameString("commit", w)) errAbort("expected keyword commit parsing commits.tmp\n"); commit->commitId = cloneString(nextWord(&line)); lineFileNext(lf, &line, &lineSize); w = nextWord(&line); if (sameString("Merge:", w)) { isMerge = TRUE; lineFileNext(lf, &line, &lineSize); w = nextWord(&line); } if (!sameString("Author:", w)) errAbort("expected keyword Author: parsing commits.tmp\n"); commit->author = cloneString(nextWord(&line)); lineFileNext(lf, &line, &lineSize); w = nextWord(&line); if (!sameString("Date:", w)) errAbort("expected keyword Date: parsing commits.tmp\n"); commit->date = cloneString(line); lineFileNext(lf, &line, &lineSize); if (!sameString("", line)) errAbort("expected blank line parsing commits.tmp\n"); /* collect the comment-lines */ struct dyString *dy = NULL; dy = dyStringNew(0); sep = ""; files = NULL; while (lineFileNext(lf, &line, &lineSize)) { if (sameString("", line)) break; w = skipLeadingSpaces(line); dyStringPrintf(dy, "%s%s", w, sep); sep = "\n"; } commit->comment = cloneString(dy->string); freeDyString(&dy); if (!isMerge) { /* collect the files-list */ while (lineFileNext(lf, &line, &lineSize)) { if (sameString("", line)) break; AllocVar(f); w = nextWord(&line); f->type = w[0]; f->path = cloneString(line); slAddHead(&files, f); } slReverse(&files); } commit->files = files; slAddHead(&commits, commit); verbose(2, "commitId: %s\n" "author: %s\n" "date: %s\n" "comment: [%s]\n" "file(s): \n" , commit->commitId , commit->author , commit->date , commit->comment); for (f=commit->files; f; f = f->next) verbose(2, "%s\n", f->path); verbose(2, "------------\n"); } lineFileClose(&lf); slReverse(&commits); unlink("commits.tmp"); return commits; } int makeHtml(char *diffPath, char *htmlPath, char *path, char *commitId) /* Make a color-coded html diff * Return the number of lines changed */ { int linesChanged = 0; FILE *h = mustOpen(htmlPath, "w"); struct lineFile *lf = lineFileOpen(diffPath, TRUE); int lineSize; char *line; char *xline = NULL; boolean inBody = FALSE; boolean inBlock = TRUE; int blockP = 0, blockN = 0; fprintf(h, "\n
\n\n", path, commitId); while (lineFileNext(lf, &line, &lineSize)) { xline = htmlEncode(line); if (line[0] == '-') { - fprintf(h, "%s\n", xline); + fprintf(h, "%s\n", xline); if (inBody) { inBlock = TRUE; ++blockN; } } else if (line[0] == '+') { - fprintf(h, "%s\n", xline); + fprintf(h, "%s\n", xline); if (inBody) { inBlock = TRUE; ++blockP; } } else { - fprintf(h, "%s\n", xline); + if (line[0] == '@') + fprintf(h, "%s\n", xline); + else + fprintf(h, "%s\n", xline); if (inBody) { if (inBlock) { inBlock = FALSE; if (blockP >= blockN) linesChanged += blockP; else linesChanged += blockN; blockP = 0; blockN = 0; } } } if (line[0] == '@') inBody = TRUE; freeMem(xline); } +// what if there is no last trailing line to end the last block? +if (inBody) + { + if (inBlock) + { + inBlock = FALSE; + if (blockP >= blockN) + linesChanged += blockP; + else + linesChanged += blockN; + blockP = 0; + blockN = 0; + } + } lineFileClose(&lf); fprintf(h, "\n