github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/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, workingDirFirst bool, 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  	if workingDirFirst {
    31  		searchPaths = append(searchPaths, baseSearchPaths...)
    32  	}
    33  
    34  	// Attempt to search relative to the location of the running binary either before
    35  	// or after searching relative to the working directory, depending on `workingDirFirst`.
    36  	var binaryDir string
    37  	if exe, err := os.Executable(); err == nil {
    38  		if exe, err = filepath.EvalSymlinks(exe); err == nil {
    39  			if exe, err = filepath.Abs(exe); err == nil {
    40  				binaryDir = filepath.Dir(exe)
    41  			}
    42  		}
    43  	}
    44  	if binaryDir != "" {
    45  		for _, baseSearchPath := range baseSearchPaths {
    46  			searchPaths = append(
    47  				searchPaths,
    48  				filepath.Join(binaryDir, baseSearchPath),
    49  			)
    50  		}
    51  	}
    52  
    53  	if !workingDirFirst {
    54  		searchPaths = append(searchPaths, baseSearchPaths...)
    55  	}
    56  
    57  	for _, parent := range searchPaths {
    58  		found, err := filepath.Abs(filepath.Join(parent, path))
    59  		if err != nil {
    60  			continue
    61  		} else if fileInfo, err := os.Stat(found); err == nil {
    62  			if filter != nil {
    63  				if filter(fileInfo) {
    64  					return found
    65  				}
    66  			} else {
    67  				return found
    68  			}
    69  		}
    70  	}
    71  
    72  	return ""
    73  }
    74  
    75  func FindPath(path string, baseSearchPaths []string, filter func(os.FileInfo) bool) string {
    76  	return findPath(path, baseSearchPaths, true, filter)
    77  }
    78  
    79  // FindFile looks for the given file in nearby ancestors relative to the current working
    80  // directory as well as the directory of the executable.
    81  func FindFile(path string) string {
    82  	return FindPath(path, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
    83  		return !fileInfo.IsDir()
    84  	})
    85  }
    86  
    87  // fileutils.FindDir looks for the given directory in nearby ancestors relative to the current working
    88  // directory as well as the directory of the executable, falling back to `./` if not found.
    89  func FindDir(dir string) (string, bool) {
    90  	found := FindPath(dir, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
    91  		return fileInfo.IsDir()
    92  	})
    93  	if found == "" {
    94  		return "./", false
    95  	}
    96  
    97  	return found, true
    98  }
    99  
   100  // FindDirRelBinary looks for the given directory in nearby ancestors relative to the
   101  // directory of the executable, then relative to the working directory, falling back to `./` if not found.
   102  func FindDirRelBinary(dir string) (string, bool) {
   103  	found := findPath(dir, commonBaseSearchPaths, false, func(fileInfo os.FileInfo) bool {
   104  		return fileInfo.IsDir()
   105  	})
   106  	if found == "" {
   107  		return "./", false
   108  	}
   109  	return found, true
   110  }