aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlookshe <github@lookshe.org>2016-01-14 20:21:36 +0100
committerlookshe <github@lookshe.org>2016-01-14 20:21:36 +0100
commit69bb0352e4e48b0eb2b4caafabaea597eab50de0 (patch)
tree3194be924b2f53c3d87d6505755f7594ab2c245a
parente64d5e04c3e22e713539da2b06e1052390aed43d (diff)
flatten tree for more direct links like github
-rw-r--r--ui-tree.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/ui-tree.c b/ui-tree.c
index 3ff2320..a8172ac 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -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 {