OSDN Git Service

fix commands
[bytom/shuttle.git] / vendor / github.com / bytom / vendor / github.com / spf13 / afero / memmap.go
diff --git a/vendor/github.com/bytom/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/bytom/vendor/github.com/spf13/afero/memmap.go
new file mode 100644 (file)
index 0000000..09498e7
--- /dev/null
@@ -0,0 +1,365 @@
+// Copyright © 2014 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 (
+       "fmt"
+       "log"
+       "os"
+       "path/filepath"
+       "strings"
+       "sync"
+       "time"
+
+       "github.com/spf13/afero/mem"
+)
+
+type MemMapFs struct {
+       mu   sync.RWMutex
+       data map[string]*mem.FileData
+       init sync.Once
+}
+
+func NewMemMapFs() Fs {
+       return &MemMapFs{}
+}
+
+func (m *MemMapFs) getData() map[string]*mem.FileData {
+       m.init.Do(func() {
+               m.data = make(map[string]*mem.FileData)
+               // Root should always exist, right?
+               // TODO: what about windows?
+               m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator)
+       })
+       return m.data
+}
+
+func (*MemMapFs) Name() string { return "MemMapFS" }
+
+func (m *MemMapFs) Create(name string) (File, error) {
+       name = normalizePath(name)
+       m.mu.Lock()
+       file := mem.CreateFile(name)
+       m.getData()[name] = file
+       m.registerWithParent(file)
+       m.mu.Unlock()
+       return mem.NewFileHandle(file), nil
+}
+
+func (m *MemMapFs) unRegisterWithParent(fileName string) error {
+       f, err := m.lockfreeOpen(fileName)
+       if err != nil {
+               return err
+       }
+       parent := m.findParent(f)
+       if parent == nil {
+               log.Panic("parent of ", f.Name(), " is nil")
+       }
+
+       parent.Lock()
+       mem.RemoveFromMemDir(parent, f)
+       parent.Unlock()
+       return nil
+}
+
+func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData {
+       pdir, _ := filepath.Split(f.Name())
+       pdir = filepath.Clean(pdir)
+       pfile, err := m.lockfreeOpen(pdir)
+       if err != nil {
+               return nil
+       }
+       return pfile
+}
+
+func (m *MemMapFs) registerWithParent(f *mem.FileData) {
+       if f == nil {
+               return
+       }
+       parent := m.findParent(f)
+       if parent == nil {
+               pdir := filepath.Dir(filepath.Clean(f.Name()))
+               err := m.lockfreeMkdir(pdir, 0777)
+               if err != nil {
+                       //log.Println("Mkdir error:", err)
+                       return
+               }
+               parent, err = m.lockfreeOpen(pdir)
+               if err != nil {
+                       //log.Println("Open after Mkdir error:", err)
+                       return
+               }
+       }
+
+       parent.Lock()
+       mem.InitializeDir(parent)
+       mem.AddToMemDir(parent, f)
+       parent.Unlock()
+}
+
+func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
+       name = normalizePath(name)
+       x, ok := m.getData()[name]
+       if ok {
+               // Only return ErrFileExists if it's a file, not a directory.
+               i := mem.FileInfo{FileData: x}
+               if !i.IsDir() {
+                       return ErrFileExists
+               }
+       } else {
+               item := mem.CreateDir(name)
+               m.getData()[name] = item
+               m.registerWithParent(item)
+       }
+       return nil
+}
+
+func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
+       name = normalizePath(name)
+
+       m.mu.RLock()
+       _, ok := m.getData()[name]
+       m.mu.RUnlock()
+       if ok {
+               return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
+       }
+
+       m.mu.Lock()
+       item := mem.CreateDir(name)
+       m.getData()[name] = item
+       m.registerWithParent(item)
+       m.mu.Unlock()
+
+       m.Chmod(name, perm|os.ModeDir)
+
+       return nil
+}
+
+func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
+       err := m.Mkdir(path, perm)
+       if err != nil {
+               if err.(*os.PathError).Err == ErrFileExists {
+                       return nil
+               }
+               return err
+       }
+       return nil
+}
+
+// Handle some relative paths
+func normalizePath(path string) string {
+       path = filepath.Clean(path)
+
+       switch path {
+       case ".":
+               return FilePathSeparator
+       case "..":
+               return FilePathSeparator
+       default:
+               return path
+       }
+}
+
+func (m *MemMapFs) Open(name string) (File, error) {
+       f, err := m.open(name)
+       if f != nil {
+               return mem.NewReadOnlyFileHandle(f), err
+       }
+       return nil, err
+}
+
+func (m *MemMapFs) openWrite(name string) (File, error) {
+       f, err := m.open(name)
+       if f != nil {
+               return mem.NewFileHandle(f), err
+       }
+       return nil, err
+}
+
+func (m *MemMapFs) open(name string) (*mem.FileData, error) {
+       name = normalizePath(name)
+
+       m.mu.RLock()
+       f, ok := m.getData()[name]
+       m.mu.RUnlock()
+       if !ok {
+               return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
+       }
+       return f, nil
+}
+
+func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
+       name = normalizePath(name)
+       f, ok := m.getData()[name]
+       if ok {
+               return f, nil
+       } else {
+               return nil, ErrFileNotFound
+       }
+}
+
+func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
+       chmod := false
+       file, err := m.openWrite(name)
+       if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
+               file, err = m.Create(name)
+               chmod = true
+       }
+       if err != nil {
+               return nil, err
+       }
+       if flag == os.O_RDONLY {
+               file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
+       }
+       if flag&os.O_APPEND > 0 {
+               _, err = file.Seek(0, os.SEEK_END)
+               if err != nil {
+                       file.Close()
+                       return nil, err
+               }
+       }
+       if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 {
+               err = file.Truncate(0)
+               if err != nil {
+                       file.Close()
+                       return nil, err
+               }
+       }
+       if chmod {
+               m.Chmod(name, perm)
+       }
+       return file, nil
+}
+
+func (m *MemMapFs) Remove(name string) error {
+       name = normalizePath(name)
+
+       m.mu.Lock()
+       defer m.mu.Unlock()
+
+       if _, ok := m.getData()[name]; ok {
+               err := m.unRegisterWithParent(name)
+               if err != nil {
+                       return &os.PathError{Op: "remove", Path: name, Err: err}
+               }
+               delete(m.getData(), name)
+       } else {
+               return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
+       }
+       return nil
+}
+
+func (m *MemMapFs) RemoveAll(path string) error {
+       path = normalizePath(path)
+       m.mu.Lock()
+       m.unRegisterWithParent(path)
+       m.mu.Unlock()
+
+       m.mu.RLock()
+       defer m.mu.RUnlock()
+
+       for p, _ := range m.getData() {
+               if strings.HasPrefix(p, path) {
+                       m.mu.RUnlock()
+                       m.mu.Lock()
+                       delete(m.getData(), p)
+                       m.mu.Unlock()
+                       m.mu.RLock()
+               }
+       }
+       return nil
+}
+
+func (m *MemMapFs) Rename(oldname, newname string) error {
+       oldname = normalizePath(oldname)
+       newname = normalizePath(newname)
+
+       if oldname == newname {
+               return nil
+       }
+
+       m.mu.RLock()
+       defer m.mu.RUnlock()
+       if _, ok := m.getData()[oldname]; ok {
+               m.mu.RUnlock()
+               m.mu.Lock()
+               m.unRegisterWithParent(oldname)
+               fileData := m.getData()[oldname]
+               delete(m.getData(), oldname)
+               mem.ChangeFileName(fileData, newname)
+               m.getData()[newname] = fileData
+               m.registerWithParent(fileData)
+               m.mu.Unlock()
+               m.mu.RLock()
+       } else {
+               return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
+       }
+       return nil
+}
+
+func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
+       f, err := m.Open(name)
+       if err != nil {
+               return nil, err
+       }
+       fi := mem.GetFileInfo(f.(*mem.File).Data())
+       return fi, nil
+}
+
+func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
+       name = normalizePath(name)
+
+       m.mu.RLock()
+       f, ok := m.getData()[name]
+       m.mu.RUnlock()
+       if !ok {
+               return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
+       }
+
+       m.mu.Lock()
+       mem.SetMode(f, mode)
+       m.mu.Unlock()
+
+       return nil
+}
+
+func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
+       name = normalizePath(name)
+
+       m.mu.RLock()
+       f, ok := m.getData()[name]
+       m.mu.RUnlock()
+       if !ok {
+               return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
+       }
+
+       m.mu.Lock()
+       mem.SetModTime(f, mtime)
+       m.mu.Unlock()
+
+       return nil
+}
+
+func (m *MemMapFs) List() {
+       for _, x := range m.data {
+               y := mem.FileInfo{FileData: x}
+               fmt.Println(x.Name(), y.Size())
+       }
+}
+
+// func debugMemMapList(fs Fs) {
+//     if x, ok := fs.(*MemMapFs); ok {
+//             x.List()
+//     }
+// }