about summary refs log tree commit diff stats
path: root/ui-tree.c
diff options
context:
space:
mode:
authorJohn Keeping2016-07-13 20:19:42 +0100
committerJohn Keeping2016-10-01 11:45:17 +0100
commit000cf294c4d3f3a72b31d8bd0186ac989f596890 (patch)
tree8950b52925fd87b21b5fda1dd8ec7011fd22f8d8 /ui-tree.c
parentui-ssdiff: fix decl-after-statement warnings (diff)
downloadcgit-000cf294c4d3f3a72b31d8bd0186ac989f596890.tar.gz
cgit-000cf294c4d3f3a72b31d8bd0186ac989f596890.zip
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@keeping.me.uk>
Diffstat (limited to 'ui-tree.c')
-rw-r--r--ui-tree.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/ui-tree.c b/ui-tree.c index 120066c..5c31e6a 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
155 print_text_buffer(basename, buf, size); 155 print_text_buffer(basename, buf, size);
156} 156}
157 157
158struct single_tree_ctx {
159 struct strbuf *path;
160 unsigned char sha1[GIT_SHA1_RAWSZ];
161 char *name;
162 size_t count;
163};
164
165static int single_tree_cb(const unsigned char *sha1, struct strbuf *base,
166 const char *pathname, unsigned mode, int stage,
167 void *cbdata)
168{
169 struct single_tree_ctx *ctx = cbdata;
170
171 if (++ctx->count > 1)
172 return -1;
173
174 if (!S_ISDIR(mode)) {
175 ctx->count = 2;
176 return -1;
177 }
178
179 ctx->name = xstrdup(pathname);
180 hashcpy(ctx->sha1, sha1);
181 strbuf_addf(ctx->path, "/%s", pathname);
182 return 0;
183}
184
185static void write_tree_link(const unsigned char *sha1, char *name,
186 char *rev, struct strbuf *fullpath)
187{
188 size_t initial_length = fullpath->len;
189 struct tree *tree;
190 struct single_tree_ctx tree_ctx = {
191 .path = fullpath,
192 .count = 1,
193 };
194 struct pathspec paths = {
195 .nr = 0
196 };
197
198 hashcpy(tree_ctx.sha1, sha1);
199
200 while (tree_ctx.count == 1) {
201 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, rev,
202 fullpath->buf);
203
204 tree = lookup_tree(tree_ctx.sha1);
205 if (!tree)
206 return;
207
208 free(tree_ctx.name);
209 tree_ctx.name = NULL;
210 tree_ctx.count = 0;
211
212 read_tree_recursive(tree, "", 0, 1, &paths, single_tree_cb,
213 &tree_ctx);
214
215 if (tree_ctx.count != 1)
216 break;
217
218 html(" / ");
219 name = tree_ctx.name;
220 }
221
222 strbuf_setlen(fullpath, initial_length);
223}
158 224
159static int ls_item(const unsigned char *sha1, struct strbuf *base, 225static int ls_item(const unsigned char *sha1, struct strbuf *base,
160 const char *pathname, unsigned mode, int stage, void *cbdata) 226 const char *pathname, unsigned mode, int stage, void *cbdata)
@@ -187,8 +253,8 @@ static int ls_item(const unsigned char *sha1, struct strbuf *base,
187 if (S_ISGITLINK(mode)) { 253 if (S_ISGITLINK(mode)) {
188 cgit_submodule_link("ls-mod", fullpath.buf, sha1_to_hex(sha1)); 254 cgit_submodule_link("ls-mod", fullpath.buf, sha1_to_hex(sha1));
189 } else if (S_ISDIR(mode)) { 255 } else if (S_ISDIR(mode)) {
190 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 256 write_tree_link(sha1, name, walk_tree_ctx->curr_rev,
191 walk_tree_ctx->curr_rev, fullpath.buf); 257 &fullpath);
192 } else { 258 } else {
193 char *ext = strrchr(name, '.'); 259 char *ext = strrchr(name, '.');
194 strbuf_addstr(&class, "ls-blob"); 260 strbuf_addstr(&class, "ls-blob");