vendor: github.com/spf13/afero@v1.2.1

go get github.com/spf13/afero@v1.2.1
go mod tidy
go mod vendor
This commit is contained in:
Radek Simko 2019-02-21 09:09:22 +00:00
parent 52b38a486a
commit 3d0b6bff07
No known key found for this signature in database
GPG Key ID: 1F1C84FE689A88D7
16 changed files with 282 additions and 115 deletions

2
go.mod
View File

@ -106,7 +106,7 @@ require (
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect
github.com/soheilhy/cmux v0.1.4 // indirect github.com/soheilhy/cmux v0.1.4 // indirect
github.com/spf13/afero v1.0.2 github.com/spf13/afero v1.2.1
github.com/terraform-providers/terraform-provider-openstack v1.15.0 github.com/terraform-providers/terraform-provider-openstack v1.15.0
github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect
github.com/ugorji/go v0.0.0-20180813092308-00b869d2f4a5 // indirect github.com/ugorji/go v0.0.0-20180813092308-00b869d2f4a5 // indirect

4
go.sum
View File

@ -358,8 +358,8 @@ github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spf13/afero v1.0.2 h1:5bRmqmInNmNFkI9NG9O0Xc/Lgl9wOWWUUA/O8XZqTCo= github.com/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M=
github.com/spf13/afero v1.0.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

View File

@ -2,8 +2,8 @@ sudo: false
language: go language: go
go: go:
- 1.7.5 - 1.9
- 1.8 - "1.10"
- tip - tip
os: os:

View File

@ -1,7 +1,6 @@
package afero package afero
import ( import (
"errors"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -9,6 +8,8 @@ import (
"time" "time"
) )
var _ Lstater = (*BasePathFs)(nil)
// The BasePathFs restricts all operations to a given path within an Fs. // The BasePathFs restricts all operations to a given path within an Fs.
// The given file name to the operations on this Fs will be prepended with // The given file name to the operations on this Fs will be prepended with
// the base path before calling the base Fs. // the base path before calling the base Fs.
@ -22,6 +23,16 @@ type BasePathFs struct {
path string path string
} }
type BasePathFile struct {
File
path string
}
func (f *BasePathFile) Name() string {
sourcename := f.File.Name()
return strings.TrimPrefix(sourcename, filepath.Clean(f.path))
}
func NewBasePathFs(source Fs, path string) Fs { func NewBasePathFs(source Fs, path string) Fs {
return &BasePathFs{source: source, path: path} return &BasePathFs{source: source, path: path}
} }
@ -30,7 +41,7 @@ func NewBasePathFs(source Fs, path string) Fs {
// else the given file with the base path prepended // else the given file with the base path prepended
func (b *BasePathFs) RealPath(name string) (path string, err error) { func (b *BasePathFs) RealPath(name string) (path string, err error) {
if err := validateBasePathName(name); err != nil { if err := validateBasePathName(name); err != nil {
return "", err return name, err
} }
bpath := filepath.Clean(b.path) bpath := filepath.Clean(b.path)
@ -52,7 +63,7 @@ func validateBasePathName(name string) error {
// On Windows a common mistake would be to provide an absolute OS path // On Windows a common mistake would be to provide an absolute OS path
// We could strip out the base part, but that would not be very portable. // We could strip out the base part, but that would not be very portable.
if filepath.IsAbs(name) { if filepath.IsAbs(name) {
return &os.PathError{Op: "realPath", Path: name, Err: errors.New("got a real OS path instead of a virtual")} return os.ErrNotExist
} }
return nil return nil
@ -111,14 +122,22 @@ func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f File,
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return nil, &os.PathError{Op: "openfile", Path: name, Err: err} return nil, &os.PathError{Op: "openfile", Path: name, Err: err}
} }
return b.source.OpenFile(name, flag, mode) sourcef, err := b.source.OpenFile(name, flag, mode)
if err != nil {
return nil, err
}
return &BasePathFile{sourcef, b.path}, nil
} }
func (b *BasePathFs) Open(name string) (f File, err error) { func (b *BasePathFs) Open(name string) (f File, err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return nil, &os.PathError{Op: "open", Path: name, Err: err} return nil, &os.PathError{Op: "open", Path: name, Err: err}
} }
return b.source.Open(name) sourcef, err := b.source.Open(name)
if err != nil {
return nil, err
}
return &BasePathFile{File: sourcef, path: b.path}, nil
} }
func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) { func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) {
@ -139,7 +158,23 @@ func (b *BasePathFs) Create(name string) (f File, err error) {
if name, err = b.RealPath(name); err != nil { if name, err = b.RealPath(name); err != nil {
return nil, &os.PathError{Op: "create", Path: name, Err: err} return nil, &os.PathError{Op: "create", Path: name, Err: err}
} }
return b.source.Create(name) sourcef, err := b.source.Create(name)
if err != nil {
return nil, err
}
return &BasePathFile{File: sourcef, path: b.path}, nil
}
func (b *BasePathFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
name, err := b.RealPath(name)
if err != nil {
return nil, false, &os.PathError{Op: "lstat", Path: name, Err: err}
}
if lstater, ok := b.source.(Lstater); ok {
return lstater.LstatIfPossible(name)
}
fi, err := b.source.Stat(name)
return fi, false, err
} }
// vim: ts=4 sw=4 noexpandtab nolist syn=go // vim: ts=4 sw=4 noexpandtab nolist syn=go

