+
+ tree = parse_tree_indirect(sha1);
+ if (!tree) {
+ cgit_print_error(fmt("Not a tree object: %s",
+ sha1_to_hex(sha1)));
+ return;
+ }
+
+ ls_head();
+ read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
+ ls_tail();
+}
+
+
+static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
+ const char *pathname, unsigned mode, int stage,
+ void *cbdata)
+{
+ static int state;
+ static char buffer[PATH_MAX];
+ char *url;
+
+ if (state == 0) {
+ memcpy(buffer, base, baselen);
+ strcpy(buffer+baselen, pathname);
+ url = cgit_pageurl(ctx.qry.repo, "tree",
+ fmt("h=%s&path=%s", curr_rev, buffer));
+ html("/");
+ cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
+ curr_rev, buffer);
+
+ if (strcmp(match_path, buffer))
+ return READ_TREE_RECURSIVE;
+
+ if (S_ISDIR(mode)) {
+ state = 1;
+ ls_head();
+ return READ_TREE_RECURSIVE;
+ } else {
+ print_object(sha1, buffer, pathname);
+ return 0;
+ }
+ }
+ ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
+ 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)
+{