Skip to content

Commit 8ce276d

Browse files
julianknutsenclaude
andcommitted
Remove wl_commons: write to fork clone with wild-west auto-push
Instead of writing to a separate wl_commons database (which had no remotes and stranded changes), post/claim/done now write directly to the fork clone's main branch. After each commit, PushWithSync pushes to both upstream (canonical) and origin (fork) with auto-retry on rejection. --no-push flag skips all pushes for offline work. Removes: WLCommonsDB, EnsureDB, EnsureWLCommons, initWLCommonsSchema, DatabaseExists, InitDB, WLCommonsDir, and associated test fakes/tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0800523 commit 8ce276d

File tree

16 files changed

+346
-345
lines changed

16 files changed

+346
-345
lines changed

cmd/wl/cmd_claim.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,48 @@ package main
33
import (
44
"fmt"
55
"io"
6-
"os"
7-
"path/filepath"
86

97
"github.com/spf13/cobra"
108
"github.com/steveyegge/wasteland/internal/commons"
11-
"github.com/steveyegge/wasteland/internal/federation"
129
"github.com/steveyegge/wasteland/internal/style"
1310
)
1411

1512
func newClaimCmd(stdout, stderr io.Writer) *cobra.Command {
16-
return &cobra.Command{
13+
var noPush bool
14+
15+
cmd := &cobra.Command{
1716
Use: "claim <wanted-id>",
1817
Short: "Claim a wanted item",
1918
Long: `Claim a wanted item on the shared wanted board.
2019
2120
Updates the wanted row: claimed_by=<your rig handle>, status='claimed'.
2221
The item must exist and have status='open'.
2322
24-
In wild-west mode (Phase 1), this writes directly to the local wl-commons
25-
database. In PR mode, this will create a DoltHub PR instead.
23+
In wild-west mode the commit is auto-pushed to upstream and origin.
24+
Use --no-push to skip pushing (offline work).
2625
2726
Examples:
28-
wl claim w-abc123`,
27+
wl claim w-abc123
28+
wl claim w-abc123 --no-push`,
2929
Args: cobra.ExactArgs(1),
3030
RunE: func(cmd *cobra.Command, args []string) error {
31-
return runClaim(cmd, stdout, stderr, args[0])
31+
return runClaim(cmd, stdout, stderr, args[0], noPush)
3232
},
3333
}
34+
35+
cmd.Flags().BoolVar(&noPush, "no-push", false, "Skip pushing to remotes (offline work)")
36+
37+
return cmd
3438
}
3539

36-
func runClaim(cmd *cobra.Command, stdout, _ io.Writer, wantedID string) error {
40+
func runClaim(cmd *cobra.Command, stdout, _ io.Writer, wantedID string, noPush bool) error {
3741
wlCfg, err := resolveWasteland(cmd)
3842
if err != nil {
3943
return fmt.Errorf("loading wasteland config: %w", err)
4044
}
4145
rigHandle := wlCfg.RigHandle
4246

43-
org, db, _ := federation.ParseUpstream(wlCfg.Upstream)
44-
commonsDir := federation.WLCommonsDir(org, db)
45-
46-
if _, err := os.Stat(filepath.Join(commonsDir, ".dolt")); err != nil {
47-
return fmt.Errorf("wl-commons database not found at %s\nRun 'wl post' first to initialize, or join a wasteland with: wl join <org/db>", commonsDir)
48-
}
49-
50-
store := commons.NewWLCommons(commonsDir)
47+
store := commons.NewWLCommons(wlCfg.LocalDir)
5148
item, err := claimWanted(store, wantedID, rigHandle)
5249
if err != nil {
5350
return err
@@ -57,6 +54,10 @@ func runClaim(cmd *cobra.Command, stdout, _ io.Writer, wantedID string) error {
5754
fmt.Fprintf(stdout, " Claimed by: %s\n", rigHandle)
5855
fmt.Fprintf(stdout, " Title: %s\n", item.Title)
5956

57+
if !noPush {
58+
_ = commons.PushWithSync(wlCfg.LocalDir, stdout)
59+
}
60+
6061
return nil
6162
}
6263

cmd/wl/cmd_done.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ import (
44
"crypto/sha256"
55
"fmt"
66
"io"
7-
"os"
8-
"path/filepath"
97
"time"
108

119
"github.com/spf13/cobra"
1210
"github.com/steveyegge/wasteland/internal/commons"
13-
"github.com/steveyegge/wasteland/internal/federation"
1411
"github.com/steveyegge/wasteland/internal/style"
1512
)
1613

1714
func newDoneCmd(stdout, stderr io.Writer) *cobra.Command {
18-
var evidence string
15+
var (
16+
evidence string
17+
noPush bool
18+
)
1919

2020
cmd := &cobra.Command{
2121
Use: "done <wanted-id>",
@@ -30,36 +30,34 @@ The --evidence flag provides the evidence URL (PR link, commit hash, etc.).
3030
A completion ID is generated as c-<hash> where hash is derived from the
3131
wanted ID, rig handle, and timestamp.
3232
33+
In wild-west mode the commit is auto-pushed to upstream and origin.
34+
Use --no-push to skip pushing (offline work).
35+
3336
Examples:
3437
wl done w-abc123 --evidence 'https://github.com/org/repo/pull/123'
35-
wl done w-abc123 --evidence 'commit abc123def'`,
38+
wl done w-abc123 --evidence 'commit abc123def'
39+
wl done w-abc123 --evidence 'commit abc123def' --no-push`,
3640
Args: cobra.ExactArgs(1),
3741
RunE: func(cmd *cobra.Command, args []string) error {
38-
return runDone(cmd, stdout, stderr, args[0], evidence)
42+
return runDone(cmd, stdout, stderr, args[0], evidence, noPush)
3943
},
4044
}
4145

4246
cmd.Flags().StringVar(&evidence, "evidence", "", "Evidence URL or description (required)")
47+
cmd.Flags().BoolVar(&noPush, "no-push", false, "Skip pushing to remotes (offline work)")
4348
_ = cmd.MarkFlagRequired("evidence")
4449

4550
return cmd
4651
}
4752

48-
func runDone(cmd *cobra.Command, stdout, _ io.Writer, wantedID, evidence string) error {
53+
func runDone(cmd *cobra.Command, stdout, _ io.Writer, wantedID, evidence string, noPush bool) error {
4954
wlCfg, err := resolveWasteland(cmd)
5055
if err != nil {
5156
return fmt.Errorf("loading wasteland config: %w", err)
5257
}
5358
rigHandle := wlCfg.RigHandle
5459

55-
org, db, _ := federation.ParseUpstream(wlCfg.Upstream)
56-
commonsDir := federation.WLCommonsDir(org, db)
57-
58-
if _, err := os.Stat(filepath.Join(commonsDir, ".dolt")); err != nil {
59-
return fmt.Errorf("wl-commons database not found at %s\nRun 'wl post' first to initialize, or join a wasteland with: wl join <org/db>", commonsDir)
60-
}
61-
62-
store := commons.NewWLCommons(commonsDir)
60+
store := commons.NewWLCommons(wlCfg.LocalDir)
6361
completionID := generateCompletionID(wantedID, rigHandle)
6462

6563
if err := submitDone(store, wantedID, rigHandle, evidence, completionID); err != nil {
@@ -72,6 +70,10 @@ func runDone(cmd *cobra.Command, stdout, _ io.Writer, wantedID, evidence string)
7270
fmt.Fprintf(stdout, " Evidence: %s\n", evidence)
7371
fmt.Fprintf(stdout, " Status: in_review\n")
7472

73+
if !noPush {
74+
_ = commons.PushWithSync(wlCfg.LocalDir, stdout)
75+
}
76+
7577
return nil
7678
}
7779

cmd/wl/cmd_fake_test.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ import (
1111
type fakeWLCommonsStore struct {
1212
mu sync.Mutex
1313
items map[string]*commons.WantedItem
14-
dbOK bool
1514

1615
// Error injection fields
17-
EnsureDBErr error
1816
InsertWantedErr error
1917
ClaimWantedErr error
2018
SubmitCompletionErr error
@@ -24,22 +22,9 @@ type fakeWLCommonsStore struct {
2422
func newFakeWLCommonsStore() *fakeWLCommonsStore {
2523
return &fakeWLCommonsStore{
2624
items: make(map[string]*commons.WantedItem),
27-
dbOK: true,
2825
}
2926
}
3027

31-
func (f *fakeWLCommonsStore) EnsureDB() error {
32-
if f.EnsureDBErr != nil {
33-
return f.EnsureDBErr
34-
}
35-
f.dbOK = true
36-
return nil
37-
}
38-
39-
func (f *fakeWLCommonsStore) DatabaseExists(dbName string) bool {
40-
return f.dbOK && dbName == commons.WLCommonsDB
41-
}
42-
4328
func (f *fakeWLCommonsStore) InsertWanted(item *commons.WantedItem) error {
4429
if f.InsertWantedErr != nil {
4530
return f.InsertWantedErr

cmd/wl/cmd_join.go

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"errors"
45
"fmt"
56
"io"
67
"os/exec"
@@ -13,6 +14,8 @@ import (
1314
"github.com/steveyegge/wasteland/internal/style"
1415
)
1516

17+
const defaultUpstream = "hop/wl-commons"
18+
1619
func newJoinCmd(stdout, stderr io.Writer) *cobra.Command {
1720
var (
1821
handle string
@@ -24,40 +27,39 @@ func newJoinCmd(stdout, stderr io.Writer) *cobra.Command {
2427
)
2528

2629
cmd := &cobra.Command{
27-
Use: "join <upstream>",
30+
Use: "join [upstream]",
2831
Short: "Join a wasteland by forking its commons",
2932
Long: `Join a wasteland community by forking its shared commons database.
3033
3134
This command:
32-
1. Forks the upstream commons to your org
35+
1. Forks the upstream commons to your org (or checks that your fork exists)
3336
2. Clones the fork locally
3437
3. Registers your rig in the rigs table
3538
4. Pushes the registration to your fork
3639
5. Saves wasteland configuration locally
3740
38-
The upstream argument is an org/database path like 'steveyegge/wl-commons'.
39-
You can join multiple wastelands simultaneously.
40-
41-
DoltHub mode (default):
42-
Requires DOLTHUB_TOKEN and DOLTHUB_ORG (or --fork-org).
43-
Forks and clones via DoltHub.
44-
45-
Offline file mode (--remote-base):
46-
Uses file:// dolt remotes. No DoltHub credentials needed.
47-
Requires --fork-org (or DOLTHUB_ORG).
41+
The upstream argument defaults to 'hop/wl-commons' (the main wasteland).
42+
You can specify a different org/database path to join other wastelands.
4843
49-
Git remote mode (--git-remote):
50-
Uses bare git repos as dolt remotes. No DoltHub credentials needed.
51-
Requires --fork-org (or DOLTHUB_ORG).
44+
Getting started:
45+
1. Sign up at https://www.dolthub.com
46+
2. Fork the commons: https://www.dolthub.com/repositories/hop/wl-commons
47+
3. Create an API token at https://www.dolthub.com/settings/tokens
48+
4. Set environment variables:
49+
export DOLTHUB_TOKEN=<your-api-token>
50+
export DOLTHUB_ORG=<your-dolthub-username>
51+
5. Run: wl join
5252
5353
Examples:
54-
wl join steveyegge/wl-commons
55-
wl join steveyegge/wl-commons --handle my-rig
56-
wl join test-org/wl-commons --remote-base /tmp/remotes --fork-org my-fork
57-
wl join test-org/wl-commons --git-remote /tmp/git-remotes --fork-org my-fork`,
58-
Args: cobra.ExactArgs(1),
54+
wl join
55+
wl join hop/wl-commons --handle my-rig`,
56+
Args: cobra.MaximumNArgs(1),
5957
RunE: func(_ *cobra.Command, args []string) error {
60-
return runJoin(stdout, stderr, args[0], handle, displayName, email, forkOrg, remoteBase, gitRemote)
58+
upstream := defaultUpstream
59+
if len(args) > 0 {
60+
upstream = args[0]
61+
}
62+
return runJoin(stdout, stderr, upstream, handle, displayName, email, forkOrg, remoteBase, gitRemote)
6163
},
6264
}
6365

@@ -150,6 +152,11 @@ func runJoin(stdout, stderr io.Writer, upstream, handle, displayName, email, for
150152
fmt.Fprintf(stdout, "Joining wasteland %s (fork to %s/%s)...\n", upstream, forkOrg, dbName)
151153
cfg, err := svc.Join(upstream, forkOrg, handle, displayName, email, wlVersion)
152154
if err != nil {
155+
var forkErr *remote.ForkRequiredError
156+
if errors.As(err, &forkErr) {
157+
printForkInstructions(stdout, forkErr)
158+
return errExit
159+
}
153160
fmt.Fprintf(stderr, "wl join: %v\n", err)
154161
return errExit
155162
}
@@ -162,6 +169,15 @@ func runJoin(stdout, stderr io.Writer, upstream, handle, displayName, email, for
162169
return nil
163170
}
164171

172+
func printForkInstructions(w io.Writer, err *remote.ForkRequiredError) {
173+
fmt.Fprintf(w, "\n%s Fork required\n\n", style.Bold.Render("!"))
174+
fmt.Fprintf(w, " To join this wasteland, fork the commons on DoltHub:\n\n")
175+
fmt.Fprintf(w, " 1. Go to %s\n", style.Bold.Render(err.ForkURL()))
176+
fmt.Fprintf(w, " 2. Click %s (top right)\n", style.Bold.Render("Fork"))
177+
fmt.Fprintf(w, " 3. Select your organization: %s\n", style.Bold.Render(err.ForkOrg))
178+
fmt.Fprintf(w, " 4. Rerun: %s\n", style.Bold.Render("wl join"))
179+
}
180+
165181
// gitConfigValue retrieves a value from git config. Returns empty string on error.
166182
func gitConfigValue(key string) string {
167183
cmd := exec.Command("git", "config", key)

cmd/wl/cmd_leave.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ func newLeaveCmd(stdout, stderr io.Writer) *cobra.Command {
1818
If only one wasteland is joined, no argument is needed.
1919
If multiple are joined, specify the upstream or use --wasteland.
2020
21-
Local data directories (fork clone, wl_commons database) are NOT deleted
22-
automatically. The command prints their paths for manual cleanup.
21+
The local fork clone directory is NOT deleted automatically.
22+
The command prints its path for manual cleanup.
2323
2424
Examples:
2525
wl leave
@@ -55,12 +55,9 @@ func runLeave(cmd *cobra.Command, stdout, _ io.Writer, positional string) error
5555
return fmt.Errorf("removing wasteland config: %w", err)
5656
}
5757

58-
org, db, _ := federation.ParseUpstream(upstream)
59-
6058
fmt.Fprintf(stdout, "%s Left wasteland: %s\n", style.Bold.Render("✓"), upstream)
6159
fmt.Fprintf(stdout, "\n Data directories (not deleted):\n")
6260
fmt.Fprintf(stdout, " Fork clone: %s\n", cfg.LocalDir)
63-
fmt.Fprintf(stdout, " WL commons: %s\n", federation.WLCommonsDir(org, db))
6461
fmt.Fprintf(stdout, "\n %s\n", style.Dim.Render("Remove these directories manually if no longer needed."))
6562

6663
return nil

0 commit comments

Comments
 (0)