Skip to content

Commit c1f56f1

Browse files
committed
":sparkles: [filesystem] Add a way to determine all parents of a path
1 parent 1fd5ab1 commit c1f56f1

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

changes/20240905230606.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:sparkles: [filesystem] Add a way to determine all parents of a path similar to python's [pathlib](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parents)

utils/filesystem/filepath.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,32 @@ import (
1313
"github.com/ARM-software/golang-utils/utils/reflection"
1414
)
1515

16-
// FilepathStem returns the final path component, without its suffix.
16+
// FilepathStem returns the final path component, without its suffix. It's similar to `stem` in python's [pathlib](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.stem)
1717
func FilepathStem(fp string) string {
1818
return strings.TrimSuffix(filepath.Base(fp), filepath.Ext(fp))
1919
}
2020

21+
// FilepathParents returns a list of to the logical ancestors of the path and it's similar to `parents` in python's [pathlib](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parents)
22+
func FilepathParents(fp string) []string {
23+
return FilePathParentsOnFilesystem(GetGlobalFileSystem(), fp)
24+
}
25+
26+
// FilePathParentsOnFilesystem is similar to FilepathParents but with the ability to be applied to a particular filesystem.
27+
func FilePathParentsOnFilesystem(fs FS, fp string) (parents []string) {
28+
cleanFp := filepath.Clean(fp)
29+
elements := strings.Split(cleanFp, string(fs.PathSeparator()))
30+
if len(elements) <= 1 {
31+
return
32+
}
33+
path := elements[0]
34+
parents = append(parents, path)
35+
for i := 1; i < len(elements)-1; i++ {
36+
path = strings.Join([]string{path, elements[i]}, string(fs.PathSeparator()))
37+
parents = append(parents, path)
38+
}
39+
return
40+
}
41+
2142
// FileTreeDepth returns the depth of a file in a tree starting from root
2243
func FileTreeDepth(fs FS, root, filePath string) (depth int64, err error) {
2344
if reflection.IsEmpty(filePath) {

utils/filesystem/filepath_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,33 @@ func TestFilepathStem(t *testing.T) {
2929
})
3030
}
3131

32+
func TestFilepathParents(t *testing.T) {
33+
34+
tests := []struct {
35+
path string
36+
expectedParents []string
37+
}{
38+
{},
39+
{
40+
path: " ",
41+
expectedParents: nil,
42+
},
43+
{
44+
path: filepath.Join("a", "great", "fake", "path", "blah"),
45+
expectedParents: []string{"a", filepath.Join("a", "great"), filepath.Join("a", "great", "fake"), filepath.Join("a", "great", "fake", "path")},
46+
},
47+
{
48+
path: "C:/foo/bar/setup.py",
49+
expectedParents: []string{"C:", filepath.Join(`C:`, `\foo`), filepath.Join(`C:`, `\foo`, `bar`)},
50+
},
51+
}
52+
for _, tt := range tests {
53+
t.Run(tt.path, func(t *testing.T) {
54+
assert.ElementsMatch(t, tt.expectedParents, FilepathParents(tt.path))
55+
})
56+
}
57+
}
58+
3259
func TestFileTreeDepth(t *testing.T) {
3360
random := fmt.Sprintf("%v %v %v", faker.Name(), faker.Name(), faker.Name())
3461
complexRandom := fmt.Sprintf("%v&#~@£*-_()^+!%v %v", faker.Name(), faker.Name(), faker.Name())

0 commit comments

Comments
 (0)