diff --git a/README b/README
index 708219a..6daad1c 100644
--- a/README
+++ b/README
-Fast and simple git webview. Using Libgit2 as the backend.
\ No newline at end of file
+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
diff --git a/app.py b/app.py
index 6391784..5ecebc9 100644
--- a/app.py
+++ b/app.py
from flask import Flask, render_template, request, abort
from dotenv import load_dotenv
-from git.repo import get_bare_repos
+from git.repository 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
diff --git a/git/repo.py b/git/repo.py
deleted file mode 100644
index 87d3be1..0000000
--- a/git/repo.py
+++ /dev/null
-from pathlib import Path
-import pygit2 as git
-
-from .config import get_repo_owner
-
-# scans given path for bare git repos and list their names and paths
-def get_bare_repos(path):
- repos = []
-
- repo_path = Path(path)
-
- for item in repo_path.iterdir():
- if item.is_dir():
- try:
- repo = git.Repository(str(item))
- if repo.is_bare:
- description = ""
- desc_file = item / "description"
- if desc_file.exists():
- try:
- description = desc_file.read_text().strip()
- except:
- pass
- owner = get_repo_owner(item)
- repo_info = {
- "name": item.name,
- "path": str(item.resolve()),
- "description": description,
- "owner": owner
- }
- repos.append(repo_info)
- except git.GitError:
- continue
- return repos
diff --git a/git/repository.py b/git/repository.py
new file mode 100644
index 0000000..2224e99
--- /dev/null
+++ b/git/repository.py
+from pathlib import Path
+import pygit2 as git
+
+from .config import get_repo_owner
+
+
+# scans given path for bare git repos and list their names and paths
+def get_bare_repos(path):
+ if not path:
+ return []
+
+ repo_path = Path(path)
+ if not repo_path.exists() or not repo_path.is_dir():
+ return []
+
+ repos = []
+
+ for item in repo_path.iterdir():
+ if not item.is_dir():
+ continue
+
+ repo = _safe_repository(item)
+ if not repo or not repo.is_bare:
+ continue
+
+ description = _read_description(item / "description")
+ owner = get_repo_owner(item)
+ repos.append(
+ {
+ "name": item.name,
+ "path": str(item.resolve()),
+ "description": description,
+ "owner": owner,
+ }
+ )
+
+ return repos
+
+
+def _safe_repository(path):
+ try:
+ return git.Repository(str(path))
+ except git.GitError:
+ return None
+
+
+def _read_description(desc_file):
+ if not desc_file.exists():
+ return ""
+ try:
+ desc_buf = desc_file.read_text().strip()
+ # if no description, git writes "Unnamed repository; edit this file 'description' to name the repository."
+ if desc_buf.startswith("Unnamed repository;"):
+ return ""
+ return desc_buf
+ except Exception:
+ return ""
diff --git a/static/styles.css b/static/styles.css
index 1b417eb..ffcb683 100644
--- a/static/styles.css
+++ b/static/styles.css
.commit-message {
margin: 1em 0;
}
-
-/* index */
-.main-layout {
- display: grid;
- grid-template-columns: 1fr 2fr;
- gap: 2em;
-}
-
-.repos-grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 8px;
-}
-
-.repo-card {
- padding: 16px;
- background-color: #f9f9f9;
-}
-
-.repo-card h4 {
- margin: 0 0 8px 0;
-}
-
-.repo-card h4 a {
- font-weight: normal;
-}
-
-.repo-card p {
- margin: 0;
- color: gray;
- font-size: 14px;
-}
-
-
diff --git a/templates/index.html b/templates/index.html
index bb411b0..5ef7141 100644
--- a/templates/index.html
+++ b/templates/index.html
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lipasto</title>
- <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
- <style>
- body {
- max-width: 1200px;
- margin: auto;
- padding: 1em;
- }
- </style>
</head>
<body>
- <div class="main-layout">
- <div>
- <h1>
- Lipasto
- </h1>
- <p>
- A git web interface for repositories. Currently supports viewing commits, trees, blobs, diffs, and references.
- </p>
- <small>
- Libgit2 - {{ version }} git
- </small>
- </div>
- <div>
- <h2>Repositories</h2>
- <div class="repos-grid">
- {% for repo in repos %}
- <div class="repo-card">
- <h4><a href="{{ url_for('repo_detail', repo_name=repo.name) }}">{{ repo.name }}</a></h4>
- {% if repo.owner %}
- <p>{{ repo.owner }}</p>
- {% else %}
- <p>-</p>
- {% endif %}
- </div>
- {% endfor %}
- </div>
- </div>
- </div>
+ <h2>Repositories</h2>
+ <table>
+ <thead>
+ <tr>
+ <th>Repository</th>
+ <th>Owner</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for repo in repos %}
+ <tr>
+ <td>
+ <a href="{{ url_for('repo_detail', repo_name=repo.name) }}">
+ {{ repo.name }}
+ </a>
+ </td>
+ <td>
+ {% if repo.owner %}
+ {{ repo.owner }}
+ {% else %}
+ -
+ {% endif %}
+ </td>
+ <td>
+ {% if repo.description %}
+ {{ repo.description }}
+ {% else %}
+ -
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <small>
+ libgit2 - {{ version }}
+ </small>
</body>
</html>
\ No newline at end of file