From c36305cb3873d7e327517f232c5ace88aa0578fa Mon Sep 17 00:00:00 2001 From: "Brandon McGinty (chatgpt)" Date: Sun, 9 Aug 2026 14:23:12 -0400 Subject: [PATCH] Return configuration save failures --- config/user_config.go | 20 +++++++++++--------- config/user_config_save_test.go | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 config/user_config_save_test.go diff --git a/config/user_config.go b/config/user_config.go index 79d2f3d..460cecd 100644 --- a/config/user_config.go +++ b/config/user_config.go @@ -46,20 +46,22 @@ type eUser struct { LocallyMuted bool // Changed from Muted to LocallyMuted to match User struct } -func (c *Config) SaveConfig() { - var data []byte +// SaveConfig atomically replaces the persisted configuration. Errors are +// returned so an unavailable directory cannot crash the client. +func (c *Config) SaveConfig() error { data, err := toml.Marshal(c.config) if err != nil { - panic(err) + return err } - err = ioutil.WriteFile(c.fn+".tmp", data, 0600) - if err != nil { - panic(err) + tmp := c.fn + ".tmp" + if err := ioutil.WriteFile(tmp, data, 0600); err != nil { + return err } - err = os.Rename(c.fn+".tmp", c.fn) - if err != nil { - panic(err) + if err := os.Rename(tmp, c.fn); err != nil { + _ = os.Remove(tmp) + return err } + return nil } func key(k uiterm.Key) *uiterm.Key { diff --git a/config/user_config_save_test.go b/config/user_config_save_test.go new file mode 100644 index 0000000..bcf65cd --- /dev/null +++ b/config/user_config_save_test.go @@ -0,0 +1,16 @@ +package config + +import ( + "path/filepath" + "testing" +) + +// Regression: a configuration write failure panicked the client instead of +// returning an error to the caller. +func TestSaveConfigReturnsWriteError(t *testing.T) { + path := filepath.Join(t.TempDir(), "missing", "barnard.toml") + cfg := NewConfig(&path) + if err := cfg.SaveConfig(); err == nil { + t.Fatal("expected configuration write error") + } +}