| 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 |