Skip to content

Commit

Permalink
Rename dir contents when renaming in-mem dirs
Browse files Browse the repository at this point in the history
Prior to this change renaming an in-memory directory would leave the
contents of the directory behind at their old paths. Now directory
entries are updated to use the new directory name.

Fixes spf13#141
  • Loading branch information
mnussbaum committed Jul 25, 2018
1 parent 787d034 commit 33ee815
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
25 changes: 25 additions & 0 deletions afero_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,31 @@ func TestRename(t *testing.T) {
}
}

func TestRenameDirectory(t *testing.T) {
fs := NewMemMapFs()
tmp := testDir(fs)
srcDir := filepath.Join(tmp, "src")
srcPath := filepath.Join(srcDir, testName)
destDir := filepath.Join(tmp, "dest")
destPath := filepath.Join(destDir, testName)

if _, err := fs.Create(srcPath); err != nil {
t.Errorf("%s: create %q failed: %v", fs.Name(), srcPath, err)
}

if err := fs.Rename(srcDir, destDir); err != nil {
t.Errorf("%s: rename %q to %q failed: %v", fs.Name(), srcDir, destDir, err)
}

if _, err := fs.Stat(srcPath); err == nil {
t.Errorf("File %q was not removed due to rename to %q", srcPath, destPath)
}

if _, err := fs.Stat(destPath); err != nil {
t.Errorf("File %q was not present after rename from %q", destPath, srcPath)
}
}

func TestRemove(t *testing.T) {
for _, fs := range Fss {

Expand Down
4 changes: 4 additions & 0 deletions mem/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ func GetFileInfo(f *FileData) *FileInfo {
return &FileInfo{f}
}

func GetDirFiles(f *FileData) []*FileData {
return f.memDir.Files()
}

func (f *File) Open() error {
atomic.StoreInt64(&f.at, 0)
atomic.StoreInt64(&f.readDirCount, 0)
Expand Down
53 changes: 53 additions & 0 deletions memmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,57 @@ func (m *MemMapFs) Create(name string) (File, error) {
return mem.NewFileHandle(file), nil
}

func (m *MemMapFs) unRegisterChildren(dirName string) ([]*mem.FileData, error) {
dir, err := m.lockfreeOpen(dirName)
if err != nil {
return nil, err
}

children := mem.GetDirFiles(dir)
if children == nil {
return children, nil
}

for _, file := range children {
fileName := file.Name()
file.Lock()
delete(m.getData(), fileName)
mem.RemoveFromMemDir(dir, file)
file.Unlock()
}

return children, nil
}

func (m *MemMapFs) registerChildren(
oldDirName string,
newDirName string,
children []*mem.FileData,
) error {
dir, err := m.lockfreeOpen(newDirName)
if err != nil {
return err
}

for _, file := range children {
oldFileName := file.Name()
newFileName := strings.Replace(
oldFileName,
oldDirName,
newDirName,
1,
)
mem.ChangeFileName(file, newFileName)

file.Lock()
m.getData()[newFileName] = file
mem.AddToMemDir(dir, file)
file.Unlock()
}

return nil
}

func (m *MemMapFs) unRegisterWithParent(fileName string) error {
f, err := m.lockfreeOpen(fileName)
if err != nil {
Expand Down Expand Up @@ -296,9 +347,11 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
m.mu.Lock()
m.unRegisterWithParent(oldname)
fileData := m.getData()[oldname]
children, _ := m.unRegisterChildren(oldname)
delete(m.getData(), oldname)
mem.ChangeFileName(fileData, newname)
m.getData()[newname] = fileData
m.registerChildren(oldname, newname, children)
m.registerWithParent(fileData)
m.mu.Unlock()
m.mu.RLock()
Expand Down

0 comments on commit 33ee815

Please sign in to comment.