View File

@ -205,7 +205,7 @@ func (u *CacheOnReadFs) OpenFile(name string, flag int, perm os.FileMode) (File,
bfi.Close() // oops, what if O_TRUNC was set and file opening in the layer failed...? bfi.Close() // oops, what if O_TRUNC was set and file opening in the layer failed...?
return nil, err return nil, err
} }
return &UnionFile{base: bfi, layer: lfi}, nil return &UnionFile{Base: bfi, Layer: lfi}, nil
} }
return u.layer.OpenFile(name, flag, perm) return u.layer.OpenFile(name, flag, perm)
} }
@ -251,7 +251,7 @@ func (u *CacheOnReadFs) Open(name string) (File, error) {
if err != nil && bfile == nil { if err != nil && bfile == nil {
return nil, err return nil, err
} }
return &UnionFile{base: bfile, layer: lfile}, nil return &UnionFile{Base: bfile, Layer: lfile}, nil
} }
func (u *CacheOnReadFs) Mkdir(name string, perm os.FileMode) error { func (u *CacheOnReadFs) Mkdir(name string, perm os.FileMode) error {
@ -286,5 +286,5 @@ func (u *CacheOnReadFs) Create(name string) (File, error) {
bfh.Close() bfh.Close()
return nil, err return nil, err
} }
return &UnionFile{base: bfh, layer: lfh}, nil return &UnionFile{Base: bfh, Layer: lfh}, nil
} }

View File

@ -8,6 +8,8 @@ import (
"time" "time"
) )
var _ Lstater = (*CopyOnWriteFs)(nil)
// The CopyOnWriteFs is a union filesystem: a read only base file system with // The CopyOnWriteFs is a union filesystem: a read only base file system with
// a possibly writeable layer on top. Changes to the file system will only // a possibly writeable layer on top. Changes to the file system will only
// be made in the overlay: Changing an existing file in the base layer which // be made in the overlay: Changing an existing file in the base layer which
@ -76,16 +78,53 @@ func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error {
func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) { func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
fi, err := u.layer.Stat(name) fi, err := u.layer.Stat(name)
if err != nil { if err != nil {
origErr := err isNotExist := u.isNotExist(err)
if isNotExist {
return u.base.Stat(name)
}
return nil, err
}
return fi, nil
}
func (u *CopyOnWriteFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
llayer, ok1 := u.layer.(Lstater)
lbase, ok2 := u.base.(Lstater)
if ok1 {
fi, b, err := llayer.LstatIfPossible(name)
if err == nil {
return fi, b, nil
}
if !u.isNotExist(err) {
return nil, b, err
}
}
if ok2 {
fi, b, err := lbase.LstatIfPossible(name)
if err == nil {
return fi, b, nil
}
if !u.isNotExist(err) {
return nil, b, err
}
}
fi, err := u.Stat(name)
return fi, false, err
}
func (u *CopyOnWriteFs) isNotExist(err error) bool {
if e, ok := err.(*os.PathError); ok { if e, ok := err.(*os.PathError); ok {
err = e.Err err = e.Err
} }
if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR { if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR {
return u.base.Stat(name) return true
} }
return nil, origErr return false
}
return fi, nil
} }
// Renaming files present only in the base layer is not permitted // Renaming files present only in the base layer is not permitted
@ -219,7 +258,7 @@ func (u *CopyOnWriteFs) Open(name string) (File, error) {
return nil, fmt.Errorf("BaseErr: %v\nOverlayErr: %v", bErr, lErr) return nil, fmt.Errorf("BaseErr: %v\nOverlayErr: %v", bErr, lErr)
} }
return &UnionFile{base: bfile, layer: lfile}, nil return &UnionFile{Base: bfile, Layer: lfile}, nil
} }
func (u *CopyOnWriteFs) Mkdir(name string, perm os.FileMode) error { func (u *CopyOnWriteFs) Mkdir(name string, perm os.FileMode) error {
@ -228,7 +267,7 @@ func (u *CopyOnWriteFs) Mkdir(name string, perm os.FileMode) error {
return u.layer.MkdirAll(name, perm) return u.layer.MkdirAll(name, perm)
} }
if dir { if dir {
return syscall.EEXIST return ErrFileExists
} }
return u.layer.MkdirAll(name, perm) return u.layer.MkdirAll(name, perm)
} }
@ -243,7 +282,8 @@ func (u *CopyOnWriteFs) MkdirAll(name string, perm os.FileMode) error {
return u.layer.MkdirAll(name, perm) return u.layer.MkdirAll(name, perm)
} }
if dir { if dir {
return syscall.EEXIST // This is in line with how os.MkdirAll behaves.
return nil
} }
return u.layer.MkdirAll(name, perm) return u.layer.MkdirAll(name, perm)
} }

