vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
|
d37d301f
Keenan Nemetz
15h ago
|
1 | # Go modules |
| 2 | ||
| 3 | A public repository on a Vole instance is a Go module. The import path is the | |
| 4 | instance's host and the repository name: | |
| 5 | ||
| 6 | ```text | |
| 7 | https://<host>/<repository> | |
| 8 | ``` | |
| 9 | ||
| 10 | Vole serves the metadata the `go` command looks for, so an import path needs no | |
| 11 | vanity service, no redirect, and no separate web host in front of the forge. | |
| 12 | Vole itself is published this way: `rodent.software/vole`. | |
| 13 | ||
| 14 | ## How the lookup works | |
| 15 | ||
| 16 | `go get` cannot clone an arbitrary URL from an import path, so it first asks the | |
| 17 | path for directions: it fetches `https://<host>/<repository>?go-get=1` and reads | |
| 18 | the `<meta name="go-import">` tag in the answer. Vole answers for a public | |
| 19 | repository with that repository's Git transport: | |
| 20 | ||
| 21 | ```console | |
| 22 | $ curl -s 'https://rodent.software/vole?go-get=1' | |
| 23 | <!doctype html> | |
| 24 | ... | |
|
b7396a11
Keenan Nemetz
2h ago
|
25 | <meta name="go-import" content="rodent.software/vole git https://rodent.software/vole.git"> |
|
d37d301f
Keenan Nemetz
15h ago
|
26 | ``` |
| 27 | ||
| 28 | Then `go` clones the repository over the smart-HTTP transport and resolves the | |
| 29 | package from the tag it finds there, exactly as it would for a module on any | |
|
b7396a11
Keenan Nemetz
2h ago
|
30 | other forge. The transport lives beside the pages: `/<repository>` is the |
| 31 | repository and `/<repository>.git` is its Git URL, so the tag's clone URL and the | |
| 32 | page a person opens are the same name. | |
| 33 | ||
| 34 | A package inside the module (`rodent.software/vole/server/web`) resolves from the | |
| 35 | same tag: the go command asks the full path first, and the tag it gets names the | |
| 36 | repository prefix. That path is not a page, and it does not need to be — the | |
| 37 | probe is answered before the router, for any path whose first segment names a | |
| 38 | public repository. | |
|
d37d301f
Keenan Nemetz
15h ago
|
39 | |
| 40 | Add the repository to a project as usual: | |
| 41 | ||
| 42 | ```console | |
| 43 | $ go get rodent.software/vole | |
| 44 | $ go doc rodent.software/vole/server/web | |
| 45 | ``` | |
| 46 | ||
| 47 | ## What the instance must have | |
| 48 | ||
| 49 | - `public_url` set to the origin people use, in `[server]` in the | |
| 50 | configuration file. The metadata's import prefix is that origin's host name; | |
| 51 | without `public_url` Vole falls back to the request's host, which is not | |
| 52 | something the go command's discovery can rely on. | |
| 53 | - The host in the import path is the host name alone. A module path cannot carry | |
| 54 | a port, so an instance reached only at `https://forge.example.com:8443` can | |
| 55 | still serve its pages, but its repositories are not importable paths; clone | |
| 56 | them by URL instead. | |
| 57 | ||
| 58 | ## Which repositories answer | |
| 59 | ||
| 60 | Only a repository an anonymous reader may read, which is the same rule that makes | |
| 61 | its pages public. The tag is fetched without credentials — that is the discovery | |
| 62 | protocol — so answering for a private repository would confirm to anyone who | |
| 63 | guessed the name that it exists. Vole answers 404 for those, like every other | |
| 64 | private path. | |
| 65 | ||
| 66 | A private repository is therefore not resolvable from its import path. Clone it | |
| 67 | where the build runs and point a `replace` at that checkout, or mirror the code in | |
| 68 | a repository that is public. | |
| 69 | ||
| 70 | ## Naming | |
| 71 | ||
| 72 | The import path is `<host>/<repository>`, so the repository name is also the last | |
|
b7396a11
Keenan Nemetz
2h ago
|
73 | element of every import path inside the module. Every name is available for this |
| 74 | except the four the forge keeps at the root for reasons a URL cannot avoid: | |
| 75 | `static` (assets), and `robots.txt`, `sitemap.xml`, and `sitemap-pages.xml` | |
| 76 | (crawlers only look for those at the root). The forge's own pages live under | |
| 77 | `/-/`, a prefix no repository name can start with, so `admin`, `login`, `activity` | |
| 78 | and the rest are ordinary repository names. | |
| 79 | ||
| 80 | Because the name is the import path, renaming a repository that other modules | |
| 81 | import breaks them: there is no forwarding layer in front of the forge. Rename | |
| 82 | the pages, or keep the name a published module depends on. | |
|
d37d301f
Keenan Nemetz
15h ago
|
83 | |
| 84 | ## Vole's own module | |
| 85 | ||
| 86 | The Vole repository is `rodent.software/vole`, so fetching the source is: | |
| 87 | ||
| 88 | ```console | |
| 89 | $ go get rodent.software/vole | |
| 90 | ``` | |
| 91 | ||
| 92 | and building from a checkout uses the same path: | |
| 93 | ||
| 94 | ```sh | |
| 95 | go build -tags libsqlite3,sqlite_fts5 -o vole rodent.software/vole/cmd/vole | |
| 96 | ``` |