1package fsext
 2
 3import (
 4	"errors"
 5	"os"
 6	"path/filepath"
 7)
 8
 9// SearchParent searches for a target file or directory starting from dir
10// and walking up the directory tree until found or root or home is reached.
11// Returns the full path to the target if found, empty string and false otherwise.
12// The search includes the starting directory itself.
13func SearchParent(dir, target string) (string, bool) {
14	absDir, err := filepath.Abs(dir)
15	if err != nil {
16		return "", false
17	}
18
19	path := filepath.Join(absDir, target)
20	if _, err := os.Stat(path); err == nil {
21		return path, true
22	} else if !errors.Is(err, os.ErrNotExist) {
23		return "", false
24	}
25
26	previousParent := absDir
27
28	for {
29		parent := filepath.Dir(previousParent)
30		if parent == previousParent || parent == HomeDir() {
31			return "", false
32		}
33
34		path := filepath.Join(parent, target)
35		if _, err := os.Stat(path); err == nil {
36			return path, true
37		} else if !errors.Is(err, os.ErrNotExist) {
38			return "", false
39		}
40
41		previousParent = parent
42	}
43}