summaryrefslogtreecommitdiffstats
path: root/src/go/pkg/multipath/multipath.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/go/pkg/multipath/multipath.go')
-rw-r--r--src/go/pkg/multipath/multipath.go90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/go/pkg/multipath/multipath.go b/src/go/pkg/multipath/multipath.go
new file mode 100644
index 000000000..6172def06
--- /dev/null
+++ b/src/go/pkg/multipath/multipath.go
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package multipath
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "slices"
+ "strings"
+
+ "github.com/mitchellh/go-homedir"
+)
+
+type ErrNotFound struct{ msg string }
+
+func (e ErrNotFound) Error() string { return e.msg }
+
+// IsNotFound returns a boolean indicating whether the error is ErrNotFound or not.
+func IsNotFound(err error) bool {
+ var errNotFound ErrNotFound
+ return errors.As(err, &errNotFound)
+}
+
+// MultiPath multi-paths
+type MultiPath []string
+
+// New multi-paths
+func New(paths ...string) MultiPath {
+ set := map[string]bool{}
+ mPath := make(MultiPath, 0)
+
+ for _, dir := range paths {
+ if dir == "" {
+ continue
+ }
+ if d, err := homedir.Expand(dir); err != nil {
+ dir = d
+ }
+ if !set[dir] {
+ mPath = append(mPath, dir)
+ set[dir] = true
+ }
+ }
+
+ return mPath
+}
+
+// Find finds a file in given paths
+func (p MultiPath) Find(filename string) (string, error) {
+ for _, dir := range p {
+ file := filepath.Join(dir, filename)
+ if _, err := os.Stat(file); !os.IsNotExist(err) {
+ return file, nil
+ }
+ }
+ return "", ErrNotFound{msg: fmt.Sprintf("can't find '%s' in %v", filename, p)}
+}
+
+func (p MultiPath) FindFiles(suffixes ...string) ([]string, error) {
+ set := make(map[string]bool)
+ var files []string
+
+ for _, dir := range p {
+ entries, err := os.ReadDir(dir)
+ if err != nil {
+ continue
+ }
+
+ for _, e := range entries {
+ if !e.Type().IsRegular() {
+ continue
+ }
+
+ ext := filepath.Ext(e.Name())
+ name := strings.TrimSuffix(e.Name(), ext)
+
+ if (len(suffixes) != 0 && !slices.Contains(suffixes, ext)) || set[name] {
+ continue
+ }
+
+ set[name] = true
+ file := filepath.Join(dir, e.Name())
+ files = append(files, file)
+ }
+ }
+
+ return files, nil
+}