Commit 24c0aad9bf

24c0aad9bf75f925497b0f6de2c8e831e67eaac9

parent: f6cb7d04f1

Verified · cmc

cmc <hello@cleberg.net> · 2026-08-24 00:14 UTC

rename: forge -> gitbay (gitbay.org)

- module path gitbay.org/gitbay; binaries gitbay and gitbayd
- config: /etc/gitbay/config.toml, /var/lib/gitbay, ~/.config/gitbay,
  gitbay.db, gitbay_session cookie, GITBAY_* hook/import env vars
- user-facing strings, usage text, ssh banner, test hostnames renamed;
  generic 'a code forge' prose kept where it means the category
- all tests updated and green

Layout: unified · split

.gitignore +2 −2
@@ -1,3 +1,3 @@
1/forge 1/gitbay
2/forged 2/gitbayd
3*.db 3*.db
cmd/forge/local.go → cmd/gitbay/local.go renamed +18 −18
@@ -9,8 +9,8 @@ import (
9 9
10 "golang.org/x/term" 10 "golang.org/x/term"
11 11
12 "github.com/krazywarez/forge/internal/cliconfig" 12 "gitbay.org/gitbay/internal/cliconfig"
13 "github.com/krazywarez/forge/internal/protocol" 13 "gitbay.org/gitbay/internal/protocol"
14) 14)
15 15
16// hasBodyFlag reports whether args already carry body/message input. 16// hasBodyFlag reports whether args already carry body/message input.
@@ -37,7 +37,7 @@ func maybeEditor(args []string, kind string) ([]string, *strings.Reader, bool, e
37 // failing — bodies are optional everywhere. 37 // failing — bodies are optional everywhere.
38 return args, nil, true, nil 38 return args, nil, true, nil
39 } 39 }
40 f, err := os.CreateTemp("", "forge-"+kind+"-*.md") 40 f, err := os.CreateTemp("", "gitbay-"+kind+"-*.md")
41 if err != nil { 41 if err != nil {
42 return nil, nil, false, err 42 return nil, nil, false, err
43 } 43 }
@@ -75,7 +75,7 @@ func runGitLocal(args ...string) int {
75 if ee, ok := err.(*exec.ExitError); ok { 75 if ee, ok := err.(*exec.ExitError); ok {
76 return ee.ExitCode() 76 return ee.ExitCode()
77 } 77 }
78 fmt.Fprintln(os.Stderr, "forge:", err) 78 fmt.Fprintln(os.Stderr, "gitbay:", err)
79 return protocol.ExitFailure 79 return protocol.ExitFailure
80 } 80 }
81 return 0 81 return 0
@@ -84,12 +84,12 @@ func runGitLocal(args ...string) int {
84// cmdRepoClone implements `forge repo clone <owner/name> [dir]`. 84// cmdRepoClone implements `forge repo clone <owner/name> [dir]`.
85func cmdRepoClone(args []string) int { 85func cmdRepoClone(args []string) int {
86 if len(args) < 1 || strings.HasPrefix(args[0], "-") { 86 if len(args) < 1 || strings.HasPrefix(args[0], "-") {
87 fmt.Fprintln(os.Stderr, "usage: forge repo clone <owner/name> [dir]") 87 fmt.Fprintln(os.Stderr, "usage: gitbay repo clone <owner/name> [dir]")
88 return protocol.ExitUsage 88 return protocol.ExitUsage
89 } 89 }
90 t, err := resolveTarget() 90 t, err := resolveTarget()
91 if err != nil { 91 if err != nil {
92 fmt.Fprintln(os.Stderr, "forge:", err) 92 fmt.Fprintln(os.Stderr, "gitbay:", err)
93 return protocol.ExitFailure 93 return protocol.ExitFailure
94 } 94 }
95 gitArgs := append([]string{"clone", t.inst.CloneURL(args[0])}, args[1:]...) 95 gitArgs := append([]string{"clone", t.inst.CloneURL(args[0])}, args[1:]...)
@@ -103,7 +103,7 @@ func cmdRepoClone(args []string) int {
103// origin and check it out as a local branch. 103// origin and check it out as a local branch.
104func cmdMRCheckout(args []string) int { 104func cmdMRCheckout(args []string) int {
105 if len(args) != 1 { 105 if len(args) != 1 {
106 fmt.Fprintln(os.Stderr, "usage: forge mr checkout <n>") 106 fmt.Fprintln(os.Stderr, "usage: gitbay mr checkout <n>")
107 return protocol.ExitUsage 107 return protocol.ExitUsage
108 } 108 }
109 n := args[0] 109 n := args[0]
@@ -124,7 +124,7 @@ func cmdInit(args []string) int {
124 case a == "--private": 124 case a == "--private":
125 private = true 125 private = true
126 case strings.HasPrefix(a, "-"): 126 case strings.HasPrefix(a, "-"):
127 fmt.Fprintln(os.Stderr, "usage: forge init [name] [--private]") 127 fmt.Fprintln(os.Stderr, "usage: gitbay init [name] [--private]")
128 return protocol.ExitUsage 128 return protocol.ExitUsage
129 default: 129 default:
130 name = a 130 name = a
@@ -133,7 +133,7 @@ func cmdInit(args []string) int {
133 if name == "" { 133 if name == "" {
134 wd, err := os.Getwd() 134 wd, err := os.Getwd()
135 if err != nil { 135 if err != nil {
136 fmt.Fprintln(os.Stderr, "forge:", err) 136 fmt.Fprintln(os.Stderr, "gitbay:", err)
137 return protocol.ExitFailure 137 return protocol.ExitFailure
138 } 138 }
139 name = filepath.Base(wd) 139 name = filepath.Base(wd)
@@ -141,12 +141,12 @@ func cmdInit(args []string) int {
141 141
142 cfg, err := cliconfig.Load() 142 cfg, err := cliconfig.Load()
143 if err != nil { 143 if err != nil {
144 fmt.Fprintln(os.Stderr, "forge:", err) 144 fmt.Fprintln(os.Stderr, "gitbay:", err)
145 return protocol.ExitFailure 145 return protocol.ExitFailure
146 } 146 }
147 inst, _, err := cfg.DefaultInstance() 147 inst, _, err := cfg.DefaultInstance()
148 if err != nil { 148 if err != nil {
149 fmt.Fprintln(os.Stderr, "forge:", err) 149 fmt.Fprintln(os.Stderr, "gitbay:", err)
150 return protocol.ExitFailure 150 return protocol.ExitFailure
151 } 151 }
152 t := target{inst: inst} 152 t := target{inst: inst}
@@ -196,7 +196,7 @@ func captureSSH(t target, serverArgv []string) (string, int) {
196 if ee, ok := err.(*exec.ExitError); ok { 196 if ee, ok := err.(*exec.ExitError); ok {
197 return "", ee.ExitCode() 197 return "", ee.ExitCode()
198 } 198 }
199 fmt.Fprintln(os.Stderr, "forge: running ssh:", err) 199 fmt.Fprintln(os.Stderr, "gitbay: running ssh:", err)
200 return "", protocol.ExitProtocol 200 return "", protocol.ExitProtocol
201 } 201 }
202 return string(out), 0 202 return string(out), 0
@@ -210,7 +210,7 @@ func quoteAll(args []string) []string {
210 return out 210 return out
211} 211}
212 212
213// cmdRemoteAdd implements `forge remote add <name> <host> [flags]`. 213// cmdRemoteAdd implements `gitbay remote add <name> <host> [flags]`.
214func cmdRemoteAdd(args []string) int { 214func cmdRemoteAdd(args []string) int {
215 var name, host, user string 215 var name, host, user string
216 var port int 216 var port int
@@ -250,19 +250,19 @@ func cmdRemoteAdd(args []string) int {
250 } else if host == "" { 250 } else if host == "" {
251 host = a 251 host = a
252 } else { 252 } else {
253 fmt.Fprintln(os.Stderr, "usage: forge remote add <name> <host> [--port n] [--user u] [--ssh-option opt]... [--default]") 253 fmt.Fprintln(os.Stderr, "usage: gitbay remote add <name> <host> [--port n] [--user u] [--ssh-option opt]... [--default]")
254 return protocol.ExitUsage 254 return protocol.ExitUsage
255 } 255 }
256 i++ 256 i++
257 } 257 }
258 } 258 }
259 if name == "" || host == "" { 259 if name == "" || host == "" {
260 fmt.Fprintln(os.Stderr, "usage: forge remote add <name> <host> [--port n] [--user u] [--ssh-option opt]... [--default]") 260 fmt.Fprintln(os.Stderr, "usage: gitbay remote add <name> <host> [--port n] [--user u] [--ssh-option opt]... [--default]")
261 return protocol.ExitUsage 261 return protocol.ExitUsage
262 } 262 }
263 cfg, err := cliconfig.Load() 263 cfg, err := cliconfig.Load()
264 if err != nil { 264 if err != nil {
265 fmt.Fprintln(os.Stderr, "forge:", err) 265 fmt.Fprintln(os.Stderr, "gitbay:", err)
266 return protocol.ExitFailure 266 return protocol.ExitFailure
267 } 267 }
268 cfg.Instances[name] = cliconfig.Instance{Host: host, Port: port, User: user, SSHOptions: sshOptions} 268 cfg.Instances[name] = cliconfig.Instance{Host: host, Port: port, User: user, SSHOptions: sshOptions}
@@ -270,7 +270,7 @@ func cmdRemoteAdd(args []string) int {
270 cfg.Default = name 270 cfg.Default = name
271 } 271 }
272 if err := cliconfig.Save(cfg); err != nil { 272 if err := cliconfig.Save(cfg); err != nil {
273 fmt.Fprintln(os.Stderr, "forge:", err) 273 fmt.Fprintln(os.Stderr, "gitbay:", err)
274 return protocol.ExitFailure 274 return protocol.ExitFailure
275 } 275 }
276 fmt.Printf("added instance %s (%s)\n", name, host) 276 fmt.Printf("added instance %s (%s)\n", name, host)
@@ -280,7 +280,7 @@ func cmdRemoteAdd(args []string) int {
280func cmdRemoteList() int { 280func cmdRemoteList() int {
281 cfg, err := cliconfig.Load() 281 cfg, err := cliconfig.Load()
282 if err != nil { 282 if err != nil {
283 fmt.Fprintln(os.Stderr, "forge:", err) 283 fmt.Fprintln(os.Stderr, "gitbay:", err)
284 return protocol.ExitFailure 284 return protocol.ExitFailure
285 } 285 }
286 for name, inst := range cfg.Instances { 286 for name, inst := range cfg.Instances {
cmd/forge/main.go → cmd/gitbay/main.go renamed +12 −12
@@ -13,12 +13,12 @@ import (
13 "github.com/spf13/cobra" 13 "github.com/spf13/cobra"
14 "github.com/spf13/cobra/doc" 14 "github.com/spf13/cobra/doc"
15 15
16 "github.com/krazywarez/forge/internal/protocol" 16 "gitbay.org/gitbay/internal/protocol"
17) 17)
18 18
19func main() { 19func main() {
20 root := &cobra.Command{ 20 root := &cobra.Command{
21 Use: "forge", 21 Use: "gitbay",
22 Short: "CLI-first git forge client", 22 Short: "CLI-first git forge client",
23 SilenceUsage: true, 23 SilenceUsage: true,
24 SilenceErrors: true, 24 SilenceErrors: true,
@@ -36,7 +36,7 @@ func main() {
36 ) 36 )
37 37
38 if err := root.Execute(); err != nil { 38 if err := root.Execute(); err != nil {
39 fmt.Fprintln(os.Stderr, "forge:", err) 39 fmt.Fprintln(os.Stderr, "gitbay:", err)
40 os.Exit(protocol.ExitUsage) 40 os.Exit(protocol.ExitUsage)
41 } 41 }
42} 42}
@@ -72,13 +72,13 @@ func pass(use, short string, o passOpts) *cobra.Command {
72func runPass(o passOpts, args []string) int { 72func runPass(o passOpts, args []string) int {
73 t, err := resolveTarget() 73 t, err := resolveTarget()
74 if err != nil { 74 if err != nil {
75 fmt.Fprintln(os.Stderr, "forge:", err) 75 fmt.Fprintln(os.Stderr, "gitbay:", err)
76 return protocol.ExitFailure 76 return protocol.ExitFailure
77 } 77 }
78 if o.needsRepo { 78 if o.needsRepo {
79 args, err = withRepo(t, args) 79 args, err = withRepo(t, args)
80 if err != nil { 80 if err != nil {
81 fmt.Fprintln(os.Stderr, "forge:", err) 81 fmt.Fprintln(os.Stderr, "gitbay:", err)
82 return protocol.ExitUsage 82 return protocol.ExitUsage
83 } 83 }
84 } 84 }
@@ -87,7 +87,7 @@ func runPass(o passOpts, args []string) int {
87 if o.editor != "" { 87 if o.editor != "" {
88 extended, body, ok, err := maybeEditor(args, o.editor) 88 extended, body, ok, err := maybeEditor(args, o.editor)
89 if err != nil { 89 if err != nil {
90 fmt.Fprintln(os.Stderr, "forge:", err) 90 fmt.Fprintln(os.Stderr, "gitbay:", err)
91 return protocol.ExitFailure 91 return protocol.ExitFailure
92 } 92 }
93 if !ok { 93 if !ok {
@@ -186,14 +186,14 @@ func authCmd() *cobra.Command {
186 186
187func repoCmd() *cobra.Command { 187func repoCmd() *cobra.Command {
188 return group("repo", "create and manage repositories", 188 return group("repo", "create and manage repositories",
189 pass("create", "create a repository: forge repo create <owner/name> [--private]", 189 pass("create", "create a repository: gitbay repo create <owner/name> [--private]",
190 passOpts{server: []string{"repo", "create"}}), 190 passOpts{server: []string{"repo", "create"}}),
191 pass("list", "list repositories you own or can access", passOpts{server: []string{"repo", "list"}}), 191 pass("list", "list repositories you own or can access", passOpts{server: []string{"repo", "list"}}),
192 pass("show", "show repository details", passOpts{server: []string{"repo", "show"}, needsRepo: true}), 192 pass("show", "show repository details", passOpts{server: []string{"repo", "show"}, needsRepo: true}),
193 pass("log", "commit log with signature states", passOpts{server: []string{"repo", "log"}, needsRepo: true}), 193 pass("log", "commit log with signature states", passOpts{server: []string{"repo", "log"}, needsRepo: true}),
194 pass("delete", "delete a repository (--yes)", passOpts{server: []string{"repo", "delete"}, needsRepo: true}), 194 pass("delete", "delete a repository (--yes)", passOpts{server: []string{"repo", "delete"}, needsRepo: true}),
195 pass("fork", "fork a repository under your account", passOpts{server: []string{"repo", "fork"}, needsRepo: true}), 195 pass("fork", "fork a repository under your account", passOpts{server: []string{"repo", "fork"}, needsRepo: true}),
196 local("clone", "clone via ssh: forge repo clone <owner/name> [dir]", cmdRepoClone), 196 local("clone", "clone via ssh: gitbay repo clone <owner/name> [dir]", cmdRepoClone),
197 importCmd(), 197 importCmd(),
198 group("access", "manage access grants", 198 group("access", "manage access grants",
199 pass("grant", "grant access: ... <user> read|write|admin", passOpts{server: []string{"repo", "access", "grant"}, needsRepo: true}), 199 pass("grant", "grant access: ... <user> read|write|admin", passOpts{server: []string{"repo", "access", "grant"}, needsRepo: true}),
@@ -232,7 +232,7 @@ func mrCmd() *cobra.Command {
232 pass("list", "list merge requests [--state ...]", passOpts{server: []string{"mr", "list"}, needsRepo: true}), 232 pass("list", "list merge requests [--state ...]", passOpts{server: []string{"mr", "list"}, needsRepo: true}),
233 pass("show", "show a merge request", passOpts{server: []string{"mr", "show"}, needsRepo: true}), 233 pass("show", "show a merge request", passOpts{server: []string{"mr", "show"}, needsRepo: true}),
234 pass("diff", "show the diff", passOpts{server: []string{"mr", "diff"}, needsRepo: true}), 234 pass("diff", "show the diff", passOpts{server: []string{"mr", "diff"}, needsRepo: true}),
235 local("checkout", "fetch and check out the MR head locally: forge mr checkout <n>", cmdMRCheckout), 235 local("checkout", "fetch and check out the MR head locally: gitbay mr checkout <n>", cmdMRCheckout),
236 pass("comment", "comment on a merge request", passOpts{server: []string{"mr", "comment"}, needsRepo: true, stdinOK: true, editor: "comment"}), 236 pass("comment", "comment on a merge request", passOpts{server: []string{"mr", "comment"}, needsRepo: true, stdinOK: true, editor: "comment"}),
237 pass("review", "review: --approve|--request-changes|--comment", passOpts{server: []string{"mr", "review"}, needsRepo: true}), 237 pass("review", "review: --approve|--request-changes|--comment", passOpts{server: []string{"mr", "review"}, needsRepo: true}),
238 pass("merge", "merge (fast-forward or merge-commit): [--strategy ff|merge]", passOpts{server: []string{"mr", "merge"}, needsRepo: true}), 238 pass("merge", "merge (fast-forward or merge-commit): [--strategy ff|merge]", passOpts{server: []string{"mr", "merge"}, needsRepo: true}),
@@ -244,7 +244,7 @@ func mrCmd() *cobra.Command {
244func importCmd() *cobra.Command { 244func importCmd() *cobra.Command {
245 return &cobra.Command{ 245 return &cobra.Command{
246 Use: "import", 246 Use: "import",
247 Short: "server-side mirror of a foreign repo: forge repo import <owner/name> --from <url> [--private] [--token-stdin]", 247 Short: "server-side mirror of a foreign repo: gitbay repo import <owner/name> --from <url> [--private] [--token-stdin]",
248 DisableFlagParsing: true, 248 DisableFlagParsing: true,
249 RunE: func(cmd *cobra.Command, args []string) error { 249 RunE: func(cmd *cobra.Command, args []string) error {
250 for _, a := range args { 250 for _, a := range args {
@@ -283,14 +283,14 @@ func webCmd() *cobra.Command {
283 283
284func remoteCmd() *cobra.Command { 284func remoteCmd() *cobra.Command {
285 return group("remote", "local instance profiles (no server contact)", 285 return group("remote", "local instance profiles (no server contact)",
286 local("add", "add a named forge instance: forge remote add <name> <host> [--port n] [--user u] [--ssh-option o]... [--default]", 286 local("add", "add a named gitbay instance: gitbay remote add <name> <host> [--port n] [--user u] [--ssh-option o]... [--default]",
287 cmdRemoteAdd), 287 cmdRemoteAdd),
288 local("list", "list configured instances", func([]string) int { return cmdRemoteList() }), 288 local("list", "list configured instances", func([]string) int { return cmdRemoteList() }),
289 ) 289 )
290} 290}
291 291
292func initCmd() *cobra.Command { 292func initCmd() *cobra.Command {
293 return local("init", "git init + repo create + set origin, in one step: forge init [name] [--private]", cmdInit) 293 return local("init", "git init + repo create + set origin, in one step: gitbay init [name] [--private]", cmdInit)
294} 294}
295 295
296// manCmd generates man pages; a CLI-first tool without man pages is not 296// manCmd generates man pages; a CLI-first tool without man pages is not
cmd/forge/ssh.go → cmd/gitbay/ssh.go renamed +4 −4
@@ -9,8 +9,8 @@ import (
9 "strconv" 9 "strconv"
10 "strings" 10 "strings"
11 11
12 "github.com/krazywarez/forge/internal/cliconfig" 12 "gitbay.org/gitbay/internal/cliconfig"
13 "github.com/krazywarez/forge/internal/protocol" 13 "gitbay.org/gitbay/internal/protocol"
14) 14)
15 15
16// context is the resolved target for a command: which instance to talk to 16// context is the resolved target for a command: which instance to talk to
@@ -105,7 +105,7 @@ func runSSH(t target, serverArgv []string, stdin io.Reader) int {
105 } 105 }
106 return code 106 return code
107 } 107 }
108 fmt.Fprintln(os.Stderr, "forge: running ssh:", err) 108 fmt.Fprintln(os.Stderr, "gitbay: running ssh:", err)
109 return protocol.ExitProtocol 109 return protocol.ExitProtocol
110} 110}
111 111
@@ -117,7 +117,7 @@ func withRepo(t target, args []string) ([]string, error) {
117 return args, nil // explicit owner/name 117 return args, nil // explicit owner/name
118 } 118 }
119 if t.repo == "" { 119 if t.repo == "" {
120 return nil, fmt.Errorf("no repository given and none inferable: pass <owner/name> or run inside a clone of a forge repository") 120 return nil, fmt.Errorf("no repository given and none inferable: pass <owner/name> or run inside a clone of a gitbay repository")
121 } 121 }
122 return append([]string{t.repo}, args...), nil 122 return append([]string{t.repo}, args...), nil
123} 123}
cmd/forged/hook.go → cmd/gitbayd/hook.go renamed +5 −5
@@ -10,9 +10,9 @@ import (
10 10
11 "github.com/spf13/cobra" 11 "github.com/spf13/cobra"
12 12
13 "github.com/krazywarez/forge/internal/gitutil" 13 "gitbay.org/gitbay/internal/gitutil"
14 "github.com/krazywarez/forge/internal/hookd" 14 "gitbay.org/gitbay/internal/hookd"
15 "github.com/krazywarez/forge/internal/policy" 15 "gitbay.org/gitbay/internal/policy"
16) 16)
17 17
18// collectIncomingCommits lists the commits this push introduces and reads 18// collectIncomingCommits lists the commits this push introduces and reads
@@ -58,7 +58,7 @@ func hookCmd() *cobra.Command {
58 repoID, err1 := strconv.ParseInt(os.Getenv(hookd.EnvRepoID), 10, 64) 58 repoID, err1 := strconv.ParseInt(os.Getenv(hookd.EnvRepoID), 10, 64)
59 userID, err2 := strconv.ParseInt(os.Getenv(hookd.EnvUserID), 10, 64) 59 userID, err2 := strconv.ParseInt(os.Getenv(hookd.EnvUserID), 10, 64)
60 if sock == "" || err1 != nil || err2 != nil { 60 if sock == "" || err1 != nil || err2 != nil {
61 return fmt.Errorf("missing FORGE_* environment; this command only runs as a git hook") 61 return fmt.Errorf("missing GITBAY_* environment; this command only runs as a git hook")
62 } 62 }
63 63
64 var updates []policy.RefUpdate 64 var updates []policy.RefUpdate
@@ -92,7 +92,7 @@ func hookCmd() *cobra.Command {
92 return collectIncomingCommits(updates) 92 return collectIncomingCommits(updates)
93 }) 93 })
94 if err != nil { 94 if err != nil {
95 return fmt.Errorf("forge daemon unreachable: %w", err) 95 return fmt.Errorf("gitbay daemon unreachable: %w", err)
96 } 96 }
97 if !resp.Allow { 97 if !resp.Allow {
98 fmt.Fprintln(os.Stderr, resp.Message) 98 fmt.Fprintln(os.Stderr, resp.Message)
cmd/forged/main.go → cmd/gitbayd/main.go renamed +15 −15
@@ -1,4 +1,4 @@
1// forged is the forge server daemon. The same binary also runs in hook mode 1// gitbayd is the forge server daemon. The same binary also runs in hook mode
2// (invoked by git via core.hooksPath) and hosts the host-local admin commands. 2// (invoked by git via core.hooksPath) and hosts the host-local admin commands.
3package main 3package main
4 4
@@ -14,18 +14,18 @@ import (
14 "github.com/spf13/cobra" 14 "github.com/spf13/cobra"
15 "golang.org/x/crypto/ssh" 15 "golang.org/x/crypto/ssh"
16 16
17 "github.com/krazywarez/forge/internal/config" 17 "gitbay.org/gitbay/internal/config"
18 "github.com/krazywarez/forge/internal/control" 18 "gitbay.org/gitbay/internal/control"
19 "github.com/krazywarez/forge/internal/gitd" 19 "gitbay.org/gitbay/internal/gitd"
20 "github.com/krazywarez/forge/internal/hookd" 20 "gitbay.org/gitbay/internal/hookd"
21 "github.com/krazywarez/forge/internal/httpd" 21 "gitbay.org/gitbay/internal/httpd"
22 "github.com/krazywarez/forge/internal/policy" 22 "gitbay.org/gitbay/internal/policy"
23 "github.com/krazywarez/forge/internal/sshd" 23 "gitbay.org/gitbay/internal/sshd"
24 "github.com/krazywarez/forge/internal/store" 24 "gitbay.org/gitbay/internal/store"
25) 25)
26 26
27func openStore(cfg config.Config) (*store.Store, error) { 27func openStore(cfg config.Config) (*store.Store, error) {
28 s, err := store.Open(filepath.Join(cfg.Server.Root, "forge.db")) 28 s, err := store.Open(filepath.Join(cfg.Server.Root, "gitbay.db"))
29 if err != nil { 29 if err != nil {
30 return nil, err 30 return nil, err
31 } 31 }
@@ -40,12 +40,12 @@ var configPath string
40 40
41func main() { 41func main() {
42 root := &cobra.Command{ 42 root := &cobra.Command{
43 Use: "forged", 43 Use: "gitbayd",
44 Short: "forge server daemon", 44 Short: "gitbay server daemon",
45 SilenceUsage: true, 45 SilenceUsage: true,
46 SilenceErrors: true, 46 SilenceErrors: true,
47 } 47 }
48 root.PersistentFlags().StringVar(&configPath, "config", "/etc/forge/config.toml", "path to config file") 48 root.PersistentFlags().StringVar(&configPath, "config", "/etc/gitbay/config.toml", "path to config file")
49 49
50 root.AddCommand( 50 root.AddCommand(
51 checkConfigCmd(), 51 checkConfigCmd(),
@@ -58,7 +58,7 @@ func main() {
58 ) 58 )
59 59
60 if err := root.Execute(); err != nil { 60 if err := root.Execute(); err != nil {
61 fmt.Fprintln(os.Stderr, "forged:", err) 61 fmt.Fprintln(os.Stderr, "gitbayd:", err)
62 os.Exit(1) 62 os.Exit(1)
63 } 63 }
64} 64}
@@ -173,7 +173,7 @@ func migrateCmd() *cobra.Command {
173 if err != nil { 173 if err != nil {
174 return err 174 return err
175 } 175 }
176 s, err := store.Open(cfg.Server.Root + "/forge.db") 176 s, err := store.Open(cfg.Server.Root + "/gitbay.db")
177 if err != nil { 177 if err != nil {
178 return err 178 return err
179 } 179 }
cmd/forged/system.go → cmd/gitbayd/system.go renamed +5 −5
@@ -7,14 +7,14 @@ import (
7 "github.com/spf13/cobra" 7 "github.com/spf13/cobra"
8 "golang.org/x/crypto/ssh" 8 "golang.org/x/crypto/ssh"
9 9
10 "github.com/krazywarez/forge/internal/config" 10 "gitbay.org/gitbay/internal/config"
11 "github.com/krazywarez/forge/internal/protocol" 11 "gitbay.org/gitbay/internal/protocol"
12 "github.com/krazywarez/forge/internal/sshd" 12 "gitbay.org/gitbay/internal/sshd"
13) 13)
14 14
15// authorizedKeysCmd backs sshd's AuthorizedKeysCommand in system mode: 15// authorizedKeysCmd backs sshd's AuthorizedKeysCommand in system mode:
16// 16//
17// AuthorizedKeysCommand /usr/bin/forged --config /etc/forge/config.toml authorized-keys %t %k 17// AuthorizedKeysCommand /usr/bin/gitbayd --config /etc/gitbay/config.toml authorized-keys %t %k
18// AuthorizedKeysCommandUser git 18// AuthorizedKeysCommandUser git
19// 19//
20// It prints a forced-command authorized_keys line for registered keys and 20// It prints a forced-command authorized_keys line for registered keys and
@@ -90,7 +90,7 @@ func shellCmd() *cobra.Command {
90 90
91 cmdline := os.Getenv("SSH_ORIGINAL_COMMAND") 91 cmdline := os.Getenv("SSH_ORIGINAL_COMMAND")
92 if cmdline == "" { 92 if cmdline == "" {
93 fmt.Fprintf(os.Stderr, "forge control plane: interactive shells are not available.\nTry: ssh <host> help\n") 93 fmt.Fprintf(os.Stderr, "gitbay control plane: interactive shells are not available.\nTry: ssh <host> help\n")
94 os.Exit(protocol.ExitUsage) 94 os.Exit(protocol.ExitUsage)
95 } 95 }
96 code := sshd.Exec(cfg, st, user, key.Scope, cmdline, os.Stdin, os.Stdout, os.Stderr) 96 code := sshd.Exec(cfg, st, user, key.Scope, cmdline, os.Stdin, os.Stdout, os.Stderr)
e2e/cli_test.go +7 −7
@@ -10,13 +10,13 @@ import (
10 "testing" 10 "testing"
11) 11)
12 12
13func buildForgeCLI(t *testing.T) string { 13func buildGitbayCLI(t *testing.T) string {
14 t.Helper() 14 t.Helper()
15 bin := filepath.Join(t.TempDir(), "forge") 15 bin := filepath.Join(t.TempDir(), "gitbay")
16 cmd := exec.Command("go", "build", "-o", bin, "github.com/krazywarez/forge/cmd/forge") 16 cmd := exec.Command("go", "build", "-o", bin, "gitbay.org/gitbay/cmd/gitbay")
17 cmd.Dir = ".." 17 cmd.Dir = ".."
18 if out, err := cmd.CombinedOutput(); err != nil { 18 if out, err := cmd.CombinedOutput(); err != nil {
19 t.Fatalf("build forge: %v\n%s", err, out) 19 t.Fatalf("build gitbay: %v\n%s", err, out)
20 } 20 }
21 return bin 21 return bin
22} 22}
@@ -51,7 +51,7 @@ func (c *cli) run(t *testing.T, dir, stdin string, args ...string) (string, stri
51 if ee, ok := err.(*exec.ExitError); ok { 51 if ee, ok := err.(*exec.ExitError); ok {
52 code = ee.ExitCode() 52 code = ee.ExitCode()
53 } else if err != nil { 53 } else if err != nil {
54 t.Fatalf("forge %v: %v", args, err) 54 t.Fatalf("gitbay %v: %v", args, err)
55 } 55 }
56 return out.String(), errOut.String(), code 56 return out.String(), errOut.String(), code
57} 57}
@@ -60,7 +60,7 @@ func (c *cli) must(t *testing.T, dir, stdin string, args ...string) string {
60 t.Helper() 60 t.Helper()
61 out, errOut, code := c.run(t, dir, stdin, args...) 61 out, errOut, code := c.run(t, dir, stdin, args...)
62 if code != 0 { 62 if code != 0 {
63 t.Fatalf("forge %v: exit %d\nstdout: %s\nstderr: %s", args, code, out, errOut) 63 t.Fatalf("gitbay %v: exit %d\nstdout: %s\nstderr: %s", args, code, out, errOut)
64 } 64 }
65 return out 65 return out
66} 66}
@@ -72,7 +72,7 @@ func TestCLI(t *testing.T) {
72 "--key", aliceKey+".pub", "--email", "alice@example.test", "--verified") 72 "--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
73 73
74 c := &cli{ 74 c := &cli{
75 bin: buildForgeCLI(t), 75 bin: buildGitbayCLI(t),
76 configDir: t.TempDir(), 76 configDir: t.TempDir(),
77 inst: inst, 77 inst: inst,
78 key: aliceKey, 78 key: aliceKey,
e2e/http_test.go +1 −1
@@ -90,7 +90,7 @@ func TestHTTPTransport(t *testing.T) {
90 } 90 }
91 if !strings.Contains(out, "remote error:") || 91 if !strings.Contains(out, "remote error:") ||
92 !strings.Contains(out, "pushes to this forge go over SSH") || 92 !strings.Contains(out, "pushes to this forge go over SSH") ||
93 !strings.Contains(out, "git@forge.test:alice/pub.git") { 93 !strings.Contains(out, "git@gitbay.test:alice/pub.git") {
94 t.Fatalf("[%s] push refusal output:\n%s", gitBin, out) 94 t.Fatalf("[%s] push refusal output:\n%s", gitBin, out)
95 } 95 }
96 for _, banned := range []string{"Username", "Password", "Authentication failed", "terminal prompts disabled", "401", "403"} { 96 for _, banned := range []string{"Username", "Password", "Authentication failed", "terminal prompts disabled", "401", "403"} {
e2e/mr_test.go +1 −1
@@ -9,7 +9,7 @@ import (
9 9
10 "golang.org/x/crypto/ssh" 10 "golang.org/x/crypto/ssh"
11 11
12 "github.com/krazywarez/forge/internal/sig" 12 "gitbay.org/gitbay/internal/sig"
13) 13)
14 14
15type mrShow struct { 15type mrShow struct {
e2e/sig_test.go +2 −2
@@ -16,7 +16,7 @@ import (
16 "github.com/ProtonMail/go-crypto/openpgp/packet" 16 "github.com/ProtonMail/go-crypto/openpgp/packet"
17 "golang.org/x/crypto/ssh" 17 "golang.org/x/crypto/ssh"
18 18
19 "github.com/krazywarez/forge/internal/sig" 19 "gitbay.org/gitbay/internal/sig"
20) 20)
21 21
22// --- fixture key helpers ------------------------------------------------- 22// --- fixture key helpers -------------------------------------------------
@@ -361,7 +361,7 @@ func TestSignatureVerification(t *testing.T) {
361 vc.Dir = dir 361 vc.Dir = dir
362 vc.Env = gpgEnv 362 vc.Env = gpgEnv
363 if out, err := vc.CombinedOutput(); err != nil { 363 if out, err := vc.CombinedOutput(); err != nil {
364 t.Errorf("git verify-commit disagrees with forge verification: %v\n%s", err, out) 364 t.Errorf("git verify-commit disagrees with gitbay verification: %v\n%s", err, out)
365 } 365 }
366 } else { 366 } else {
367 t.Log("gpg not installed; skipping git verify-commit cross-check") 367 t.Log("gpg not installed; skipping git verify-commit cross-check")
e2e/ssh_test.go +13 −13
@@ -1,4 +1,4 @@
1// Package e2e drives a real forged with the real ssh and git clients. 1// Package e2e drives a real gitbayd with the real ssh and git clients.
2package e2e 2package e2e
3 3
4import ( 4import (
@@ -14,7 +14,7 @@ import (
14) 14)
15 15
16type instance struct { 16type instance struct {
17 forged string // path to built binary 17 gitbayd string // path to built binary
18 root string 18 root string
19 config string 19 config string
20 port int 20 port int
@@ -24,13 +24,13 @@ type instance struct {
24 sshDir string // per-user client keys live here 24 sshDir string // per-user client keys live here
25} 25}
26 26
27func buildForged(t *testing.T) string { 27func buildGitbayd(t *testing.T) string {
28 t.Helper() 28 t.Helper()
29 bin := filepath.Join(t.TempDir(), "forged") 29 bin := filepath.Join(t.TempDir(), "gitbayd")
30 cmd := exec.Command("go", "build", "-o", bin, "github.com/krazywarez/forge/cmd/forged") 30 cmd := exec.Command("go", "build", "-o", bin, "gitbay.org/gitbay/cmd/gitbayd")
31 cmd.Dir = ".." 31 cmd.Dir = ".."
32 if out, err := cmd.CombinedOutput(); err != nil { 32 if out, err := cmd.CombinedOutput(); err != nil {
33 t.Fatalf("build forged: %v\n%s", err, out) 33 t.Fatalf("build gitbayd: %v\n%s", err, out)
34 } 34 }
35 return bin 35 return bin
36} 36}
@@ -53,7 +53,7 @@ func startInstance(t *testing.T) *instance {
53func startInstanceWith(t *testing.T, extra string) *instance { 53func startInstanceWith(t *testing.T, extra string) *instance {
54 t.Helper() 54 t.Helper()
55 inst := &instance{ 55 inst := &instance{
56 forged: buildForged(t), 56 gitbayd: buildGitbayd(t),
57 root: t.TempDir(), 57 root: t.TempDir(),
58 port: freePort(t), 58 port: freePort(t),
59 httpPort: freePort(t), 59 httpPort: freePort(t),
@@ -64,7 +64,7 @@ func startInstanceWith(t *testing.T, extra string) *instance {
64 cfg := fmt.Sprintf(` 64 cfg := fmt.Sprintf(`
65[server] 65[server]
66root = %q 66root = %q
67site_url = "https://forge.test" 67site_url = "https://gitbay.test"
68[ssh] 68[ssh]
69port = %d 69port = %d
70[http] 70[http]
@@ -79,7 +79,7 @@ port = %d
79 t.Fatal(err) 79 t.Fatal(err)
80 } 80 }
81 81
82 inst.proc = exec.Command(inst.forged, "--config", inst.config, "serve") 82 inst.proc = exec.Command(inst.gitbayd, "--config", inst.config, "serve")
83 inst.proc.Stderr = os.Stderr 83 inst.proc.Stderr = os.Stderr
84 if err := inst.proc.Start(); err != nil { 84 if err := inst.proc.Start(); err != nil {
85 t.Fatal(err) 85 t.Fatal(err)
@@ -98,19 +98,19 @@ port = %d
98 return inst 98 return inst
99 } 99 }
100 if time.Now().After(deadline) { 100 if time.Now().After(deadline) {
101 t.Fatal("forged did not start listening") 101 t.Fatal("gitbayd did not start listening")
102 } 102 }
103 time.Sleep(50 * time.Millisecond) 103 time.Sleep(50 * time.Millisecond)
104 } 104 }
105} 105}
106 106
107// admin runs a forged admin command against the instance's database. 107// admin runs a gitbayd admin command against the instance's database.
108func (i *instance) admin(t *testing.T, args ...string) string { 108func (i *instance) admin(t *testing.T, args ...string) string {
109 t.Helper() 109 t.Helper()
110 cmd := exec.Command(i.forged, append([]string{"--config", i.config}, args...)...) 110 cmd := exec.Command(i.gitbayd, append([]string{"--config", i.config}, args...)...)
111 out, err := cmd.CombinedOutput() 111 out, err := cmd.CombinedOutput()
112 if err != nil { 112 if err != nil {
113 t.Fatalf("forged %v: %v\n%s", args, err, out) 113 t.Fatalf("gitbayd %v: %v\n%s", args, err, out)
114 } 114 }
115 return string(out) 115 return string(out)
116} 116}
e2e/system_test.go +4 −4
@@ -24,14 +24,14 @@ func TestSystemSSHMode(t *testing.T) {
24 t.Fatal(err) 24 t.Fatal(err)
25 } 25 }
26 26
27 // forged in system mode: no embedded SSH listener; hookd + http still run. 27 // gitbayd in system mode: no embedded SSH listener; hookd + http still run.
28 inst := startInstanceWith(t, "") // placeholder to reuse helpers; killed below 28 inst := startInstanceWith(t, "") // placeholder to reuse helpers; killed below
29 inst.proc.Process.Kill() 29 inst.proc.Process.Kill()
30 inst.proc.Wait() 30 inst.proc.Wait()
31 cfg := fmt.Sprintf(` 31 cfg := fmt.Sprintf(`
32[server] 32[server]
33root = %q 33root = %q
34site_url = "https://forge.test" 34site_url = "https://gitbay.test"
35[ssh] 35[ssh]
36mode = "system" 36mode = "system"
37[http] 37[http]
@@ -41,7 +41,7 @@ tls = "off"
41 if err := os.WriteFile(inst.config, []byte(cfg), 0o600); err != nil { 41 if err := os.WriteFile(inst.config, []byte(cfg), 0o600); err != nil {
42 t.Fatal(err) 42 t.Fatal(err)
43 } 43 }
44 inst.proc = exec.Command(inst.forged, "--config", inst.config, "serve") 44 inst.proc = exec.Command(inst.gitbayd, "--config", inst.config, "serve")
45 inst.proc.Stderr = os.Stderr 45 inst.proc.Stderr = os.Stderr
46 if err := inst.proc.Start(); err != nil { 46 if err := inst.proc.Start(); err != nil {
47 t.Fatal(err) 47 t.Fatal(err)
@@ -65,7 +65,7 @@ tls = "off"
65 // wrapper script argument — only the command path is ownership-checked. 65 // wrapper script argument — only the command path is ownership-checked.
66 wrapper := filepath.Join(sshdDir, "akc.sh") 66 wrapper := filepath.Join(sshdDir, "akc.sh")
67 script := fmt.Sprintf("#!/bin/sh\nexec %q --config %q authorized-keys \"$1\" \"$2\"\n", 67 script := fmt.Sprintf("#!/bin/sh\nexec %q --config %q authorized-keys \"$1\" \"$2\"\n",
68 inst.forged, inst.config) 68 inst.gitbayd, inst.config)
69 if err := os.WriteFile(wrapper, []byte(script), 0o755); err != nil { 69 if err := os.WriteFile(wrapper, []byte(script), 0o755); err != nil {
70 t.Fatal(err) 70 t.Fatal(err)
71 } 71 }
e2e/web_test.go +1 −1
@@ -12,7 +12,7 @@ import (
12 12
13 "golang.org/x/crypto/ssh" 13 "golang.org/x/crypto/ssh"
14 14
15 "github.com/krazywarez/forge/internal/sig" 15 "gitbay.org/gitbay/internal/sig"
16) 16)
17 17
18func (i *instance) get(t *testing.T, path string) (int, string) { 18func (i *instance) get(t *testing.T, path string) (int, string) {
go.mod +1 −1
@@ -1,4 +1,4 @@
1module github.com/krazywarez/forge 1module gitbay.org/gitbay
2 2
3go 1.27.0 3go 1.27.0
4 4
internal/cliconfig/cliconfig.go +3 −3
@@ -46,10 +46,10 @@ type Config struct {
46 46
47func Path() string { 47func Path() string {
48 if x := os.Getenv("XDG_CONFIG_HOME"); x != "" { 48 if x := os.Getenv("XDG_CONFIG_HOME"); x != "" {
49 return filepath.Join(x, "forge", "config.toml") 49 return filepath.Join(x, "gitbay", "config.toml")
50 } 50 }
51 home, _ := os.UserHomeDir() 51 home, _ := os.UserHomeDir()
52 return filepath.Join(home, ".config", "forge", "config.toml") 52 return filepath.Join(home, ".config", "gitbay", "config.toml")
53} 53}
54 54
55func Load() (Config, error) { 55func Load() (Config, error) {
@@ -95,7 +95,7 @@ func (c Config) DefaultInstance() (Instance, string, error) {
95 return inst, name, nil 95 return inst, name, nil
96 } 96 }
97 } 97 }
98 return Instance{}, "", fmt.Errorf("no forge instance configured; run: forge remote add <name> <host>") 98 return Instance{}, "", fmt.Errorf("no gitbay instance configured; run: gitbay remote add <name> <host>")
99} 99}
100 100
101var ( 101var (
internal/cliconfig/cliconfig_test.go +10 −10
@@ -11,12 +11,12 @@ func TestParseRemoteURL(t *testing.T) {
11 repo string 11 repo string
12 ok bool 12 ok bool
13 }{ 13 }{
14 {"ssh://git@forge.example/alice/proj.git", "forge.example", 0, "git", "alice/proj", true}, 14 {"ssh://git@gitbay.example/alice/proj.git", "gitbay.example", 0, "git", "alice/proj", true},
15 {"ssh://git@forge.example:2222/alice/proj.git", "forge.example", 2222, "git", "alice/proj", true}, 15 {"ssh://git@gitbay.example:2222/alice/proj.git", "gitbay.example", 2222, "git", "alice/proj", true},
16 {"ssh://forge.example/alice/proj", "forge.example", 0, "", "alice/proj", true}, 16 {"ssh://gitbay.example/alice/proj", "gitbay.example", 0, "", "alice/proj", true},
17 {"git@forge.example:alice/proj.git", "forge.example", 0, "git", "alice/proj", true}, 17 {"git@gitbay.example:alice/proj.git", "gitbay.example", 0, "git", "alice/proj", true},
18 {"git@forge.example:alice/proj", "forge.example", 0, "git", "alice/proj", true}, 18 {"git@gitbay.example:alice/proj", "gitbay.example", 0, "git", "alice/proj", true},
19 {"https://forge.example/alice/proj.git", "", 0, "", "", false}, 19 {"https://gitbay.example/alice/proj.git", "", 0, "", "", false},
20 {"/local/path/repo.git", "", 0, "", "", false}, 20 {"/local/path/repo.git", "", 0, "", "", false},
21 } 21 }
22 for _, tc := range cases { 22 for _, tc := range cases {
@@ -35,12 +35,12 @@ func TestParseRemoteURL(t *testing.T) {
35} 35}
36 36
37func TestCloneURL(t *testing.T) { 37func TestCloneURL(t *testing.T) {
38 i := Instance{Host: "forge.example"} 38 i := Instance{Host: "gitbay.example"}
39 if got := i.CloneURL("a/b"); got != "ssh://git@forge.example/a/b.git" { 39 if got := i.CloneURL("a/b"); got != "ssh://git@gitbay.example/a/b.git" {
40 t.Errorf("CloneURL = %s", got) 40 t.Errorf("CloneURL = %s", got)
41 } 41 }
42 i = Instance{Host: "forge.example", Port: 2222, User: "u"} 42 i = Instance{Host: "gitbay.example", Port: 2222, User: "u"}
43 if got := i.CloneURL("a/b"); got != "ssh://u@forge.example:2222/a/b.git" { 43 if got := i.CloneURL("a/b"); got != "ssh://u@gitbay.example:2222/a/b.git" {
44 t.Errorf("CloneURL = %s", got) 44 t.Errorf("CloneURL = %s", got)
45 } 45 }
46} 46}
internal/config/config.go +3 −3
@@ -1,4 +1,4 @@
1// Package config loads and validates the forged server configuration. 1// Package config loads and validates the gitbayd server configuration.
2package config 2package config
3 3
4import ( 4import (
@@ -69,7 +69,7 @@ type Mail struct {
69// Default returns the configuration used when a key is absent from the file. 69// Default returns the configuration used when a key is absent from the file.
70func Default() Config { 70func Default() Config {
71 return Config{ 71 return Config{
72 Server: Server{Root: "/var/lib/forge"}, 72 Server: Server{Root: "/var/lib/gitbay"},
73 SSH: SSH{Mode: "embedded", Port: 22}, 73 SSH: SSH{Mode: "embedded", Port: 22},
74 HTTP: HTTP{Addr: ":443", TLS: "acme"}, 74 HTTP: HTTP{Addr: ":443", TLS: "acme"},
75 Web: Web{Mode: "view_only"}, 75 Web: Web{Mode: "view_only"},
@@ -154,7 +154,7 @@ func (c Config) Validate() error {
154 } 154 }
155 if c.Web.PasswordAuth && c.Web.Mode == "accounts" { 155 if c.Web.PasswordAuth && c.Web.Mode == "accounts" {
156 errs = append(errs, errors.New( 156 errs = append(errs, errors.New(
157 "web.password_auth is not implemented yet; browser sessions are minted over SSH (forge web login)")) 157 "web.password_auth is not implemented yet; browser sessions are minted over SSH (gitbay web login)"))
158 } 158 }
159 159
160 return errors.Join(errs...) 160 return errors.Join(errs...)
internal/config/config_test.go +6 −6
@@ -18,8 +18,8 @@ func writeConfig(t *testing.T, body string) string {
18 18
19const minimal = ` 19const minimal = `
20[server] 20[server]
21root = "/var/lib/forge" 21root = "/var/lib/gitbay"
22site_url = "https://forge.example" 22site_url = "https://gitbay.example"
23` 23`
24 24
25func TestLoadMinimal(t *testing.T) { 25func TestLoadMinimal(t *testing.T) {
@@ -52,7 +52,7 @@ func TestContradictions(t *testing.T) {
52 }, 52 },
53 { 53 {
54 "system ssh with open registration", 54 "system ssh with open registration",
55 minimal + "\n[ssh]\nmode = \"system\"\n[registration]\nmode = \"open\"\n[mail]\nsmtp_host = \"mx.example\"\nfrom = \"forge@example\"\n", 55 minimal + "\n[ssh]\nmode = \"system\"\n[registration]\nmode = \"open\"\n[mail]\nsmtp_host = \"mx.example\"\nfrom = \"gitbay@example\"\n",
56 "requires registration.mode = \"closed\"", 56 "requires registration.mode = \"closed\"",
57 }, 57 },
58 { 58 {
@@ -72,12 +72,12 @@ func TestContradictions(t *testing.T) {
72 }, 72 },
73 { 73 {
74 "unknown key", 74 "unknown key",
75 "[server]\nroot = \"/var/lib/forge\"\nsite_url = \"https://forge.example\"\nbogus = 1\n", 75 "[server]\nroot = \"/var/lib/gitbay\"\nsite_url = \"https://gitbay.example\"\nbogus = 1\n",
76 "unknown config key", 76 "unknown config key",
77 }, 77 },
78 { 78 {
79 "missing site_url", 79 "missing site_url",
80 "[server]\nroot = \"/var/lib/forge\"\n", 80 "[server]\nroot = \"/var/lib/gitbay\"\n",
81 "site_url", 81 "site_url",
82 }, 82 },
83 } 83 }
@@ -101,7 +101,7 @@ func TestValidCombinations(t *testing.T) {
101 }{ 101 }{
102 { 102 {
103 "invite with smtp", 103 "invite with smtp",
104 minimal + "\n[registration]\nmode = \"invite\"\n[mail]\nsmtp_host = \"mx.example\"\nfrom = \"forge@example\"\n", 104 minimal + "\n[registration]\nmode = \"invite\"\n[mail]\nsmtp_host = \"mx.example\"\nfrom = \"gitbay@example\"\n",
105 }, 105 },
106 { 106 {
107 "system ssh closed registration", 107 "system ssh closed registration",
internal/control/control.go +3 −3
@@ -10,9 +10,9 @@ import (
10 "reflect" 10 "reflect"
11 "slices" 11 "slices"
12 12
13 "github.com/krazywarez/forge/internal/config" 13 "gitbay.org/gitbay/internal/config"
14 "github.com/krazywarez/forge/internal/protocol" 14 "gitbay.org/gitbay/internal/protocol"
15 "github.com/krazywarez/forge/internal/store" 15 "gitbay.org/gitbay/internal/store"
16) 16)
17 17
18type Ctx struct { 18type Ctx struct {
internal/control/control_test.go +1 −1
@@ -4,7 +4,7 @@ import (
4 "strings" 4 "strings"
5 "testing" 5 "testing"
6 6
7 "github.com/krazywarez/forge/internal/protocol" 7 "gitbay.org/gitbay/internal/protocol"
8) 8)
9 9
10// TestEveryCommandReachableFromBareSSH asserts that each registered command's 10// TestEveryCommandReachableFromBareSSH asserts that each registered command's
internal/control/identity.go +2 −2
@@ -7,8 +7,8 @@ import (
7 7
8 "golang.org/x/crypto/ssh" 8 "golang.org/x/crypto/ssh"
9 9
10 "github.com/krazywarez/forge/internal/protocol" 10 "gitbay.org/gitbay/internal/protocol"
11 "github.com/krazywarez/forge/internal/store" 11 "gitbay.org/gitbay/internal/store"
12) 12)
13 13
14func init() { 14func init() {
internal/control/import.go +5 −5
@@ -10,9 +10,9 @@ import (
10 "strings" 10 "strings"
11 "time" 11 "time"
12 12
13 "github.com/krazywarez/forge/internal/gitutil" 13 "gitbay.org/gitbay/internal/gitutil"
14 "github.com/krazywarez/forge/internal/policy" 14 "gitbay.org/gitbay/internal/policy"
15 "github.com/krazywarez/forge/internal/protocol" 15 "gitbay.org/gitbay/internal/protocol"
16) 16)
17 17
18func init() { 18func init() {
@@ -27,7 +27,7 @@ func init() {
27const askpassScript = `#!/bin/sh 27const askpassScript = `#!/bin/sh
28case "$1" in 28case "$1" in
29 Username*) echo "x-access-token" ;; 29 Username*) echo "x-access-token" ;;
30 *) echo "${FORGE_IMPORT_TOKEN}" ;; 30 *) echo "${GITBAY_IMPORT_TOKEN}" ;;
31esac 31esac
32` 32`
33 33
@@ -96,7 +96,7 @@ func runRepoImport(c *Ctx, args []string) int {
96 } 96 }
97 env = []string{ 97 env = []string{
98 "GIT_ASKPASS=" + askpass, 98 "GIT_ASKPASS=" + askpass,
99 "FORGE_IMPORT_TOKEN=" + token, 99 "GITBAY_IMPORT_TOKEN=" + token,
100 "GIT_TERMINAL_PROMPT=0", 100 "GIT_TERMINAL_PROMPT=0",
101 } 101 }
102 } else { 102 } else {
internal/control/issue.go +3 −3
@@ -7,9 +7,9 @@ import (
7 "strconv" 7 "strconv"
8 "strings" 8 "strings"
9 9
10 "github.com/krazywarez/forge/internal/policy" 10 "gitbay.org/gitbay/internal/policy"
11 "github.com/krazywarez/forge/internal/protocol" 11 "gitbay.org/gitbay/internal/protocol"
12 "github.com/krazywarez/forge/internal/store" 12 "gitbay.org/gitbay/internal/store"
13) 13)
14 14
15const maxBodyBytes = 64 << 10 15const maxBodyBytes = 64 << 10
internal/control/mr.go +4 −4
@@ -7,10 +7,10 @@ import (
7 "strconv" 7 "strconv"
8 "strings" 8 "strings"
9 9
10 "github.com/krazywarez/forge/internal/gitutil" 10 "gitbay.org/gitbay/internal/gitutil"
11 "github.com/krazywarez/forge/internal/policy" 11 "gitbay.org/gitbay/internal/policy"
12 "github.com/krazywarez/forge/internal/protocol" 12 "gitbay.org/gitbay/internal/protocol"
13 "github.com/krazywarez/forge/internal/store" 13 "gitbay.org/gitbay/internal/store"
14) 14)
15 15
16func init() { 16func init() {
internal/control/repo.go +4 −4
@@ -9,10 +9,10 @@ import (
9 "slices" 9 "slices"
10 "strings" 10 "strings"
11 11
12 "github.com/krazywarez/forge/internal/gitutil" 12 "gitbay.org/gitbay/internal/gitutil"
13 "github.com/krazywarez/forge/internal/policy" 13 "gitbay.org/gitbay/internal/policy"
14 "github.com/krazywarez/forge/internal/protocol" 14 "gitbay.org/gitbay/internal/protocol"
15 "github.com/krazywarez/forge/internal/store" 15 "gitbay.org/gitbay/internal/store"
16) 16)
17 17
18// RepoDir returns the on-disk path for a repository. 18// RepoDir returns the on-disk path for a repository.
internal/control/sig.go +5 −5
@@ -8,11 +8,11 @@ import (
8 "strconv" 8 "strconv"
9 "time" 9 "time"
10 10
11 "github.com/krazywarez/forge/internal/gitutil" 11 "gitbay.org/gitbay/internal/gitutil"
12 "github.com/krazywarez/forge/internal/policy" 12 "gitbay.org/gitbay/internal/policy"
13 "github.com/krazywarez/forge/internal/protocol" 13 "gitbay.org/gitbay/internal/protocol"
14 "github.com/krazywarez/forge/internal/sig" 14 "gitbay.org/gitbay/internal/sig"
15 "github.com/krazywarez/forge/internal/store" 15 "gitbay.org/gitbay/internal/store"
16) 16)
17 17
18func init() { 18func init() {
internal/control/web.go +2 −2
@@ -5,8 +5,8 @@ import (
5 "io" 5 "io"
6 "time" 6 "time"
7 7
8 "github.com/krazywarez/forge/internal/protocol" 8 "gitbay.org/gitbay/internal/protocol"
9 "github.com/krazywarez/forge/internal/store" 9 "gitbay.org/gitbay/internal/store"
10) 10)
11 11
12func newStoredToken() (token, hash string, err error) { return store.NewToken() } 12func newStoredToken() (token, hash string, err error) { return store.NewToken() }
internal/gitd/gitd.go +3 −3
@@ -13,9 +13,9 @@ import (
13 "strings" 13 "strings"
14 "time" 14 "time"
15 15
16 "github.com/krazywarez/forge/internal/config" 16 "gitbay.org/gitbay/internal/config"
17 "github.com/krazywarez/forge/internal/control" 17 "gitbay.org/gitbay/internal/control"
18 "github.com/krazywarez/forge/internal/store" 18 "gitbay.org/gitbay/internal/store"
19) 19)
20 20
21type Server struct { 21type Server struct {
internal/gitutil/gitutil.go +1 −1
@@ -31,7 +31,7 @@ func InitBare(path, defaultBranch, hooksPath string) error {
31 31
32// Transport streams one git transport service (upload-pack, receive-pack, 32// Transport streams one git transport service (upload-pack, receive-pack,
33// upload-archive). extraEnv entries are appended to the process environment; 33// upload-archive). extraEnv entries are appended to the process environment;
34// hooks read the FORGE_* variables from it. 34// hooks read the GITBAY_* variables from it.
35func Transport(service, repoPath string, stdin io.Reader, stdout, errW io.Writer, extraEnv []string) error { 35func Transport(service, repoPath string, stdin io.Reader, stdout, errW io.Writer, extraEnv []string) error {
36 var args []string 36 var args []string
37 switch service { 37 switch service {
internal/gitutil/merge.go +1 −1
@@ -137,7 +137,7 @@ func CommitFileChange(dir, branch, path string, content []byte, name, email, mes
137 137
138 // Stage the parent tree in a temporary index, splice the blob in, and 138 // Stage the parent tree in a temporary index, splice the blob in, and
139 // write the new tree. 139 // write the new tree.
140 idx, err := os.CreateTemp("", "forge-index-*") 140 idx, err := os.CreateTemp("", "gitbay-index-*")
141 if err != nil { 141 if err != nil {
142 return "", err 142 return "", err
143 } 143 }
internal/hookd/hookd.go +14 −14
@@ -1,5 +1,5 @@
1// Package hookd is the unix-socket bridge between git hooks and the daemon. 1// Package hookd is the unix-socket bridge between git hooks and the daemon.
2// The hook process (forged in hook mode) computes git facts — it inherits 2// The hook process (gitbayd in hook mode) computes git facts — it inherits
3// git's quarantine environment, which the daemon does not see — and sends 3// git's quarantine environment, which the daemon does not see — and sends
4// them here; the daemon answers with a policy decision. 4// them here; the daemon answers with a policy decision.
5// 5//
@@ -17,20 +17,20 @@ import (
17 "os" 17 "os"
18 "path/filepath" 18 "path/filepath"
19 19
20 "github.com/krazywarez/forge/internal/config" 20 "gitbay.org/gitbay/internal/config"
21 "github.com/krazywarez/forge/internal/control" 21 "gitbay.org/gitbay/internal/control"
22 "github.com/krazywarez/forge/internal/gitutil" 22 "gitbay.org/gitbay/internal/gitutil"
23 "github.com/krazywarez/forge/internal/policy" 23 "gitbay.org/gitbay/internal/policy"
24 "github.com/krazywarez/forge/internal/sig" 24 "gitbay.org/gitbay/internal/sig"
25 "github.com/krazywarez/forge/internal/store" 25 "gitbay.org/gitbay/internal/store"
26) 26)
27 27
28// Env variable names passed to git transport subprocesses and inherited by 28// Env variable names passed to git transport subprocesses and inherited by
29// hooks. 29// hooks.
30const ( 30const (
31 EnvSocket = "FORGE_HOOK_SOCKET" 31 EnvSocket = "GITBAY_HOOK_SOCKET"
32 EnvRepoID = "FORGE_REPO_ID" 32 EnvRepoID = "GITBAY_REPO_ID"
33 EnvUserID = "FORGE_USER_ID" 33 EnvUserID = "GITBAY_USER_ID"
34) 34)
35 35
36type Request struct { 36type Request struct {
@@ -59,7 +59,7 @@ type Response struct {
59// SocketPath returns the hook socket location. It prefers the server root, 59// SocketPath returns the hook socket location. It prefers the server root,
60// but unix socket paths are capped (~104 bytes on macOS, 108 on Linux), so 60// but unix socket paths are capped (~104 bytes on macOS, 108 on Linux), so
61// deep roots fall back to a hashed name under the system temp directory. 61// deep roots fall back to a hashed name under the system temp directory.
62// Hooks receive the chosen path via FORGE_HOOK_SOCKET, so both sides always 62// Hooks receive the chosen path via GITBAY_HOOK_SOCKET, so both sides always
63// agree. 63// agree.
64func SocketPath(root string) string { 64func SocketPath(root string) string {
65 p := filepath.Join(root, "hook.sock") 65 p := filepath.Join(root, "hook.sock")
@@ -67,7 +67,7 @@ func SocketPath(root string) string {
67 return p 67 return p
68 } 68 }
69 sum := sha256.Sum256([]byte(root)) 69 sum := sha256.Sum256([]byte(root))
70 return filepath.Join(os.TempDir(), fmt.Sprintf("forge-%x.sock", sum[:8])) 70 return filepath.Join(os.TempDir(), fmt.Sprintf("gitbay-%x.sock", sum[:8]))
71} 71}
72 72
73type Server struct { 73type Server struct {
@@ -250,12 +250,12 @@ func Ask(socketPath string, req Request, commits func() (CommitsPayload, error))
250// WriteHookScripts (re)generates the shared hooks directory. Called at 250// WriteHookScripts (re)generates the shared hooks directory. Called at
251// daemon startup so a moved binary self-heals; every repo points here via 251// daemon startup so a moved binary self-heals; every repo points here via
252// core.hooksPath. 252// core.hooksPath.
253func WriteHookScripts(hooksDir, forgedPath string) error { 253func WriteHookScripts(hooksDir, gitbaydPath string) error {
254 if err := os.MkdirAll(hooksDir, 0o755); err != nil { 254 if err := os.MkdirAll(hooksDir, 0o755); err != nil {
255 return err 255 return err
256 } 256 }
257 for _, hook := range []string{"pre-receive", "post-receive"} { 257 for _, hook := range []string{"pre-receive", "post-receive"} {
258 script := fmt.Sprintf("#!/bin/sh\nexec %q hook %s\n", forgedPath, hook) 258 script := fmt.Sprintf("#!/bin/sh\nexec %q hook %s\n", gitbaydPath, hook)
259 if err := os.WriteFile(filepath.Join(hooksDir, hook), []byte(script), 0o755); err != nil { 259 if err := os.WriteFile(filepath.Join(hooksDir, hook), []byte(script), 0o755); err != nil {
260 return err 260 return err
261 } 261 }
internal/httpd/accounts.go +5 −5
@@ -7,13 +7,13 @@ import (
7 "strings" 7 "strings"
8 "time" 8 "time"
9 9
10 "github.com/krazywarez/forge/internal/control" 10 "gitbay.org/gitbay/internal/control"
11 "github.com/krazywarez/forge/internal/gitutil" 11 "gitbay.org/gitbay/internal/gitutil"
12 "github.com/krazywarez/forge/internal/policy" 12 "gitbay.org/gitbay/internal/policy"
13 "github.com/krazywarez/forge/internal/store" 13 "gitbay.org/gitbay/internal/store"
14) 14)
15 15
16const sessionCookie = "forge_session" 16const sessionCookie = "gitbay_session"
17 17
18// viewer returns the logged-in user, or a zero User for anonymous visitors. 18// viewer returns the logged-in user, or a zero User for anonymous visitors.
19// Only meaningful in accounts mode; in view_only no session route exists so 19// Only meaningful in accounts mode; in view_only no session route exists so
internal/httpd/routes_test.go +2 −2
@@ -4,8 +4,8 @@ import (
4 "strings" 4 "strings"
5 "testing" 5 "testing"
6 6
7 "github.com/krazywarez/forge/internal/config" 7 "gitbay.org/gitbay/internal/config"
8 "github.com/krazywarez/forge/internal/policy" 8 "gitbay.org/gitbay/internal/policy"
9) 9)
10 10
11// TestViewOnlyHasNoMutatingRoutes is the structural guarantee from the plan: 11// TestViewOnlyHasNoMutatingRoutes is the structural guarantee from the plan:
internal/httpd/smart.go +3 −3
@@ -14,9 +14,9 @@ import (
14 "os/exec" 14 "os/exec"
15 "strings" 15 "strings"
16 16
17 "github.com/krazywarez/forge/internal/config" 17 "gitbay.org/gitbay/internal/config"
18 "github.com/krazywarez/forge/internal/control" 18 "gitbay.org/gitbay/internal/control"
19 "github.com/krazywarez/forge/internal/store" 19 "gitbay.org/gitbay/internal/store"
20) 20)
21 21
22type Server struct { 22type Server struct {
internal/httpd/web.go +6 −6
@@ -4,7 +4,7 @@ import (
4 "bytes" 4 "bytes"
5 "fmt" 5 "fmt"
6 6
7 "github.com/krazywarez/forge/internal/policy" 7 "gitbay.org/gitbay/internal/policy"
8 "html/template" 8 "html/template"
9 "net/http" 9 "net/http"
10 "path" 10 "path"
@@ -17,11 +17,11 @@ import (
17 "github.com/alecthomas/chroma/v2/styles" 17 "github.com/alecthomas/chroma/v2/styles"
18 "github.com/yuin/goldmark" 18 "github.com/yuin/goldmark"
19 19
20 "github.com/krazywarez/forge/internal/control" 20 "gitbay.org/gitbay/internal/control"
21 "github.com/krazywarez/forge/internal/gitutil" 21 "gitbay.org/gitbay/internal/gitutil"
22 "github.com/krazywarez/forge/internal/sig" 22 "gitbay.org/gitbay/internal/sig"
23 "github.com/krazywarez/forge/internal/store" 23 "gitbay.org/gitbay/internal/store"
24 "github.com/krazywarez/forge/internal/web" 24 "gitbay.org/gitbay/internal/web"
25) 25)
26 26
27const maxRenderBytes = 1 << 20 // largest blob rendered inline 27const maxRenderBytes = 1 << 20 // largest blob rendered inline
internal/policy/access.go +1 −1
@@ -3,7 +3,7 @@ package policy
3import ( 3import (
4 "strings" 4 "strings"
5 5
6 "github.com/krazywarez/forge/internal/store" 6 "gitbay.org/gitbay/internal/store"
7) 7)
8 8
9// CanRead reports whether user may read repo over an authenticated channel. 9// CanRead reports whether user may read repo over an authenticated channel.
internal/policy/access_test.go +1 −1
@@ -3,7 +3,7 @@ package policy
3import ( 3import (
4 "testing" 4 "testing"
5 5
6 "github.com/krazywarez/forge/internal/store" 6 "gitbay.org/gitbay/internal/store"
7) 7)
8 8
9var ( 9var (
internal/sshd/sshd.go +10 −10
@@ -17,13 +17,13 @@ import (
17 17
18 "golang.org/x/crypto/ssh" 18 "golang.org/x/crypto/ssh"
19 19
20 "github.com/krazywarez/forge/internal/config" 20 "gitbay.org/gitbay/internal/config"
21 "github.com/krazywarez/forge/internal/control" 21 "gitbay.org/gitbay/internal/control"
22 "github.com/krazywarez/forge/internal/gitutil" 22 "gitbay.org/gitbay/internal/gitutil"
23 "github.com/krazywarez/forge/internal/hookd" 23 "gitbay.org/gitbay/internal/hookd"
24 "github.com/krazywarez/forge/internal/policy" 24 "gitbay.org/gitbay/internal/policy"
25 "github.com/krazywarez/forge/internal/protocol" 25 "gitbay.org/gitbay/internal/protocol"
26 "github.com/krazywarez/forge/internal/store" 26 "gitbay.org/gitbay/internal/store"
27) 27)
28 28
29type Server struct { 29type Server struct {
@@ -37,7 +37,7 @@ func New(cfg config.Config, st *store.Store) (*Server, error) {
37 37
38 sc := &ssh.ServerConfig{ 38 sc := &ssh.ServerConfig{
39 PublicKeyCallback: s.authenticate, 39 PublicKeyCallback: s.authenticate,
40 ServerVersion: "SSH-2.0-forged", 40 ServerVersion: "SSH-2.0-gitbayd",
41 } 41 }
42 signers, err := loadHostKeys(cfg) 42 signers, err := loadHostKeys(cfg)
43 if err != nil { 43 if err != nil {
@@ -158,7 +158,7 @@ func (s *Server) handleSession(sconn *ssh.ServerConn, ch ssh.Channel, reqs <-cha
158 return 158 return
159 case "shell": 159 case "shell":
160 req.Reply(true, nil) 160 req.Reply(true, nil)
161 fmt.Fprintf(ch, "forge control plane: interactive shells are not available.\nTry: ssh %s help\n", s.cfg.Server.SiteURL) 161 fmt.Fprintf(ch, "gitbay control plane: interactive shells are not available.\nTry: ssh %s help\n", s.cfg.Server.SiteURL)
162 sendExit(ch, protocol.ExitUsage) 162 sendExit(ch, protocol.ExitUsage)
163 return 163 return
164 case "pty-req", "env": 164 case "pty-req", "env":
@@ -190,7 +190,7 @@ func (s *Server) runExec(sconn *ssh.ServerConn, ch ssh.Channel, cmdline string)
190 190
191// Exec runs one SSH exec command line for an authenticated key. It is the 191// Exec runs one SSH exec command line for an authenticated key. It is the
192// single dispatch path shared by the embedded listener and the system-sshd 192// single dispatch path shared by the embedded listener and the system-sshd
193// forced command (forged shell). 193// forced command (gitbayd shell).
194func Exec(cfg config.Config, st *store.Store, user store.User, scope, cmdline string, 194func Exec(cfg config.Config, st *store.Store, user store.User, scope, cmdline string,
195 stdin io.Reader, stdout, stderr io.Writer) int { 195 stdin io.Reader, stdout, stderr io.Writer) int {
196 argv, err := protocol.Tokenize(cmdline) 196 argv, err := protocol.Tokenize(cmdline)
internal/store/signatures.go +1 −1
@@ -5,7 +5,7 @@ import (
5 "errors" 5 "errors"
6 "time" 6 "time"
7 7
8 "github.com/krazywarez/forge/internal/sig" 8 "gitbay.org/gitbay/internal/sig"
9) 9)
10 10
11// AddPGPKey registers an OpenPGP key and bumps the key epoch. 11// AddPGPKey registers an OpenPGP key and bumps the key epoch.
internal/store/store_test.go +1 −1
@@ -8,7 +8,7 @@ import (
8 8
9func open(t *testing.T) *Store { 9func open(t *testing.T) *Store {
10 t.Helper() 10 t.Helper()
11 s, err := Open(filepath.Join(t.TempDir(), "forge.db")) 11 s, err := Open(filepath.Join(t.TempDir(), "gitbay.db"))
12 if err != nil { 12 if err != nil {
13 t.Fatal(err) 13 t.Fatal(err)
14 } 14 }