Diff between 5bb0fa6a35b1d54bacad8b2189a6af36a1a7bbaf and 5d0853e00d22fb2613c3a5dbeef2964edfd8fe53

Changed Files

File Additions Deletions Status
README +1 -1 modified
app.py +2 -35 modified
git/blame.py +0 -73 deleted
git/commit.py +9 -6 modified
highlight.py +0 -13 modified
templates/base.html +0 -1 modified
templates/blame.html +0 -73 deleted
templates/blob.html +0 -1 modified
templates/index.html +1 -1 modified
templates/overview.html +0 -32 deleted

Full Patch

diff --git a/README b/README
index 6daad1c..325dc7f 100644
--- a/README
+++ b/README
@@ -1,3 +1,3 @@
 Fast, minimal git webview. Using Libgit2 as git backend
 
-- Browse bare repos with commit history, refs, trees, blobs, diffs, patches, and blame views
\ No newline at end of file
+- Browse bare repos with commit history, refs, trees, blobs, diffs, and patches
\ No newline at end of file
diff --git a/app.py b/app.py
index 022c370..b585b1d 100644
--- a/app.py
+++ b/app.py
@@ -1,6 +1,6 @@
 import os
 import subprocess
-from flask import Flask, render_template, request, abort
+from flask import Flask, render_template, request, abort, redirect, url_for
 from dotenv import load_dotenv
 
 from git.repository import get_bare_repos
@@ -10,7 +10,6 @@ from git.tree import get_tree_items
 from git.blob import get_blob
 from git.misc import get_version, validate_repo_name, validate_ref, validate_ref_as_commit, sanitize_path
 from git.diff import get_diff
-from git.blame import get_blame
 from highlight import highlight_diff
 from filters import register_filters
 
@@ -50,18 +49,7 @@ def repo_detail(repo_name):
     ref = request.args.get('ref', 'HEAD').strip()
     if not validate_ref_as_commit(f"{repo_path}/{repo_name}", ref):
         abort(400, "Invalid ref")
-    commits = get_commits(f"{repo_path}/{repo_name}", ref=ref, max_count=10)
-    refs = get_references(f"{repo_path}/{repo_name}")
-    readme = None
-    for filename in ['README.md', 'README']:
-        try:
-            readme_blob = get_blob(f"{repo_path}/{repo_name}", ref, filename)
-            if readme_blob:
-                readme = readme_blob['content']
-                break
-        except:
-            pass
-    return render_template("overview.html", repo_name=repo_name, refs=refs, commits=commits, readme=readme)
+    return redirect(url_for('repo_commits', repo_name=repo_name, ref=ref))
 
 @app.route("/<repo_name>/commits")
 def repo_commits(repo_name):
@@ -142,27 +130,6 @@ def repo_blob_path(repo_name, path):
     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, refs=refs)
 
-@app.route("/<repo_name>/blame/<path:path>")
-def repo_blame_path(repo_name, path):
-    if not validate_repo_name(repo_name):
-        abort(404)
-    ref = request.args.get('ref', 'HEAD').strip()
-    if not validate_ref(f"{repo_path}/{repo_name}", ref):
-        abort(400, "Invalid ref")
-    try:
-        path = sanitize_path(path)
-    except ValueError:
-        abort(400, "Invalid path")
-    refs = get_references(f"{repo_path}/{repo_name}")
-    
-    # if ajax (for loading)
-    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
-        blame, style = get_blame(f"{repo_path}/{repo_name}", ref, path)
-        return {'blame': blame, 'style': style}
-    
-    # initial
-    return render_template("blame.html", repo_name=repo_name, ref=ref, path=path, refs=refs)
-
 @app.route("/<repo_name>/diff")
 def repo_diff(repo_name):
     if not validate_repo_name(repo_name):
