From b783f57e0135a033eeedae913473a4c07a7bc0fe Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Tue, 15 Sep 2020 06:39:35 +0000 Subject: [PATCH] writeConfig operations are atomic --- viper.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/viper.go b/viper.go index c3130c2..cc1a4f1 100644 --- a/viper.go +++ b/viper.go @@ -1490,17 +1490,27 @@ func (v *Viper) writeConfig(filename string, force bool) error { if v.config == nil { v.config = make(map[string]interface{}) } - flags := os.O_CREATE | os.O_TRUNC | os.O_WRONLY - if !force { - flags |= os.O_EXCL - } - f, err := v.fs.OpenFile(filename, flags, v.configPermissions) + + exists, err := afero.Exists(v.fs, filename) + if err != nil { + return err + } + if exists && !force { + return fmt.Errorf("file already exists: %s", filename) + } + f, err := afero.TempFile(v.fs, filepath.Dir(filename), filepath.Base(filename)+"-") if err != nil { return err } - defer f.Close() if err := v.marshalWriter(f, configType); err != nil { + f.Close() + return err + } + f.Close() + + err = v.fs.Rename(f.Name(), filename) + if err != nil { return err }