func AtomicWrite(path string, createDestDirs bool, contents []byte, perms os.FileMode, backup bool) error {
	if path == "" {
		return ErrMissingDest
	}

	parent := filepath.Dir(path)
	if _, err := os.Stat(parent); os.IsNotExist(err) {
		if createDestDirs {
			if err := os.MkdirAll(parent, 0755); err != nil {
				return err
			}
		} else {
			return ErrNoParentDir
		}
	}

	f, err := ioutil.TempFile(parent, "")
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())

	if _, err := f.Write(contents); err != nil {
		return err
	}

	if err := f.Sync(); err != nil {
		return err
	}

	if err := f.Close(); err != nil {
		return err
	}

	// If the user did not explicitly set permissions, attempt to lookup the
	// current permissions on the file. If the file does not exist, fall back to
	// the default. Otherwise, inherit the current permissions.
	if perms == 0 {
		currentInfo, err := os.Stat(path)
		if err != nil {
			if os.IsNotExist(err) {
				perms = DefaultFilePerms
			} else {
				return err
			}
		} else {
			perms = currentInfo.Mode()

			// The file exists, so try to preserve the ownership as well.
			if err := preserveFilePermissions(f.Name(), currentInfo); err != nil {
				log.Printf("[WARN] (runner) could not preserve file permissions for %q: %v",
					f.Name(), err)
			}
		}
	}

	if err := os.Chmod(f.Name(), perms); err != nil {
		return err
	}

	// If we got this far, it means we are about to save the file. Copy the
	// current contents of the file onto disk (if it exists) so we have a backup.
	if backup {
		if _, err := os.Stat(path); !os.IsNotExist(err) {
			if err := copyFile(path, path+".bak"); err != nil {
				return err
			}
		}
	}

	if err := os.Rename(f.Name(), path); err != nil {
		return err
	}

	return nil
}
func AtomicWrite(path string, createDestDirs bool, contents []byte, perms os.FileMode, backup bool) error {
	if path == "" {
		return ErrMissingDest
	}

	parent := filepath.Dir(path)
	if _, err := os.Stat(parent); os.IsNotExist(err) {
		if createDestDirs {
			if err := os.MkdirAll(parent, 0755); err != nil {
				return err
			}
		} else {
			return ErrNoParentDir
		}
	}

	f, err := ioutil.TempFile(parent, "")
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())

	if _, err := f.Write(contents); err != nil {
		return err
	}

	if err := f.Sync(); err != nil {
		return err
	}

	if err := f.Close(); err != nil {
		return err
	}

	// If the user did not explicitly set permissions, attempt to lookup the
	// current permissions on the file. If the file does not exist, fall back to
	// the default. Otherwise, inherit the current permissions.
	if perms == 0 {
		currentInfo, err := os.Stat(path)
		if err != nil {
			if os.IsNotExist(err) {
				perms = DefaultFilePerms
			} else {
				return err
			}
		} else {
			perms = currentInfo.Mode()

			// The file exists, so try to preserve the ownership as well.
			if err := preserveFilePermissions(f.Name(), currentInfo); err != nil {
				log.Printf("[WARN] (runner) could not preserve file permissions for %q: %v",
					f.Name(), err)
			}
		}
	}

	if err := os.Chmod(f.Name(), perms); err != nil {
		return err
	}

	// If we got this far, it means we are about to save the file. Copy the
	// current contents of the file onto disk (if it exists) so we have a backup.
	if backup {
		if _, err := os.Stat(path); !os.IsNotExist(err) {
			if err := copyFile(path, path+".bak"); err != nil {
				return err
			}
		}
	}

	if err := os.Rename(f.Name(), path); err != nil {
		return err
	}

	return nil
}
// AtomicWrite accepts a destination path and the template contents. It writes
// the template contents to a TempFile on disk, returning if any errors occur.
//
// If the parent destination directory does not exist, it will be created
// automatically with permissions 0755. To use a different permission, create
// the directory first or use `chmod` in a Command.
//
// If the destination path exists, all attempts will be made to preserve the
// existing file permissions. If those permissions cannot be read, an error is
// returned. If the file does not exist, it will be created automatically with
// permissions 0644. To use a different permission, create the destination file
// first or use `chmod` in a Command.
//
// If no errors occur, the Tempfile is "renamed" (moved) to the destination
// path.