Diff options
Diffstat (limited to '')
-rw-r--r--source/ui-refs.c144
1 file changed, 101 insertions, 43 deletions
diff --git a/source/ui-refs.c b/source/ui-refs.c
index c8e8f3f..69a2cc1 100644
--- a/source/ui-refs.c
+++ b/source/ui-refs.c
@@ -3,19 +3,33 @@
* the whole of a repository's refs page. Every row is one ref beside
* the commit or tag object it points at, ordered newest first, with branches
* then reordered by name unless branch-sort asks for age. A section longer
- * than max-ref-count is cut short and ends in a link to a dedicated heads or
+ * than its cap is cut short and ends in a link to a dedicated heads or
* tags page, which walks the same list one offset at a time.
*/
#define USE_THE_REPOSITORY_VARIABLE
#include "cgit.h"
-#include "filter.h"
#include "html.h"
-#include "shared.h"
+#include "parsing.h"
#include "ui-refs.h"
#include "ui-shared.h"
+struct refinfo {
+ const char *refname;
+ struct object *object;
+ union {
+ struct taginfo *tag;
+ struct commitinfo *commit;
+ };
+};
+
+struct reflist {
+ struct refinfo **refs;
+ int alloc;
+ int count;
+};
+
// The slice of a sorted ref list that one page shows, with end one past the
// last row. size is what a full page holds, so it also decides whether the
// list needs a pager.
@@ -25,6 +39,68 @@ struct ref_page {
int end;
};
+static void free_refinfo(struct refinfo *ref)
+{
+ free((char *)ref->refname);
+ switch (ref->object->type) {
+ case OBJ_TAG:
+ cgit_free_taginfo(ref->tag);
+ break;
+ case OBJ_COMMIT:
+ cgit_free_commitinfo(ref->commit);
+ break;
+ }
+ free(ref);
+}
+
+static struct refinfo *make_refinfo(const char *refname, const struct object_id *oid)
+{
+ struct refinfo *ref;
+
+ ref = xcalloc(1, sizeof(struct refinfo));
+ ref->refname = xstrdup(refname);
+ ref->object = parse_object(the_repository, oid);
+ if (!ref->object) {
+ free((char *)ref->refname);
+ free(ref);
+ return NULL;
+ }
+ switch (ref->object->type) {
+ case OBJ_TAG:
+ ref->tag = cgit_parse_tag((struct tag *)ref->object);
+ break;
+ case OBJ_COMMIT:
+ ref->commit = cgit_parse_commit((struct commit *)ref->object);
+ break;
+ }
+ return ref;
+}
+
+static void free_reflist_inner(struct reflist *list)
+{
+ int i;
+
+ for (i = 0; i < list->count; i++)
+ free_refinfo(list->refs[i]);
+ free(list->refs);
+}
+
+/*
+ * Matches git's reference iteration callback, and appends each ref it is given
+ * to the struct reflist passed as cb_data.
+ */
+static int refs_cb(const struct reference *ref, void *cb_data)
+{
+ struct reflist *list = (struct reflist *)cb_data;
+ struct refinfo *info = make_refinfo(ref->name, ref->oid);
+
+ if (info) {
+ ALLOC_GROW(list->refs, list->count + 1, list->alloc);
+ list->refs[list->count++] = info;
+ }
+ return 0;
+}
+
/*
* The tagger date and the committer date live in a union in struct refinfo and
* only the member matching the object type is ever filled, so assuming a ref
@@ -32,13 +108,11 @@ struct ref_page {
*/
static timestamp_t ref_date(struct refinfo *ref)
{
- if (!ref->object)
- return 0;
switch (ref->object->type) {
case OBJ_TAG:
return ref->tag ? ref->tag->tagger_date : 0;
case OBJ_COMMIT:
- return ref->commit ? ref->commit->committer_date : 0;
+ return ref->commit->committer_date;
}
return 0;
}
@@ -71,9 +145,9 @@ static void collect_branches(struct reflist *list)
{
list->refs = NULL;
list->alloc = list->count = 0;
- refs_for_each_branch_ref(get_main_ref_store(the_repository), cgit_refs_cb, list);
+ refs_for_each_branch_ref(get_main_ref_store(the_repository), refs_cb, list);
if (ctx.repo->enable_remote_branches)
- refs_for_each_remote_ref(get_main_ref_store(the_repository), cgit_refs_cb, list);
+ refs_for_each_remote_ref(get_main_ref_store(the_repository), refs_cb, list);
}
/*
@@ -99,13 +173,13 @@ static void print_branch_header(int columns)
htmlf("<th%s class='left' scope='col'>Age</th></tr>\n", age_colspan(columns));
}
-static int print_branch(struct refinfo *ref, int columns)
+static void print_branch(struct refinfo *ref, int columns)
{
struct commitinfo *info = ref->commit;
const char *name = ref->refname;
if (!info)
- return 1;
+ return;
html("<tr class='branch'><td>");
cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0, NULL, NULL, ctx.qry.showmsg, 0);
html("</td><td>");
@@ -113,12 +187,7 @@ static int print_branch(struct refinfo *ref, int columns)
if (ref->object->type == OBJ_COMMIT) {
cgit_commit_link(info->subject, NULL, NULL, name, NULL, NULL);
html("</td><td class='col-author'>");
- // A filter must not be handed a NULL argument.
- cgit_open_filter(
- ctx.repo->email_filter, info->author_email ? info->author_email : "", "refs"
- );
- html_txt(info->author);
- cgit_close_filter(ctx.repo->email_filter);
+ cgit_print_person(info->author, info->author_email, "refs", 0);
htmlf("</td><td%s>", age_colspan(columns));
cgit_print_age(info->committer_date, info->committer_tz, -1);
} else {
@@ -128,14 +197,13 @@ static int print_branch(struct refinfo *ref, int columns)
htmlf("</td><td class='col-author'></td><td%s>", age_colspan(columns));
}
html("</td></tr>\n");
- return 0;
}
static void collect_tags(struct reflist *list)
{
list->refs = NULL;
list->alloc = list->count = 0;
- refs_for_each_tag_ref(get_main_ref_store(the_repository), cgit_refs_cb, list);
+ refs_for_each_tag_ref(get_main_ref_store(the_repository), refs_cb, list);
}
static void print_tag_header(int columns)
@@ -149,7 +217,7 @@ static void print_tag_header(int columns)
htmlf("<th%s class='left' scope='col'>Age</th></tr>\n", age_colspan(columns));
}
-static int print_tag(struct refinfo *ref, int columns)
+static void print_tag(struct refinfo *ref, int columns)
{
struct taginfo *info = NULL;
const char *name = ref->refname;
@@ -163,7 +231,7 @@ static int print_tag(struct refinfo *ref, int columns)
obj = tag->tagged;
info = ref->tag;
if (!info)
- return 1;
+ return;
}
html("<tr class='tag'><td>");
@@ -175,18 +243,10 @@ static int print_tag(struct refinfo *ref, int columns)
cgit_object_link(obj, 0);
html("</td><td class='col-author'>");
if (info) {
- if (info->tagger) {
- cgit_open_filter(ctx.repo->email_filter, info->tagger_email, "refs");
- html_txt(info->tagger);
- cgit_close_filter(ctx.repo->email_filter);
- }
+ if (info->tagger)
+ cgit_print_person(info->tagger, info->tagger_email, "refs", 0);
} else if (ref->object->type == OBJ_COMMIT) {
- cgit_open_filter(
- ctx.repo->email_filter, ref->commit->author_email ? ref->commit->author_email : "",
- "refs"
- );
- html_txt(ref->commit->author);
- cgit_close_filter(ctx.repo->email_filter);
+ cgit_print_person(ref->commit->author, ref->commit->author_email, "refs", 0);
}
htmlf("</td><td%s>", age_colspan(columns));
if (info) {
@@ -196,8 +256,6 @@ static int print_tag(struct refinfo *ref, int columns)
cgit_print_age(ref->commit->commit->date, 0, -1);
}
html("</td></tr>\n");
-
- return 0;
}
static void print_refs_link(const char *path, int columns)
@@ -258,9 +316,9 @@ static void print_branches_page(int pagesize)
print_branch_header(REF_COLUMNS);
collect_branches(&list);
- cgit_qsort(list.refs, list.count, sizeof(*list.refs), cmp_date);
+ QSORT(list.refs, list.count, cmp_date);
if (ctx.repo->branch_sort == 0)
- cgit_qsort(list.refs, list.count, sizeof(*list.refs), cmp_name);
+ QSORT(list.refs, list.count, cmp_name);
page = page_bounds(pagesize, list.count);
@@ -271,7 +329,7 @@ static void print_branches_page(int pagesize)
print_ref_pager(page.start, page.size, list.count, "heads");
html("</tbody>\n");
- cgit_free_reflist_inner(&list);
+ free_reflist_inner(&list);
}
static void print_tags_page(int pagesize)
@@ -283,7 +341,7 @@ static void print_tags_page(int pagesize)
collect_tags(&list);
if (list.count == 0)
return;
- cgit_qsort(list.refs, list.count, sizeof(*list.refs), cmp_date);
+ QSORT(list.refs, list.count, cmp_date);
page = page_bounds(pagesize, list.count);
@@ -295,7 +353,7 @@ static void print_tags_page(int pagesize)
print_ref_pager(page.start, page.size, list.count, "tags");
html("</tbody>\n");
- cgit_free_reflist_inner(&list);
+ free_reflist_inner(&list);
}
void cgit_print_branches(int maxcount, int columns)
@@ -312,9 +370,9 @@ void cgit_print_branches(int maxcount, int columns)
// The date sort covers the list, the name sort only the rows about to
// be shown, so the section holds the newest branches rather than the
// first ones by name.
- cgit_qsort(list.refs, list.count, sizeof(*list.refs), cmp_date);
+ QSORT(list.refs, list.count, cmp_date);
if (ctx.repo->branch_sort == 0)
- cgit_qsort(list.refs, maxcount, sizeof(*list.refs), cmp_name);
+ QSORT(list.refs, maxcount, cmp_name);
for (i = 0; i < maxcount; i++)
print_branch(list.refs[i], columns);
@@ -323,7 +381,7 @@ void cgit_print_branches(int maxcount, int columns)
print_refs_link("heads", columns);
html("</tbody>\n");
- cgit_free_reflist_inner(&list);
+ free_reflist_inner(&list);
}
void cgit_print_tags(int maxcount, int columns)
@@ -334,7 +392,7 @@ void cgit_print_tags(int maxcount, int columns)
collect_tags(&list);
if (list.count == 0)
return;
- cgit_qsort(list.refs, list.count, sizeof(*list.refs), cmp_date);
+ QSORT(list.refs, list.count, cmp_date);
if (maxcount <= 0 || maxcount > list.count)
maxcount = list.count;
print_tag_header(columns);
@@ -345,7 +403,7 @@ void cgit_print_tags(int maxcount, int columns)
print_refs_link("tags", columns);
html("</tbody>\n");
- cgit_free_reflist_inner(&list);
+ free_reflist_inner(&list);
}
void cgit_print_refs(void)