]> gitweb.ps.run Git - ps-cgit/blob - ui-refs.c
cgit.c: free tmp variable
[ps-cgit] / ui-refs.c
1 /* ui-refs.c: browse symbolic refs
2  *
3  * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
4  *
5  * Licensed under GNU General Public License v2
6  *   (see COPYING for full license text)
7  */
8
9 #include "cgit.h"
10 #include "ui-refs.h"
11 #include "html.h"
12 #include "ui-shared.h"
13
14 static int cmp_age(int age1, int age2)
15 {
16         if (age1 != 0 && age2 != 0)
17                 return age2 - age1;
18
19         if (age1 == 0 && age2 == 0)
20                 return 0;
21
22         if (age1 == 0)
23                 return +1;
24
25         return -1;
26 }
27
28 static int cmp_ref_name(const void *a, const void *b)
29 {
30         struct refinfo *r1 = *(struct refinfo **)a;
31         struct refinfo *r2 = *(struct refinfo **)b;
32
33         return strcmp(r1->refname, r2->refname);
34 }
35
36 static int cmp_branch_age(const void *a, const void *b)
37 {
38         struct refinfo *r1 = *(struct refinfo **)a;
39         struct refinfo *r2 = *(struct refinfo **)b;
40
41         return cmp_age(r1->commit->committer_date, r2->commit->committer_date);
42 }
43
44 static int get_ref_age(struct refinfo *ref)
45 {
46         if (!ref->object)
47                 return 0;
48         switch (ref->object->type) {
49         case OBJ_TAG:
50                 return ref->tag ? ref->tag->tagger_date : 0;
51         case OBJ_COMMIT:
52                 return ref->commit ? ref->commit->committer_date : 0;
53         }
54         return 0;
55 }
56
57 static int cmp_tag_age(const void *a, const void *b)
58 {
59         struct refinfo *r1 = *(struct refinfo **)a;
60         struct refinfo *r2 = *(struct refinfo **)b;
61
62         return cmp_age(get_ref_age(r1), get_ref_age(r2));
63 }
64
65 static int print_branch(struct refinfo *ref)
66 {
67         struct commitinfo *info = ref->commit;
68         char *name = (char *)ref->refname;
69
70         if (!info)
71                 return 1;
72         html("<tr><td>");
73         cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0, NULL, NULL,
74                       ctx.qry.showmsg);
75         html("</td><td>");
76
77         if (ref->object->type == OBJ_COMMIT) {
78                 cgit_commit_link(info->subject, NULL, NULL, name, NULL, NULL, 0);
79                 html("</td><td>");
80                 cgit_open_filter(ctx.repo->email_filter, info->author_email, "refs");
81                 html_txt(info->author);
82                 cgit_close_filter(ctx.repo->email_filter);
83                 html("</td><td colspan='2'>");
84                 cgit_print_age(info->commit->date, -1, NULL);
85         } else {
86                 html("</td><td></td><td>");
87                 cgit_object_link(ref->object);
88         }
89         html("</td></tr>\n");
90         return 0;
91 }
92
93 static void print_tag_header()
94 {
95         html("<tr class='nohover'><th class='left'>Tag</th>"
96              "<th class='left'>Download</th>"
97              "<th class='left'>Author</th>"
98              "<th class='left' colspan='2'>Age</th></tr>\n");
99 }
100
101 static void print_tag_downloads(const struct cgit_repo *repo, const char *ref)
102 {
103         const struct cgit_snapshot_format* f;
104         struct strbuf filename = STRBUF_INIT;
105         const char *basename;
106         int free_ref = 0;
107
108         if (!ref || strlen(ref) < 2)
109                 return;
110
111         basename = cgit_repobasename(repo->url);
112         if (prefixcmp(ref, basename) != 0) {
113                 if ((ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1]))
114                         ref++;
115                 if (isdigit(ref[0])) {
116                         ref = fmtalloc("%s-%s", basename, ref);
117                         free_ref = 1;
118                 }
119         }
120
121         for (f = cgit_snapshot_formats; f->suffix; f++) {
122                 if (!(repo->snapshots & f->bit))
123                         continue;
124                 strbuf_reset(&filename);
125                 strbuf_addf(&filename, "%s%s", ref, f->suffix);
126                 cgit_snapshot_link(filename.buf, NULL, NULL, NULL, NULL, filename.buf);
127                 html("&nbsp;&nbsp;");
128         }
129
130         if (free_ref)
131                 free((char *)ref);
132         strbuf_release(&filename);
133 }
134
135 static int print_tag(struct refinfo *ref)
136 {
137         struct tag *tag = NULL;
138         struct taginfo *info = NULL;
139         char *name = (char *)ref->refname;
140         struct object *obj = ref->object;
141
142         if (obj->type == OBJ_TAG) {
143                 tag = (struct tag *)obj;
144                 obj = tag->tagged;
145                 info = ref->tag;
146                 if (!tag || !info)
147                         return 1;
148         }
149
150         html("<tr><td>");
151         cgit_tag_link(name, NULL, NULL, ctx.qry.head, name);
152         html("</td><td>");
153         if (ctx.repo->snapshots && (obj->type == OBJ_COMMIT))
154                 print_tag_downloads(ctx.repo, name);
155         else
156                 cgit_object_link(obj);
157         html("</td><td>");
158         if (info) {
159                 if (info->tagger) {
160                         cgit_open_filter(ctx.repo->email_filter, info->tagger_email, "refs");
161                         html_txt(info->tagger);
162                         cgit_close_filter(ctx.repo->email_filter);
163                 }
164         } else if (ref->object->type == OBJ_COMMIT) {
165                 cgit_open_filter(ctx.repo->email_filter, ref->commit->author_email, "refs");
166                 html_txt(ref->commit->author);
167                 cgit_close_filter(ctx.repo->email_filter);
168         }
169         html("</td><td colspan='2'>");
170         if (info) {
171                 if (info->tagger_date > 0)
172                         cgit_print_age(info->tagger_date, -1, NULL);
173         } else if (ref->object->type == OBJ_COMMIT) {
174                 cgit_print_age(ref->commit->commit->date, -1, NULL);
175         }
176         html("</td></tr>\n");
177
178         return 0;
179 }
180
181 static void print_refs_link(char *path)
182 {
183         html("<tr class='nohover'><td colspan='5'>");
184         cgit_refs_link("[...]", NULL, NULL, ctx.qry.head, NULL, path);
185         html("</td></tr>");
186 }
187
188 void cgit_print_branches(int maxcount)
189 {
190         struct reflist list;
191         int i;
192
193         html("<tr class='nohover'><th class='left'>Branch</th>"
194              "<th class='left'>Commit message</th>"
195              "<th class='left'>Author</th>"
196              "<th class='left' colspan='2'>Age</th></tr>\n");
197
198         list.refs = NULL;
199         list.alloc = list.count = 0;
200         for_each_branch_ref(cgit_refs_cb, &list);
201         if (ctx.repo->enable_remote_branches)
202                 for_each_remote_ref(cgit_refs_cb, &list);
203
204         if (maxcount == 0 || maxcount > list.count)
205                 maxcount = list.count;
206
207         qsort(list.refs, list.count, sizeof(*list.refs), cmp_branch_age);
208         if (ctx.repo->branch_sort == 0)
209                 qsort(list.refs, maxcount, sizeof(*list.refs), cmp_ref_name);
210
211         for (i = 0; i < maxcount; i++)
212                 print_branch(list.refs[i]);
213
214         if (maxcount < list.count)
215                 print_refs_link("heads");
216
217         cgit_free_reflist_inner(&list);
218 }
219
220 void cgit_print_tags(int maxcount)
221 {
222         struct reflist list;
223         int i;
224
225         list.refs = NULL;
226         list.alloc = list.count = 0;
227         for_each_tag_ref(cgit_refs_cb, &list);
228         if (list.count == 0)
229                 return;
230         qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age);
231         if (!maxcount)
232                 maxcount = list.count;
233         else if (maxcount > list.count)
234                 maxcount = list.count;
235         print_tag_header();
236         for (i = 0; i < maxcount; i++)
237                 print_tag(list.refs[i]);
238
239         if (maxcount < list.count)
240                 print_refs_link("tags");
241
242         cgit_free_reflist_inner(&list);
243 }
244
245 void cgit_print_refs()
246 {
247
248         html("<table class='list nowrap'>");
249
250         if (ctx.qry.path && !prefixcmp(ctx.qry.path, "heads"))
251                 cgit_print_branches(0);
252         else if (ctx.qry.path && !prefixcmp(ctx.qry.path, "tags"))
253                 cgit_print_tags(0);
254         else {
255                 cgit_print_branches(0);
256                 html("<tr class='nohover'><td colspan='5'>&nbsp;</td></tr>");
257                 cgit_print_tags(0);
258         }
259         html("</table>");
260 }