Skip to content

Commit c213f3e

Browse files
feat: migrate to Taskfile, fix TUI refresh, handle locked store (#6)
Replace Makefile with Taskfile.yml Reorder Domains.Update so refreshRows runs after table.Update Translate bbolt timeout to store.ErrLocked with clear CLI message
1 parent f21e89c commit c213f3e

6 files changed

Lines changed: 79 additions & 40 deletions

File tree

Makefile

Lines changed: 0 additions & 37 deletions
This file was deleted.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ xattr -d com.apple.quarantine ./mkdev
7171
```sh
7272
git clone https://github.com/venkatkrishna07/mkdev.git
7373
cd mkdev
74-
make build
74+
task build
7575
cp bin/mkdev ~/bin/ # or /usr/local/bin
7676
```
7777

Taskfile.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
version: '3'
2+
3+
vars:
4+
BIN: bin/mkdev
5+
PKG: ./...
6+
GOFLAGS: -trimpath
7+
VERSION:
8+
sh: git describe --tags --dirty --always 2>/dev/null || echo "dev"
9+
COMMIT:
10+
sh: git rev-parse --short HEAD 2>/dev/null || echo "none"
11+
DATE:
12+
sh: date -u +%Y-%m-%dT%H:%M:%SZ
13+
LDFLAGS: >-
14+
-X github.com/venkatkrishna07/mkdev/internal/version.Version={{.VERSION}}
15+
-X github.com/venkatkrishna07/mkdev/internal/version.Commit={{.COMMIT}}
16+
-X github.com/venkatkrishna07/mkdev/internal/version.Date={{.DATE}}
17+
18+
tasks:
19+
default:
20+
desc: List tasks
21+
cmds:
22+
- task --list
23+
24+
build:
25+
desc: Build mkdev binary
26+
cmds:
27+
- mkdir -p bin
28+
- go build {{.GOFLAGS}} -ldflags "{{.LDFLAGS}}" -o {{.BIN}} ./cmd/mkdev
29+
30+
test:
31+
desc: Run tests with race detector
32+
cmds:
33+
- go test {{.GOFLAGS}} -race -count=1 -timeout=60s {{.PKG}}
34+
35+
lint:
36+
desc: Run golangci-lint
37+
cmds:
38+
- golangci-lint run
39+
40+
run:
41+
desc: Build and run mkdev
42+
deps: [build]
43+
cmds:
44+
- "{{.BIN}}"
45+
46+
coverage:
47+
desc: Run tests with coverage report
48+
cmds:
49+
- go test {{.GOFLAGS}} -race -count=1 -coverprofile=coverage.txt -covermode=atomic {{.PKG}}
50+
- go tool cover -func=coverage.txt | tail -1
51+
52+
tidy:
53+
desc: Tidy modules and format code
54+
cmds:
55+
- go mod tidy
56+
- gofmt -w .
57+
58+
clean:
59+
desc: Remove build artifacts
60+
cmds:
61+
- rm -rf bin coverage.txt

internal/cli/root.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package cli
22

33
import (
4+
"errors"
5+
"fmt"
46
"log/slog"
57
"os"
68
"path/filepath"
79

810
"github.com/spf13/cobra"
11+
"github.com/venkatkrishna07/mkdev/internal/store"
912
"github.com/venkatkrishna07/mkdev/internal/version"
1013
)
1114

@@ -55,6 +58,11 @@ func New() *cobra.Command {
5558
// Execute runs the root command and returns its exit code.
5659
func Execute() int {
5760
if err := New().Execute(); err != nil {
61+
if errors.Is(err, store.ErrLocked) {
62+
fmt.Fprintln(os.Stderr, "mkdev: another instance is already running (state.db is locked).")
63+
fmt.Fprintln(os.Stderr, " quit the running instance and try again.")
64+
return 1
65+
}
5866
slog.Error("command failed", "err", err)
5967
return 1
6068
}

internal/store/store.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ import (
88
"time"
99

1010
bolt "go.etcd.io/bbolt"
11+
bolterrors "go.etcd.io/bbolt/errors"
1112
)
1213

1314
var bucketRoutes = []byte("routes")
1415

1516
// ErrNotFound is returned when a record does not exist.
1617
var ErrNotFound = errors.New("store: not found")
1718

19+
// ErrLocked is returned when the database file is held by another process.
20+
var ErrLocked = errors.New("store: database locked by another process")
21+
1822
// Store wraps a bbolt database.
1923
type Store struct {
2024
db *bolt.DB
@@ -27,6 +31,9 @@ func Open(path string) (*Store, error) {
2731
}
2832
db, err := bolt.Open(path, 0o600, &bolt.Options{Timeout: 2 * time.Second})
2933
if err != nil {
34+
if errors.Is(err, bolterrors.ErrTimeout) {
35+
return nil, fmt.Errorf("%w: %s", ErrLocked, path)
36+
}
3037
return nil, fmt.Errorf("store: open %s: %w", path, err)
3138
}
3239
err = db.Update(func(tx *bolt.Tx) error {

internal/tui/tabs/domains.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ func (d Domains) Init() tea.Cmd { return nil }
114114

115115
// Update handles route refresh and window-size events.
116116
func (d Domains) Update(in tea.Msg) (Domains, tea.Cmd) {
117+
var cmd tea.Cmd
118+
d.table, cmd = d.table.Update(in)
117119
switch m := in.(type) {
118120
case msg.RoutesRefreshed:
119121
d.routes = m.Routes
@@ -126,8 +128,6 @@ func (d Domains) Update(in tea.Msg) (Domains, tea.Cmd) {
126128
d.table.SetWidth(tableTotalWidth(cols))
127129
d.fitHeight()
128130
}
129-
var cmd tea.Cmd
130-
d.table, cmd = d.table.Update(in)
131131
return d, cmd
132132
}
133133

0 commit comments

Comments
 (0)