diff --git a/app.py b/app.py
index 487b947..eac0345 100644
--- a/app.py
+++ b/app.py
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__)
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
'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
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
+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
<p>Author: {{ commit.author.name }} <{{ commit.author.email }}></p>
<p>Committer: {{ commit.committer.name }} <{{ commit.committer.email }}></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
{% 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
<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
+{% 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