github.com/shulhan/golangci-lint@v1.10.1/pkg/fsutils/fsutils.go (about) 1 package fsutils 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "sync" 8 ) 9 10 func IsDir(filename string) bool { 11 fi, err := os.Stat(filename) 12 return err == nil && fi.IsDir() 13 } 14 15 var cachedWd string 16 var cachedWdError error 17 var getWdOnce sync.Once 18 var useCache = true 19 20 func UseWdCache(use bool) { 21 useCache = use 22 } 23 24 func Getwd() (string, error) { 25 if !useCache { // for tests 26 return os.Getwd() 27 } 28 29 getWdOnce.Do(func() { 30 cachedWd, cachedWdError = os.Getwd() 31 if cachedWdError != nil { 32 return 33 } 34 35 evaledWd, err := EvalSymlinks(cachedWd) 36 if err != nil { 37 cachedWd, cachedWdError = "", fmt.Errorf("can't eval symlinks on wd %s: %s", cachedWd, err) 38 return 39 } 40 41 cachedWd = evaledWd 42 }) 43 44 return cachedWd, cachedWdError 45 } 46 47 var evalSymlinkCache sync.Map 48 49 type evalSymlinkRes struct { 50 path string 51 err error 52 } 53 54 func EvalSymlinks(path string) (string, error) { 55 r, ok := evalSymlinkCache.Load(path) 56 if ok { 57 er := r.(evalSymlinkRes) 58 return er.path, er.err 59 } 60 61 var er evalSymlinkRes 62 er.path, er.err = filepath.EvalSymlinks(path) 63 evalSymlinkCache.Store(path, er) 64 65 return er.path, er.err 66 } 67 68 func ShortestRelPath(path string, wd string) (string, error) { 69 if wd == "" { // get it if user don't have cached working dir 70 var err error 71 wd, err = Getwd() 72 if err != nil { 73 return "", fmt.Errorf("can't get working directory: %s", err) 74 } 75 } 76 77 evaledPath, err := EvalSymlinks(path) 78 if err != nil { 79 return "", fmt.Errorf("can't eval symlinks for path %s: %s", path, err) 80 } 81 path = evaledPath 82 83 // make path absolute and then relative to be able to fix this case: 84 // we'are in /test dir, we want to normalize ../test, and have file file.go in this dir; 85 // it must have normalized path file.go, not ../test/file.go, 86 var absPath string 87 if filepath.IsAbs(path) { 88 absPath = path 89 } else { 90 absPath = filepath.Join(wd, path) 91 } 92 93 relPath, err := filepath.Rel(wd, absPath) 94 if err != nil { 95 return "", fmt.Errorf("can't get relative path for path %s and root %s: %s", 96 absPath, wd, err) 97 } 98 99 return relPath, nil 100 }