diff --git a/git/blame.py b/git/blame.py
deleted file mode 100644
index e49463f..0000000
--- a/git/blame.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import pygit2 as git
-from highlight import get_highlight_blame_style, highlight_line
-
-# discourage using blame because its very expensive, especially on repos with long commits history
-# retrieves blame information for a file at given ref and path
-def get_blame(repo_path, ref="HEAD", file_path=""):
-    repo = git.Repository(repo_path)
-    obj = repo.revparse_single(ref)
-    # TODO: doesnt work with tree refs
-    if obj.type == git.GIT_OBJECT_COMMIT:
-        commit = obj
-    else:
-        commit = obj.peel(git.GIT_OBJECT_COMMIT)
-
-    # traverse to the blob path
-    # TODO: make this common across more modules
-    tree = commit.tree
-    blob = None
-    if file_path:
-        parts = file_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)
-                        found = True
-                        break
-                    elif entry.type == git.GIT_OBJECT_TREE:
-                        tree = repo.get(entry.id)
-                        found = True
-                        break
-            if not found:
-                return None  # path not found
-    if blob is None:
-        return None
-
-    blame = repo.blame(file_path)
-    
-    # get blob content lines directly. maybe later use lines_in_hunk
-    content_lines = blob.data.decode('utf-8', errors='replace').splitlines()
-    
-    # create a list to hold blame info per line
-    blame_lines = [None] * len(content_lines)
-    for hunk in blame:
-        # https://libgit2.org/docs/reference/main/blame/git_blame_hunk.html
-        start = hunk.final_start_line_number - 1  # to 0 index, since using python lists
-        end = start + hunk.lines_in_hunk
-        commit = repo.get(hunk.final_commit_id)  # last commit oid
-        # TODO: more info if needed
-        info = {
-            'commit_id': str(hunk.final_commit_id),
-            'author': {
-                'name': commit.author.name,
-                'time': commit.author.time,
-            },
-        }
-        # fill premade info for lines in this hunk
-        for i in range(start, min(end, len(blame_lines))): # prevent index overflow, with min
-            blame_lines[i] = info
-    
-    # combine content lines with their blame info
-    result = []
-    for i, line in enumerate(content_lines):
-        result.append({
-            'line_num': i + 1,
-            'content': line,
-            'blame': blame_lines[i],
-            # highlight every line individually
-            'highlighted': highlight_line(line, file_path)
-        })
-        
-    return result, get_highlight_blame_style()
\ No newline at end of file
diff --git a/git/commit.py b/git/commit.py
index 9792037..d30b3cf 100644
--- a/git/commit.py
+++ b/git/commit.py
@@ -19,12 +19,15 @@ def get_commits(path, ref="HEAD", max_count=None, skip=0):
     repo = git.Repository(path)
     commits = []
     # TODO: accept blob oids to filter commits that touch specific blobs
-    obj = repo.revparse_single(ref)
-    if obj.type == git.GIT_OBJECT_COMMIT:
-        commit = obj
-    else:
-        commit = obj.peel(git.GIT_OBJECT_COMMIT)
-    walker = repo.walk(commit.id, git.GIT_SORT_TIME)
+    try:
+        obj = repo.revparse_single(ref)
+    except Exception:
+        # PYGIT DOES NOT REURN LIBGIT ERRORS!??! >:(
+        # only generic exception....
+        return [], f"invalid reference"
+    
+    # revwalk
+    walker = repo.walk(obj.id, git.GIT_SORT_TIME)
 
     n = 0
     for commit in walker:
diff --git a/highlight.py b/highlight.py
index c6eaa8a..8c974ad 100644
--- a/highlight.py
+++ b/highlight.py
@@ -41,19 +41,6 @@ def highlight_code(data, filename):
     return f"<style>{css}</style>{highlighted}"
 
 
-# get CSS styles for blame view
-def get_highlight_blame_style():
-    formatter = _formatter(cssclass="blame-code")
-    return formatter.get_style_defs(".blame-code")
-
-
-# highlight a single line of code with filename-based lexer
-def highlight_line(line, filename):
-    # Use nowrap to avoid wrapping in <div><pre>...</pre></div>
-    formatter = _formatter(cssclass="blame-code", nowrap=True)
-    return highlight(line, _safe_lexer(line, filename), formatter)
-
-
 # highlight diff with DiffLexer
 def highlight_diff(data):
     formatter = _formatter()
diff --git a/templates/base.html b/templates/base.html
index 076527f..a003975 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -10,7 +10,6 @@
         <a href="/">Home</a>
         {% set repo_name = request.view_args.get('repo_name') %}
         {% if repo_name %}
-            | <a href="{{ url_for('repo_detail', repo_name=repo_name) }}?ref={{ current_ref }}">Overview</a>
             | <a href="{{ url_for('repo_commits', repo_name=repo_name) }}?ref={{ current_ref }}">Commits</a>
             | <a href="{{ url_for('repo_refs', repo_name=repo_name) }}">Refs</a>
             | <a href="{{ url_for('repo_tree_path', repo_name=repo_name) }}?ref={{ current_ref }}">Tree</a>
