mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 05:51:51 +08:00
66 lines
1.4 KiB
Go
66 lines
1.4 KiB
Go
package safepath
|
|
|
|
import (
|
|
"context"
|
|
"path"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
type WalkFunc = func(ctx context.Context, path string) error
|
|
|
|
// Walk walks the given folder path and calls the given function for each folder.
|
|
func Walk(ctx context.Context, p string, fn WalkFunc) error {
|
|
if p == "." || p == "/" {
|
|
return nil
|
|
}
|
|
|
|
var currentPath string
|
|
for _, folder := range strings.Split(p, "/") {
|
|
if folder == "" {
|
|
// Trailing / leading slash?
|
|
continue
|
|
}
|
|
|
|
currentPath = path.Join(currentPath, folder)
|
|
if err := fn(ctx, currentPath); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Depth returns the depth of the given path.
|
|
func Depth(p string) int {
|
|
return len(Split(p))
|
|
}
|
|
|
|
// Split splits the given path into segments.
|
|
func Split(p string) []string {
|
|
trimmed := strings.Trim(p, "/")
|
|
if trimmed == "" {
|
|
return []string{}
|
|
}
|
|
return strings.Split(trimmed, "/")
|
|
}
|
|
|
|
// SortByDepth will sort any resource, by its path depth. You must pass in
|
|
// a way to get said path. Ties are alphabetical by default.
|
|
func SortByDepth[T any](items []T, pathExtractor func(T) string, asc bool) {
|
|
sort.Slice(items, func(i, j int) bool {
|
|
pathI, pathJ := pathExtractor(items[i]), pathExtractor(items[j])
|
|
depthI, depthJ := Depth(pathI), Depth(pathJ)
|
|
|
|
if depthI == depthJ {
|
|
// alphabetical by default if depth is the same
|
|
return pathI < pathJ
|
|
}
|
|
|
|
if asc {
|
|
return depthI < depthJ
|
|
}
|
|
return depthI > depthJ
|
|
})
|
|
}
|