Pygitweb
Gitweb reimplementation using Python, FastAPI, and Pygit2, ported from git/gitweb/gitweb.perl.
Config
Settings load from ~/.pygitweb/settings.json (or PYGITWEB_SETTINGS_CONFIG), PYGITWEB_*
environment variables, and optionally a .env file in the working directory via
pydantic-settings. See pygitweb/config.py and pygitweb/settings.schema.json for the full schema. Common ones:
PYGITWEB_PROJECTROOT— absolute path to directory containing git repositories (default:$HOME)PYGITWEB_PROJECTS_LIST— directory to scan, or path to a project-list file (default:PROJECTROOT)PYGITWEB_EXPORT_OK— filename that must exist to allow export (e.g.git-daemon-export-ok); empty = no checkPYGITWEB_SITE_NAME— site name in titles (default:PyGitWeb)PYGITWEB_GIT— path to the git executable (default:git)PYGITWEB_AUTH—0/false/offdisables auth;1/true/onenables it. If unset or empty, auth defaults to on.PYGITWEB_AUTH_CONFIG— path to the auth JSON file (default:~/.pygitweb/auth.json). Generated to a reasonable default if not present.PYGITWEB_SETTINGS_CONFIG— path to the settings JSON file (default:~/.pygitweb/settings.json). Created from the environment on first run if missing.- Browser login:
GET /login(optional?next=/path),POST /loginwith form fieldsusername,password,next; sets an HttpOnly cookie with an opaque in-process session id (also accepted by protected routes viaAuthorization: Bearer). Sessions are wiped when the process exits.GET /logout?next=/revokes the session and clears the cookie.
Routes
Load the /docs page for a detailed view of routes (below the readme).
No-project routes
GET /: project listGET /index: plain text project index (path, owner)GET /opml: OPML feed listGET /project/{name}: Project dispatch (See actions table)
Hook management routes
GET /project/{name}/hooks: JSON{hooks: [...samples...], bundles: [...]}with current status (installed,not_installed,different) for every pygittools sample and bundlePOST /project/{name}/hook?name=<sample-or-bundle>&op=<add|remove|check>: install, remove, or check one sample or bundle.namemay be a sample filename (e.g.post-receive.notify) or a bundle name (e.g.update, which expands topost-commit.notify+post-receive.notify).add/removerefuse to clobber a custom hook with different content (returns409)
Actions
| Action | Query parameters | URL | Description |
|---|---|---|---|
| summary | (default) or a |
GET /project/{project} |
Project summary (description, owner, HEAD, tree link). |
| tree | h, f |
GET /project/{project}?a=tree&h=...&f=... |
Directory listing (tree). |
| blob | h, f |
GET /project/{project}?a=blob&h=...&f=... |
File view (HTML). |
| blob_plain | h, f |
GET /project/{project}?a=blob_plain&h=...&f=... |
Raw file download. |
| log | h, updates, pf |
GET /project/{project}?a=log&h=... |
Commit log. Supports long-poll subscribe. |
| shortlog | h, updates, pf |
GET /project/{project}?a=shortlog&h=... |
Shortlog. Supports long-poll subscribe. |
| history | h, f, updates, pf |
GET /project/{project}?a=history&h=...&f=... |
History of a file or path. Supports long-poll subscribe. |
| heads | updates, pf |
GET /project/{project}?a=heads |
List branch heads. Supports long-poll subscribe. |
| tags | updates, pf |
GET /project/{project}?a=tags |
List all tags. Supports long-poll subscribe. |
| tag | h |
GET /project/{project}?a=tag&h=... |
Single tag view (tag ref or hash). |
| commit | h |
GET /project/{project}?a=commit&h=... |
Commit information. |
| commitdiff | h |
GET /project/{project}?a=commitdiff&h=... |
Commit diff (unified diff rendered with diff2html). |
| patch | h |
GET /project/{project}?a=patch&h=... |
Single-commit patch (plain text). |
| patches | h, hb |
GET /project/{project}?a=patches&h=...&hb=... |
Multi-commit patches for range hb..h (plain text). |
| blobdiff | h, hb, f, fp |
GET /project/{project}?a=blobdiff&h=...&hb=...&f=...&fp=... |
Blob diff (two versions of a file) rendered with diff2html. |
| blobpatch | h, hb, f, fp |
GET /project/{project}?a=blobpatch&h=...&hb=...&f=...&fp=... |
Blob diff as plain unified diff. |
| remotes | — | GET /project/{project}?a=remotes |
List repo remotes. |
| object | h |
GET /project/{project}?a=object&h=... |
Show object by type (commit, tree, tag, or blob). |
| blame_raw | h, f |
GET /project/{project}?a=blame_raw&h=...&f=... |
File blame as JSON: array of {commit_id, commit_msg, commit_author, time, line_range}. Contiguous lines from the same commit are merged. |
| blame | h, f |
GET /project/{project}?a=blame&h=...&f=... |
File blame HTML view (syntax-highlighted source, line numbers, commit links per line range; hover shows author and date). |
| blame_incremental | — | TODO | |
| blame_data | — | TODO | |
| rss | — | TODO | |
| atom | — | TODO | |
| search | patterns, paths, globs, heading, sort, max_count, multiline |
GET /project/{project}?a=search&patterns=... |
Ripgrep search (via python-ripgrep); returns JSON. paths are relative to the project tree and cannot escape it. |
| search (page) | — | GET /project/{project}/search |
Per-project search UI page. |
| search_help | — | TODO |
Query parameter short names (CGI mapping)
p→ projecta→ actionf→ file_namefp→ file_parenth→ hashhp→ hash_parenthb→ hash_basehpb→ hash_parent_basepg→ pageo→ orders→ searchtextst→ searchtypesf→ snapshot_formatopt→ extra_optionssr→ search_use_regexpby_tag→ ctagds→ diff_stylepf→ project_filterupdates→ long-poll subscription flag (trueparks the request up to 30s; returns200 OKwith an empty body on timeout/shutdown, or the action data when the queue is notified)
Live updates (long polling)
Supported actions (history, log, shortlog, heads, tags) accept updates=true to
subscribe to the project's change queue. The request is held for up to 30 seconds:
- A
POST /_internal/notify?project=<name>(typically from a server-side git hook) wakes matching subscribers, who then receive the freshly-rendered action response. - If no notification arrives in 30 seconds (or the server is shutting down), the response is
200 OKwith an empty body. - Combine with
pf=<prefix>to subscribe to every project under a path prefix instead of just the URL project (the action is still rendered for the URL project).
The notify endpoint is intended for loopback use by pygittools post-receive hooks (see
pygittools/hook_samples/post-receive.notify). The server enforces loopback-only access and
rejects unknown projects; production deployments should still restrict it at the reverse proxy.
Hook management
The project summary page exposes a Hooks row that lists installed hooks and lets you
install or remove pygittools samples, including the update bundle: post-receive.notify
(feeds the change queue when refs are pushed) and post-commit.notify (feeds the change
queue when a working clone of this repo records a local commit). Either is sufficient to
wake long-poll subscribers; installing both covers server-side and client-side commit paths.
The same operations are available programmatically via
POST /project/{name}/hook?name=<sample-or-bundle>&op=<...>. Bundle status is
INSTALLED only when every member is installed, DIFFERENT if any member's path holds
a custom hook (the bundle then refuses to install or remove anything to preserve the
custom hook), otherwise NOT_INSTALLED. When PYGITWEB_AUTH is enabled, add and remove
require a valid access token (Authorization: Bearer … from POST /token, or the cookie from POST /login); check is always allowed.
Release files for pygitweb 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pygitweb-0.2.3.tar.gz | 144.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pygitweb-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 323.4 kB
Release files / pygitweb-0.2.3.tar.gz
| Download URL | pygitweb-0.2.3.tar.gz |
|---|---|
| Size | 144.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e902cc45eff63df5e884bbcc4c19d81a0862306c5c10c36b42171a57affb0dab
|
|
BLAKE2b-256 checksum How to use checksums |
1411a30bd360ad1eb53f5d5c6e278beb894d905f653bfc31dc2686f2b903d07e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.22 {"installer":{"name":"uv","version":"0.11.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / pygitweb-0.2.3-py3-none-any.whl
| Download URL | pygitweb-0.2.3-py3-none-any.whl |
|---|---|
| Size | 179.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6ad5f3d202150b2f766047fb9fe4b9aca31e27983723cf12205874e9c3cf0155
|
|
BLAKE2b-256 checksum How to use checksums |
00c8069e201e969303fd2fb4d9d589546d658b082ce73edc5b161c23229ed198
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.22 {"installer":{"name":"uv","version":"0.11.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|