1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
// source-forge publishes the source tree of a project as a browseable,
// syntax-highlighted static site, rendered on demand from SQLite.
//
// It has four subcommands:
//
// project Declare, redirect, or list published projects. A project must be
// declared with `project add` — which also creates its bare repo —
// before anything can be pushed to it; the post-receive hook
// rejects pushes to any repo with no declared project.
// ingest Read a `git archive` tar stream on stdin and store the tree in
// SQLite under a fresh generation, then atomically make it live.
// Directory listings are computed here, honouring any checked-in
// ".source-forge" metadata files (see meta.go).
// serve Serve directory listings and highlighted files over HTTP,
// rendering each file lazily and caching the highlighted HTML back
// in the DB.
// git-post-receive-hook
// Run as a git post-receive hook: read pushed ref updates on stdin
// and re-ingest the tree on every push to the project's declared
// branch (see `project add`). Installed once, generically, via
// core.hooksPath rather than per repo — see nixos-module.nix.
// Echoes the published URL back to the pusher when given
// --base-url.
//
// The design goal is scraper resilience: only rendered static content is ever
// exposed (no git history, no per-request compute after the first render of a
// file), so crawlers hitting every link cost almost nothing.
//
// When ingesting from a git repo, two extra artifacts are stored alongside the
// tree so it can be consumed offline: a clonable git bundle at
// "/<project>.bundle", and a gzipped tarball at "/<project>.tar.gz" that is
// directly usable as a Nix flake (`nix run https://host/<project>.tar.gz#pkg`)
// without running a git server.
//
// Typical use:
//
// source-forge project add --db forge.db --repos /var/lib/source-forge \
// --project Profpatsch --branch canon
// git push ssh://source-forge@host/var/lib/source-forge/Profpatsch.git canon
// source-forge serve --db forge.db --addr 127.0.0.1:8790 \
// --base-url http://localhost:8790
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 {
usage()
os.Exit(2)
}
cmd := os.Args[1]
args := os.Args[2:]
var err error
switch cmd {
case "project":
err = runProject(args)
case "ingest":
err = runIngest(args)
case "serve":
err = runServe(args)
case "git-post-receive-hook":
err = runPostReceiveHook(args)
case "-h", "--help", "help":
usage()
return
default:
fmt.Fprintf(os.Stderr, "source-forge: unknown subcommand %q\n\n", cmd)
usage()
os.Exit(2)
}
if err != nil {
fmt.Fprintf(os.Stderr, "source-forge %s: %v\n", cmd, err)
os.Exit(1)
}
}
func usage() {
fmt.Fprint(os.Stderr, `source-forge — on-demand source browser backed by SQLite
Usage:
source-forge project add --db <path> --repos <dir> --project <name> [--branch <name>] [--base-url <url>]
source-forge project set-branch --db <path> [--repos <dir>] --project <name> --branch <name>
source-forge project list --db <path>
source-forge ingest --db <path> --project <name> --branch <name> < archive.tar
source-forge serve --db <path> --addr <host:port> [--base-url <url>]
source-forge git-post-receive-hook --db <path> [--git-dir <path>] [--base-url <url>]
Run 'source-forge <subcommand> --help' for subcommand flags.
`)
}
|