Skip to content

Commit

Permalink
remove mem fs with descendants
Browse files Browse the repository at this point in the history
  • Loading branch information
hanagantig committed Sep 23, 2023
1 parent ee6eef7 commit ecbd067
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
20 changes: 18 additions & 2 deletions memmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,22 @@ func (m *MemMapFs) Remove(name string) error {
defer m.mu.Unlock()

if _, ok := m.getData()[name]; ok {
descendants := m.findDescendants(name)
for i := 1; i <= len(descendants); i++ {
descendant := descendants[len(descendants)-i]
descName := descendant.Name()
err := m.unRegisterWithParent(descName)
if err != nil {
return &os.PathError{Op: "descendant remove", Path: name, Err: err}
}
delete(m.getData(), descName)
}

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}
Expand All @@ -299,14 +311,18 @@ func (m *MemMapFs) Remove(name string) error {
func (m *MemMapFs) RemoveAll(path string) error {
path = normalizePath(path)
m.mu.Lock()
m.unRegisterWithParent(path)
_ = m.unRegisterWithParent(path)
m.mu.Unlock()

m.mu.RLock()
defer m.mu.RUnlock()

for p := range m.getData() {
if p == path || strings.HasPrefix(p, path+FilePathSeparator) {
separator := FilePathSeparator
if path == FilePathSeparator {
separator = ""
}
if p == path || strings.HasPrefix(p, path+separator) {
m.mu.RUnlock()
m.mu.Lock()
delete(m.getData(), p)
Expand Down
67 changes: 67 additions & 0 deletions memmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -918,3 +918,70 @@ func TestMemMapFsRename(t *testing.T) {
}
}
}

func TestMemMapFsRemove(t *testing.T) {
t.Parallel()

testData := map[string]struct {
dirsToCreate []string
dirsToRemove []string
expectedErrMsg string
}{
"Remove child before - success": {
dirsToCreate: []string{"/parent1/parent2/fileForDelete1.txt"},
dirsToRemove: []string{
"/parent1/parent2/fileForDelete1.txt",
"/parent1/parent2",
},
},
"Remove parent before - should return error": {
dirsToCreate: []string{"/parent1/parent2/fileForDelete1.txt"},
dirsToRemove: []string{
"/parent1/parent2",
"/parent1/parent2/fileForDelete1.txt",
},
expectedErrMsg: "remove /parent1/parent2/fileForDelete1.txt: file does not exist",
},
"Remove root and then parent1 - should return error": {
dirsToCreate: []string{"/root/parent1/parent2/fileForDelete1.txt"},
dirsToRemove: []string{
"/root",
"/root/parent1",
},
expectedErrMsg: "remove /root/parent1: file does not exist",
},
"Remove parent2 and then parent 1 - success": {
dirsToCreate: []string{"/parent1/parent2/fileForDelete1.txt"},
dirsToRemove: []string{
"/parent1/parent2",
"/parent1",
},
},
}

fs := &MemMapFs{}

for caseName, td := range testData {
_, err := fs.Stat("/")
if err == nil {
err = fs.RemoveAll("/")
if err != nil {
t.Fatalf("%s: RemoveAll %q failed: %v", fs.Name(), "/", err)
}
}

for _, toCreate := range td.dirsToCreate {
err = fs.MkdirAll(toCreate, os.FileMode(0775))
if err != nil && err.Error() != td.expectedErrMsg {
t.Fatalf("#CASE %v %s: Mkdir %q failed: %v", caseName, fs.Name(), toCreate, err)
}
}

for _, toRemove := range td.dirsToRemove {
err = fs.Remove(toRemove)
if err != nil && err.Error() != td.expectedErrMsg {
t.Fatalf("#CASE %v %s: Remove %q failed: %v", caseName, fs.Name(), toRemove, err)
}
}
}
}

0 comments on commit ecbd067

Please sign in to comment.