From fd54a2feaa3f86c3925ed6985fd903a3986d2d3c Mon Sep 17 00:00:00 2001 From: Bruno Michel Date: Fri, 9 Nov 2018 12:02:59 +0100 Subject: [PATCH 1/2] Fix renaming a dir with sub-directories --- memmap.go | 14 +++++++++++++- memmap_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/memmap.go b/memmap.go index 5c265f92..50075cc9 100644 --- a/memmap.go +++ b/memmap.go @@ -279,7 +279,7 @@ func (m *MemMapFs) RemoveAll(path string) error { defer m.mu.RUnlock() for p := range m.getData() { - if strings.HasPrefix(p, path) { + if strings.HasPrefix(p, path+FilePathSeparator) { m.mu.RUnlock() m.mu.Lock() delete(m.getData(), p) @@ -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+FilePathSeparator) { + 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..8547fe6f 100644 --- a/memmap_test.go +++ b/memmap_test.go @@ -683,3 +683,47 @@ func TestMemFsLstatIfPossible(t *testing.T) { t.Fatalf("Function indicated lstat was called. This should never be true.") } } + +func TestMemFsRenameDir(t *testing.T) { + const srcPath = "/src" + const dstPath = "/dst" + const subDir = "dir" + + fs := NewMemMapFs() + + err := fs.MkdirAll(srcPath+FilePathSeparator+subDir, 0777) + if err != nil { + t.Errorf("MkDirAll failed: %s", err) + return + } + + err = fs.Rename(srcPath, dstPath) + if err != nil { + t.Errorf("Rename failed: %s", err) + return + } + + _, err = fs.Stat(srcPath + FilePathSeparator + subDir) + if err == nil { + t.Errorf("SubDir still exists in the source dir") + return + } + + _, err = fs.Stat(dstPath + FilePathSeparator + subDir) + if err != nil { + t.Errorf("SubDir stat in the destination dir: %s", err) + return + } + + err = fs.Mkdir(srcPath, 0777) + if err != nil { + t.Errorf("Cannot recreate the source dir: %s", err) + return + } + + err = fs.Mkdir(srcPath+FilePathSeparator+subDir, 0777) + if err != nil { + t.Errorf("Cannot recreate the subdir in the source dir: %s", err) + return + } +} From 2bdaf65d48e901c56dcb38168fa7731e2ae02ed6 Mon Sep 17 00:00:00 2001 From: Dave Armstrong Date: Thu, 2 Sep 2021 16:12:48 +0100 Subject: [PATCH 2/2] (GH-141) Fix renaming a dir with sub-directories --- memmap.go | 4 +-- memmap_test.go | 79 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/memmap.go b/memmap.go index 50075cc9..c31638a5 100644 --- a/memmap.go +++ b/memmap.go @@ -279,7 +279,7 @@ func (m *MemMapFs) RemoveAll(path string) error { defer m.mu.RUnlock() for p := range m.getData() { - if strings.HasPrefix(p, path+FilePathSeparator) { + if strings.HasPrefix(p, path) { m.mu.RUnlock() m.mu.Lock() delete(m.getData(), p) @@ -316,7 +316,7 @@ func (m *MemMapFs) Rename(oldname, newname string) error { } for p, fileData := range m.getData() { - if strings.HasPrefix(p, oldname+FilePathSeparator) { + if strings.HasPrefix(p, oldname) { m.mu.RUnlock() m.mu.Lock() delete(m.getData(), p) diff --git a/memmap_test.go b/memmap_test.go index 8547fe6f..c6814c04 100644 --- a/memmap_test.go +++ b/memmap_test.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "testing" "time" ) @@ -685,45 +686,73 @@ func TestMemFsLstatIfPossible(t *testing.T) { } 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" - const subDir = "dir" fs := NewMemMapFs() - err := fs.MkdirAll(srcPath+FilePathSeparator+subDir, 0777) - if err != nil { - t.Errorf("MkDirAll failed: %s", err) - return + // set up the nested file structure + for _, path := range testDirs { + err := fs.Mkdir(path, 0777) + if err != nil { + t.Error(err) + } } - err = fs.Rename(srcPath, dstPath) - if err != nil { - t.Errorf("Rename failed: %s", err) - return + // add some files + for _, file := range testFiles { + _, err := fs.Create(file) + if err != nil { + t.Error(err) + } } - _, err = fs.Stat(srcPath + FilePathSeparator + subDir) - if err == nil { - t.Errorf("SubDir still exists in the source dir") + // rename the top level path + err := fs.Rename(srcPath, dstPath) + if err != nil { + t.Errorf("Rename failed: %s", err) return } - _, err = fs.Stat(dstPath + FilePathSeparator + subDir) - if err != nil { - t.Errorf("SubDir stat in the destination dir: %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 + } } - err = fs.Mkdir(srcPath, 0777) - if err != nil { - t.Errorf("Cannot recreate the source dir: %s", err) - 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 + } } - err = fs.Mkdir(srcPath+FilePathSeparator+subDir, 0777) - if err != nil { - t.Errorf("Cannot recreate the subdir in the source dir: %s", err) - 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