~gitpocket/gitpocket

refactor(gitpocket): rename the project from basin to gitpocket

commit
330f2c8fb5306fa4dd4c12600d7dbc79856be191 browse tree
parent
1fd283fc829e7046a396996351597530b6e0387a
author
james <j@cpl0.zip>
signature
Verified ~james signed with a key registered by ~james
date
2026-11-13 10:04 UTC

8 files changed, +30 −30

.gitignore modified

@@ -1 +1 @@
1-basin
1+gitpocket

README.md modified

@@ -1,4 +1,4 @@
1-# basin
1+# gitpocket
22
33 Small and lightweight git server for self hosting. Repositories are served over SSH and HTTPS, trees and logs and diffs and READMEs are rendered on the server rather than in the browser, and pull requests are handled without a working tree ever being checked out. The only JavaScript on the reading side is KaTeX, which is served only when a page contains mathematics.
44
@@ -11,7 +11,7 @@ Small and lightweight git server for self hosting. Repositories are served over
1111 - Forks and pull requests from either a branch or a fork. Discussion comments and inline review comments on any line of the diff are Markdown, review threads can be resolved and go to an outdated section when the line leaves the diff, and a request can be closed or reopened or brought up to date from its source at any point
1212 - Three merge strategies, a merge commit with an editable message, a squash authored by the request author, or a rebase that replays each commit onto the target. All three are built from `merge-tree` and `commit-tree` without a working tree and fail cleanly on conflict
1313 - Collaborators per repository who can push, read it when private and merge pull requests, while settings and deletion stay with the owner
14-- A per user disk quota set with `basin quota 2G` and enforced on push over both transports
14+- A per user disk quota set with `gitpocket quota 2G` and enforced on push over both transports
1515 - Signature verification for both SSH and PGP. Register the key in settings, sign commits with it, and they show `Verified ~you`. PGP keys are imported into a server keyring and matched by primary fingerprint, SSH keys through an allowed signers file matched by fingerprint. Keys are public at `~you.keys` and `~you.pgp`
1616 - Issues per repository with Markdown bodies and comments, open and closed states, and an open count in the tab strip
1717 - Stars, so a profile shows what someone found worth keeping, and a star count next to every repository title
@@ -38,18 +38,18 @@ SQLite comes from the modernc port, which is pure Go, so a `CGO_ENABLED=0` build
3838 ## Install
3939
4040 ```
41-CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o basin .
42-useradd -r -m -d /srv/basin -s /bin/sh git
43-install -m 755 basin /usr/local/bin/basin
41+CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o gitpocket .
42+useradd -r -m -d /srv/gitpocket -s /bin/sh git
43+install -m 755 gitpocket /usr/local/bin/gitpocket
4444 ```
4545
4646 ```
4747 [Service]
4848 User=git
49-ExecStart=/usr/local/bin/basin -root /srv/basin serve -listen 127.0.0.1:3200 -host git.example.org
49+ExecStart=/usr/local/bin/gitpocket -root /srv/gitpocket serve -listen 127.0.0.1:3200 -host git.example.org
5050 Restart=always
5151 ProtectSystem=strict
52-ReadWritePaths=/srv/basin
52+ReadWritePaths=/srv/gitpocket
5353 ```
5454
5555 Put a reverse proxy with TLS in front of it. The proxy needs to forward `Host` and `X-Forwarded-Proto`, and it should set `X-Forwarded-For` to the client address rather than appending to it because the rate limiter keys on the first value it finds there. Turn request buffering off and raise the body limit as well, otherwise larger pushes over HTTPS will be cut short.
@@ -58,28 +58,28 @@ Put a reverse proxy with TLS in front of it. The proxy needs to forward `Host` a
5858 Match User git
5959 AuthenticationMethods publickey
6060 AuthorizedKeysFile none
61- AuthorizedKeysCommand /usr/local/bin/basin -root /srv/basin keys %u %h %t %k
61+ AuthorizedKeysCommand /usr/local/bin/gitpocket -root /srv/gitpocket keys %u %h %t %k
6262 AuthorizedKeysCommandUser root
6363 PermitTTY no
6464 DisableForwarding yes
6565 ```
6666
67-The `keys` command runs as root and opens the database read only and answers sshd with a forced command of `basin shell <user>`. That in turn runs as the login user, checks what `SSH_ORIGINAL_COMMAND` is actually asking for against the database, and then execs straight into `git upload-pack` or `git receive-pack` so nothing is left running afterwards.
67+The `keys` command runs as root and opens the database read only and answers sshd with a forced command of `gitpocket shell <user>`. That in turn runs as the login user, checks what `SSH_ORIGINAL_COMMAND` is actually asking for against the database, and then execs straight into `git upload-pack` or `git receive-pack` so nothing is left running afterwards.
6868
6969 ```
70-sudo -u git basin -root /srv/basin invite
70+sudo -u git gitpocket -root /srv/gitpocket invite
7171 ```
7272
73-If you would rather let anyone sign up then `serve -open` skips the invite step entirely. `basin user <name>` creates an account from the command line with the password read from stdin, and `-ssh-user` changes the account name that appears in clone URLs if you did not call yours `git`.
73+If you would rather let anyone sign up then `serve -open` skips the invite step entirely. `gitpocket user <name>` creates an account from the command line with the password read from stdin, and `-ssh-user` changes the account name that appears in clone URLs if you did not call yours `git`.
7474
7575 Mail is configured in `smtp.json` under the root directory and is read once at startup. Plain SMTP takes `host`, `port`, `user`, `password`, `from` and `starttls`, but many VPS providers block every outbound submission port, so `api` and `key` post each message as JSON to a Resend compatible HTTPS endpoint instead.
7676
7777 ```
78-{"api": "https://api.resend.com/emails", "key": "re_...", "from": "basin <noreply@git.example.org>"}
79-sudo -u git basin -root /srv/basin mail you@example.org
78+{"api": "https://api.resend.com/emails", "key": "re_...", "from": "gitpocket <noreply@git.example.org>"}
79+sudo -u git gitpocket -root /srv/gitpocket mail you@example.org
8080 ```
8181
82-`basin feature ~you/a ~you/b` chooses the projects on the logged out front page in that order, `-~you/a` drops one again, and with none chosen the page falls back to the most recently pushed. `basin backup file` writes a consistent copy of the database with `vacuum into`, which is safe to run from a timer while the server is live.
82+`gitpocket feature ~you/a ~you/b` chooses the projects on the logged out front page in that order, `-~you/a` drops one again, and with none chosen the page falls back to the most recently pushed. `gitpocket backup file` writes a consistent copy of the database with `vacuum into`, which is safe to run from a timer while the server is live.
8383
8484 ## Use
8585

edit.go modified

@@ -47,7 +47,7 @@ func hook(root, kind, spec string) int {
4747 return 0
4848 }
4949 name := strings.TrimSuffix(repoDir, ".git")
50- store, err := openStore(filepath.Join(root, "basin.db"), true)
50+ store, err := openStore(filepath.Join(root, "gitpocket.db"), true)
5151 if err != nil {
5252 return 0
5353 }
@@ -74,16 +74,16 @@ func hook(root, kind, spec string) int {
7474 continue
7575 }
7676 if f[1] == zero {
77- fmt.Fprintf(os.Stderr, "basin: %s is protected and cannot be deleted\n", branch)
77+ fmt.Fprintf(os.Stderr, "gitpocket: %s is protected and cannot be deleted\n", branch)
7878 return 1
7979 }
8080 if prot.RequirePR && f[0] != zero {
81- fmt.Fprintf(os.Stderr, "basin: %s only accepts changes through pull requests\n", branch)
81+ fmt.Fprintf(os.Stderr, "gitpocket: %s only accepts changes through pull requests\n", branch)
8282 return 1
8383 }
8484 if f[0] != zero {
8585 if _, err := g.run(nil, "merge-base", "--is-ancestor", f[0], f[1]); err != nil {
86- fmt.Fprintf(os.Stderr, "basin: %s is protected, force pushes are refused\n", branch)
86+ fmt.Fprintf(os.Stderr, "gitpocket: %s is protected, force pushes are refused\n", branch)
8787 return 1
8888 }
8989 }
@@ -92,7 +92,7 @@ func hook(root, kind, spec string) int {
9292 }
9393
9494 func (g Git) Commit1(branch, parent, filePath string, content []byte, remove bool, message, name, email string) (string, error) {
95- index, err := os.CreateTemp("", "basin-index")
95+ index, err := os.CreateTemp("", "gitpocket-index")
9696 if err != nil {
9797 return "", err
9898 }

go.mod modified

@@ -1,4 +1,4 @@
1-module basin
1+module gitpocket
22
33 go 1.27.1
44

main.go modified

@@ -13,9 +13,9 @@ import (
1313 )
1414
1515 func main() {
16- root := flag.String("root", "/srv/basin", "data directory holding basin.db and repos/")
16+ root := flag.String("root", "/srv/gitpocket", "data directory holding gitpocket.db and repos/")
1717 flag.Usage = func() {
18- fmt.Fprintln(os.Stderr, `usage: basin [-root dir] command
18+ fmt.Fprintln(os.Stderr, `usage: gitpocket [-root dir] command
1919
2020 serve [-listen addr] [-host name] [-open] [-ssh-user name] run the web server
2121 keys user home type key sshd AuthorizedKeysCommand
@@ -110,7 +110,7 @@ func main() {
110110 if len(args) != 2 {
111111 os.Exit(2)
112112 }
113- if err := loadMailer(*root).Send(args[1], "test message from basin", "Mail delivery from this forge works.\n"); err != nil {
113+ if err := loadMailer(*root).Send(args[1], "test message from gitpocket", "Mail delivery from this forge works.\n"); err != nil {
114114 log.Fatal(err)
115115 }
116116 fmt.Println("sent")
@@ -162,7 +162,7 @@ func mustStore(root string) *Store {
162162 if err := os.MkdirAll(filepath.Join(root, "repos"), 0o755); err != nil {
163163 log.Fatal(err)
164164 }
165- store, err := openStore(filepath.Join(root, "basin.db"), false)
165+ store, err := openStore(filepath.Join(root, "gitpocket.db"), false)
166166 if err != nil {
167167 log.Fatal(err)
168168 }
@@ -182,6 +182,6 @@ func serve(root string, args []string) {
182182 Handler: newServer(store, root, *host, *open, *sshUser).handler(),
183183 ReadHeaderTimeout: 10 * time.Second,
184184 }
185- log.Printf("basin listening on %s for %s", *listen, *host)
185+ log.Printf("gitpocket listening on %s for %s", *listen, *host)
186186 log.Fatal(srv.ListenAndServe())
187187 }

shell.go modified

@@ -13,7 +13,7 @@ func keys(root, binary string, args []string) int {
1313 if len(args) != 4 {
1414 return 1
1515 }
16- store, err := openStore(filepath.Join(root, "basin.db"), true)
16+ store, err := openStore(filepath.Join(root, "gitpocket.db"), true)
1717 if err != nil {
1818 return 1
1919 }
@@ -50,7 +50,7 @@ func shell(root, name string) int {
5050 if !ok || !validName(owner) || !validName(repoName) {
5151 return fail("repository path must be ~owner/repo")
5252 }
53- store, err := openStore(filepath.Join(root, "basin.db"), true)
53+ store, err := openStore(filepath.Join(root, "gitpocket.db"), true)
5454 if err != nil {
5555 return fail("database unavailable")
5656 }

templates/reset.html modified

@@ -8,6 +8,6 @@
88 <label>Username or email <input name="who" required autofocus></label>
99 <div class="actions"><button class="btn primary">Send reset link ▸</button></div>
1010 </form>
11-{{else}}<p>This server has no outgoing mail configured, so passwords are reset by the administrator with <code>basin passwd</code>.</p>{{end}}
11+{{else}}<p>This server has no outgoing mail configured, so passwords are reset by the administrator with <code>gitpocket passwd</code>.</p>{{end}}
1212 </div>
1313 {{end}}

web.go modified

@@ -408,7 +408,7 @@ func (s *Server) writeKeyring() {
408408
409409 func pgpFingerprint(armored string) (string, error) {
410410 cmd := exec.Command("gpg", "--batch", "--with-colons", "--import-options", "show-only", "--import")
411- dir, err := os.MkdirTemp("", "basin-gpg")
411+ dir, err := os.MkdirTemp("", "gitpocket-gpg")
412412 if err != nil {
413413 return "", err
414414 }