commit 87360fe2526f7713c4626d04da521579141fcf68
parent c750958b95624fd6bd45f817e255fe19aa412534
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Wed,  6 Jan 2016 17:45:02 +0100

use git_reference for tags and branches, sort branches also

this removes some lines and somewhat simplifies it

Diffstat:
Mstagit.c | 285+++++++++++++++++++++++++++++++------------------------------------------------
1 file changed, 113 insertions(+), 172 deletions(-)

diff --git a/stagit.c b/stagit.c @@ -775,199 +775,140 @@ err: } int -writebranches(FILE *fp) +refs_cmp(const void *v1, const void *v2) { - struct commitinfo *ci; - git_branch_iterator *it = NULL; - git_branch_t branch; - git_reference *ref = NULL, *dref = NULL; - const git_oid *id = NULL; - const char *branchname = NULL; - size_t len; - int ret = -1; - - /* log for local branches */ - if (git_branch_iterator_new(&it, repo, GIT_BRANCH_LOCAL)) - return -1; - - fputs("<h2>Branches</h2><table id=\"branches\"><thead>\n<tr><td>Branch</td><td>Age</td>" - "<td>Commit message</td>" - "<td>Author</td><td>Files</td><td class=\"num\">+</td>" - "<td class=\"num\">-</td></tr>\n</thead><tbody>\n", fp); - - while (!git_branch_next(&ref, &branch, it)) { - if (git_branch_name(&branchname, ref)) - continue; - - id = NULL; - switch (git_reference_type(ref)) { - case GIT_REF_SYMBOLIC: - if (git_reference_resolve(&dref, ref)) - goto err; - id = git_reference_target(dref); - break; - case GIT_REF_OID: - id = git_reference_target(ref); - break; - default: - continue; - } - if (!id) - goto err; - if (!(ci = commitinfo_getbyoid(id))) - break; - - relpath = ""; - - fputs("<tr><td>", fp); - xmlencode(fp, branchname, strlen(branchname)); - fputs("</td><td>", fp); - if (ci->author) - printtimeshort(fp, &(ci->author->when)); - fputs("</td><td>", fp); - if (ci->summary) { - if ((len = strlen(ci->summary)) > summarylen) { - xmlencode(fp, ci->summary, summarylen - 1); - fputs("…", fp); - } else { - xmlencode(fp, ci->summary, len); - } - } - 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); - - relpath = "../"; + git_reference *r1 = (*(git_reference **)v1); + git_reference *r2 = (*(git_reference **)v2); + int t1, t2; - commitinfo_free(ci); - git_reference_free(ref); - git_reference_free(dref); - ref = NULL; - dref = NULL; - } - ret = 0; + t1 = git_reference_is_branch(r1); + t2 = git_reference_is_branch(r2); -err: - fputs("</tbody></table>", fp); - git_reference_free(ref); - git_reference_free(dref); - git_branch_iterator_free(it); + if (t1 != t2) + return t1 - t2; - return ret; + return strcmp(git_reference_shorthand(r1), + git_reference_shorthand(r2)); } int -tagcompare(void *s1, void *s2) -{ - return strcmp(*(char **)s1, *(char **)s2); -} - -int -writetags(FILE *fp) +writerefs(FILE *fp) { struct commitinfo *ci; - git_strarray tagnames; - git_object *obj = NULL; - git_tag *tag = NULL; const git_oid *id = NULL; - size_t i, len; - - /* summary page with branches and tags */ - memset(&tagnames, 0, sizeof(tagnames)); - if (git_tag_list(&tagnames, repo)) + git_object *obj = NULL; + git_reference *dref = NULL, *r, *ref = NULL; + git_reference_iterator *it = NULL; + git_reference **refs = NULL; + size_t count, i, j, len, refcount = 0; + const char *cols[] = { "Branch", "Tag" }; /* first column title */ + const char *titles[] = { "Branches", "Tags" }; + const char *ids[] = { "branches", "tags" }; + const char *name; + + if (git_reference_iterator_new(&it, repo)) return -1; - if (!tagnames.count) { - git_strarray_free(&tagnames); - return 0; - } - - /* sort names */ - qsort(tagnames.strings, tagnames.count, sizeof(char *), - (int (*)(const void *, const void *))&tagcompare); - - fputs("<h2>Tags</h2><table id=\"tags\"><thead>\n<tr><td>Tag</td>" - "<td>Age</td><td>Commit message</td>" - "<td>Author</td><td>Files</td><td class=\"num\">+</td>" - "<td class=\"num\">-</td></tr>\n</thead><tbody>\n", fp); - - for (i = 0; i < tagnames.count; i++) { - if (git_revparse_single(&obj, repo, tagnames.strings[i])) - continue; - id = git_object_id(obj); - /* lookup actual commit (from annotated tag etc) */ - if (!git_tag_lookup(&tag, repo, id)) { - git_object_free(obj); - obj = NULL; - if (git_tag_peel(&obj, tag)) + for (refcount = 0; !git_reference_next(&ref, it); refcount++) { + if (!(refs = reallocarray(refs, refcount + 1, sizeof(git_reference *)))) + err(1, "realloc"); + refs[refcount] = ref; + } + git_reference_iterator_free(it); + + /* sort by type then shorthand name */ + qsort(refs, refcount, sizeof(git_reference *), refs_cmp); + + for (j = 0; j < 2; j++) { + for (i = 0, count = 0; i < refcount; i++) { + if (git_reference_is_branch(refs[i]) && j == 0) + ; + else if (git_reference_is_tag(refs[i]) && j == 1) + ; + else + continue; + + id = NULL; + r = NULL; + switch (git_reference_type(refs[i])) { + case GIT_REF_SYMBOLIC: + if (git_reference_resolve(&dref, refs[i])) + goto err; + r = dref; + break; + case GIT_REF_OID: + r = refs[i]; + break; + default: + continue; + } + if (!(id = git_reference_target(r))) + goto err; + if (git_reference_peel(&obj, r, GIT_OBJ_ANY)) + goto err; + if (!(id = git_object_id(obj))) + goto err; + if (!(ci = commitinfo_getbyoid(id))) break; - git_tag_free(tag); - tag = NULL; - id = git_object_id(obj); - } - - if (!(ci = commitinfo_getbyoid(id))) - break; - relpath = ""; + /* print header if it has an entry (first). */ + if (++count == 1) { + fprintf(fp, "<h2>%s</h2><table id=\"%s\"><thead>\n<tr><td>%s</td>" + "<td>Age</td><td>Commit message</td>" + "<td>Author</td><td>Files</td><td class=\"num\">+</td>" + "<td class=\"num\">-</td></tr>\n</thead><tbody>\n", + titles[j], ids[j], cols[j]); + } - fputs("<tr><td>", fp); - xmlencode(fp, tagnames.strings[i], strlen(tagnames.strings[i])); - fputs("</td><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); + relpath = ""; + name = git_reference_shorthand(r); + + fputs("<tr><td>", fp); + xmlencode(fp, name, strlen(name)); + fputs("</td><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("</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); + + relpath = "../"; + + commitinfo_free(ci); + git_reference_free(dref); + dref = NULL; } - 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); - - relpath = "../"; - - commitinfo_free(ci); - git_object_free(obj); - obj = NULL; + /* table footer */ + if (count) + fputs("</tbody></table>", fp); } - fputs("</tbody></table>", fp); - git_strarray_free(&tagnames); - git_tag_free(tag); - git_object_free(obj); - return 0; -} +err: + git_reference_free(dref); -int -writerefs(FILE *fp) -{ - int ret; + for (i = 0; i < refcount; i++) + git_reference_free(refs[i]); + free(refs); - if ((ret = writebranches(fp))) - return ret; - fputs("<br/>", fp); - return writetags(fp); + return 0; } int