diff --git a/memmap.go b/memmap.go index 5c265f92..c31638a5 100644 --- a/memmap.go +++ b/memmap.go @@ -314,6 +314,18 @@ func (m *MemMapFs) Rename(oldname, newname string) error { } else { return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound} } + + for p, fileData := range m.getData() { + if strings.HasPrefix(p, oldname) { + m.mu.RUnlock() + m.mu.Lock() + delete(m.getData(), p) + p := strings.Replace(p, oldname, newname, 1) + m.getData()[p] = fileData + m.mu.Unlock() + m.mu.RLock() + } + } return nil } diff --git a/memmap_test.go b/memmap_test.go index 627b1067..c6814c04 100644 --- a/memmap_test.go +++ b/memmap_test.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "testing" "time" ) @@ -683,3 +684,75 @@ func TestMemFsLstatIfPossible(t *testing.T) { t.Fatalf("Function indicated lstat was called. This should never be true.") } } + +func TestMemFsRenameDir(t *testing.T) { + + testDirs := []string { + "/src/subdir1/", + "/src/subdir1/subdir2/", + "/src/subdir1/subdir2/subdir3", + } + + testFiles := []string { + "/src/subdir1/testFile1.txt", + "/src/subdir1/subdir2/testFile3.txt", + "/src/subdir1/subdir2/testFile4.txt", + "/src/subdir1/subdir2/subdir3/testFile5.txt", + } + + const srcPath = "/src" + const dstPath = "/dst" + + fs := NewMemMapFs() + + // set up the nested file structure + for _, path := range testDirs { + err := fs.Mkdir(path, 0777) + if err != nil { + t.Error(err) + } + } + + // add some files + for _, file := range testFiles { + _, err := fs.Create(file) + if err != nil { + t.Error(err) + } + } + + // rename the top level path + err := fs.Rename(srcPath, dstPath) + if err != nil { + t.Errorf("Rename failed: %s", err) + return + } + + // check that all sub dirs have been renamed + for _, path := range testDirs { + expectedPath := strings.ReplaceAll(path, srcPath, dstPath) + _, err = fs.Stat(expectedPath) + if err != nil { + t.Errorf("Failed to rename dir: %s to %s", path, expectedPath) + return + } + } + + // check that all files in all sub dirs have been renamed + for _, path := range testFiles { + expectedFile := strings.ReplaceAll(path, srcPath, dstPath) + _, err = fs.Stat(expectedFile) + if err != nil { + t.Errorf("Failed to rename file: %s to %s", path, expectedFile) + return + } + } + + // check that we the original source dirs can be created again + for _, path := range testDirs { + err := fs.Mkdir(path, 0777) + if err != nil { + t.Errorf("Failed to recreate dir: %s", path) + } + } +} \ No newline at end of file