diff options
Diffstat (limited to 'ui-tree.c')
-rw-r--r-- | ui-tree.c | 109 |
1 files changed, 91 insertions, 18 deletions
@@ -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(); |