From mboxrd@z Thu Jan 1 00:00:00 1970 From: jamie.couture at gmail.com (Jamie Couture) Date: Wed, 13 Jul 2016 18:12:17 -0400 Subject: Display of directories that contain only one subdirectory In-Reply-To: <20160713194928.ebdeywwvx2vhgyxn@john.keeping.me.uk> References: <20160713194928.ebdeywwvx2vhgyxn@john.keeping.me.uk> Message-ID: Was working on a solution when this came in. However, this looks much better than what I was trying to attempt. Gave it a spin. Works great. On Wednesday, 13 July 2016, John Keeping wrote: > On Wed, Jul 13, 2016 at 07:57:23PM +0200, Erik Brangs wrote: > > I use cgit via websites that use it to provide a repository browser, > > i.e. I don't have my own deployment. IMHO it would be nice to get a > > more comfortable navigation for directories that only contain one > > subdirectory. For example, for a path like "contrib/hooks" at > > https://git.zx2c4.com/cgit/tree/ , you first need to click on > > "contrib" and then again on "hooks". Navigation could be simplified by > > providing a link for "contrib/hooks" that points directly to the > > "contrib/hooks" path. > > > > GitHub's repository browser implements this feature. For example, at > > https://github.com/torvalds/linux/tree/master/tools , there's a link > > for "kvm/kvm_stat" that points directly to > > "https://github.com/torvalds/linux/tree/master/tools/kvm/kvm_stat" . > > > > I looked at cgitrc.5.txt and didn't find any evidence that this > > feature was already implemented for cgit. Assuming I didn't miss > > anything, would someone be interested in implementing it? > > It turns out it's not too difficult, patch below. This is slightly > different from Github's behaviour because it allows clicking on > intermediate directories; it wouldn't be hard to collect the full path > instead but I actually prefer this way of doing things. > > -- >8 -- > Subject: [PATCH] tree: allow skipping through single-child trees > > If we have only a single element in a directory (for example in Java > package paths), display multiple directories in one go so that it is > possible to navigate directly to the first directory that contains > either files or multiple directories. > > Signed-off-by: John Keeping > > --- > ui-tree.c | 70 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 68 insertions(+), 2 deletions(-) > > diff --git a/ui-tree.c b/ui-tree.c > index 120066c..2252490 100644 > --- a/ui-tree.c > +++ b/ui-tree.c > @@ -155,6 +155,72 @@ static void print_object(const unsigned char *sha1, > char *path, const char *base > print_text_buffer(basename, buf, size); > } > > +struct single_tree_ctx { > + struct strbuf *path; > + unsigned char sha1[GIT_SHA1_RAWSZ]; > + char *name; > + size_t count; > +}; > + > +static int single_tree_cb(const unsigned char *sha1, struct strbuf *base, > + const char *pathname, unsigned mode, int stage, > + void *cbdata) > +{ > + struct single_tree_ctx *ctx = cbdata; > + > + if (++ctx->count > 1) > + return -1; > + > + if (!S_ISDIR(mode)) { > + ctx->count = 2; > + return -1; > + } > + > + ctx->name = xstrdup(pathname); > + memcpy(ctx->sha1, sha1, GIT_SHA1_RAWSZ); > + strbuf_addf(ctx->path, "/%s", pathname); > + return 0; > +} > + > +static void write_tree_link(const unsigned char *sha1, char *name, > + char *rev, struct strbuf *fullpath) > +{ > + size_t initial_length = fullpath->len; > + struct tree *tree; > + struct single_tree_ctx tree_ctx = { > + .path = fullpath, > + .count = 1, > + }; > + struct pathspec paths = { > + .nr = 0 > + }; > + > + memcpy(tree_ctx.sha1, sha1, GIT_SHA1_RAWSZ); > + > + while (tree_ctx.count == 1) { > + cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, rev, > + fullpath->buf); > + > + tree = lookup_tree(tree_ctx.sha1); > + if (!tree) > + return; > + > + free(tree_ctx.name); > + tree_ctx.name = NULL; > + tree_ctx.count = 0; > + > + read_tree_recursive(tree, "", 0, 1, &paths, single_tree_cb, > + &tree_ctx); > + > + if (tree_ctx.count != 1) > + break; > + > + html(" / "); > + name = tree_ctx.name; > + } > + > + strbuf_setlen(fullpath, initial_length); > +} > > static int ls_item(const unsigned char *sha1, struct strbuf *base, > const char *pathname, unsigned mode, int stage, void > *cbdata) > @@ -187,8 +253,8 @@ 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)) { > - cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, > - walk_tree_ctx->curr_rev, fullpath.buf); > + write_tree_link(sha1, name, walk_tree_ctx->curr_rev, > + &fullpath); > } else { > char *ext = strrchr(name, '.'); > strbuf_addstr(&class, "ls-blob"); > -- > 2.9.0.465.g8850cbc > > _______________________________________________ > CGit mailing list > CGit at lists.zx2c4.com > http://lists.zx2c4.com/mailman/listinfo/cgit > -------------- next part -------------- An HTML attachment was scrubbed... URL: