| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package local | 5 package local |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "io" | 9 "io" |
| 10 "os" | 10 "os" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 // EnsureDirectory creates a directory at given native path if it doesn'
t | 38 // EnsureDirectory creates a directory at given native path if it doesn'
t |
| 39 // exist yet. It takes an absolute path or a path relative to the curren
t | 39 // exist yet. It takes an absolute path or a path relative to the curren
t |
| 40 // working directory and always returns absolute path. | 40 // working directory and always returns absolute path. |
| 41 EnsureDirectory(path string) (string, error) | 41 EnsureDirectory(path string) (string, error) |
| 42 | 42 |
| 43 // EnsureSymlink creates a symlink pointing to a target. It will create
full | 43 // EnsureSymlink creates a symlink pointing to a target. It will create
full |
| 44 // directory path to the symlink if necessary. | 44 // directory path to the symlink if necessary. |
| 45 EnsureSymlink(path string, target string) error | 45 EnsureSymlink(path string, target string) error |
| 46 | 46 |
| 47 » // EnsureFile creates a file with given content. If will create full dir
ectory | 47 » // EnsureFile creates a file and calls the function to write file conten
t. |
| 48 » // path to the file if necessary. | 48 » // It will create full directory path to the file if necessary. |
| 49 » EnsureFile(path string, body io.Reader) error | 49 » EnsureFile(path string, write func(*os.File) error) error |
| 50 | 50 |
| 51 // EnsureFileGone removes a file, logging the errors (if any). Missing f
ile is | 51 // EnsureFileGone removes a file, logging the errors (if any). Missing f
ile is |
| 52 // not an error. | 52 // not an error. |
| 53 EnsureFileGone(path string) error | 53 EnsureFileGone(path string) error |
| 54 | 54 |
| 55 // EnsureDirectoryGone recursively removes a directory. | 55 // EnsureDirectoryGone recursively removes a directory. |
| 56 EnsureDirectoryGone(path string) error | 56 EnsureDirectoryGone(path string) error |
| 57 | 57 |
| 58 // Renames oldpath to newpath. If newpath already exists (be it a file o
r a | 58 // Renames oldpath to newpath. If newpath already exists (be it a file o
r a |
| 59 // directory), removes it first. If oldpath is a symlink, it's moved as
is | 59 // directory), removes it first. If oldpath is a symlink, it's moved as
is |
| 60 // (e.g. as a symlink). | 60 // (e.g. as a symlink). |
| 61 Replace(oldpath, newpath string) error | 61 Replace(oldpath, newpath string) error |
| 62 } | 62 } |
| 63 | 63 |
| 64 // NewFileSystem returns default FileSystem implementation that operates with | 64 // NewFileSystem returns default FileSystem implementation that operates with |
| 65 // files under a given path. All methods accept absolute paths or paths relative | 65 // files under a given path. All methods accept absolute paths or paths relative |
| 66 // to current working directory. FileSystem will ensure they are under 'root' | 66 // to current working directory. FileSystem will ensure they are under 'root' |
| 67 // directory. | 67 // directory. |
| 68 func NewFileSystem(root string, logger logging.Logger) FileSystem { | 68 func NewFileSystem(root string, logger logging.Logger) FileSystem { |
| 69 if logger == nil { | 69 if logger == nil { |
| 70 logger = logging.Null() | 70 logger = logging.Null() |
| 71 } | 71 } |
| 72 abs, err := filepath.Abs(root) | 72 abs, err := filepath.Abs(root) |
| 73 if err != nil { | 73 if err != nil { |
| 74 return &fsImplErr{err} | 74 return &fsImplErr{err} |
| 75 } | 75 } |
| 76 return &fsImpl{abs, logger} | 76 return &fsImpl{abs, logger} |
| 77 } | 77 } |
| 78 | 78 |
| 79 // EnsureFile creates a file with the given content. |
| 80 // It will create full directory path to the file if necessary. |
| 81 func EnsureFile(fs FileSystem, path string, content io.Reader) error { |
| 82 return fs.EnsureFile(path, func(f *os.File) error { |
| 83 _, err := io.Copy(f, content) |
| 84 return err |
| 85 }) |
| 86 } |
| 87 |
| 79 // fsImplErr implements FileSystem by returning given error from all methods. | 88 // fsImplErr implements FileSystem by returning given error from all methods. |
| 80 type fsImplErr struct { | 89 type fsImplErr struct { |
| 81 err error | 90 err error |
| 82 } | 91 } |
| 83 | 92 |
| 84 func (f *fsImplErr) Root() string { return ""
} | 93 func (f *fsImplErr) Root() string {
return "" } |
| 85 func (f *fsImplErr) CwdRelToAbs(path string) (string, error) { return "",
f.err } | 94 func (f *fsImplErr) CwdRelToAbs(path string) (string, error) {
return "", f.err } |
| 86 func (f *fsImplErr) RootRelToAbs(path string) (string, error) { return "",
f.err } | 95 func (f *fsImplErr) RootRelToAbs(path string) (string, error) {
return "", f.err } |
| 87 func (f *fsImplErr) EnsureDirectory(path string) (string, error) { return "",
f.err } | 96 func (f *fsImplErr) EnsureDirectory(path string) (string, error) {
return "", f.err } |
| 88 func (f *fsImplErr) EnsureSymlink(path string, target string) error { return f.e
rr } | 97 func (f *fsImplErr) EnsureSymlink(path string, target string) error {
return f.err } |
| 89 func (f *fsImplErr) EnsureFile(path string, body io.Reader) error { return f.e
rr } | 98 func (f *fsImplErr) EnsureFile(path string, write func(*os.File) error) error {
return f.err } |
| 90 func (f *fsImplErr) EnsureFileGone(path string) error { return f.e
rr } | 99 func (f *fsImplErr) EnsureFileGone(path string) error {
return f.err } |
| 91 func (f *fsImplErr) EnsureDirectoryGone(path string) error { return f.e
rr } | 100 func (f *fsImplErr) EnsureDirectoryGone(path string) error {
return f.err } |
| 92 func (f *fsImplErr) Replace(oldpath, newpath string) error { return f.e
rr } | 101 func (f *fsImplErr) Replace(oldpath, newpath string) error {
return f.err } |
| 93 | 102 |
| 94 /// Implementation. | 103 /// Implementation. |
| 95 | 104 |
| 96 type fsImpl struct { | 105 type fsImpl struct { |
| 97 root string | 106 root string |
| 98 logger logging.Logger | 107 logger logging.Logger |
| 99 } | 108 } |
| 100 | 109 |
| 101 func (f *fsImpl) Root() string { | 110 func (f *fsImpl) Root() string { |
| 102 return f.root | 111 return f.root |
| (...skipping 28 matching lines...) Expand all Loading... |
| 131 return "", err | 140 return "", err |
| 132 } | 141 } |
| 133 // MkdirAll returns nil if path already exists. | 142 // MkdirAll returns nil if path already exists. |
| 134 if err = os.MkdirAll(path, 0777); err != nil { | 143 if err = os.MkdirAll(path, 0777); err != nil { |
| 135 return "", err | 144 return "", err |
| 136 } | 145 } |
| 137 // TODO(vadimsh): Do not fail if path already exists and is a regular fi
le? | 146 // TODO(vadimsh): Do not fail if path already exists and is a regular fi
le? |
| 138 return path, nil | 147 return path, nil |
| 139 } | 148 } |
| 140 | 149 |
| 141 func (f *fsImpl) EnsureFile(path string, body io.Reader) error { | 150 func (f *fsImpl) EnsureFile(path string, write func(*os.File) error) error { |
| 142 path, err := f.CwdRelToAbs(path) | 151 path, err := f.CwdRelToAbs(path) |
| 143 if err != nil { | 152 if err != nil { |
| 144 return err | 153 return err |
| 145 } | 154 } |
| 146 if _, err := f.EnsureDirectory(filepath.Dir(path)); err != nil { | 155 if _, err := f.EnsureDirectory(filepath.Dir(path)); err != nil { |
| 147 return err | 156 return err |
| 148 } | 157 } |
| 149 | 158 |
| 150 // Create a temp file with new content. | 159 // Create a temp file with new content. |
| 151 temp := tempFileName(path) | 160 temp := tempFileName(path) |
| 152 » if err := createFile(temp, body); err != nil { | 161 » if err := createFile(temp, write); err != nil { |
| 153 return err | 162 return err |
| 154 } | 163 } |
| 155 | 164 |
| 156 // Replace the current file (if there's one) with a new one. Use nuclear | 165 // Replace the current file (if there's one) with a new one. Use nuclear |
| 157 // version (f.Replace) instead of simple atomicReplace to handle various
edge | 166 // version (f.Replace) instead of simple atomicReplace to handle various
edge |
| 158 // cases handled by the nuclear version (e.g replacing a non-empty direc
tory). | 167 // cases handled by the nuclear version (e.g replacing a non-empty direc
tory). |
| 159 if err := f.Replace(temp, path); err != nil { | 168 if err := f.Replace(temp, path); err != nil { |
| 160 if err2 := os.Remove(temp); err2 != nil && !os.IsNotExist(err2)
{ | 169 if err2 := os.Remove(temp); err2 != nil && !os.IsNotExist(err2)
{ |
| 161 f.logger.Warningf("fs: failed to remove %s - %s", temp,
err2) | 170 f.logger.Warningf("fs: failed to remove %s - %s", temp,
err2) |
| 162 } | 171 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 ts := time.Now().UnixNano() | 318 ts := time.Now().UnixNano() |
| 310 lastUsedTimeLock.Lock() | 319 lastUsedTimeLock.Lock() |
| 311 if ts <= lastUsedTime { | 320 if ts <= lastUsedTime { |
| 312 ts = lastUsedTime + 1 | 321 ts = lastUsedTime + 1 |
| 313 } | 322 } |
| 314 lastUsedTime = ts | 323 lastUsedTime = ts |
| 315 lastUsedTimeLock.Unlock() | 324 lastUsedTimeLock.Unlock() |
| 316 return fmt.Sprintf("%v_%v", os.Getpid(), ts) | 325 return fmt.Sprintf("%v_%v", os.Getpid(), ts) |
| 317 } | 326 } |
| 318 | 327 |
| 319 // createFile creates a file with the given content. | 328 // createFile creates a file and calls the function to write file content. |
| 320 func createFile(path string, content io.Reader) (err error) { | 329 func createFile(path string, write func(*os.File) error) (err error) { |
| 321 file, err := os.Create(path) | 330 file, err := os.Create(path) |
| 322 if err != nil { | 331 if err != nil { |
| 323 return err | 332 return err |
| 324 } | 333 } |
| 325 defer func() { | 334 defer func() { |
| 326 closeErr := file.Close() | 335 closeErr := file.Close() |
| 327 if err == nil { | 336 if err == nil { |
| 328 err = closeErr | 337 err = closeErr |
| 329 } | 338 } |
| 330 }() | 339 }() |
| 331 » _, err = io.Copy(file, content) | 340 » return write(file) |
| 332 » return err | |
| 333 } | 341 } |
| OLD | NEW |