.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / internal / renameio / renameio.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/internal/renameio/renameio.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/internal/renameio/renameio.go
new file mode 100644 (file)
index 0000000..5e0dfa2
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package renameio writes files atomically by renaming temporary files.
+package renameio
+
+import (
+       "bytes"
+       "io"
+       "math/rand"
+       "os"
+       "path/filepath"
+       "strconv"
+
+       "honnef.co/go/tools/internal/robustio"
+)
+
+const patternSuffix = ".tmp"
+
+// Pattern returns a glob pattern that matches the unrenamed temporary files
+// created when writing to filename.
+func Pattern(filename string) string {
+       return filepath.Join(filepath.Dir(filename), filepath.Base(filename)+patternSuffix)
+}
+
+// WriteFile is like ioutil.WriteFile, but first writes data to an arbitrary
+// file in the same directory as filename, then renames it atomically to the
+// final name.
+//
+// That ensures that the final location, if it exists, is always a complete file.
+func WriteFile(filename string, data []byte, perm os.FileMode) (err error) {
+       return WriteToFile(filename, bytes.NewReader(data), perm)
+}
+
+// WriteToFile is a variant of WriteFile that accepts the data as an io.Reader
+// instead of a slice.
+func WriteToFile(filename string, data io.Reader, perm os.FileMode) (err error) {
+       f, err := tempFile(filepath.Dir(filename), filepath.Base(filename), perm)
+       if err != nil {
+               return err
+       }
+       defer func() {
+               // Only call os.Remove on f.Name() if we failed to rename it: otherwise,
+               // some other process may have created a new file with the same name after
+               // that.
+               if err != nil {
+                       f.Close()
+                       os.Remove(f.Name())
+               }
+       }()
+
+       if _, err := io.Copy(f, data); err != nil {
+               return err
+       }
+       // Sync the file before renaming it: otherwise, after a crash the reader may
+       // observe a 0-length file instead of the actual contents.
+       // See https://golang.org/issue/22397#issuecomment-380831736.
+       if err := f.Sync(); err != nil {
+               return err
+       }
+       if err := f.Close(); err != nil {
+               return err
+       }
+
+       return robustio.Rename(f.Name(), filename)
+}
+
+// ReadFile is like ioutil.ReadFile, but on Windows retries spurious errors that
+// may occur if the file is concurrently replaced.
+//
+// Errors are classified heuristically and retries are bounded, so even this
+// function may occasionally return a spurious error on Windows.
+// If so, the error will likely wrap one of:
+//     - syscall.ERROR_ACCESS_DENIED
+//     - syscall.ERROR_FILE_NOT_FOUND
+//     - internal/syscall/windows.ERROR_SHARING_VIOLATION
+func ReadFile(filename string) ([]byte, error) {
+       return robustio.ReadFile(filename)
+}
+
+// tempFile creates a new temporary file with given permission bits.
+func tempFile(dir, prefix string, perm os.FileMode) (f *os.File, err error) {
+       for i := 0; i < 10000; i++ {
+               name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+patternSuffix)
+               f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm)
+               if os.IsExist(err) {
+                       continue
+               }
+               break
+       }
+       return
+}