use git_reference for tags and branches, sort branches also - stagit-gopher - A… | |
git clone git://bitreich.org/stagit-gopher/ git://enlrupgkhuxnvlhsf6lc3fziv5h2h… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit 87360fe2526f7713c4626d04da521579141fcf68 | |
parent c750958b95624fd6bd45f817e255fe19aa412534 | |
Author: Hiltjo Posthuma <[email protected]> | |
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: | |
M stagit.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>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->nam… | |
- 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_refer… | |
+ 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\"><thea… | |
+ "<td>Age</td><td>Commit message</td>" | |
+ "<td>Author</td><td>Files</td><td class=… | |
+ "<td class=\"num\">-</td></tr>\n</thead>… | |
+ 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, … | |
- 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\">", r… | |
+ if ((len = strlen(ci->summary)) > summarylen) { | |
+ xmlencode(fp, ci->summary, summarylen … | |
+ 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->aut… | |
+ 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->nam… | |
- 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 |