diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Cap and paginate the ref listings
Diffstat (limited to 'source')
| -rw-r--r-- | source/cgit.c | 3 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/cgit.h | 1 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-refs.c | 128 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3 files changed, 118 insertions, 14 deletions
diff --git a/source/cgit.c b/source/cgit.c index ce8b340..5fcd17f 100644 --- a/source/cgit.c +++ b/source/cgit.c @@ -257,6 +257,8 @@ static void config_cb(const char *name, const char *value) ctx.cfg.max_repodesc_len = atoi(value); else if (!strcmp(name, "max-blob-size")) ctx.cfg.max_blob_size = atoi(value); + else if (!strcmp(name, "max-ref-count")) + ctx.cfg.max_ref_count = atoi(value); else if (!strcmp(name, "max-repo-count")) { ctx.cfg.max_repo_count = atoi(value); if (ctx.cfg.max_repo_count <= 0) @@ -417,6 +419,7 @@ static void prepare_context(void) ctx.cfg.max_repo_count = 50; ctx.cfg.max_commit_count = 50; ctx.cfg.max_msg_len = 80; + ctx.cfg.max_ref_count = 200; /* refs beyond this paginate */ ctx.cfg.max_repodesc_len = 80; ctx.cfg.max_blob_size = 10 * 1024; /* 10 MB; bounds per-request memory */ ctx.cfg.max_stats = 0; diff --git a/source/cgit.h b/source/cgit.h index d921e76..1b28023 100644 --- a/source/cgit.h +++ b/source/cgit.h @@ -250,6 +250,7 @@ struct cgit_config { int max_repo_count; int max_commit_count; int max_msg_len; + int max_ref_count; int max_repodesc_len; int max_blob_size; int max_stats; diff --git a/source/ui-refs.c b/source/ui-refs.c index 500adfd..a38bfc4 100644 --- a/source/ui-refs.c +++ b/source/ui-refs.c @@ -145,23 +145,60 @@ static void print_refs_link(const char *path) html("</td></tr>"); } -void cgit_print_branches(int maxcount) +/* Prev/next links for the dedicated branch and tag pages, so each + * category pages independently instead of sharing one endless page. */ +static void print_ref_pager(int ofs, int pagesize, int count, const char *path) { - struct reflist list; - int i; + char *url; + + html("<tr class='nohover'><td colspan='5' class='refs-pager'>"); + if (ofs > 0) { + url = cgit_pageurl(ctx.qry.repo, fmt("refs/%s", path), + fmt("ofs=%d", ofs > pagesize ? ofs - pagesize : 0)); + html("<a href='"); + html_attr(url); + html("'>[prev]</a> "); + free(url); + } + htmlf("%d - %d of %d", ofs + 1, + ofs + pagesize < count ? ofs + pagesize : count, count); + if (ofs + pagesize < count) { + url = cgit_pageurl(ctx.qry.repo, fmt("refs/%s", path), + fmt("ofs=%d", ofs + pagesize)); + html(" <a href='"); + html_attr(url); + html("'>[next]</a>"); + free(url); + } + html("</td></tr>"); +} +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); + if (ctx.repo->enable_remote_branches) + refs_for_each_remote_ref(get_main_ref_store(the_repository), + cgit_refs_cb, list); +} + +static void print_branch_header(void) +{ html("<tr class='nohover'><th class='left'>Branch</th>" "<th class='left'>Commit message</th>" "<th class='left'>Author</th>" "<th class='left' colspan='2'>Age</th></tr>\n"); +} - list.refs = NULL; - list.alloc = list.count = 0; - refs_for_each_branch_ref(get_main_ref_store(the_repository), - cgit_refs_cb, &list); - if (ctx.repo->enable_remote_branches) - refs_for_each_remote_ref(get_main_ref_store(the_repository), - cgit_refs_cb, &list); +void cgit_print_branches(int maxcount) +{ + struct reflist list; + int i; + + print_branch_header(); + collect_branches(&list); if (maxcount == 0 || maxcount > list.count) maxcount = list.count; @@ -205,19 +242,82 @@ void cgit_print_tags(int maxcount) cgit_free_reflist_inner(&list); } +/* The dedicated branch page lists everything, a page at a time. The + * whole list is name-sorted (or age-sorted per branch-sort) so the + * order is stable across pages. */ +static void print_branches_page(int pagesize) +{ + struct reflist list; + int i, ofs, end; + + print_branch_header(); + collect_branches(&list); + + qsort(list.refs, list.count, sizeof(*list.refs), cmp_branch_age); + if (ctx.repo->branch_sort == 0) + qsort(list.refs, list.count, sizeof(*list.refs), cmp_ref_name); + + if (pagesize <= 0 || pagesize > list.count) + pagesize = list.count; + ofs = ctx.qry.ofs > 0 ? ctx.qry.ofs : 0; + if (ofs > list.count) + ofs = list.count; + end = ofs + pagesize < list.count ? ofs + pagesize : list.count; + + for (i = ofs; i < end; i++) + print_branch(list.refs[i]); + + if (pagesize < list.count) + print_ref_pager(ofs, pagesize, list.count, "heads"); + + cgit_free_reflist_inner(&list); +} + +static void print_tags_page(int pagesize) +{ + struct reflist list; + int i, ofs, end; + + list.refs = NULL; + list.alloc = list.count = 0; + refs_for_each_tag_ref(get_main_ref_store(the_repository), + cgit_refs_cb, &list); + if (list.count == 0) + return; + qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age); + + if (pagesize <= 0 || pagesize > list.count) + pagesize = list.count; + ofs = ctx.qry.ofs > 0 ? ctx.qry.ofs : 0; + if (ofs > list.count) + ofs = list.count; + end = ofs + pagesize < list.count ? ofs + pagesize : list.count; + + print_tag_header(); + for (i = ofs; i < end; i++) + print_tag(list.refs[i]); + + if (pagesize < list.count) + print_ref_pager(ofs, pagesize, list.count, "tags"); + + cgit_free_reflist_inner(&list); +} + void cgit_print_refs(void) { cgit_print_layout_start(); html("<table class='list nowrap'>"); if (ctx.qry.path && starts_with(ctx.qry.path, "heads")) - cgit_print_branches(0); + print_branches_page(ctx.cfg.max_ref_count); else if (ctx.qry.path && starts_with(ctx.qry.path, "tags")) - cgit_print_tags(0); + print_tags_page(ctx.cfg.max_ref_count); else { - cgit_print_branches(0); + /* The combined page caps each section, with the [...] rows + * leading to the dedicated pages above. */ + cgit_print_branches(ctx.cfg.max_ref_count); html("<tr class='nohover'><td colspan='5'> </td></tr>"); - cgit_print_tags(0); + cgit_print_tags(ctx.cfg.max_ref_count); } html("</table>"); cgit_print_layout_end(); |
