Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(724)

Unified Diff: go/src/infra/tools/cipd/local/fs.go

Issue 1258673004: cipd: Make it work on Windows. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: go/src/infra/tools/cipd/local/fs.go
diff --git a/go/src/infra/tools/cipd/local/fs.go b/go/src/infra/tools/cipd/local/fs.go
index 69c1bc2660e4c37e47cba96c294b4fc8e3d51b54..803dab86560ef849d4ac0f1db67b456986eba7d8 100644
--- a/go/src/infra/tools/cipd/local/fs.go
+++ b/go/src/infra/tools/cipd/local/fs.go
@@ -6,6 +6,7 @@ package local
import (
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -43,6 +44,10 @@ type FileSystem interface {
// directory path to the symlink if necessary.
EnsureSymlink(path string, target string) error
+ // EnsureFile creates a file with given content. If will create full directory
+ // path to the file if necessary.
+ EnsureFile(path string, body []byte, perm os.FileMode) error
+
// EnsureFileGone removes a file, logging the errors (if any). Missing file is
// not an error.
EnsureFileGone(path string) error
@@ -78,14 +83,15 @@ type fsImplErr struct {
// Root returns absolute path to a directory FileSystem operates in. All FS
// actions are restricted to this directory.
-func (f *fsImplErr) Root() string { return "" }
-func (f *fsImplErr) CwdRelToAbs(path string) (string, error) { return "", f.err }
-func (f *fsImplErr) RootRelToAbs(path string) (string, error) { return "", f.err }
-func (f *fsImplErr) EnsureDirectory(path string) (string, error) { return "", f.err }
-func (f *fsImplErr) EnsureSymlink(path string, target string) error { return f.err }
-func (f *fsImplErr) EnsureFileGone(path string) error { return f.err }
-func (f *fsImplErr) EnsureDirectoryGone(path string) error { return f.err }
-func (f *fsImplErr) Replace(oldpath, newpath string) error { return f.err }
+func (f *fsImplErr) Root() string { return "" }
+func (f *fsImplErr) CwdRelToAbs(path string) (string, error) { return "", f.err }
+func (f *fsImplErr) RootRelToAbs(path string) (string, error) { return "", f.err }
+func (f *fsImplErr) EnsureDirectory(path string) (string, error) { return "", f.err }
+func (f *fsImplErr) EnsureSymlink(path string, target string) error { return f.err }
+func (f *fsImplErr) EnsureFile(path string, body []byte, perm os.FileMode) error { return f.err }
+func (f *fsImplErr) EnsureFileGone(path string) error { return f.err }
+func (f *fsImplErr) EnsureDirectoryGone(path string) error { return f.err }
+func (f *fsImplErr) Replace(oldpath, newpath string) error { return f.err }
/// Implementation.
@@ -130,9 +136,38 @@ func (f *fsImpl) EnsureDirectory(path string) (string, error) {
if err = os.MkdirAll(path, 0777); err != nil {
return "", err
}
+ // TODO(vadimsh): Do not fail if path already exists and is a regular file?
nodir 2015/07/29 20:43:47 probably not, because this func must ensure that a
Vadim Sh. 2015/07/29 21:04:28 I mean if a/b/c exists and is a regular file, Ensu
nodir 2015/07/29 21:08:59 Acknowledged.
return path, nil
}
+func (f *fsImpl) EnsureFile(path string, body []byte, perm os.FileMode) error {
+ path, err := f.CwdRelToAbs(path)
+ if err != nil {
+ return err
+ }
+ if _, err := f.EnsureDirectory(filepath.Dir(path)); err != nil {
+ return err
+ }
+
+ // Create a temp file with new content.
+ temp := fmt.Sprintf("%s_%s", path, pseudoRand())
+ if err := ioutil.WriteFile(temp, body, perm); err != nil {
+ return err
+ }
+
+ // Replace the current file (if there's one) with a new one. Use nuclear
+ // version (f.Replace) instead of simple atomicReplace to handle various edge
+ // cases handled by the nuclear version (e.g replacing a non-empty directory).
+ if err := f.Replace(temp, path); err != nil {
+ if err2 := os.Remove(temp); err2 != nil && !os.IsNotExist(err2) {
+ f.logger.Warningf("fs: failed to remove %s - %s", temp, err2)
+ }
+ return err
+ }
+
+ return nil
+}
+
func (f *fsImpl) EnsureSymlink(path string, target string) error {
path, err := f.CwdRelToAbs(path)
if err != nil {
@@ -151,10 +186,11 @@ func (f *fsImpl) EnsureSymlink(path string, target string) error {
return err
}
- // Atomically replace the current symlink with a new one.
- if err := os.Rename(temp, path); err != nil {
- err2 := os.Remove(temp)
- if err2 != nil {
+ // Replace the current symlink with a new one. Use nuclear version (f.Replace)
+ // instead of simple atomicReplace to handle various edge cases handled by
+ // the nuclear version (e.g replacing a non-empty directory).
Vadim Sh. 2015/07/28 01:20:18 it's a prep work for "replace locked files". The c
+ if err := f.Replace(temp, path); err != nil {
+ if err2 := os.Remove(temp); err2 != nil && !os.IsNotExist(err2) {
f.logger.Warningf("fs: failed to remove %s - %s", temp, err2)
}
return err
@@ -168,8 +204,7 @@ func (f *fsImpl) EnsureFileGone(path string) error {
if err != nil {
return err
}
- err = os.Remove(path)
- if err != nil && !os.IsNotExist(err) {
+ if err = os.Remove(path); err != nil && !os.IsNotExist(err) {
f.logger.Warningf("fs: failed to remove %s - %s", path, err)
return err
}
@@ -183,7 +218,7 @@ func (f *fsImpl) EnsureDirectoryGone(path string) error {
}
// Make directory "disappear" instantly by renaming it first.
temp := fmt.Sprintf("%s_%v", path, pseudoRand())
- if err = os.Rename(path, temp); err != nil {
+ if err = atomicRename(path, temp); err != nil {
if os.IsNotExist(err) {
return nil
}
@@ -221,13 +256,13 @@ func (f *fsImpl) Replace(oldpath, newpath string) error {
}
// Try a regular move first. Replaces files and empty directories.
- if err = os.Rename(oldpath, newpath); err == nil {
+ if err = atomicRename(oldpath, newpath); err == nil {
return nil
}
// Move existing path away, if it is there.
temp := fmt.Sprintf("%s_%s", newpath, pseudoRand())
- if err = os.Rename(newpath, temp); err != nil {
+ if err = atomicRename(newpath, temp); err != nil {
if !os.IsNotExist(err) {
f.logger.Warningf("fs: failed to rename(%v, %v) - %s", newpath, temp, err)
return err
@@ -236,11 +271,11 @@ func (f *fsImpl) Replace(oldpath, newpath string) error {
}
// 'newpath' now should be available.
- if err := os.Rename(oldpath, newpath); err != nil {
+ if err := atomicRename(oldpath, newpath); err != nil {
f.logger.Warningf("fs: failed to rename(%v, %v) - %s", oldpath, newpath, err)
// Try to return the path back... May be too late already.
if temp != "" {
- if err := os.Rename(temp, newpath); err != nil {
+ if err := atomicRename(temp, newpath); err != nil {
f.logger.Errorf("fs: failed to rename(%v, %v) after unsuccessful move - %s", temp, newpath, err)
}
}

Powered by Google App Engine
This is Rietveld 408576698