diff options
Diffstat (limited to 'atomictemp/atomictemp.go')
-rw-r--r-- | atomictemp/atomictemp.go | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/atomictemp/atomictemp.go b/atomictemp/atomictemp.go new file mode 100644 index 0000000..b56d095 --- /dev/null +++ b/atomictemp/atomictemp.go @@ -0,0 +1,48 @@ +// Create a temporary file in the directory of the given destination +// file, then rename the temporary file over the destination file if +// writes to the temporary file complete without error. +// +// Used to atomically update files. +// +// Note: This is not guaranteed and depends on the sync semantics of the +// underlying filesystem. +package atomictemp + +import ( + "io" + "os" + "path/filepath" +) + +// Create a temporary file in the directory of the given destination +// file, then rename the temporary file over the destination file if +// writes to the temporary file complete without error. +// +// Used to atomically update files. +// +// Note: This is not guaranteed and depends on the sync semantics of the +// underlying filesystem. +func Create(dstPath string, fn func(io.Writer) error) error { + // open temp output file + f, err := os.CreateTemp(filepath.Dir(dstPath), "") + if err != nil { + return err + } + + // build absolute path to temporary file + // tmpPath := filepath.Join(filepath.Dir(dstPath), f.Name()) + defer os.Remove(f.Name()) + + // invoke callback + if err = fn(f); err != nil { + return err + } + + // close temp file + if err = f.Close(); err != nil { + return err + } + + // rename to destination file, return result + return os.Rename(f.Name(), dstPath) +} |