Diff between f9506811c70cce56ed89f40ebb32e43afc13765e and 0b527f29faa2f2e2c09ee32bcdde0b605c57dc40

Changed Files

File Additions Deletions Status
app.py +7 -0 modified
git/blob.py +39 -0 added
git/tree.py +1 -0 modified
templates/blob.html +11 -0 added
templates/commit.html +1 -1 modified
templates/tree.html +1 -1 modified

Full Patch

diff --git a/app.py b/app.py
index eac0345..290e17b 100644
--- a/app.py
+++ b/app.py
@@ -4,6 +4,7 @@ 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
+from git.blob import get_blob
 
 app = Flask(__name__)
 
@@ -43,5 +44,11 @@ def repo_tree_path(repo_name, path):
     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)
 
+@app.route("/<repo_name>/blob/<path:path>")
+def repo_blob_path(repo_name, path):
+    ref = request.args.get('ref', 'HEAD')
+    blob = get_blob(f"{repo_path}/{repo_name}", ref, path)
+    return render_template("blob.html", repo_name=repo_name, ref=ref, path=path, blob=blob)
+
 if __name__ == "__main__":
     app.run(debug=True)
\ No newline at end of file
diff --git a/git/blob.py b/git/blob.py
new file mode 100644
index 0000000..96496a6
--- /dev/null
+++ b/git/blob.py
@@ -0,0 +1,39 @@
+import pygit2 as git
+
+# retrieves a blob content for given ref and path
+def get_blob(repo_path, ref="HEAD", blob_path=""):
+    repo = git.Repository(repo_path)
+    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:
+        commit = obj.peel(git.GIT_OBJECT_COMMIT)
+        tree = commit.tree
+
+    # traverse to the blob path
+    # TODO: improve the code, just quick and dirty
+    if blob_path:
+        parts = blob_path.rstrip('/').split('/')
+        for part in parts:
+            found = False
+            for entry in tree:
+                if entry.name == part:
+                    if entry.type == git.GIT_OBJECT_BLOB:
+                        blob = repo.get(entry.id)
+                        return {
+                            'name': entry.name,
+                            'id': str(entry.id),
+                            'path': blob_path,
+                            'size': blob.size,
+                            'is_binary': blob.is_binary,
+                            'content': blob.data.decode('utf-8', errors='replace')
+                        }
+                    elif entry.type == git.GIT_OBJECT_TREE:
+                        tree = repo.get(entry.id)
+                        found = True
+                        break
+            if not found:
+                return None  # path not found
+    return None  # blob not found
diff --git a/git/tree.py b/git/tree.py
index d17cc52..46f6522 100644
--- a/git/tree.py
+++ b/git/tree.py
@@ -35,6 +35,7 @@ def get_tree_items(repo_path, ref="HEAD", tree_path=""):
         item = {
             'name': entry.name,
             'type': 'tree' if entry.type == git.GIT_OBJECT_TREE else 'blob',
+            'size': entry.size if entry.type == git.GIT_OBJECT_BLOB else None,
             'id': str(entry.id),
             'path': entry.name if not tree_path else f"{tree_path}/{entry.name}"
         }
diff --git a/templates/blob.html b/templates/blob.html
new file mode 100644
index 0000000..72352fc
--- /dev/null
+++ b/templates/blob.html
@@ -0,0 +1,11 @@
+{% block content %}
+<h1>Blob: {{ blob.name }}</h1>
+<p>Blob hash: {{ blob.id }}</p>
+<p>Size: {{ blob.size }} bytes</p>
+<h2>Content:</h2>
+{% if blob.is_binary %}
+    <pre>Binary...</pre>
+{% else %}
+<pre>{{ blob.content }}</pre>
+{% endif %}
+{% endblock %}
\ No newline at end of file
diff --git a/templates/commit.html b/templates/commit.html
index 80c35d7..c95a0d8 100644
--- a/templates/commit.html
+++ b/templates/commit.html
@@ -4,7 +4,7 @@
     <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>Tree: <a href="{{ url_for('repo_tree_path', repo_name=repo_name, path='') }}?ref={{ commit.tree_id }}">{{ commit.tree_id }}</a></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>
diff --git a/templates/tree.html b/templates/tree.html
index 037a237..9bee483 100644
--- a/templates/tree.html
+++ b/templates/tree.html
@@ -6,7 +6,7 @@
                 {% 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 }})
+                    <a href="{{ url_for('repo_blob_path', repo_name=repo_name, path=item.path) }}?ref={{ ref }}">{{ item.name }} ({{ item.type }}) {{ item.size }} bytes</a>
                 {% endif %}
             </li>
         {% endfor %}