diff --git a/templates/blame.html b/templates/blame.html
deleted file mode 100644
index ddca83c..0000000
--- a/templates/blame.html
+++ /dev/null
@@ -1,73 +0,0 @@
-{% extends "base.html" %}
-
-{% block content %}
-<style id="blame-style"></style>
-<h2>Blame: {{ path }}</h2>
-<div id="loading">Loading blame information, this may take a while for large files...</div>
-<div id="pomeranian" style="display: none;">
-    <p>Server is taking its time... anyways, here's a tug of war match between two toasted pomeranians:</p>
-    <iframe width="560" height="315" src="https://www.youtube.com/embed/Q-KciIbk_oA?si=c_DqdaVbYMlfhxW7&amp;controls=0&amp;autoplay=1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
-</div>
-<div id="blame-content" style="display: none;">
-</div>
-<script>
-document.addEventListener('DOMContentLoaded', function() {
-    const repoName = window.location.pathname.split('/')[1];
-    const loading = document.getElementById('loading');
-    const pomeranian = document.getElementById('pomeranian');
-    const pomeranianIframe = pomeranian.querySelector('iframe');
-    const blameContent = document.getElementById('blame-content');
-
-    const showPomeranian = () => {
-        loading.style.display = 'none';
-        pomeranian.style.display = 'block';
-    };
-
-    const hidePomeranian = () => {
-        pomeranian.style.display = 'none';
-        if (pomeranianIframe) {
-            pomeranianIframe.src = 'about:blank';
-        }
-    };
-
-    const pomeranianTimeout = setTimeout(showPomeranian, 5000);
-    
-    fetch(window.location.href, {
-        headers: {
-            // let server know that this is ajax
-            'X-Requested-With': 'XMLHttpRequest'
-        }
-    })
-    .then(response => response.json())
-    .then(data => {
-        clearTimeout(pomeranianTimeout);
-        document.getElementById('blame-style').innerHTML = data.style;
-        
-        // add blame content, previosly templating
-        let content = '<div class="blame-code"><pre>';
-        if (data.blame && data.blame.length > 0) {
-            data.blame.forEach(line => {
-                content += `${String(line.line_num).padStart(4)} `;
-                if (line.blame) {
-                    content += `<a href="/${repoName}/commits/${line.blame.commit_id}">${line.blame.commit_id.substring(0, 8)}</a> ${line.blame.author.name.substring(0, 15).padEnd(15)} ${new Date(line.blame.author.time * 1000).toISOString().slice(0, 19).replace('T', ' ')}`;
-                }
-                content += ` | ${line.highlighted}\n`;
-            });
-        } else {
-            content += 'No blame info';
-        }
-        content += '</pre></div>';
-        
-        blameContent.innerHTML = content;
-        loading.style.display = 'none';
-        hidePomeranian();
-        blameContent.style.display = 'block';
-    })
-    .catch(error => {
-        clearTimeout(pomeranianTimeout);
-        loading.innerHTML = 'Error loading blame';
-        hidePomeranian();
-    });
-});
-</script>
-{% endblock %}
\ No newline at end of file
diff --git a/templates/blob.html b/templates/blob.html
index f7e675f..54bfbf6 100644
--- a/templates/blob.html
+++ b/templates/blob.html
@@ -4,7 +4,6 @@
 <h2>Blob: {{ blob.name }}</h2>
 <p>Blob id: {{ blob.id }}</p>
 <p>Size: {{ blob.size | size }}</p>
-<p><a href="{{ url_for('repo_blame_path', repo_name=repo_name, path=path) }}?ref={{ ref }}">Blame</a></p>
 <div>
 {% if blob.is_binary %}
     <pre>Binary...</pre>
diff --git a/templates/index.html b/templates/index.html
index fc1eb28..042b713 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -19,7 +19,7 @@
             {% for repo in repos %}
             <tr>
                 <td>
-                    <a href="{{ url_for('repo_detail', repo_name=repo.name) }}">
+                    <a href="{{ url_for('repo_commits', repo_name=repo.name) }}">
                         {{ repo.name }}
                     </a>
                 </td>
diff --git a/templates/overview.html b/templates/overview.html
deleted file mode 100644
index 2a83efb..0000000
--- a/templates/overview.html
+++ /dev/null
@@ -1,32 +0,0 @@
-{% extends "base.html" %}
-
-{% block content %}
-<h2>{{ repo_name }}</h2>
-<h3>Latest commits</h3>
-<table>
-        <thead>
-            <tr style="font-weight: bold;">
-                <td>Commit</td>
-                <td>Message</td>
-                <td>Author</td>
-                <td>Age</td>
-                <td>Changes</td>
-            </tr>
-        </thead>
-        <tbody>
-            {% for commit in commits %}
-            <tr>
-                <td valign="top" nowrap><a href="{{ url_for('commit_detail', repo_name=repo_name, commit_id=commit.id) }}">{{ commit.id[:8] }}</a></td>
-                <td valign="top">{{ commit.message }}</td>
-                <td valign="top" nowrap>{{ commit.author.name }}</td>
-                <td valign="top" nowrap>{{ commit.date | age }}</td>
-                <td valign="top" nowrap>{{ commit.diff_stats.files_changed }} file{% if commit.diff_stats.files_changed != 1 %}s{% endif %}, <span style="color: green;">+{{ commit.diff_stats.insertions }}</span>, <span style="color: red;">-{{ commit.diff_stats.deletions }}</span></td>
-            </tr>
-            {% endfor %}
-        </tbody>
-    </table>
-{% if readme %}
-<h3>README</h3>
-<pre>{{ readme }}</pre>
-{% endif %}
-{% endblock %}
\ No newline at end of file