diff options
| -rw-r--r-- | ui-tree.c | 70 |
1 files changed, 68 insertions, 2 deletions
| @@ -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 | ||
| 158 | struct single_tree_ctx { | ||
| 159 | struct strbuf *path; | ||
| 160 | unsigned char sha1[GIT_SHA1_RAWSZ]; | ||
| 161 | char *name; | ||
| 162 | size_t count; | ||
| 163 | }; | ||
| 164 | |||
| 165 | static 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 | |||
| 185 | static 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 | ||
| 159 | static int ls_item(const unsigned char *sha1, struct strbuf *base, | 225 | static 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"); |
