sort branches and tags by time (descending)
In general version tags are done in chronological order, so this will have a better sorting for tagged (versioned) releases. Request from Caltlgin Stsodaat and others, thanks!
1 files changed, 92 insertions(+), 72 deletions(-) | |||
---|---|---|---|
M | stagit.c | +92 | -72 |
1@@ -48,6 +48,12 @@ struct commitinfo {
2 size_t ndeltas;
3 };
4
5+/* reference and associated data for sorting */
6+struct referenceinfo {
7+ struct git_reference *ref;
8+ struct commitinfo *ci;
9+};
10+
11 static git_repository *repo;
12
13 static const char *relpath = "";
14@@ -938,113 +944,127 @@ writefiles(FILE *fp, const git_oid *id)
15 int
16 refs_cmp(const void *v1, const void *v2)
17 {
18- git_reference *r1 = (*(git_reference **)v1);
19- git_reference *r2 = (*(git_reference **)v2);
20+ struct referenceinfo *r1 = (struct referenceinfo *)v1;
21+ struct referenceinfo *r2 = (struct referenceinfo *)v2;
22+ time_t t1, t2;
23 int r;
24
25- if ((r = git_reference_is_branch(r1) - git_reference_is_branch(r2)))
26+ if ((r = git_reference_is_tag(r1->ref) - git_reference_is_tag(r2->ref)))
27+ return r;
28+
29+ t1 = r1->ci->author ? r1->ci->author->when.time : 0;
30+ t2 = r2->ci->author ? r2->ci->author->when.time : 0;
31+ if ((r = t1 > t2 ? -1 : (t1 == t2 ? 0 : 1)))
32 return r;
33
34- return strcmp(git_reference_shorthand(r1),
35- git_reference_shorthand(r2));
36+ return strcmp(git_reference_shorthand(r1->ref),
37+ git_reference_shorthand(r2->ref));
38 }
39
40 int
41 writerefs(FILE *fp)
42 {
43+ struct referenceinfo *ris = NULL;
44 struct commitinfo *ci;
45 const git_oid *id = NULL;
46 git_object *obj = NULL;
47 git_reference *dref = NULL, *r, *ref = NULL;
48 git_reference_iterator *it = NULL;
49- git_reference **refs = NULL;
50 size_t count, i, j, refcount;
51 const char *titles[] = { "Branches", "Tags" };
52 const char *ids[] = { "branches", "tags" };
53- const char *name;
54+ const char *s;
55
56 if (git_reference_iterator_new(&it, repo))
57 return -1;
58
59- for (refcount = 0; !git_reference_next(&ref, it); refcount++) {
60- if (!(refs = reallocarray(refs, refcount + 1, sizeof(git_reference *))))
61- err(1, "realloc");
62- refs[refcount] = ref;
63- }
64- git_reference_iterator_free(it);
65-
66- /* sort by type then shorthand name */
67- qsort(refs, refcount, sizeof(git_reference *), refs_cmp);
68-
69- for (j = 0; j < 2; j++) {
70- for (i = 0, count = 0; i < refcount; i++) {
71- if (!(git_reference_is_branch(refs[i]) && j == 0) &&
72- !(git_reference_is_tag(refs[i]) && j == 1))
73- continue;
74+ for (refcount = 0; !git_reference_next(&ref, it); ) {
75+ if (!git_reference_is_branch(ref) && !git_reference_is_tag(ref)) {
76+ git_reference_free(ref);
77+ ref = NULL;
78+ continue;
79+ }
80
81- switch (git_reference_type(refs[i])) {
82- case GIT_REF_SYMBOLIC:
83- if (git_reference_resolve(&dref, refs[i]))
84- goto err;
85- r = dref;
86- break;
87- case GIT_REF_OID:
88- r = refs[i];
89- break;
90- default:
91- continue;
92- }
93- if (!git_reference_target(r) ||
94- git_reference_peel(&obj, r, GIT_OBJ_ANY))
95+ switch (git_reference_type(ref)) {
96+ case GIT_REF_SYMBOLIC:
97+ if (git_reference_resolve(&dref, ref))
98 goto err;
99- if (!(id = git_object_id(obj)))
100- goto err;
101- if (!(ci = commitinfo_getbyoid(id)))
102- break;
103+ r = dref;
104+ break;
105+ case GIT_REF_OID:
106+ r = ref;
107+ break;
108+ default:
109+ continue;
110+ }
111+ if (!git_reference_target(r) ||
112+ git_reference_peel(&obj, r, GIT_OBJ_ANY))
113+ goto err;
114+ if (!(id = git_object_id(obj)))
115+ goto err;
116+ if (!(ci = commitinfo_getbyoid(id)))
117+ break;
118
119- /* print header if it has an entry (first). */
120- if (++count == 1) {
121- fprintf(fp, "<h2>%s</h2><table id=\"%s\">"
122- "<thead>\n<tr><td><b>Name</b></td>"
123- "<td><b>Last commit date</b></td>"
124- "<td><b>Author</b></td>\n</tr>\n"
125- "</thead><tbody>\n",
126- titles[j], ids[j]);
127- }
128+ if (!(ris = reallocarray(ris, refcount + 1, sizeof(*ris))))
129+ err(1, "realloc");
130+ ris[refcount].ci = ci;
131+ ris[refcount].ref = r;
132+ refcount++;
133
134- relpath = "";
135- name = git_reference_shorthand(r);
136+ git_object_free(obj);
137+ obj = NULL;
138+ git_reference_free(dref);
139+ dref = NULL;
140+ }
141+ git_reference_iterator_free(it);
142
143- fputs("<tr><td>", fp);
144- xmlencode(fp, name, strlen(name));
145- fputs("</td><td>", fp);
146- if (ci->author)
147- printtimeshort(fp, &(ci->author->when));
148- fputs("</td><td>", fp);
149- if (ci->author)
150- xmlencode(fp, ci->author->name, strlen(ci->author->name));
151- fputs("</td></tr>\n", fp);
152+ /* sort by type, date then shorthand name */
153+ qsort(ris, refcount, sizeof(*ris), refs_cmp);
154
155- relpath = "../";
156+ for (i = 0, j = 0, count = 0; i < refcount; i++) {
157+ if (j == 0 && git_reference_is_tag(ris[i].ref)) {
158+ if (count)
159+ fputs("</tbody></table><br/>\n", fp);
160+ count = 0;
161+ j = 1;
162+ }
163
164- commitinfo_free(ci);
165- git_object_free(obj);
166- obj = NULL;
167- git_reference_free(dref);
168- dref = NULL;
169+ /* print header if it has an entry (first). */
170+ if (++count == 1) {
171+ fprintf(fp, "<h2>%s</h2><table id=\"%s\">"
172+ "<thead>\n<tr><td><b>Name</b></td>"
173+ "<td><b>Last commit date</b></td>"
174+ "<td><b>Author</b></td>\n</tr>\n"
175+ "</thead><tbody>\n",
176+ titles[j], ids[j]);
177 }
178- /* table footer */
179- if (count)
180- fputs("</tbody></table><br/>", fp);
181+
182+ ci = ris[i].ci;
183+ s = git_reference_shorthand(ris[i].ref);
184+
185+ fputs("<tr><td>", fp);
186+ xmlencode(fp, s, strlen(s));
187+ fputs("</td><td>", fp);
188+ if (ci->author)
189+ printtimeshort(fp, &(ci->author->when));
190+ fputs("</td><td>", fp);
191+ if (ci->author)
192+ xmlencode(fp, ci->author->name, strlen(ci->author->name));
193+ fputs("</td></tr>\n", fp);
194 }
195+ /* table footer */
196+ if (count)
197+ fputs("</tbody></table><br/>\n", fp);
198
199 err:
200 git_object_free(obj);
201 git_reference_free(dref);
202
203- for (i = 0; i < refcount; i++)
204- git_reference_free(refs[i]);
205- free(refs);
206+ for (i = 0; i < refcount; i++) {
207+ commitinfo_free(ris[i].ci);
208+ git_reference_free(ris[i].ref);
209+ }
210+ free(ris);
211
212 return 0;
213 }