Display of directories that contain only one subdirectory

Jamie Couture jamie.couture at gmail.com
Thu Jul 14 00:12:17 CEST 2016


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 <john at keeping.me.uk> 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 <john at keeping.me.uk <javascript:;>>
> ---
>  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 <javascript:;>
> http://lists.zx2c4.com/mailman/listinfo/cgit
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.zx2c4.com/pipermail/cgit/attachments/20160713/e6744fde/attachment.html>


More information about the CGit mailing list