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  }