netdata/netdata

View on GitHub
src/go/collectors/go.d.plugin/pkg/multipath/multipath.go

Summary

Maintainability
A
0 mins
Test Coverage
// 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
}