3
vendor/github.com/spf13/afero/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/spf13/afero
require golang.org/x/text v0.3.0

2
vendor/github.com/spf13/afero/go.sum generated vendored Normal file
View File

@ -0,0 +1,2 @@
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

27
vendor/github.com/spf13/afero/lstater.go generated vendored Normal file
View File

@ -0,0 +1,27 @@
// Copyright © 2018 Steve Francia <spf@spf13.com>.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package afero
import (
"os"
)
// Lstater is an optional interface in Afero. It is only implemented by the
// filesystems saying so.
// It will call Lstat if the filesystem iself is, or it delegates to, the os filesystem.
// Else it will call Stat.
// In addtion to the FileInfo, it will return a boolean telling whether Lstat was called or not.
type Lstater interface {
LstatIfPossible(name string) (os.FileInfo, bool, error)
}

View File

@ -33,8 +33,8 @@ import (
// built-ins from that package. // built-ins from that package.
func Glob(fs Fs, pattern string) (matches []string, err error) { func Glob(fs Fs, pattern string) (matches []string, err error) {
if !hasMeta(pattern) { if !hasMeta(pattern) {
// afero does not support Lstat directly. // Lstat not supported by a ll filesystems.
if _, err = lstatIfOs(fs, pattern); err != nil { if _, err = lstatIfPossible(fs, pattern); err != nil {
return nil, nil return nil, nil
} }
return []string{pattern}, nil return []string{pattern}, nil

View File

@ -131,6 +131,9 @@ func (f *File) Sync() error {
} }
func (f *File) Readdir(count int) (res []os.FileInfo, err error) { func (f *File) Readdir(count int) (res []os.FileInfo, err error) {
if !f.fileData.dir {
return nil, &os.PathError{Op: "readdir", Path: f.fileData.name, Err: errors.New("not a dir")}
}
var outLength int64 var outLength int64
f.fileData.Lock() f.fileData.Lock()

View File

@ -19,6 +19,8 @@ import (
"time" "time"
) )
var _ Lstater = (*OsFs)(nil)
// OsFs is a Fs implementation that uses functions provided by the os package. // OsFs is a Fs implementation that uses functions provided by the os package.
// //
// For details in any method, check the documentation of the os package // For details in any method, check the documentation of the os package
@ -92,3 +94,8 @@ func (OsFs) Chmod(name string, mode os.FileMode) error {
func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error { func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
return os.Chtimes(name, atime, mtime) return os.Chtimes(name, atime, mtime)
} }
func (OsFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
fi, err := os.Lstat(name)
return fi, true, err
}

View File

@ -60,7 +60,7 @@ func walk(fs Fs, path string, info os.FileInfo, walkFn filepath.WalkFunc) error
for _, name := range names { for _, name := range names {
filename := filepath.Join(path, name) filename := filepath.Join(path, name)
fileInfo, err := lstatIfOs(fs, filename) fileInfo, err := lstatIfPossible(fs, filename)
if err != nil { if err != nil {
if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir { if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
return err return err
@ -77,15 +77,13 @@ func walk(fs Fs, path string, info os.FileInfo, walkFn filepath.WalkFunc) error
return nil return nil
} }
// if the filesystem is OsFs use Lstat, else use fs.Stat // if the filesystem supports it, use Lstat, else use fs.Stat
func lstatIfOs(fs Fs, path string) (info os.FileInfo, err error) { func lstatIfPossible(fs Fs, path string) (os.FileInfo, error) {
_, ok := fs.(*OsFs) if lfs, ok := fs.(Lstater); ok {
if ok { fi, _, err := lfs.LstatIfPossible(path)
info, err = os.Lstat(path) return fi, err
} else {
info, err = fs.Stat(path)
} }
return return fs.Stat(path)
} }
// Walk walks the file tree rooted at root, calling walkFn for each file or // Walk walks the file tree rooted at root, calling walkFn for each file or
@ -100,7 +98,7 @@ func (a Afero) Walk(root string, walkFn filepath.WalkFunc) error {
} }
func Walk(fs Fs, root string, walkFn filepath.WalkFunc) error { func Walk(fs Fs, root string, walkFn filepath.WalkFunc) error {
info, err := lstatIfOs(fs, root) info, err := lstatIfPossible(fs, root)
if err != nil { if err != nil {
return walkFn(root, nil, err) return walkFn(root, nil, err)
} }

View File

@ -6,6 +6,8 @@ import (
"time" "time"
) )
var _ Lstater = (*ReadOnlyFs)(nil)
type ReadOnlyFs struct { type ReadOnlyFs struct {
source Fs source Fs
} }
@ -34,6 +36,14 @@ func (r *ReadOnlyFs) Stat(name string) (os.FileInfo, error) {
return r.source.Stat(name) return r.source.Stat(name)
} }
func (r *ReadOnlyFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
if lsf, ok := r.source.(Lstater); ok {
return lsf.LstatIfPossible(name)
}
fi, err := r.Stat(name)
return fi, false, err
}
func (r *ReadOnlyFs) Rename(o, n string) error { func (r *ReadOnlyFs) Rename(o, n string) error {
return syscall.EPERM return syscall.EPERM
} }

View File

@ -21,8 +21,9 @@ import (
// successful read in the overlay will move the cursor position in the base layer // successful read in the overlay will move the cursor position in the base layer
// by the number of bytes read. // by the number of bytes read.
type UnionFile struct { type UnionFile struct {
base File Base File
layer File Layer File
Merger DirsMerger
off int off int
files []os.FileInfo files []os.FileInfo
} }
@ -31,22 +32,22 @@ func (f *UnionFile) Close() error {
// first close base, so we have a newer timestamp in the overlay. If we'd close // first close base, so we have a newer timestamp in the overlay. If we'd close
// the overlay first, we'd get a cacheStale the next time we access this file // the overlay first, we'd get a cacheStale the next time we access this file
// -> cache would be useless ;-) // -> cache would be useless ;-)
if f.base != nil { if f.Base != nil {
f.base.Close() f.Base.Close()
} }
if f.layer != nil { if f.Layer != nil {
return f.layer.Close() return f.Layer.Close()
} }
return BADFD return BADFD
} }
func (f *UnionFile) Read(s []byte) (int, error) { func (f *UnionFile) Read(s []byte) (int, error) {
if f.layer != nil { if f.Layer != nil {
n, err := f.layer.Read(s) n, err := f.Layer.Read(s)
if (err == nil || err == io.EOF) && f.base != nil { if (err == nil || err == io.EOF) && f.Base != nil {
// advance the file position also in the base file, the next // advance the file position also in the base file, the next
// call may be a write at this position (or a seek with SEEK_CUR) // call may be a write at this position (or a seek with SEEK_CUR)
if _, seekErr := f.base.Seek(int64(n), os.SEEK_CUR); seekErr != nil { if _, seekErr := f.Base.Seek(int64(n), os.SEEK_CUR); seekErr != nil {
// only overwrite err in case the seek fails: we need to // only overwrite err in case the seek fails: we need to
// report an eventual io.EOF to the caller // report an eventual io.EOF to the caller
err = seekErr err = seekErr
@ -54,109 +55,150 @@ func (f *UnionFile) Read(s []byte) (int, error) {
} }
return n, err return n, err
} }
if f.base != nil { if f.Base != nil {
return f.base.Read(s) return f.Base.Read(s)
} }
return 0, BADFD return 0, BADFD
} }
func (f *UnionFile) ReadAt(s []byte, o int64) (int, error) { func (f *UnionFile) ReadAt(s []byte, o int64) (int, error) {
if f.layer != nil { if f.Layer != nil {
n, err := f.layer.ReadAt(s, o) n, err := f.Layer.ReadAt(s, o)
if (err == nil || err == io.EOF) && f.base != nil { if (err == nil || err == io.EOF) && f.Base != nil {
_, err = f.base.Seek(o+int64(n), os.SEEK_SET) _, err = f.Base.Seek(o+int64(n), os.SEEK_SET)
} }
return n, err return n, err
} }
if f.base != nil { if f.Base != nil {
return f.base.ReadAt(s, o) return f.Base.ReadAt(s, o)
} }
return 0, BADFD return 0, BADFD
} }
func (f *UnionFile) Seek(o int64, w int) (pos int64, err error) { func (f *UnionFile) Seek(o int64, w int) (pos int64, err error) {
if f.layer != nil { if f.Layer != nil {
pos, err = f.layer.Seek(o, w) pos, err = f.Layer.Seek(o, w)
if (err == nil || err == io.EOF) && f.base != nil { if (err == nil || err == io.EOF) && f.Base != nil {
_, err = f.base.Seek(o, w) _, err = f.Base.Seek(o, w)
} }
return pos, err return pos, err
} }
if f.base != nil { if f.Base != nil {
return f.base.Seek(o, w) return f.Base.Seek(o, w)
} }
return 0, BADFD return 0, BADFD
} }
func (f *UnionFile) Write(s []byte) (n int, err error) { func (f *UnionFile) Write(s []byte) (n int, err error) {
if f.layer != nil { if f.Layer != nil {
n, err = f.layer.Write(s) n, err = f.Layer.Write(s)
if err == nil && f.base != nil { // hmm, do we have fixed size files where a write may hit the EOF mark? if err == nil && f.Base != nil { // hmm, do we have fixed size files where a write may hit the EOF mark?
_, err = f.base.Write(s) _, err = f.Base.Write(s)
} }
return n, err return n, err
} }
if f.base != nil { if f.Base != nil {
return f.base.Write(s) return f.Base.Write(s)
} }
return 0, BADFD return 0, BADFD
} }
func (f *UnionFile) WriteAt(s []byte, o int64) (n int, err error) { func (f *UnionFile) WriteAt(s []byte, o int64) (n int, err error) {
if f.layer != nil { if f.Layer != nil {
n, err = f.layer.WriteAt(s, o) n, err = f.Layer.WriteAt(s, o)
if err == nil && f.base != nil { if err == nil && f.Base != nil {
_, err = f.base.WriteAt(s, o) _, err = f.Base.WriteAt(s, o)
} }
return n, err return n, err
} }
if f.base != nil { if f.Base != nil {
return f.base.WriteAt(s, o) return f.Base.WriteAt(s, o)
} }
return 0, BADFD return 0, BADFD
} }
func (f *UnionFile) Name() string { func (f *UnionFile) Name() string {
if f.layer != nil { if f.Layer != nil {
return f.layer.Name() return f.Layer.Name()
} }
return f.base.Name() return f.Base.Name()
} }
// Readdir will weave the two directories together and // DirsMerger is how UnionFile weaves two directories together.
// return a single view of the overlayed directories // It takes the FileInfo slices from the layer and the base and returns a
func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) { // single view.
if f.off == 0 { type DirsMerger func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error)
var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) {
var files = make(map[string]os.FileInfo) var files = make(map[string]os.FileInfo)
var rfi []os.FileInfo
if f.layer != nil { for _, fi := range lofi {
rfi, err = f.layer.Readdir(-1)
if err != nil {
return nil, err
}
for _, fi := range rfi {
files[fi.Name()] = fi files[fi.Name()] = fi
} }
}
if f.base != nil { for _, fi := range bofi {
rfi, err = f.base.Readdir(-1)
if err != nil {
return nil, err
}
for _, fi := range rfi {
if _, exists := files[fi.Name()]; !exists { if _, exists := files[fi.Name()]; !exists {
files[fi.Name()] = fi files[fi.Name()] = fi
} }
} }
}
rfi := make([]os.FileInfo, len(files))
i := 0
for _, fi := range files { for _, fi := range files {
f.files = append(f.files, fi) rfi[i] = fi
i++
}
return rfi, nil
}
// Readdir will weave the two directories together and
// return a single view of the overlayed directories
// At the end of the directory view, the error is io.EOF.
func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
var merge DirsMerger = f.Merger
if merge == nil {
merge = defaultUnionMergeDirsFn
}
if f.off == 0 {
var lfi []os.FileInfo
if f.Layer != nil {
lfi, err = f.Layer.Readdir(-1)
if err != nil {
return nil, err
} }
} }
var bfi []os.FileInfo
if f.Base != nil {
bfi, err = f.Base.Readdir(-1)
if err != nil {
return nil, err
}
}
merged, err := merge(lfi, bfi)
if err != nil {
return nil, err
}
f.files = append(f.files, merged...)
}
if f.off >= len(f.files) {
return nil, io.EOF
}
if c == -1 { if c == -1 {
return f.files[f.off:], nil return f.files[f.off:], nil
} }
if c > len(f.files) {
c = len(f.files)
}
defer func() { f.off += c }() defer func() { f.off += c }()
return f.files[f.off:c], nil return f.files[f.off:c], nil
} }
@ -174,53 +216,53 @@ func (f *UnionFile) Readdirnames(c int) ([]string, error) {
} }
func (f *UnionFile) Stat() (os.FileInfo, error) { func (f *UnionFile) Stat() (os.FileInfo, error) {
if f.layer != nil { if f.Layer != nil {
return f.layer.Stat() return f.Layer.Stat()
} }
if f.base != nil { if f.Base != nil {
return f.base.Stat() return f.Base.Stat()
} }
return nil, BADFD return nil, BADFD
} }
func (f *UnionFile) Sync() (err error) { func (f *UnionFile) Sync() (err error) {
if f.layer != nil { if f.Layer != nil {
err = f.layer.Sync() err = f.Layer.Sync()
if err == nil && f.base != nil { if err == nil && f.Base != nil {
err = f.base.Sync() err = f.Base.Sync()
} }
return err return err
} }
if f.base != nil { if f.Base != nil {
return f.base.Sync() return f.Base.Sync()
} }
return BADFD return BADFD
} }
func (f *UnionFile) Truncate(s int64) (err error) { func (f *UnionFile) Truncate(s int64) (err error) {
if f.layer != nil { if f.Layer != nil {
err = f.layer.Truncate(s) err = f.Layer.Truncate(s)
if err == nil && f.base != nil { if err == nil && f.Base != nil {
err = f.base.Truncate(s) err = f.Base.Truncate(s)
} }
return err return err
} }
if f.base != nil { if f.Base != nil {
return f.base.Truncate(s) return f.Base.Truncate(s)
} }
return BADFD return BADFD
} }
func (f *UnionFile) WriteString(s string) (n int, err error) { func (f *UnionFile) WriteString(s string) (n int, err error) {
if f.layer != nil { if f.Layer != nil {
n, err = f.layer.WriteString(s) n, err = f.Layer.WriteString(s)
if err == nil && f.base != nil { if err == nil && f.Base != nil {
_, err = f.base.WriteString(s) _, err = f.Base.WriteString(s)
} }
return n, err return n, err
} }
if f.base != nil { if f.Base != nil {
return f.base.WriteString(s) return f.Base.WriteString(s)
} }
return 0, BADFD return 0, BADFD
} }

2
vendor/modules.txt vendored
View File

@ -413,7 +413,7 @@ github.com/posener/complete/cmd
github.com/posener/complete/match github.com/posener/complete/match
# github.com/satori/go.uuid v0.0.0-20160927100844-b061729afc07 # github.com/satori/go.uuid v0.0.0-20160927100844-b061729afc07
github.com/satori/go.uuid github.com/satori/go.uuid
# github.com/spf13/afero v1.0.2 # github.com/spf13/afero v1.2.1
github.com/spf13/afero github.com/spf13/afero
github.com/spf13/afero/mem github.com/spf13/afero/mem
# github.com/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d # github.com/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d