aboutsummaryrefslogtreecommitdiffstats
path: root/ui-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui-tree.c')
-rw-r--r--ui-tree.c109
1 files changed, 91 insertions, 18 deletions
diff --git a/ui-tree.c b/ui-tree.c
index 120066c..15e39e6 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -15,6 +15,15 @@ struct walk_tree_context {
char *curr_rev;
char *match_path;
int state;
+ bool dir_mode;
+};
+
+struct flatten_walk_tree_context {
+ int counter;
+ int path_added;
+ unsigned char last_sha1[20];
+ char* path;
+ char* last_path;
};
static void print_text_buffer(const char *name, char *buf, unsigned long size)
@@ -86,7 +95,7 @@ static void print_binary_buffer(char *buf, unsigned long size)
static void set_title_from_path(const char *path)
{
- size_t path_len, path_index, path_last_end;
+ size_t path_len;
char *new_title;
if (!path)
@@ -96,20 +105,7 @@ static void set_title_from_path(const char *path)
new_title = xmalloc(path_len + 3 + strlen(ctx.page.title) + 1);
new_title[0] = '\0';
- for (path_index = path_len, path_last_end = path_len; path_index-- > 0;) {
- if (path[path_index] == '/') {
- if (path_index == path_len - 1) {
- path_last_end = path_index - 1;
- continue;
- }
- strncat(new_title, &path[path_index + 1], path_last_end - path_index - 1);
- strcat(new_title, "\\");
- path_last_end = path_index;
- }
- }
- if (path_last_end)
- strncat(new_title, path, path_last_end);
-
+ strcat(new_title, path);
strcat(new_title, " - ");
strcat(new_title, ctx.page.title);
ctx.page.title = new_title;
@@ -155,6 +151,38 @@ static void print_object(const unsigned char *sha1, char *path, const char *base
print_text_buffer(basename, buf, size);
}
+static int flatten_tree_item(const unsigned char *sha1, struct strbuf *base,
+ const char *pathname, unsigned mode, int stage, void *cbdata)
+{
+ struct flatten_walk_tree_context* fwt_ctx = cbdata;
+ // increment counter of child elements
+ fwt_ctx->counter++;
+ if (!S_ISDIR(mode) || fwt_ctx->counter > 1) {
+ if (fwt_ctx->counter > 1) {
+ // if the first child element was a directory we have to use the path before
+ free(fwt_ctx->path);
+ fwt_ctx->path = xstrdup(fwt_ctx->last_path);
+ }
+ // flag that we ended
+ fwt_ctx->counter = -1;
+ // -1 to break read_tree_recursive
+ return -1;
+ }
+ // save last path and concatenate new one
+ char* tmp = xstrdup(fwt_ctx->path);
+ free(fwt_ctx->path);
+ free(fwt_ctx->last_path);
+ fwt_ctx->last_path = xstrdup(tmp);
+ fwt_ctx->path = (char*) malloc(sizeof(char) * (2 + strlen(tmp) + strlen(pathname)));
+ strcpy(fwt_ctx->path, tmp);
+ strcat(fwt_ctx->path, "/");
+ strcat(fwt_ctx->path, pathname);
+ free(tmp);
+ fwt_ctx->path_added++;
+ // save hash of found element
+ hashcpy(fwt_ctx->last_sha1, sha1);
+ return 0;
+}
static int ls_item(const unsigned char *sha1, struct strbuf *base,
const char *pathname, unsigned mode, int stage, void *cbdata)
@@ -166,6 +194,10 @@ static int ls_item(const unsigned char *sha1, struct strbuf *base,
enum object_type type;
unsigned long size = 0;
+ if ((!S_ISDIR(mode) && walk_tree_ctx->dir_mode) || (S_ISDIR(mode) && !walk_tree_ctx->dir_mode)) {
+ return 0;
+ }
+
name = xstrdup(pathname);
strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "",
ctx.qry.path ? "/" : "", name);
@@ -187,6 +219,36 @@ static int ls_item(const unsigned char *sha1, struct strbuf *base,
if (S_ISGITLINK(mode)) {
cgit_submodule_link("ls-mod", fullpath.buf, sha1_to_hex(sha1));
} else if (S_ISDIR(mode)) {
+ struct flatten_walk_tree_context fwt_ctx;
+ // initialize paths
+ fwt_ctx.path = (char*) malloc(sizeof(char) * 1);
+ strcpy(fwt_ctx.path, "");
+ fwt_ctx.last_path = (char*) malloc(sizeof(char) * 1);
+ strcpy(fwt_ctx.last_path, "");
+ // start at actual position
+ hashcpy(fwt_ctx.last_sha1, sha1);
+ do {
+ fwt_ctx.counter = 0;
+ struct tree* tree;
+ struct pathspec path = {
+ .nr = 0
+ };
+ tree = parse_tree_indirect(fwt_ctx.last_sha1);
+ read_tree_recursive(tree, "", 0, 1, &path, flatten_tree_item, &fwt_ctx);
+ } while (fwt_ctx.counter != -1);
+ if (fwt_ctx.path_added) {
+ // append found path to fullpath and name
+ strbuf_addf(&fullpath, "%s", fwt_ctx.path);
+ char* tmp = xstrdup(name);
+ free(name);
+ name = (char*) malloc(sizeof(char) * (1 + strlen(tmp) + strlen(fwt_ctx.path)));
+ strcpy(name, tmp);
+ strcat(name, fwt_ctx.path);
+ free(tmp);
+ }
+ // cleanup
+ free(fwt_ctx.path);
+ free(fwt_ctx.last_path);
cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
walk_tree_ctx->curr_rev, fullpath.buf);
} else {
@@ -249,6 +311,9 @@ static void ls_tree(const unsigned char *sha1, char *path, struct walk_tree_cont
}
ls_head();
+ walk_tree_ctx->dir_mode = true;
+ read_tree_recursive(tree, "", 0, 1, &paths, ls_item, walk_tree_ctx);
+ walk_tree_ctx->dir_mode = false;
read_tree_recursive(tree, "", 0, 1, &paths, ls_item, walk_tree_ctx);
ls_tail();
}
@@ -268,12 +333,16 @@ static int walk_tree(const unsigned char *sha1, struct strbuf *base,
if (S_ISDIR(mode)) {
walk_tree_ctx->state = 1;
- set_title_from_path(buffer);
- ls_head();
+ if (walk_tree_ctx->dir_mode) {
+ set_title_from_path(buffer);
+ ls_head();
+ }
return READ_TREE_RECURSIVE;
} else {
walk_tree_ctx->state = 2;
- print_object(sha1, buffer, pathname, walk_tree_ctx->curr_rev);
+ if (walk_tree_ctx->dir_mode) {
+ print_object(sha1, buffer, pathname, walk_tree_ctx->curr_rev);
+ }
return 0;
}
}
@@ -325,6 +394,10 @@ void cgit_print_tree(const char *rev, char *path)
goto cleanup;
}
+ walk_tree_ctx.dir_mode = true;
+ read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
+ walk_tree_ctx.state = 0;
+ walk_tree_ctx.dir_mode = false;
read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
if (walk_tree_ctx.state == 1)
ls_tail();