Skip to content

Commit 6f145c1

Browse files
Merge pull request #354 from rest-sh/fix/config-edit-write-message-main
fix: suppress unchanged config edit writes
2 parents 118150a + ca6af63 commit 6f145c1

2 files changed

Lines changed: 77 additions & 5 deletions

File tree

internal/cli/api.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"errors"
77
"fmt"
88
"net/http"
9+
"os"
910
"reflect"
1011
"sort"
1112
"strings"
13+
"time"
1214

1315
"github.com/rest-sh/restish/v2/internal/auth"
1416
"github.com/rest-sh/restish/v2/internal/cache"
@@ -1142,6 +1144,10 @@ func (c *CLI) runAPIInspect(cmd *cobra.Command, args []string) error {
11421144
func (c *CLI) runConfigEdit(cmd *cobra.Command, args []string) error {
11431145
cfgPath := c.configFilePath()
11441146
oldCfg := c.cfg
1147+
before, err := statConfigEditFile(cfgPath)
1148+
if err != nil {
1149+
return err
1150+
}
11451151
editorCmd, err := c.editorCommand(cfgPath)
11461152
if err != nil {
11471153
return err
@@ -1155,10 +1161,47 @@ func (c *CLI) runConfigEdit(cmd *cobra.Command, args []string) error {
11551161
if err := c.reloadConfigAfterMutation("config edit", oldCfg); err != nil {
11561162
return err
11571163
}
1158-
c.printConfigWrittenPath()
1164+
after, err := statConfigEditFile(cfgPath)
1165+
if err != nil {
1166+
return err
1167+
}
1168+
if after.changedFrom(before) {
1169+
c.printConfigWrittenPath()
1170+
}
11591171
return nil
11601172
}
11611173

1174+
type configEditFileState struct {
1175+
exists bool
1176+
modTime time.Time
1177+
size int64
1178+
}
1179+
1180+
func statConfigEditFile(path string) (configEditFileState, error) {
1181+
info, err := os.Stat(path)
1182+
if errors.Is(err, os.ErrNotExist) {
1183+
return configEditFileState{}, nil
1184+
}
1185+
if err != nil {
1186+
return configEditFileState{}, err
1187+
}
1188+
return configEditFileState{
1189+
exists: true,
1190+
modTime: info.ModTime(),
1191+
size: info.Size(),
1192+
}, nil
1193+
}
1194+
1195+
func (s configEditFileState) changedFrom(old configEditFileState) bool {
1196+
if s.exists != old.exists {
1197+
return true
1198+
}
1199+
if !s.exists {
1200+
return false
1201+
}
1202+
return !s.modTime.Equal(old.modTime) || s.size != old.size
1203+
}
1204+
11621205
func apiNamesWithSpecCacheRelevantChanges(oldCfg, newCfg *config.Config) []string {
11631206
namesSeen := map[string]struct{}{}
11641207
if oldCfg != nil {

internal/cli/api_test.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,10 @@ func TestFlagHeaderTakesPrecedenceOverProfile(t *testing.T) {
222222
}
223223
}
224224

225-
// TestAPIEditUsesCliStdout verifies that runAPIEdit wires the editor subprocess
226-
// to c.Stdout rather than os.Stdout, so embedders that redirect c.Stdout capture
227-
// any output the editor produces.
228-
func TestAPIEditUsesCliStdout(t *testing.T) {
225+
// TestConfigEditUsesCliStdout verifies that runConfigEdit wires the editor
226+
// subprocess to c.Stdout rather than os.Stdout, so embedders that redirect
227+
// c.Stdout capture any output the editor produces.
228+
func TestConfigEditUsesCliStdout(t *testing.T) {
229229
if runtime.GOOS == "windows" {
230230
t.Skip("editor test uses a POSIX shell script")
231231
}
@@ -253,6 +253,35 @@ func TestAPIEditUsesCliStdout(t *testing.T) {
253253
if !strings.Contains(out.String(), "editor-stdout") {
254254
t.Errorf("expected editor stdout in c.Stdout, got: %q", out.String())
255255
}
256+
if strings.Contains(out.String(), "Wrote config:") {
257+
t.Errorf("expected unchanged config edit not to print written path, got: %q", out.String())
258+
}
259+
}
260+
261+
func TestConfigEditPrintsWrittenPathWhenFileChanges(t *testing.T) {
262+
if runtime.GOOS == "windows" {
263+
t.Skip("editor test uses a POSIX shell script")
264+
}
265+
266+
dir := t.TempDir()
267+
268+
scriptPath := filepath.Join(dir, "editor.sh")
269+
if err := os.WriteFile(scriptPath, []byte("#!/bin/sh\nprintf '{\"theme\":{\"ok\":\"green\"}}\\n' > \"$1\"\n"), 0o755); err != nil {
270+
t.Fatal(err)
271+
}
272+
t.Setenv("VISUAL", scriptPath)
273+
t.Setenv("EDITOR", "")
274+
275+
c, out, _ := newTestCLI(t)
276+
cfgPath := filepath.Join(dir, "restish.json")
277+
if err := os.WriteFile(cfgPath, []byte("{}"), 0o600); err != nil {
278+
t.Fatal(err)
279+
}
280+
c.Hooks().ConfigPath = cfgPath
281+
282+
if err := c.Run([]string{"restish", "config", "edit"}); err != nil {
283+
t.Fatalf("config edit: %v", err)
284+
}
256285
if !strings.Contains(out.String(), "Wrote config: "+cfgPath) {
257286
t.Errorf("expected written config path in c.Stdout, got: %q", out.String())
258287
}

0 commit comments

Comments
 (0)