OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 // Package managedfs offers a managed filesystem. A managed filesystem assumes | 5 // Package managedfs offers a managed filesystem. A managed filesystem assumes |
6 // that it has ownership of a specified directory and all of that directory's | 6 // that it has ownership of a specified directory and all of that directory's |
7 // contents, and tracks directory and creation. | 7 // contents, and tracks directory and creation. |
8 // | 8 // |
9 // This is useful in enabling the reuse of managed directories. In between uses, | 9 // This is useful in enabling the reuse of managed directories. In between uses, |
10 // new files may be added and old files may be deleted. A managed filesystem | 10 // new files may be added and old files may be deleted. A managed filesystem |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 root *Dir | 57 root *Dir |
58 } | 58 } |
59 | 59 |
60 // New creates a new managed filesystem rooted at the target directory. | 60 // New creates a new managed filesystem rooted at the target directory. |
61 // | 61 // |
62 // The filesystem will create rootDir if it does not exist, and assumes total | 62 // The filesystem will create rootDir if it does not exist, and assumes total |
63 // ownership of its contents. | 63 // ownership of its contents. |
64 func New(rootDir string) (*Filesystem, error) { | 64 func New(rootDir string) (*Filesystem, error) { |
65 rootDir = filepath.Clean(rootDir) | 65 rootDir = filepath.Clean(rootDir) |
66 if err := ensureDirectory(rootDir); err != nil { | 66 if err := ensureDirectory(rootDir); err != nil { |
67 » » return nil, errors.Annotate(err).Reason("failed to create root d
irectory").Err() | 67 » » return nil, errors.Annotate(err, "failed to create root director
y").Err() |
68 } | 68 } |
69 fs := Filesystem{ | 69 fs := Filesystem{ |
70 rootDir: rootDir, | 70 rootDir: rootDir, |
71 } | 71 } |
72 fs.root = &Dir{ | 72 fs.root = &Dir{ |
73 fs: &fs, | 73 fs: &fs, |
74 relPath: "", | 74 relPath: "", |
75 elem: "", | 75 elem: "", |
76 } | 76 } |
77 return &fs, nil | 77 return &fs, nil |
(...skipping 30 matching lines...) Expand all Loading... |
108 return filepath.Join(d.fs.rootDir, d.relPath) | 108 return filepath.Join(d.fs.rootDir, d.relPath) |
109 } | 109 } |
110 | 110 |
111 // RelPath returns the path of this Dir relative to its filesystem root. | 111 // RelPath returns the path of this Dir relative to its filesystem root. |
112 func (d *Dir) RelPath() string { return d.relPath } | 112 func (d *Dir) RelPath() string { return d.relPath } |
113 | 113 |
114 // RelPathFrom returns the relative path from d to targpath. It also asserts | 114 // RelPathFrom returns the relative path from d to targpath. It also asserts |
115 // that targpath is under the Filesystem root. | 115 // that targpath is under the Filesystem root. |
116 func (d *Dir) RelPathFrom(targpath string) (string, error) { | 116 func (d *Dir) RelPathFrom(targpath string) (string, error) { |
117 if !isSubpath(d.fs.rootDir, targpath) { | 117 if !isSubpath(d.fs.rootDir, targpath) { |
118 » » return "", errors.Reason("[%(path)s] is not a subpath of [%(root
)s]"). | 118 » » return "", errors.Reason("[%s] is not a subpath of [%s]", targpa
th, d.fs.rootDir).Err() |
119 » » » D("path", targpath).D("root", d.fs.rootDir).Err() | |
120 } | 119 } |
121 | 120 |
122 rel, err := filepath.Rel(d.String(), targpath) | 121 rel, err := filepath.Rel(d.String(), targpath) |
123 if err != nil { | 122 if err != nil { |
124 » » return "", errors.Annotate(err).Reason("could not calculate rela
tive path from [%(dir)s] to [%(path)s]"). | 123 » » return "", errors.Annotate(err, "could not calculate relative pa
th from [%s] to [%s]", |
125 » » » D("dir", d.String()).D("path", targpath).Err() | 124 » » » d.String(), targpath).Err() |
126 } | 125 } |
127 return rel, nil | 126 return rel, nil |
128 } | 127 } |
129 | 128 |
130 // Ignore configures d to be marked as ignored. This causes it and all of its | 129 // Ignore configures d to be marked as ignored. This causes it and all of its |
131 // contents to be exempt from cleanup. | 130 // contents to be exempt from cleanup. |
132 func (d *Dir) Ignore() { | 131 func (d *Dir) Ignore() { |
133 d.fs.lock.Lock() | 132 d.fs.lock.Lock() |
134 defer d.fs.lock.Unlock() | 133 defer d.fs.lock.Unlock() |
135 d.ignored = true | 134 d.ignored = true |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 d.subdirs[elem] = subDir | 179 d.subdirs[elem] = subDir |
181 return | 180 return |
182 } | 181 } |
183 | 182 |
184 // EnsureDirectory returns a managed sub-directory composed by joining all of | 183 // EnsureDirectory returns a managed sub-directory composed by joining all of |
185 // the specified elements together. | 184 // the specified elements together. |
186 // | 185 // |
187 // If the described directory doesn't exist, it will be created. | 186 // If the described directory doesn't exist, it will be created. |
188 func (d *Dir) EnsureDirectory(elem string, elems ...string) (*Dir, error) { | 187 func (d *Dir) EnsureDirectory(elem string, elems ...string) (*Dir, error) { |
189 if !isValidSinglePathComponent(elem) { | 188 if !isValidSinglePathComponent(elem) { |
190 » » return nil, errors.Reason("invalid path component #0: %(comp)q")
. | 189 » » return nil, errors.Reason("invalid path component #0: %q", elem)
.Err() |
191 » » » D("comp", elem).Err() | |
192 } | 190 } |
193 | 191 |
194 // No element may have a path separator in it. | 192 // No element may have a path separator in it. |
195 components := make([]string, 0, len(elems)+2) | 193 components := make([]string, 0, len(elems)+2) |
196 components = append(components, d.String()) | 194 components = append(components, d.String()) |
197 components = append(components, elem) | 195 components = append(components, elem) |
198 for i, comp := range elems { | 196 for i, comp := range elems { |
199 if !isValidSinglePathComponent(comp) { | 197 if !isValidSinglePathComponent(comp) { |
200 » » » return nil, errors.Reason("invalid path component #%(ind
ex)d: %(comp)q"). | 198 » » » return nil, errors.Reason("invalid path component #%d: %
q", i+1, comp).Err() |
201 » » » » D("index", i+1).D("comp", comp).Err() | |
202 } | 199 } |
203 components = append(components, comp) | 200 components = append(components, comp) |
204 } | 201 } |
205 | 202 |
206 // Make the full subdirectory path. | 203 // Make the full subdirectory path. |
207 fullPath := filepath.Join(components...) | 204 fullPath := filepath.Join(components...) |
208 if err := ensureDirectory(fullPath); err != nil { | 205 if err := ensureDirectory(fullPath); err != nil { |
209 » » return nil, errors.Annotate(err).Reason("failed to create direct
ory [%(path)s]").D("path", fullPath).Err() | 206 » » return nil, errors.Annotate(err, "failed to create directory [%s
]", fullPath).Err() |
210 } | 207 } |
211 | 208 |
212 // Return the last managed directory node. | 209 // Return the last managed directory node. |
213 return d.GetSubDirectory(elem, elems...), nil | 210 return d.GetSubDirectory(elem, elems...), nil |
214 } | 211 } |
215 | 212 |
216 // ShallowSymlinkFrom creates one symlink under d per regular file in dir. | 213 // ShallowSymlinkFrom creates one symlink under d per regular file in dir. |
217 func (d *Dir) ShallowSymlinkFrom(dir string, rel bool) error { | 214 func (d *Dir) ShallowSymlinkFrom(dir string, rel bool) error { |
218 fis, err := ioutil.ReadDir(dir) | 215 fis, err := ioutil.ReadDir(dir) |
219 if err != nil { | 216 if err != nil { |
220 » » return errors.Annotate(err).Reason("failed to read directory [%(
path)s]").D("path", dir).Err() | 217 » » return errors.Annotate(err, "failed to read directory [%s]", dir
).Err() |
221 } | 218 } |
222 | 219 |
223 for _, fi := range fis { | 220 for _, fi := range fis { |
224 if fi.IsDir() { | 221 if fi.IsDir() { |
225 continue | 222 continue |
226 } | 223 } |
227 | 224 |
228 f := d.File(fi.Name()) | 225 f := d.File(fi.Name()) |
229 if err := f.SymlinkFrom(filepath.Join(dir, fi.Name()), rel); err
!= nil { | 226 if err := f.SymlinkFrom(filepath.Join(dir, fi.Name()), rel); err
!= nil { |
230 return err | 227 return err |
231 } | 228 } |
232 } | 229 } |
233 | 230 |
234 return nil | 231 return nil |
235 } | 232 } |
236 | 233 |
237 // File creates a new managed File immediately within d. | 234 // File creates a new managed File immediately within d. |
238 func (d *Dir) File(name string) *File { | 235 func (d *Dir) File(name string) *File { |
239 if !isValidSinglePathComponent(name) { | 236 if !isValidSinglePathComponent(name) { |
240 » » panic(errors.Reason("invalid path component: %(name)q").D("name"
, name).Err()) | 237 » » panic(errors.Reason("invalid path component: %q", name).Err()) |
241 } | 238 } |
242 | 239 |
243 // Register this file with its managed directory. | 240 // Register this file with its managed directory. |
244 return d.registerFile(name) | 241 return d.registerFile(name) |
245 } | 242 } |
246 | 243 |
247 func (d *Dir) registerFile(name string) *File { | 244 func (d *Dir) registerFile(name string) *File { |
248 d.fs.lock.RLock() | 245 d.fs.lock.RLock() |
249 _, registered := d.files[name] | 246 _, registered := d.files[name] |
250 d.fs.lock.RUnlock() | 247 d.fs.lock.RUnlock() |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 } | 281 } |
285 | 282 |
286 func (d *Dir) cleanupLocked() error { | 283 func (d *Dir) cleanupLocked() error { |
287 if d.ignored { | 284 if d.ignored { |
288 return nil | 285 return nil |
289 } | 286 } |
290 | 287 |
291 // List the contents of this directory. | 288 // List the contents of this directory. |
292 fis, err := ioutil.ReadDir(d.String()) | 289 fis, err := ioutil.ReadDir(d.String()) |
293 if err != nil { | 290 if err != nil { |
294 » » return errors.Annotate(err).Reason("failed to read directory %(d
ir)q").D("dir", d.String()).Err() | 291 » » return errors.Annotate(err, "failed to read directory %q", d.Str
ing()).Err() |
295 } | 292 } |
296 | 293 |
297 for _, fi := range fis { | 294 for _, fi := range fis { |
298 name := fi.Name() | 295 name := fi.Name() |
299 if fi.IsDir() { | 296 if fi.IsDir() { |
300 if subD := d.subdirs[name]; subD != nil { | 297 if subD := d.subdirs[name]; subD != nil { |
301 // Cleanup our subdirectory. | 298 // Cleanup our subdirectory. |
302 if err := subD.cleanupLocked(); err != nil { | 299 if err := subD.cleanupLocked(); err != nil { |
303 return err | 300 return err |
304 } | 301 } |
305 continue | 302 continue |
306 } | 303 } |
307 } else { | 304 } else { |
308 // This is a file/symlink/etc. Delete it if it's not man
aged. | 305 // This is a file/symlink/etc. Delete it if it's not man
aged. |
309 if _, ok := d.files[name]; ok { | 306 if _, ok := d.files[name]; ok { |
310 continue | 307 continue |
311 } | 308 } |
312 } | 309 } |
313 | 310 |
314 // This is unmanaged. Delete it. | 311 // This is unmanaged. Delete it. |
315 fiPath := filepath.Join(d.String(), name) | 312 fiPath := filepath.Join(d.String(), name) |
316 | 313 |
317 // Safety / sanity check, the path under consideration for delet
ion MUST be | 314 // Safety / sanity check, the path under consideration for delet
ion MUST be |
318 // underneath of our filesystem's root. | 315 // underneath of our filesystem's root. |
319 if !isSubpath(d.fs.rootDir, fiPath) { | 316 if !isSubpath(d.fs.rootDir, fiPath) { |
320 » » » panic(errors.Reason("about to delete [%(path)q], which i
s not a subdirectory of [%(root)q]"). | 317 » » » panic(errors.Reason("about to delete [%q], which is not
a subdirectory of [%q]", |
321 » » » » D("path", fiPath).D("root", d.fs.rootDir).Err()) | 318 » » » » fiPath, d.fs.rootDir).Err()) |
322 } | 319 } |
323 | 320 |
324 if err := os.RemoveAll(fiPath); err != nil { | 321 if err := os.RemoveAll(fiPath); err != nil { |
325 » » » return errors.Annotate(err).Reason("failed to delete unm
anaged [%(path)q]").D("path", fiPath).Err() | 322 » » » return errors.Annotate(err, "failed to delete unmanaged
[%q]", fiPath).Err() |
326 } | 323 } |
327 } | 324 } |
328 return nil | 325 return nil |
329 } | 326 } |
330 | 327 |
331 // File is a managed file within a managed Dir. | 328 // File is a managed file within a managed Dir. |
332 type File struct { | 329 type File struct { |
333 dir *Dir | 330 dir *Dir |
334 | 331 |
335 name string | 332 name string |
(...skipping 12 matching lines...) Expand all Loading... |
348 | 345 |
349 // SymlinkFrom writes a symlink from the specified path to f's location. | 346 // SymlinkFrom writes a symlink from the specified path to f's location. |
350 // | 347 // |
351 // If rel is true, the symlink's target will be "from" relative to the managed | 348 // If rel is true, the symlink's target will be "from" relative to the managed |
352 // filesystem's root. If it goes above the root, it is an error. | 349 // filesystem's root. If it goes above the root, it is an error. |
353 func (f *File) SymlinkFrom(from string, rel bool) error { | 350 func (f *File) SymlinkFrom(from string, rel bool) error { |
354 to := f.String() | 351 to := f.String() |
355 | 352 |
356 // Assert that our "from" field exists. | 353 // Assert that our "from" field exists. |
357 if _, err := os.Stat(from); err != nil { | 354 if _, err := os.Stat(from); err != nil { |
358 » » return errors.Annotate(err).Reason("failed to stat symlink from
[%(path)s]"). | 355 » » return errors.Annotate(err, "failed to stat symlink from [%s]",
from).Err() |
359 » » » D("path", from).Err() | |
360 } | 356 } |
361 | 357 |
362 // "from" must be a path under the filesystem base. | 358 // "from" must be a path under the filesystem base. |
363 if rel { | 359 if rel { |
364 var err error | 360 var err error |
365 if from, err = f.dir.RelPathFrom(from); err != nil { | 361 if from, err = f.dir.RelPathFrom(from); err != nil { |
366 » » » return errors.Annotate(err).Reason("failed to calculate
relative path").Err() | 362 » » » return errors.Annotate(err, "failed to calculate relativ
e path").Err() |
367 } | 363 } |
368 } | 364 } |
369 | 365 |
370 if st, err := os.Lstat(to); err == nil { | 366 if st, err := os.Lstat(to); err == nil { |
371 if st.Mode()&os.ModeSymlink != 0 { | 367 if st.Mode()&os.ModeSymlink != 0 { |
372 // to is a symlink. Is it a symlink to "from"? | 368 // to is a symlink. Is it a symlink to "from"? |
373 currentFrom, err := os.Readlink(to) | 369 currentFrom, err := os.Readlink(to) |
374 if err == nil && currentFrom == from { | 370 if err == nil && currentFrom == from { |
375 // The symlink already exists! | 371 // The symlink already exists! |
376 return nil | 372 return nil |
377 } | 373 } |
378 } | 374 } |
379 | 375 |
380 // The file exists, but is not a symlink to "from". Try to delet
e it. | 376 // The file exists, but is not a symlink to "from". Try to delet
e it. |
381 if err := os.Remove(to); err != nil { | 377 if err := os.Remove(to); err != nil { |
382 return err | 378 return err |
383 } | 379 } |
384 } | 380 } |
385 | 381 |
386 if err := os.Symlink(from, to); err != nil { | 382 if err := os.Symlink(from, to); err != nil { |
387 » » return errors.Annotate(err).Reason("failed to symlink [%(from)s]
=> [%(to)s]"). | 383 » » return errors.Annotate(err, "failed to symlink [%s] => [%s]", fr
om, to).Err() |
388 » » » D("from", from).D("to", to).Err() | |
389 } | 384 } |
390 return nil | 385 return nil |
391 } | 386 } |
392 | 387 |
393 // CopyFrom copies contents from the specified path to f's location. | 388 // CopyFrom copies contents from the specified path to f's location. |
394 func (f *File) CopyFrom(src string) (rerr error) { | 389 func (f *File) CopyFrom(src string) (rerr error) { |
395 dst := f.String() | 390 dst := f.String() |
396 | 391 |
397 s, err := os.Open(src) | 392 s, err := os.Open(src) |
398 if err != nil { | 393 if err != nil { |
399 » » return errors.Annotate(err).Reason("failed to open [%(source)s]"
). | 394 » » return errors.Annotate(err, "failed to open [%s]", src).Err() |
400 » » » D("source", src).Err() | |
401 } | 395 } |
402 defer func() { | 396 defer func() { |
403 cerr := s.Close() | 397 cerr := s.Close() |
404 if rerr == nil && cerr != nil { | 398 if rerr == nil && cerr != nil { |
405 rerr = cerr | 399 rerr = cerr |
406 } | 400 } |
407 }() | 401 }() |
408 | 402 |
409 d, err := createFile(dst) | 403 d, err := createFile(dst) |
410 if err != nil { | 404 if err != nil { |
411 » » return errors.Annotate(err).Reason("failed to create [%(dest)s]"
). | 405 » » return errors.Annotate(err, "failed to create [%s]", dst).Err() |
412 » » » D("dest", dst).Err() | |
413 } | 406 } |
414 defer func() { | 407 defer func() { |
415 cerr := d.Close() | 408 cerr := d.Close() |
416 if rerr == nil && cerr != nil { | 409 if rerr == nil && cerr != nil { |
417 rerr = cerr | 410 rerr = cerr |
418 } | 411 } |
419 }() | 412 }() |
420 | 413 |
421 withBuffer(func(buf []byte) { | 414 withBuffer(func(buf []byte) { |
422 _, err = io.CopyBuffer(d, s, buf) | 415 _, err = io.CopyBuffer(d, s, buf) |
423 }) | 416 }) |
424 if err != nil { | 417 if err != nil { |
425 » » return errors.Annotate(err).Reason("failed to copy from [%(sourc
e)s] => [%(dest)s]"). | 418 » » return errors.Annotate(err, "failed to copy from [%s] => [%s]",
src, dst).Err() |
426 » » » D("source", src).D("dest", dst).Err() | |
427 } | 419 } |
428 return nil | 420 return nil |
429 } | 421 } |
430 | 422 |
431 // SameAs returns true if the spceified path is the exact same file as the | 423 // SameAs returns true if the spceified path is the exact same file as the |
432 // file at f's location. | 424 // file at f's location. |
433 func (f *File) SameAs(other string) (bool, error) { | 425 func (f *File) SameAs(other string) (bool, error) { |
434 // Stat each file and check if they are the same. | 426 // Stat each file and check if they are the same. |
435 myPath := f.String() | 427 myPath := f.String() |
436 myStat, err := os.Lstat(myPath) | 428 myStat, err := os.Lstat(myPath) |
437 if err != nil { | 429 if err != nil { |
438 if isNotExist(err) { | 430 if isNotExist(err) { |
439 return false, nil | 431 return false, nil |
440 } | 432 } |
441 » » return false, errors.Annotate(err).Reason("failed to stat [%(sel
f)s]"). | 433 » » return false, errors.Annotate(err, "failed to stat [%s]", myPath
).Err() |
442 » » » D("self", myPath).Err() | |
443 } | 434 } |
444 | 435 |
445 otherStat, err := os.Lstat(other) | 436 otherStat, err := os.Lstat(other) |
446 if err != nil { | 437 if err != nil { |
447 if isNotExist(err) { | 438 if isNotExist(err) { |
448 return false, nil | 439 return false, nil |
449 } | 440 } |
450 » » return false, errors.Annotate(err).Reason("failed to stat [%(oth
er)s]"). | 441 » » return false, errors.Annotate(err, "failed to stat [%s]", other)
.Err() |
451 » » » D("other", other).Err() | |
452 } | 442 } |
453 | 443 |
454 if os.SameFile(myStat, otherStat) { | 444 if os.SameFile(myStat, otherStat) { |
455 return true, nil | 445 return true, nil |
456 } | 446 } |
457 | 447 |
458 // Not the same file, and both exist, so let's compare byte-for-byte. | 448 // Not the same file, and both exist, so let's compare byte-for-byte. |
459 myFD, err := os.Open(f.String()) | 449 myFD, err := os.Open(f.String()) |
460 if err != nil { | 450 if err != nil { |
461 » » return false, errors.Annotate(err).Reason("failed to open [%(sel
f)s]"). | 451 » » return false, errors.Annotate(err, "failed to open [%s]", myPath
).Err() |
462 » » » D("self", myPath).Err() | |
463 } | 452 } |
464 defer myFD.Close() | 453 defer myFD.Close() |
465 | 454 |
466 otherFD, err := os.Open(other) | 455 otherFD, err := os.Open(other) |
467 if err != nil { | 456 if err != nil { |
468 » » return false, errors.Annotate(err).Reason("failed to option [%(o
ther)s]"). | 457 » » return false, errors.Annotate(err, "failed to option [%s]", othe
r).Err() |
469 » » » D("other", other).Err() | |
470 } | 458 } |
471 defer otherFD.Close() | 459 defer otherFD.Close() |
472 | 460 |
473 same := false | 461 same := false |
474 withBuffer(func(myBuf []byte) { | 462 withBuffer(func(myBuf []byte) { |
475 withBuffer(func(otherBuf []byte) { | 463 withBuffer(func(otherBuf []byte) { |
476 same, err = byteCompare(myFD, otherFD, myBuf, otherBuf) | 464 same, err = byteCompare(myFD, otherFD, myBuf, otherBuf) |
477 }) | 465 }) |
478 }) | 466 }) |
479 if err != nil { | 467 if err != nil { |
480 » » return false, errors.Annotate(err).Reason("failed to compare fil
es [%(self)s] to [$(other)s]"). | 468 » » return false, errors.Annotate(err, "failed to compare files [%s]
to [%s]", myPath, other).Err() |
481 » » » D("self", myPath).D("other", other).Err() | |
482 } | 469 } |
483 return same, nil | 470 return same, nil |
484 } | 471 } |
485 | 472 |
486 // GenerateTextProto writes the specified object as rendered text protobuf to | 473 // GenerateTextProto writes the specified object as rendered text protobuf to |
487 // f's location. | 474 // f's location. |
488 func (f *File) GenerateTextProto(c context.Context, msg proto.Message) error { | 475 func (f *File) GenerateTextProto(c context.Context, msg proto.Message) error { |
489 return f.WriteDataFrom(func(fd io.Writer) error { | 476 return f.WriteDataFrom(func(fd io.Writer) error { |
490 if gh := f.dir.fs.GenHeader; len(gh) > 0 { | 477 if gh := f.dir.fs.GenHeader; len(gh) > 0 { |
491 for _, h := range gh { | 478 for _, h := range gh { |
(...skipping 12 matching lines...) Expand all Loading... |
504 | 491 |
505 if gn := f.dir.fs.GenName; gn != "" { | 492 if gn := f.dir.fs.GenName; gn != "" { |
506 genNote := fmt.Sprintf("# GENERATED by %q at: %s\n\n", g
n, clock.Now(c)) | 493 genNote := fmt.Sprintf("# GENERATED by %q at: %s\n\n", g
n, clock.Now(c)) |
507 if _, err := fmt.Fprint(fd, genNote); err != nil { | 494 if _, err := fmt.Fprint(fd, genNote); err != nil { |
508 return err | 495 return err |
509 } | 496 } |
510 } | 497 } |
511 | 498 |
512 // Write YAML contents. | 499 // Write YAML contents. |
513 if err := proto.MarshalText(fd, msg); err != nil { | 500 if err := proto.MarshalText(fd, msg); err != nil { |
514 » » » return errors.Annotate(err).Err() | 501 » » » return errors.Annotate(err, "").Err() |
515 } | 502 } |
516 return nil | 503 return nil |
517 }) | 504 }) |
518 } | 505 } |
519 | 506 |
520 // GenerateYAML writes the specified object as a YAML file to f's location. | 507 // GenerateYAML writes the specified object as a YAML file to f's location. |
521 func (f *File) GenerateYAML(c context.Context, obj interface{}) error { | 508 func (f *File) GenerateYAML(c context.Context, obj interface{}) error { |
522 d, err := yaml.Marshal(obj) | 509 d, err := yaml.Marshal(obj) |
523 if err != nil { | 510 if err != nil { |
524 return err | 511 return err |
(...skipping 17 matching lines...) Expand all Loading... |
542 | 529 |
543 if gn := f.dir.fs.GenName; gn != "" { | 530 if gn := f.dir.fs.GenName; gn != "" { |
544 genNote := fmt.Sprintf("# GENERATED by %q at: %s\n\n", g
n, clock.Now(c)) | 531 genNote := fmt.Sprintf("# GENERATED by %q at: %s\n\n", g
n, clock.Now(c)) |
545 if _, err := fmt.Fprint(fd, genNote); err != nil { | 532 if _, err := fmt.Fprint(fd, genNote); err != nil { |
546 return err | 533 return err |
547 } | 534 } |
548 } | 535 } |
549 | 536 |
550 // Write YAML contents. | 537 // Write YAML contents. |
551 if _, err := fd.Write(d); err != nil { | 538 if _, err := fd.Write(d); err != nil { |
552 » » » return errors.Annotate(err).Err() | 539 » » » return errors.Annotate(err, "").Err() |
553 } | 540 } |
554 return nil | 541 return nil |
555 }) | 542 }) |
556 } | 543 } |
557 | 544 |
558 // GenerateGo writes Go contents to the supplied filesystem. | 545 // GenerateGo writes Go contents to the supplied filesystem. |
559 func (f *File) GenerateGo(c context.Context, content string) error { | 546 func (f *File) GenerateGo(c context.Context, content string) error { |
560 return f.WriteDataFrom(func(fd io.Writer) error { | 547 return f.WriteDataFrom(func(fd io.Writer) error { |
561 if gh := f.dir.fs.GenHeader; len(gh) > 0 { | 548 if gh := f.dir.fs.GenHeader; len(gh) > 0 { |
562 for _, h := range gh { | 549 for _, h := range gh { |
(...skipping 12 matching lines...) Expand all Loading... |
575 | 562 |
576 if gn := f.dir.fs.GenName; gn != "" { | 563 if gn := f.dir.fs.GenName; gn != "" { |
577 genNote := fmt.Sprintf("// GENERATED by %q at: %s\n\n",
gn, clock.Now(c)) | 564 genNote := fmt.Sprintf("// GENERATED by %q at: %s\n\n",
gn, clock.Now(c)) |
578 if _, err := fmt.Fprint(fd, genNote); err != nil { | 565 if _, err := fmt.Fprint(fd, genNote); err != nil { |
579 return err | 566 return err |
580 } | 567 } |
581 } | 568 } |
582 | 569 |
583 // Write Go content. | 570 // Write Go content. |
584 if _, err := fmt.Fprint(fd, content); err != nil { | 571 if _, err := fmt.Fprint(fd, content); err != nil { |
585 » » » return errors.Annotate(err).Err() | 572 » » » return errors.Annotate(err, "").Err() |
586 } | 573 } |
587 return nil | 574 return nil |
588 }) | 575 }) |
589 } | 576 } |
590 | 577 |
591 // ReadAll reads the contents of the file at f's location. | 578 // ReadAll reads the contents of the file at f's location. |
592 func (f *File) ReadAll() ([]byte, error) { | 579 func (f *File) ReadAll() ([]byte, error) { |
593 return ioutil.ReadFile(f.String()) | 580 return ioutil.ReadFile(f.String()) |
594 } | 581 } |
595 | 582 |
(...skipping 14 matching lines...) Expand all Loading... |
610 } | 597 } |
611 defer func() { | 598 defer func() { |
612 if closeErr := fd.Close(); err == nil { | 599 if closeErr := fd.Close(); err == nil { |
613 err = closeErr | 600 err = closeErr |
614 } | 601 } |
615 }() | 602 }() |
616 | 603 |
617 err = fn(fd) | 604 err = fn(fd) |
618 return | 605 return |
619 } | 606 } |
OLD | NEW |