Diff between a0eb6cf4de80c2596728ea50c780daa6a013ffe2 and f9506811c70cce56ed89f40ebb32e43afc13765e

Changed Files

File Additions Deletions Status
app.py +8 -0 modified
git/commit.py +1 -0 modified
git/ref.py +2 -0 modified
git/tree.py +42 -0 added
templates/commit.html +2 -0 modified
templates/commits.html +1 -0 modified
templates/refs.html +1 -1 modified
templates/tree.html +14 -0 added

Full Patch

diff --git a/app.py b/app.py
index 487b947..eac0345 100644
--- a/app.py
+++ b/app.py
@@ -3,6 +3,7 @@ from flask import Flask, render_template, request
 from git.repo import get_bare_repos
 from git.commit import get_commits, get_commit
 from git.ref import get_refs
+from git.tree import get_tree_items
 
 app = Flask(__name__)
 
@@ -35,5 +36,12 @@ def repo_refs(repo_name):
     refs = get_refs(f"{repo_path}/{repo_name}")
     return render_template("refs.html", repo_name=repo_name, refs=refs)
 
+@app.route("/<repo_name>/tree", defaults={'path': ''})
+@app.route("/<repo_name>/tree/<path:path>")
+def repo_tree_path(repo_name, path):
+    ref = request.args.get('ref', 'HEAD')
+    tree_items = get_tree_items(f"{repo_path}/{repo_name}", ref, path)
+    return render_template("tree.html", repo_name=repo_name, ref=ref, path=path, tree_items=tree_items)
+
 if __name__ == "__main__":
     app.run(debug=True)
\ No newline at end of file
diff --git a/git/commit.py b/git/commit.py
index 5607e8c..ba70b8c 100644
--- a/git/commit.py
+++ b/git/commit.py
@@ -69,6 +69,7 @@ def get_commit(path, commit_hash):
         'message': commit.message.strip(),
         'author': commit.author,
         'committer': commit.committer,
+        'tree_id': str(commit.tree.id),
         'date': commit.commit_time,
         'diff_stats': diff_stats,
         'diff': diff.patch if diff else None
diff --git a/git/ref.py b/git/ref.py
index 1283bed..40a8312 100644
--- a/git/ref.py
+++ b/git/ref.py
@@ -8,6 +8,8 @@ def get_refs(path):
         ref = repo.lookup_reference(ref_name)
         refs.append({
             'name': ref.name,
+            'shorthand': ref.shorthand,
+            # TODO: type, branch or tag
             'target': str(ref.target)
         })
     return refs
\ No newline at end of file
diff --git a/git/tree.py b/git/tree.py
new file mode 100644
index 0000000..d17cc52
--- /dev/null
+++ b/git/tree.py
@@ -0,0 +1,42 @@
+import pygit2 as git
+
+# retrieves the tree items for a given ref and path
+def get_tree_items(repo_path, ref="HEAD", tree_path=""):
+    repo = git.Repository(repo_path)
+    # TODO: dwim for ref
+    obj = repo.revparse_single(ref)
+    if obj.type == git.GIT_OBJECT_COMMIT:
+        tree = obj.tree
+    elif obj.type == git.GIT_OBJECT_TREE:
+        tree = obj
+    else:
+        # for other refs like tags, branches
+        commit = obj.peel(git.GIT_OBJECT_COMMIT)
+        tree = commit.tree
+
+    # TODO: optimize path traversal, if possible
+    if tree_path:
+        # go down the tree to right path
+        parts = tree_path.rstrip('/').split('/')
+        for part in parts:
+            found = False
+            for entry in tree:
+                # look for matching tree entry
+                # if found, go to it
+                if entry.name == part and entry.type == git.GIT_OBJECT_TREE:
+                    tree = repo.get(entry.id)
+                    found = True
+                    break
+            if not found:
+                return []  # path not found
+
+    items = []
+    for entry in tree:
+        item = {
+            'name': entry.name,
+            'type': 'tree' if entry.type == git.GIT_OBJECT_TREE else 'blob',
+            'id': str(entry.id),
+            'path': entry.name if not tree_path else f"{tree_path}/{entry.name}"
+        }
+        items.append(item)
+    return items
\ No newline at end of file
diff --git a/templates/commit.html b/templates/commit.html
index ed8eeeb..80c35d7 100644
--- a/templates/commit.html
+++ b/templates/commit.html
@@ -4,6 +4,8 @@
     <p>Author: {{ commit.author.name }} &lt;{{ commit.author.email }}&gt;</p>
     <p>Committer: {{ commit.committer.name }} &lt;{{ commit.committer.email }}&gt;</p>
     <p>Date: {{ commit.date }}</p>
+    <p>Tree: {{ commit.tree_id }}</p>
+    <p><a href="{{ url_for('repo_tree_path', repo_name=repo_name, path='') }}?ref={{ commit.id }}">View Tree</a></p>
     <h2>Diff Stats</h2>
     <ul>
         <li>Files Changed: {{ commit.diff_stats.files_changed }}</li>
diff --git a/templates/commits.html b/templates/commits.html
index f9d63f7..e9ba28a 100644
--- a/templates/commits.html
+++ b/templates/commits.html
@@ -1,5 +1,6 @@
 {% block content %}
     <h1>Commits for {{ repo_name }}</h1>
+    <p><a href="{{ url_for('repo_tree_path', repo_name=repo_name, path='') }}?ref={{ ref }}">View Tree</a></p>
     <ul>
         {% for commit in commits %}
             <li>
diff --git a/templates/refs.html b/templates/refs.html
index f4b8af2..0741998 100644
--- a/templates/refs.html
+++ b/templates/refs.html
@@ -3,7 +3,7 @@
     <ul>
         {% for ref in refs %}
             <li>
-            {{ ref.name }} - {{ ref.target }}
+            {{ ref.name }} - {{ ref.target }} - <a href="{{ url_for('repo_tree_path', repo_name=repo_name, path='') }}?ref={{ ref.shorthand }}">View Tree</a>
             </li>
         {% endfor %}
     </ul>
diff --git a/templates/tree.html b/templates/tree.html
new file mode 100644
index 0000000..037a237
--- /dev/null
+++ b/templates/tree.html
@@ -0,0 +1,14 @@
+{% block content %}
+    <h1>Tree for {{ repo_name }} at {{ ref }}{% if path %} / {{ path }}{% endif %}</h1>
+    <ul>
+        {% for item in tree_items %}
+            <li>
+                {% if item.type == 'tree' %}
+                    <a href="{{ url_for('repo_tree_path', repo_name=repo_name, path=item.path) }}?ref={{ ref }}">{{ item.name }} ({{ item.type }})/</a>
+                {% else %}
+                    {{ item.name }} ({{ item.type }})
+                {% endif %}
+            </li>
+        {% endfor %}
+    </ul>
+{% endblock %}
\ No newline at end of file