github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/utils/fileutils/fileutils.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package fileutils
     5  
     6  import (
     7  	"os"
     8  	"path/filepath"
     9  )
    10  
    11  var (
    12  	commonBaseSearchPaths = []string{
    13  		".",
    14  		"..",
    15  		"../..",
    16  		"../../..",
    17  	}
    18  )
    19  
    20  func FindPath(path string, baseSearchPaths []string, filter func(os.FileInfo) bool) string {
    21  	if filepath.IsAbs(path) {
    22  		if _, err := os.Stat(path); err == nil {
    23  			return path
    24  		}
    25  
    26  		return ""
    27  	}
    28  
    29  	searchPaths := []string{}
    30  	searchPaths = append(searchPaths, baseSearchPaths...)
    31  
    32  	// Additionally attempt to search relative to the location of the running binary.
    33  	var binaryDir string
    34  	if exe, err := os.Executable(); err == nil {
    35  		if exe, err = filepath.EvalSymlinks(exe); err == nil {
    36  			if exe, err = filepath.Abs(exe); err == nil {
    37  				binaryDir = filepath.Dir(exe)
    38  			}
    39  		}
    40  	}
    41  	if binaryDir != "" {
    42  		for _, baseSearchPath := range baseSearchPaths {
    43  			searchPaths = append(
    44  				searchPaths,
    45  				filepath.Join(binaryDir, baseSearchPath),
    46  			)
    47  		}
    48  	}
    49  
    50  	for _, parent := range searchPaths {
    51  		found, err := filepath.Abs(filepath.Join(parent, path))
    52  		if err != nil {
    53  			continue
    54  		} else if fileInfo, err := os.Stat(found); err == nil {
    55  			if filter != nil {
    56  				if filter(fileInfo) {
    57  					return found
    58  				}
    59  			} else {
    60  				return found
    61  			}
    62  		}
    63  	}
    64  
    65  	return ""
    66  }
    67  
    68  // FindFile looks for the given file in nearby ancestors relative to the current working
    69  // directory as well as the directory of the executable.
    70  func FindFile(path string) string {
    71  	return FindPath(path, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
    72  		return !fileInfo.IsDir()
    73  	})
    74  }
    75  
    76  // fileutils.FindDir looks for the given directory in nearby ancestors relative to the current working
    77  // directory as well as the directory of the executable, falling back to `./` if not found.
    78  func FindDir(dir string) (string, bool) {
    79  	found := FindPath(dir, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
    80  		return fileInfo.IsDir()
    81  	})
    82  	if found == "" {
    83  		return "./", false
    84  	}
    85  
    86  	return found, true
    87  }