Skip to content

Commit 50058df

Browse files
committed
Add edit command to config
1 parent 69276e5 commit 50058df

File tree

2 files changed

+81
-10
lines changed

2 files changed

+81
-10
lines changed

cmd/meshexec/cli_test.go

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

33
import (
4+
"os"
5+
"path/filepath"
46
"testing"
57

68
core "github.com/monster0506/meshexec/internal"
@@ -181,3 +183,65 @@ func TestCloneFlags_ParsingOnly(t *testing.T) {
181183
t.Fatalf("unexpected clone flags: target=%q dest=%q", cloneTarget, cloneDest)
182184
}
183185
}
186+
187+
func TestConfigEdit_InvokesEditorWithExistingFile(t *testing.T) {
188+
// Arrange stub editor
189+
oldRun := configRunEditor
190+
defer func() { configRunEditor = oldRun }()
191+
called := false
192+
var gotEditor string
193+
var gotArgs []string
194+
configRunEditor = func(editor string, args []string) error {
195+
called = true
196+
gotEditor = editor
197+
gotArgs = append([]string(nil), args...)
198+
return nil
199+
}
200+
201+
// Use a temporary config file
202+
tmp, err := os.CreateTemp(t.TempDir(), "cfg-*.toml")
203+
if err != nil {
204+
t.Fatalf("temp file: %v", err)
205+
}
206+
_ = tmp.Close()
207+
208+
// Act
209+
execArgs(t, "-c", tmp.Name(), "config", "edit")
210+
211+
// Assert
212+
if !called {
213+
t.Fatalf("expected editor to be invoked")
214+
}
215+
if gotEditor == "" {
216+
t.Fatalf("expected an editor command to be chosen")
217+
}
218+
if len(gotArgs) == 0 || gotArgs[len(gotArgs)-1] != tmp.Name() {
219+
t.Fatalf("expected editor args to end with config path; args=%v path=%q", gotArgs, tmp.Name())
220+
}
221+
}
222+
223+
func TestConfigEdit_CreatesDefaultWhenMissing(t *testing.T) {
224+
// Arrange: stub editor to no-op
225+
oldRun := configRunEditor
226+
defer func() { configRunEditor = oldRun }()
227+
configRunEditor = func(editor string, args []string) error { return nil }
228+
229+
// Use path inside temp dir that does not exist yet
230+
dir := t.TempDir()
231+
cfgPath := filepath.Join(dir, "config.toml")
232+
if _, err := os.Stat(cfgPath); !os.IsNotExist(err) {
233+
t.Fatalf("expected non-existent path for test, got err=%v", err)
234+
}
235+
236+
// Act
237+
execArgs(t, "-c", cfgPath, "config", "edit")
238+
239+
// Assert: file should now exist and be non-empty
240+
st, err := os.Stat(cfgPath)
241+
if err != nil {
242+
t.Fatalf("expected config file to be created: %v", err)
243+
}
244+
if st.Size() == 0 {
245+
t.Fatalf("expected created config to be non-empty")
246+
}
247+
}

cmd/meshexec/config.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"strings"
1010

1111
"github.com/monster0506/meshexec/internal"
12-
"github.com/monster0506/meshexec/internal/config"
1312
"github.com/spf13/cobra"
1413
)
1514

@@ -19,6 +18,18 @@ var configCmd = &cobra.Command{
1918
Long: `Manage MeshExec CLI configuration files and settings.`,
2019
}
2120

21+
// indirections for testability
22+
var (
23+
// configNewManagerWithLevel is declared in network.go for package-wide reuse
24+
configRunEditor = func(editor string, argsWithFile []string) error {
25+
c := exec.Command(editor, argsWithFile...)
26+
c.Stdin = os.Stdin
27+
c.Stdout = os.Stdout
28+
c.Stderr = os.Stderr
29+
return c.Run()
30+
}
31+
)
32+
2233
var configShowCmd = &cobra.Command{
2334
Use: "show",
2435
Short: "Show current configuration",
@@ -28,7 +39,7 @@ var configShowCmd = &cobra.Command{
2839
if verbose {
2940
logLevel = "debug"
3041
}
31-
manager := config.NewManagerWithLevel(logLevel)
42+
manager := configNewManagerWithLevel(logLevel)
3243

3344
// Get config path from global flags
3445
configPath, _ := cmd.Root().PersistentFlags().GetString("config")
@@ -64,7 +75,7 @@ var configInitCmd = &cobra.Command{
6475
if verbose {
6576
logLevel = "debug"
6677
}
67-
manager := config.NewManagerWithLevel(logLevel)
78+
manager := configNewManagerWithLevel(logLevel)
6879

6980
// Get config path from global flags
7081
configPath, _ := cmd.Root().PersistentFlags().GetString("config")
@@ -92,7 +103,7 @@ var configEditCmd = &cobra.Command{
92103
if verbose {
93104
logLevel = "debug"
94105
}
95-
manager := config.NewManagerWithLevel(logLevel)
106+
manager := configNewManagerWithLevel(logLevel)
96107

97108
// Respect global --config path
98109
if configPath, _ := cmd.Root().PersistentFlags().GetString("config"); configPath != "" {
@@ -157,11 +168,7 @@ var configEditCmd = &cobra.Command{
157168
logger.Info("config edit: opening editor", map[string]interface{}{"editor": editor, "args": strings.Join(editorArgs, " "), "path": cfgPath})
158169
}
159170

160-
c := exec.Command(editor, argsWithFile...)
161-
c.Stdin = os.Stdin
162-
c.Stdout = os.Stdout
163-
c.Stderr = os.Stderr
164-
if err := c.Run(); err != nil {
171+
if err := configRunEditor(editor, argsWithFile); err != nil {
165172
me := internal.NewConfigError("editor_failed", "failed to open editor", map[string]interface{}{"editor": editor, "error": err.Error()})
166173
fmt.Fprintln(os.Stderr, internal.FormatUserError(me))
167174
os.Exit(1)
@@ -188,7 +195,7 @@ var configValidateCmd = &cobra.Command{
188195
if verbose {
189196
logLevel = "debug"
190197
}
191-
manager := config.NewManagerWithLevel(logLevel)
198+
manager := configNewManagerWithLevel(logLevel)
192199
configPath, _ := cmd.Root().PersistentFlags().GetString("config")
193200
if configPath != "" {
194201
manager.SetConfigPath(configPath)

0 commit comments

Comments
 (0)