+ struct pathspec paths = {
+ .nr = 0
+ };
+
+ tree = parse_tree_indirect(sha1);
+ if (!tree) {
+ cgit_print_error_page(404, "Not found",
+ "Not a tree object: %s", sha1_to_hex(sha1));
+ return;
+ }
+
+ ls_head();
+ read_tree_recursive(tree, "", 0, 1, &paths, ls_item, walk_tree_ctx);
+ ls_tail();
+}
+
+
+static int walk_tree(const unsigned char *sha1, struct strbuf *base,
+ const char *pathname, unsigned mode, int stage, void *cbdata)
+{
+ struct walk_tree_context *walk_tree_ctx = cbdata;
+ static char buffer[PATH_MAX];
+
+ if (walk_tree_ctx->state == 0) {
+ memcpy(buffer, base->buf, base->len);
+ strcpy(buffer + base->len, pathname);
+ if (strcmp(walk_tree_ctx->match_path, buffer))
+ return READ_TREE_RECURSIVE;
+
+ if (S_ISDIR(mode)) {
+ walk_tree_ctx->state = 1;
+ ls_head();
+ return READ_TREE_RECURSIVE;
+ } else {
+ walk_tree_ctx->state = 2;
+ print_object(sha1, buffer, pathname, walk_tree_ctx->curr_rev);
+ return 0;
+ }
+ }
+ ls_item(sha1, base, pathname, mode, stage, walk_tree_ctx);
+ return 0;
+}
+
+/*
+ * Show a tree or a blob
+ * rev: the commit pointing at the root tree object
+ * path: path to tree or blob
+ */
+void cgit_print_tree(const char *rev, char *path)
+{