# lilgit

A read-only HTTP(S) frontend for git, 
built on [Lilush](https://lilush.link) runtime.

Features:

- `git clone`/`fetch` over smart-HTTP
-  browsing UI:
   - repo index
   - directory trees at any ref
   - markdown/djot rendered as HTML
   - raw file serving. 

Everything is served straight from the git object database,
i.e. from bare repositories on disk.

Pushes to served repositories appear immediately — the git core's
mtime caches invalidate themselves. 

No support for `git push` over HTTP, push over ssh to the bare repo instead.

## URL scheme

| Path | Behavior |
|---|---|
| `/` | repo index |
| `/{repo}` | redirect to the default-branch tree |
| `/{repo}/tree/{ref}/{path}/` | directory listing, README rendered below |
| `/{repo}/blob/{ref}/{path}` | markdown/djot as HTML; source as text; images/binaries raw |
| `/{repo}/raw/{ref}/{path}` | raw bytes, extension-guessed MIME |
| `/{repo}/refs` | branches and tags |
| `/{repo}/log/{ref}` | commit log (first-parent, paged via `?after=<sha>`) |
| `/{repo}/commit/{sha}` | commit view: metadata, message, changed files |

`{ref}` is a branch (slashes allowed), tag, full `refs/...` path,
`HEAD`, or a full 40-hex sha; sha-pinned URLs are served as immutable.
Clone URLs (`/{repo}` or `/{repo}.git`) coexist with browse URLs.
Tree and blob pages carry breadcrumbs and a ref switcher; setting
`show_sizes` in the config adds blob sizes to listings (costs a full
blob inflate per entry).

## Configuration

Read from `LILGIT_CONFIG_FILE` (default `/etc/lilgit/config.json`); a
missing file means pure defaults. CLI flags (`--ip`, `--port`, `--dir`,
`--title`) override everything.

```json
{
    "ip": "127.0.0.1",
    "port": 8091,
    "site_title": "my code",
    "repos_dir": "/srv/git",
    "repos": [
        {
            "name": "lilush",
            "path": "/srv/git/lilush.git",
            "description": "Linux Shell & Lua Framework",
            "default_branch": "master"
        }
    ],
    "ssl": { "default": { "cert": "...", "key": "..." } }
}
```

Repositories are discovered in `repos_dir` at startup (dirs with `HEAD`
or `.git/HEAD`); explicit `repos` entries win on name collision. The
`ssl` table enables built-in TLS (SNI-capable); omit it when running
behind a reverse proxy.

## Tests

Run from the pack root:

```
lilush tests/run.lua
LILGIT_E2E=1 lilush tests/run.lua
```

The e2e spec forks a real server and drives it with the git and curl
binaries.

## Roadmap

Performance sweep:

- Cache rendered markdown keyed by blob sha: `markdown.render_html`
  dominates response time on large documents (several seconds for a
  doc the size of lilush's `MNEME.md`), while the git object access
  itself is sub-millisecond.
- Header-only object reads (`read_object_header`) in the lilush git
  core, so `show_sizes` listings stop inflating every blob.
- Profile pure-Lua pack building on `git clone` for large repos.

Deferred features:

- SIGHUP rescan of `repos_dir` (today: restart to pick up new repos).
- Source blob view with line numbers and optional client-side
  syntax highlighting.
- Content diffs in the commit view (needs a line-diff implementation;
  today it lists changed files only, against the first parent).
- Full-history log across all parents (today: first-parent walk).
- Search across repos.
- Tarball snapshots (needs a tar writer).
