diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Add `enable-tree-group-dirs` to list dirs first
Diffstat (limited to 'source')
-rw-r--r--source/cgit.c2
-rw-r--r--source/cgit.h1
-rw-r--r--source/ui-tree.c65
3 files changed, 63 insertions, 5 deletions
diff --git a/source/cgit.c b/source/cgit.c
index 91dd9a7..29b2131 100644
--- a/source/cgit.c
+++ b/source/cgit.c
@@ -199,6 +199,8 @@ static void config_cb(const char *name, const char *value)
ctx.cfg.enable_html_serving = atoi(value);
else if (!strcmp(name, "enable-tree-linenumbers"))
ctx.cfg.enable_tree_linenumbers = atoi(value);
+ else if (!strcmp(name, "enable-tree-group-dirs"))
+ ctx.cfg.enable_tree_group_dirs = atoi(value);
else if (!strcmp(name, "enable-git-config"))
ctx.cfg.enable_git_config = atoi(value);
else if (!strcmp(name, "enable-cache-list"))
diff --git a/source/cgit.h b/source/cgit.h
index 634d2f5..ab7b284 100644
--- a/source/cgit.h
+++ b/source/cgit.h
@@ -242,6 +242,7 @@ struct cgit_config {
int enable_subject_links;
int enable_html_serving;
int enable_tree_linenumbers;
+ int enable_tree_group_dirs;
int enable_git_config;
int enable_cache_list;
int local_time;
diff --git a/source/ui-tree.c b/source/ui-tree.c
index 5ac8c9a..cbaca38 100644
--- a/source/ui-tree.c
+++ b/source/ui-tree.c
@@ -13,10 +13,18 @@
#include "html.h"
#include "ui-shared.h"
+struct tree_ls_entry {
+ struct object_id oid;
+ char *name;
+ unsigned mode;
+};
+
struct walk_tree_context {
char *curr_rev;
char *match_path;
int state;
+ struct tree_ls_entry *entries;
+ size_t entries_nr, entries_alloc;
};
static void print_text_buffer(const char *name, char *buf, unsigned long size)
@@ -200,10 +208,9 @@ static void write_tree_link(const struct object_id *oid, char *name,
strbuf_setlen(fullpath, initial_length);
}
-static int ls_item(const struct object_id *oid, struct strbuf *base,
- const char *pathname, unsigned mode, void *cbdata)
+static void render_ls_item(const struct object_id *oid, const char *pathname,
+ unsigned mode, struct walk_tree_context *walk_tree_ctx)
{
- struct walk_tree_context *walk_tree_ctx = cbdata;
char *name;
struct strbuf fullpath = STRBUF_INIT;
struct strbuf linkpath = STRBUF_INIT;
@@ -278,9 +285,55 @@ cleanup:
free(name);
strbuf_release(&fullpath);
strbuf_release(&class);
+}
+
+static int ls_item(const struct object_id *oid, struct strbuf *base,
+ const char *pathname, unsigned mode, void *cbdata)
+{
+ struct walk_tree_context *walk_tree_ctx = cbdata;
+
+ /* When grouping directories first, collect the entries now and render
+ * them once the whole level has been read (see ls_flush). */
+ if (ctx.cfg.enable_tree_group_dirs) {
+ struct tree_ls_entry *e;
+ ALLOC_GROW(walk_tree_ctx->entries, walk_tree_ctx->entries_nr + 1,
+ walk_tree_ctx->entries_alloc);
+ e = &walk_tree_ctx->entries[walk_tree_ctx->entries_nr++];
+ oidcpy(&e->oid, oid);
+ e->name = xstrdup(pathname);
+ e->mode = mode;
+ return 0;
+ }
+
+ render_ls_item(oid, pathname, mode, walk_tree_ctx);
return 0;
}
+/* Render any entries collected by ls_item, directories first and then the
+ * rest, keeping git's ordering within each group. A no-op unless directory
+ * grouping is enabled, in which case nothing was collected. */
+static void ls_flush(struct walk_tree_context *walk_tree_ctx)
+{
+ size_t i;
+
+ for (i = 0; i < walk_tree_ctx->entries_nr; i++) {
+ struct tree_ls_entry *e = &walk_tree_ctx->entries[i];
+ if (S_ISDIR(e->mode))
+ render_ls_item(&e->oid, e->name, e->mode, walk_tree_ctx);
+ }
+ for (i = 0; i < walk_tree_ctx->entries_nr; i++) {
+ struct tree_ls_entry *e = &walk_tree_ctx->entries[i];
+ if (!S_ISDIR(e->mode))
+ render_ls_item(&e->oid, e->name, e->mode, walk_tree_ctx);
+ }
+
+ for (i = 0; i < walk_tree_ctx->entries_nr; i++)
+ free(walk_tree_ctx->entries[i].name);
+ free(walk_tree_ctx->entries);
+ walk_tree_ctx->entries = NULL;
+ walk_tree_ctx->entries_nr = walk_tree_ctx->entries_alloc = 0;
+}
+
static void ls_head(void)
{
cgit_print_layout_start();
@@ -315,6 +368,7 @@ static void ls_tree(const struct object_id *oid, const char *path, struct walk_t
ls_head();
read_tree(the_repository, tree, &paths, ls_item, walk_tree_ctx);
+ ls_flush(walk_tree_ctx);
ls_tail();
}
@@ -395,9 +449,10 @@ void cgit_print_tree(const char *rev, char *path)
read_tree(the_repository, repo_get_commit_tree(the_repository, commit),
&paths, walk_tree, &walk_tree_ctx);
- if (walk_tree_ctx.state == 1)
+ if (walk_tree_ctx.state == 1) {
+ ls_flush(&walk_tree_ctx);
ls_tail();
- else if (walk_tree_ctx.state == 2)
+ } else if (walk_tree_ctx.state == 2)
cgit_print_layout_end();
else
cgit_print_error_page(404, "Not found", "Path not found");