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

Side by Side Diff: client/cipd/local/fs.go

Issue 1872363004: cipd: accept a function in EnsureFile (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: rebased Created 4 years, 8 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 unified diff | Download patch
« no previous file with comments | « client/cipd/local/deployer.go ('k') | client/cipd/local/fs_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « client/cipd/local/deployer.go ('k') | client/cipd/local/fs_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698