use git_reference for tags and branches, sort branches also
this removes some lines and somewhat simplifies it
1 files changed, 113 insertions(+), 172 deletions(-) | |||
---|---|---|---|
M | stagit.c | +113 | -172 |
1@@ -775,199 +775,140 @@ err:
2 }
3
4 int
5-writebranches(FILE *fp)
6+refs_cmp(const void *v1, const void *v2)
7 {
8- struct commitinfo *ci;
9- git_branch_iterator *it = NULL;
10- git_branch_t branch;
11- git_reference *ref = NULL, *dref = NULL;
12- const git_oid *id = NULL;
13- const char *branchname = NULL;
14- size_t len;
15- int ret = -1;
16-
17- /* log for local branches */
18- if (git_branch_iterator_new(&it, repo, GIT_BRANCH_LOCAL))
19- return -1;
20-
21- fputs("<h2>Branches</h2><table id=\"branches\"><thead>\n<tr><td>Branch</td><td>Age</td>"
22- "<td>Commit message</td>"
23- "<td>Author</td><td>Files</td><td class=\"num\">+</td>"
24- "<td class=\"num\">-</td></tr>\n</thead><tbody>\n", fp);
25-
26- while (!git_branch_next(&ref, &branch, it)) {
27- if (git_branch_name(&branchname, ref))
28- continue;
29-
30- id = NULL;
31- switch (git_reference_type(ref)) {
32- case GIT_REF_SYMBOLIC:
33- if (git_reference_resolve(&dref, ref))
34- goto err;
35- id = git_reference_target(dref);
36- break;
37- case GIT_REF_OID:
38- id = git_reference_target(ref);
39- break;
40- default:
41- continue;
42- }
43- if (!id)
44- goto err;
45- if (!(ci = commitinfo_getbyoid(id)))
46- break;
47-
48- relpath = "";
49-
50- fputs("<tr><td>", fp);
51- xmlencode(fp, branchname, strlen(branchname));
52- fputs("</td><td>", fp);
53- if (ci->author)
54- printtimeshort(fp, &(ci->author->when));
55- fputs("</td><td>", fp);
56- if (ci->summary) {
57- if ((len = strlen(ci->summary)) > summarylen) {
58- xmlencode(fp, ci->summary, summarylen - 1);
59- fputs("…", fp);
60- } else {
61- xmlencode(fp, ci->summary, len);
62- }
63- }
64- fputs("</td><td>", fp);
65- if (ci->author)
66- xmlencode(fp, ci->author->name, strlen(ci->author->name));
67- fputs("</td><td class=\"num\">", fp);
68- fprintf(fp, "%zu", ci->filecount);
69- fputs("</td><td class=\"num\">", fp);
70- fprintf(fp, "+%zu", ci->addcount);
71- fputs("</td><td class=\"num\">", fp);
72- fprintf(fp, "-%zu", ci->delcount);
73- fputs("</td></tr>\n", fp);
74-
75- relpath = "../";
76+ git_reference *r1 = (*(git_reference **)v1);
77+ git_reference *r2 = (*(git_reference **)v2);
78+ int t1, t2;
79
80- commitinfo_free(ci);
81- git_reference_free(ref);
82- git_reference_free(dref);
83- ref = NULL;
84- dref = NULL;
85- }
86- ret = 0;
87+ t1 = git_reference_is_branch(r1);
88+ t2 = git_reference_is_branch(r2);
89
90-err:
91- fputs("</tbody></table>", fp);
92- git_reference_free(ref);
93- git_reference_free(dref);
94- git_branch_iterator_free(it);
95+ if (t1 != t2)
96+ return t1 - t2;
97
98- return ret;
99+ return strcmp(git_reference_shorthand(r1),
100+ git_reference_shorthand(r2));
101 }
102
103 int
104-tagcompare(void *s1, void *s2)
105-{
106- return strcmp(*(char **)s1, *(char **)s2);
107-}
108-
109-int
110-writetags(FILE *fp)
111+writerefs(FILE *fp)
112 {
113 struct commitinfo *ci;
114- git_strarray tagnames;
115- git_object *obj = NULL;
116- git_tag *tag = NULL;
117 const git_oid *id = NULL;
118- size_t i, len;
119-
120- /* summary page with branches and tags */
121- memset(&tagnames, 0, sizeof(tagnames));
122- if (git_tag_list(&tagnames, repo))
123+ git_object *obj = NULL;
124+ git_reference *dref = NULL, *r, *ref = NULL;
125+ git_reference_iterator *it = NULL;
126+ git_reference **refs = NULL;
127+ size_t count, i, j, len, refcount = 0;
128+ const char *cols[] = { "Branch", "Tag" }; /* first column title */
129+ const char *titles[] = { "Branches", "Tags" };
130+ const char *ids[] = { "branches", "tags" };
131+ const char *name;
132+
133+ if (git_reference_iterator_new(&it, repo))
134 return -1;
135- if (!tagnames.count) {
136- git_strarray_free(&tagnames);
137- return 0;
138- }
139-
140- /* sort names */
141- qsort(tagnames.strings, tagnames.count, sizeof(char *),
142- (int (*)(const void *, const void *))&tagcompare);
143-
144- fputs("<h2>Tags</h2><table id=\"tags\"><thead>\n<tr><td>Tag</td>"
145- "<td>Age</td><td>Commit message</td>"
146- "<td>Author</td><td>Files</td><td class=\"num\">+</td>"
147- "<td class=\"num\">-</td></tr>\n</thead><tbody>\n", fp);
148-
149- for (i = 0; i < tagnames.count; i++) {
150- if (git_revparse_single(&obj, repo, tagnames.strings[i]))
151- continue;
152- id = git_object_id(obj);
153
154- /* lookup actual commit (from annotated tag etc) */
155- if (!git_tag_lookup(&tag, repo, id)) {
156- git_object_free(obj);
157- obj = NULL;
158- if (git_tag_peel(&obj, tag))
159+ for (refcount = 0; !git_reference_next(&ref, it); refcount++) {
160+ if (!(refs = reallocarray(refs, refcount + 1, sizeof(git_reference *))))
161+ err(1, "realloc");
162+ refs[refcount] = ref;
163+ }
164+ git_reference_iterator_free(it);
165+
166+ /* sort by type then shorthand name */
167+ qsort(refs, refcount, sizeof(git_reference *), refs_cmp);
168+
169+ for (j = 0; j < 2; j++) {
170+ for (i = 0, count = 0; i < refcount; i++) {
171+ if (git_reference_is_branch(refs[i]) && j == 0)
172+ ;
173+ else if (git_reference_is_tag(refs[i]) && j == 1)
174+ ;
175+ else
176+ continue;
177+
178+ id = NULL;
179+ r = NULL;
180+ switch (git_reference_type(refs[i])) {
181+ case GIT_REF_SYMBOLIC:
182+ if (git_reference_resolve(&dref, refs[i]))
183+ goto err;
184+ r = dref;
185+ break;
186+ case GIT_REF_OID:
187+ r = refs[i];
188+ break;
189+ default:
190+ continue;
191+ }
192+ if (!(id = git_reference_target(r)))
193+ goto err;
194+ if (git_reference_peel(&obj, r, GIT_OBJ_ANY))
195+ goto err;
196+ if (!(id = git_object_id(obj)))
197+ goto err;
198+ if (!(ci = commitinfo_getbyoid(id)))
199 break;
200- git_tag_free(tag);
201- tag = NULL;
202- id = git_object_id(obj);
203- }
204-
205- if (!(ci = commitinfo_getbyoid(id)))
206- break;
207
208- relpath = "";
209+ /* print header if it has an entry (first). */
210+ if (++count == 1) {
211+ fprintf(fp, "<h2>%s</h2><table id=\"%s\"><thead>\n<tr><td>%s</td>"
212+ "<td>Age</td><td>Commit message</td>"
213+ "<td>Author</td><td>Files</td><td class=\"num\">+</td>"
214+ "<td class=\"num\">-</td></tr>\n</thead><tbody>\n",
215+ titles[j], ids[j], cols[j]);
216+ }
217
218- fputs("<tr><td>", fp);
219- xmlencode(fp, tagnames.strings[i], strlen(tagnames.strings[i]));
220- fputs("</td><td>", fp);
221- if (ci->author)
222- printtimeshort(fp, &(ci->author->when));
223- fputs("</td><td>", fp);
224- if (ci->summary) {
225- fprintf(fp, "<a href=\"%scommit/%s.html\">", relpath, ci->oid);
226- if ((len = strlen(ci->summary)) > summarylen) {
227- xmlencode(fp, ci->summary, summarylen - 1);
228- fputs("…", fp);
229- } else {
230- xmlencode(fp, ci->summary, len);
231+ relpath = "";
232+ name = git_reference_shorthand(r);
233+
234+ fputs("<tr><td>", fp);
235+ xmlencode(fp, name, strlen(name));
236+ fputs("</td><td>", fp);
237+ if (ci->author)
238+ printtimeshort(fp, &(ci->author->when));
239+ fputs("</td><td>", fp);
240+ if (ci->summary) {
241+ fprintf(fp, "<a href=\"%scommit/%s.html\">", relpath, ci->oid);
242+ if ((len = strlen(ci->summary)) > summarylen) {
243+ xmlencode(fp, ci->summary, summarylen - 1);
244+ fputs("…", fp);
245+ } else {
246+ xmlencode(fp, ci->summary, len);
247+ }
248+ fputs("</a>", fp);
249 }
250- fputs("</a>", fp);
251+ fputs("</td><td>", fp);
252+ if (ci->author)
253+ xmlencode(fp, ci->author->name, strlen(ci->author->name));
254+ fputs("</td><td class=\"num\">", fp);
255+ fprintf(fp, "%zu", ci->filecount);
256+ fputs("</td><td class=\"num\">", fp);
257+ fprintf(fp, "+%zu", ci->addcount);
258+ fputs("</td><td class=\"num\">", fp);
259+ fprintf(fp, "-%zu", ci->delcount);
260+ fputs("</td></tr>\n", fp);
261+
262+ relpath = "../";
263+
264+ commitinfo_free(ci);
265+ git_reference_free(dref);
266+ dref = NULL;
267 }
268- fputs("</td><td>", fp);
269- if (ci->author)
270- xmlencode(fp, ci->author->name, strlen(ci->author->name));
271- fputs("</td><td class=\"num\">", fp);
272- fprintf(fp, "%zu", ci->filecount);
273- fputs("</td><td class=\"num\">", fp);
274- fprintf(fp, "+%zu", ci->addcount);
275- fputs("</td><td class=\"num\">", fp);
276- fprintf(fp, "-%zu", ci->delcount);
277- fputs("</td></tr>\n", fp);
278-
279- relpath = "../";
280-
281- commitinfo_free(ci);
282- git_object_free(obj);
283- obj = NULL;
284+ /* table footer */
285+ if (count)
286+ fputs("</tbody></table>", fp);
287 }
288- fputs("</tbody></table>", fp);
289- git_strarray_free(&tagnames);
290- git_tag_free(tag);
291- git_object_free(obj);
292
293- return 0;
294-}
295+err:
296+ git_reference_free(dref);
297
298-int
299-writerefs(FILE *fp)
300-{
301- int ret;
302+ for (i = 0; i < refcount; i++)
303+ git_reference_free(refs[i]);
304+ free(refs);
305
306- if ((ret = writebranches(fp)))
307- return ret;
308- fputs("<br/>", fp);
309- return writetags(fp);
310+ return 0;
311 }
312
313 int