diff options
author | lookshe <github@lookshe.org> | 2016-01-14 20:21:36 +0100 |
---|---|---|
committer | lookshe <github@lookshe.org> | 2016-01-14 20:21:36 +0100 |
commit | 69bb0352e4e48b0eb2b4caafabaea597eab50de0 (patch) | |
tree | 3194be924b2f53c3d87d6505755f7594ab2c245a | |
parent | e64d5e04c3e22e713539da2b06e1052390aed43d (diff) |
flatten tree for more direct links like github
-rw-r--r-- | ui-tree.c | 70 |
1 files changed, 70 insertions, 0 deletions
@@ -17,6 +17,14 @@ struct walk_tree_context { int state; }; +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) { unsigned long lineno, idx; @@ -122,6 +130,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) @@ -154,6 +194,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 { |