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 }