detached 6489acf

fix(kill): address review feedback

commit
6489acff9605f1ffe0f9b690bbf5f6dd8b25e398
author
brice · · 2026-07-03 07:30 UTC
parent
cd05aa6
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
6 files · +18 -12
M README.md +2 -2
@@ -19,8 +19,8 @@ vev attach <name> attach to an existing named session (alias: a)
1919 vev attach user@host[:session] attach to a remote vev daemon over SSH
2020 vev ls list sessions
2121 vev kill <name> kill a named session
22-vev kill --all kill all sessions
23-vev kill --daemon kill the active vev daemon
22+vev kill --all kill all sessions and stop the daemon
23+vev kill --daemon stop the active vev daemon
2424 vev --help show help
2525 vev --version show version
2626 ```
@@ -19,8 +19,8 @@ vev attach <name> attach to an existing named session (alias: a)
19 vev attach user@host[:session] attach to a remote vev daemon over SSH19 vev attach user@host[:session] attach to a remote vev daemon over SSH
20 vev ls list sessions20 vev ls list sessions
21 vev kill <name> kill a named session21 vev kill <name> kill a named session
22-vev kill --all kill all sessions22+vev kill --all kill all sessions and stop the daemon
23-vev kill --daemon kill the active vev daemon23+vev kill --daemon stop the active vev daemon
24 vev --help show help24 vev --help show help
25 vev --version show version25 vev --version show version
26 ```26 ```
M internal/app/daemon_integration_test.go +1 -0
@@ -197,6 +197,7 @@ func TestIntegration_KillAllShutsDownDaemon(t *testing.T) {
197197
198198 killTr, err := ipc.Dial(dir)
199199 require.NoError(t, err)
200+ defer func() { _ = killTr.Close() }()
200201 require.NoError(t, killTr.Send(ports.Frame{Type: ports.MsgKill, Payload: ports.MarshalKill(ports.Kill{All: true})}))
201202
202203 _, err = killTr.Recv()
@@ -197,6 +197,7 @@ func TestIntegration_KillAllShutsDownDaemon(t *testing.T) {
197 197
198 killTr, err := ipc.Dial(dir)198 killTr, err := ipc.Dial(dir)
199 require.NoError(t, err)199 require.NoError(t, err)
200+ defer func() { _ = killTr.Close() }()
200 require.NoError(t, killTr.Send(ports.Frame{Type: ports.MsgKill, Payload: ports.MarshalKill(ports.Kill{All: true})}))201 require.NoError(t, killTr.Send(ports.Frame{Type: ports.MsgKill, Payload: ports.MarshalKill(ports.Kill{All: true})}))
201 202
202 _, err = killTr.Recv()203 _, err = killTr.Recv()
M internal/app/run.go +9 -3
@@ -71,8 +71,8 @@ usage:
7171 attach through SSH to a remote vev daemon
7272 vev ls list sessions
7373 vev kill <name> kill a named session
74- vev kill --all kill all sessions
75- vev kill --daemon kill the active vev daemon
74+ vev kill --all kill all sessions and stop the daemon
75+ vev kill --daemon stop the active vev daemon
7676 vev --help show this help
7777 vev --version show version`
7878
@@ -140,6 +140,12 @@ func parseArgs(args []string) (command, error) {
140140 if len(args) < 2 || args[1] == "" {
141141 return command{}, usagef("`kill` requires a session name, --all, or --daemon")
142142 }
143+ if args[1] == "--" {
144+ if len(args) != 3 || args[2] == "" {
145+ return command{}, usagef("`kill --` requires a session name")
146+ }
147+ return command{kind: kindKill, name: args[2]}, nil
148+ }
143149 if len(args) > 2 {
144150 return command{}, usagef("`kill` accepts exactly one session name, --all, or --daemon")
145151 }
@@ -374,7 +380,7 @@ func printKillSuccess(name string, all, daemon bool) {
374380 return
375381 }
376382 if all {
377- fmt.Println("killed all sessions")
383+ fmt.Println("killed all sessions and stopped daemon")
378384 return
379385 }
380386 fmt.Printf("killed %s\n", name)
@@ -71,8 +71,8 @@ usage:
71 attach through SSH to a remote vev daemon71 attach through SSH to a remote vev daemon
72 vev ls list sessions72 vev ls list sessions
73 vev kill <name> kill a named session73 vev kill <name> kill a named session
74- vev kill --all kill all sessions74+ vev kill --all kill all sessions and stop the daemon
75- vev kill --daemon kill the active vev daemon75+ vev kill --daemon stop the active vev daemon
76 vev --help show this help76 vev --help show this help
77 vev --version show version`77 vev --version show version`
78 78
@@ -140,6 +140,12 @@ func parseArgs(args []string) (command, error) {
140 if len(args) < 2 || args[1] == "" {140 if len(args) < 2 || args[1] == "" {
141 return command{}, usagef("`kill` requires a session name, --all, or --daemon")141 return command{}, usagef("`kill` requires a session name, --all, or --daemon")
142 }142 }
143+ if args[1] == "--" {
144+ if len(args) != 3 || args[2] == "" {
145+ return command{}, usagef("`kill --` requires a session name")
146+ }
147+ return command{kind: kindKill, name: args[2]}, nil
148+ }
143 if len(args) > 2 {149 if len(args) > 2 {
144 return command{}, usagef("`kill` accepts exactly one session name, --all, or --daemon")150 return command{}, usagef("`kill` accepts exactly one session name, --all, or --daemon")
145 }151 }
@@ -374,7 +380,7 @@ func printKillSuccess(name string, all, daemon bool) {
374 return380 return
375 }381 }
376 if all {382 if all {
377- fmt.Println("killed all sessions")383+ fmt.Println("killed all sessions and stopped daemon")
378 return384 return
379 }385 }
380 fmt.Printf("killed %s\n", name)386 fmt.Printf("killed %s\n", name)
M internal/app/run_test.go +2 -0
@@ -35,9 +35,11 @@ func TestParseArgs(t *testing.T) {
3535 {name: "ls", args: []string{"ls"}, wantKind: kindList},
3636 {name: "list", args: []string{"list"}, wantKind: kindList},
3737 {name: "kill named", args: []string{"kill", "work"}, wantKind: kindKill, wantName: "work"},
38+ {name: "kill dashed name via terminator", args: []string{"kill", "--", "--all"}, wantKind: kindKill, wantName: "--all"},
3839 {name: "kill all", args: []string{"kill", "--all"}, wantKind: kindKill, wantAll: true},
3940 {name: "kill daemon", args: []string{"kill", "--daemon"}, wantKind: kindKill, wantDaemon: true},
4041 {name: "kill without name", args: []string{"kill"}, wantErr: true},
42+ {name: "kill terminator without name", args: []string{"kill", "--"}, wantErr: true},
4143 {name: "kill all rejects extra arg", args: []string{"kill", "--all", "extra"}, wantErr: true},
4244 {name: "kill daemon rejects extra arg", args: []string{"kill", "--daemon", "extra"}, wantErr: true},
4345 {name: "kill extra arg", args: []string{"kill", "work", "extra"}, wantErr: true},
@@ -35,9 +35,11 @@ func TestParseArgs(t *testing.T) {
35 {name: "ls", args: []string{"ls"}, wantKind: kindList},35 {name: "ls", args: []string{"ls"}, wantKind: kindList},
36 {name: "list", args: []string{"list"}, wantKind: kindList},36 {name: "list", args: []string{"list"}, wantKind: kindList},
37 {name: "kill named", args: []string{"kill", "work"}, wantKind: kindKill, wantName: "work"},37 {name: "kill named", args: []string{"kill", "work"}, wantKind: kindKill, wantName: "work"},
38+ {name: "kill dashed name via terminator", args: []string{"kill", "--", "--all"}, wantKind: kindKill, wantName: "--all"},
38 {name: "kill all", args: []string{"kill", "--all"}, wantKind: kindKill, wantAll: true},39 {name: "kill all", args: []string{"kill", "--all"}, wantKind: kindKill, wantAll: true},
39 {name: "kill daemon", args: []string{"kill", "--daemon"}, wantKind: kindKill, wantDaemon: true},40 {name: "kill daemon", args: []string{"kill", "--daemon"}, wantKind: kindKill, wantDaemon: true},
40 {name: "kill without name", args: []string{"kill"}, wantErr: true},41 {name: "kill without name", args: []string{"kill"}, wantErr: true},
42+ {name: "kill terminator without name", args: []string{"kill", "--"}, wantErr: true},
41 {name: "kill all rejects extra arg", args: []string{"kill", "--all", "extra"}, wantErr: true},43 {name: "kill all rejects extra arg", args: []string{"kill", "--all", "extra"}, wantErr: true},
42 {name: "kill daemon rejects extra arg", args: []string{"kill", "--daemon", "extra"}, wantErr: true},44 {name: "kill daemon rejects extra arg", args: []string{"kill", "--daemon", "extra"}, wantErr: true},
43 {name: "kill extra arg", args: []string{"kill", "work", "extra"}, wantErr: true},45 {name: "kill extra arg", args: []string{"kill", "work", "extra"}, wantErr: true},
M internal/ports/wire.go +0 -2
@@ -430,8 +430,6 @@ func MarshalKill(m Kill) []byte {
430430 w.putString(m.Name)
431431 if m.All {
432432 w.putUint8(1)
433- } else {
434- w.putUint8(0)
435433 }
436434 return w.b
437435 }
@@ -430,8 +430,6 @@ func MarshalKill(m Kill) []byte {
430 w.putString(m.Name)430 w.putString(m.Name)
431 if m.All {431 if m.All {
432 w.putUint8(1)432 w.putUint8(1)
433- } else {
434- w.putUint8(0)
435 }433 }
436 return w.b434 return w.b
437 }435 }
M internal/ports/wire_test.go +4 -5
@@ -319,8 +319,8 @@ func TestKillGoldenAndRoundTrip(t *testing.T) {
319319 msg Kill
320320 want []byte
321321 }{
322- {name: "named", msg: Kill{Name: "main"}, want: []byte{0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x00}},
323- {name: "empty", msg: Kill{Name: ""}, want: []byte{0x00, 0x00, 0x00}},
322+ {name: "named", msg: Kill{Name: "main"}, want: []byte{0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e}},
323+ {name: "empty", msg: Kill{Name: ""}, want: []byte{0x00, 0x00}},
324324 {name: "all", msg: Kill{All: true}, want: []byte{0x00, 0x00, 0x01}},
325325 }
326326
@@ -340,8 +340,7 @@ func TestKillGoldenAndRoundTrip(t *testing.T) {
340340 })
341341 }
342342
343- full := MarshalKill(tests[0].msg)
344- legacy := full[:len(full)-1]
343+ legacy := MarshalKill(tests[0].msg)
345344 back, err := UnmarshalKill(legacy)
346345 if err != nil {
347346 t.Fatalf("UnmarshalKill(legacy) error = %v", err)
@@ -350,7 +349,7 @@ func TestKillGoldenAndRoundTrip(t *testing.T) {
350349 t.Fatalf("legacy round trip = %#v, want named kill", back)
351350 }
352351 assertAllPrefixesFail(t, legacy, UnmarshalKill)
353- assertTrailingGarbageFails(t, full, UnmarshalKill)
352+ assertTrailingGarbageFails(t, append(append([]byte(nil), legacy...), 0x00), UnmarshalKill)
354353 }
355354
356355 func TestSessionsGoldenAndRoundTrip(t *testing.T) {
@@ -319,8 +319,8 @@ func TestKillGoldenAndRoundTrip(t *testing.T) {
319 msg Kill319 msg Kill
320 want []byte320 want []byte
321 }{321 }{
322- {name: "named", msg: Kill{Name: "main"}, want: []byte{0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x00}},322+ {name: "named", msg: Kill{Name: "main"}, want: []byte{0x00, 0x04, 0x6d, 0x61, 0x69, 0x6e}},
323- {name: "empty", msg: Kill{Name: ""}, want: []byte{0x00, 0x00, 0x00}},323+ {name: "empty", msg: Kill{Name: ""}, want: []byte{0x00, 0x00}},
324 {name: "all", msg: Kill{All: true}, want: []byte{0x00, 0x00, 0x01}},324 {name: "all", msg: Kill{All: true}, want: []byte{0x00, 0x00, 0x01}},
325 }325 }
326 326
@@ -340,8 +340,7 @@ func TestKillGoldenAndRoundTrip(t *testing.T) {
340 })340 })
341 }341 }
342 342
343- full := MarshalKill(tests[0].msg)343+ legacy := MarshalKill(tests[0].msg)
344- legacy := full[:len(full)-1]
345 back, err := UnmarshalKill(legacy)344 back, err := UnmarshalKill(legacy)
346 if err != nil {345 if err != nil {
347 t.Fatalf("UnmarshalKill(legacy) error = %v", err)346 t.Fatalf("UnmarshalKill(legacy) error = %v", err)
@@ -350,7 +349,7 @@ func TestKillGoldenAndRoundTrip(t *testing.T) {
350 t.Fatalf("legacy round trip = %#v, want named kill", back)349 t.Fatalf("legacy round trip = %#v, want named kill", back)
351 }350 }
352 assertAllPrefixesFail(t, legacy, UnmarshalKill)351 assertAllPrefixesFail(t, legacy, UnmarshalKill)
353- assertTrailingGarbageFails(t, full, UnmarshalKill)352+ assertTrailingGarbageFails(t, append(append([]byte(nil), legacy...), 0x00), UnmarshalKill)
354 }353 }
355 354
356 func TestSessionsGoldenAndRoundTrip(t *testing.T) {355 func TestSessionsGoldenAndRoundTrip(t *testing.T) {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close