stagit-responsive

My mobile friendly fork of stagit
Log | Files | Refs | README | LICENSE

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