from textual.widgets import Tree from textual.widgets.tree import TreeNode from textual import work from collections import defaultdict from util import get_icon_from_name_and_type import requests def tree(): return defaultdict(tree) class RepoDirectoryTree(Tree): DEFAULT_CSS = """ RepoDirectoryTree { dock: left; width: 30; background: $background; } """ ICON_NODE_EXPANDED = "" ICON_NODE = "" def __init__(self, repo_owner: str, repo_name: str, root_sha: str, name: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False): super().__init__(label="\ue5ff Files", id=id, classes=classes, disabled=disabled) self.repo_owner = repo_owner self.repo_name = repo_name self.repo_tree = None def load_repo_tree(self): root_branch_sha = self.screen.most_recent_commit["commit"]["tree"]["sha"] # get list of paths in repo tree root = tree() page_number = 1 while True: contents = requests.get( self.app.GITEA_HOST + f"api/v1/repos/{self.repo_owner}/{self.repo_name}/git/trees/{root_branch_sha}", params={ "recursive": True, "page": page_number, "page_size": 25 } ).json() for file in contents["tree"]: node = root for part in file["path"].split("/"): node = node[part] if not contents["truncated"]: break page_number += 1 # walk the tree we generated and add all the leaves def walk(tree, prefix="", tree_node: TreeNode = None): if tree_node == None: tree_node = self.root for name, node in tree.items(): if len(node) > 0: # directory new_tree_node = tree_node.add(f"[cyan]\ue5ff[/cyan] {name}", data={"path": prefix + name + "/"}) # walk new found directory walk(node, prefix + name + "/", new_tree_node) else: # file tree_node.add_leaf(f"[cyan]{get_icon_from_name_and_type(name, False)}[/cyan] {name}", data={"path": prefix + name}) walk(root) self.root.expand_all() self.repo_tree = root