github.com/gogf/gf/v2@v2.7.4/os/gcfg/gcfg_adapter_file_path.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gcfg 8 9 import ( 10 "bytes" 11 "context" 12 "fmt" 13 "os" 14 15 "github.com/gogf/gf/v2/errors/gcode" 16 "github.com/gogf/gf/v2/errors/gerror" 17 "github.com/gogf/gf/v2/internal/intlog" 18 "github.com/gogf/gf/v2/os/gfile" 19 "github.com/gogf/gf/v2/os/gres" 20 "github.com/gogf/gf/v2/os/gspath" 21 "github.com/gogf/gf/v2/text/gstr" 22 ) 23 24 // SetPath sets the configuration `directory` path for file search. 25 // The parameter `path` can be absolute or relative `directory` path, 26 // but absolute `directory` path is strongly recommended. 27 // 28 // Note that this parameter is a path to a directory not a file. 29 func (a *AdapterFile) SetPath(directoryPath string) (err error) { 30 var ( 31 isDir = false 32 realPath = "" 33 ) 34 if file := gres.Get(directoryPath); file != nil { 35 realPath = directoryPath 36 isDir = file.FileInfo().IsDir() 37 } else { 38 // Absolute path. 39 realPath = gfile.RealPath(directoryPath) 40 if realPath == "" { 41 // Relative path. 42 a.searchPaths.RLockFunc(func(array []string) { 43 for _, v := range array { 44 if searchedPath, _ := gspath.Search(v, directoryPath); searchedPath != "" { 45 realPath = searchedPath 46 break 47 } 48 } 49 }) 50 } 51 if realPath != "" { 52 isDir = gfile.IsDir(realPath) 53 } 54 } 55 // Path not exist. 56 if realPath == "" { 57 buffer := bytes.NewBuffer(nil) 58 if a.searchPaths.Len() > 0 { 59 buffer.WriteString(fmt.Sprintf( 60 `SetPath failed: cannot find directory "%s" in following paths:`, 61 directoryPath, 62 )) 63 a.searchPaths.RLockFunc(func(array []string) { 64 for k, v := range array { 65 buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v)) 66 } 67 }) 68 } else { 69 buffer.WriteString(fmt.Sprintf( 70 `SetPath failed: path "%s" does not exist`, 71 directoryPath, 72 )) 73 } 74 return gerror.New(buffer.String()) 75 } 76 // Should be a directory. 77 if !isDir { 78 return gerror.NewCodef( 79 gcode.CodeInvalidParameter, 80 `SetPath failed: path "%s" should be directory type`, 81 directoryPath, 82 ) 83 } 84 // Repeated path check. 85 if a.searchPaths.Search(realPath) != -1 { 86 return nil 87 } 88 a.jsonMap.Clear() 89 a.searchPaths.Clear() 90 a.searchPaths.Append(realPath) 91 intlog.Print(context.TODO(), "SetPath:", realPath) 92 return nil 93 } 94 95 // AddPath adds an absolute or relative `directory` path to the search paths. 96 // 97 // Note that this parameter is paths to a directories not files. 98 func (a *AdapterFile) AddPath(directoryPaths ...string) (err error) { 99 for _, directoryPath := range directoryPaths { 100 if err = a.doAddPath(directoryPath); err != nil { 101 return err 102 } 103 } 104 return nil 105 } 106 107 // doAddPath adds an absolute or relative `directory` path to the search paths. 108 func (a *AdapterFile) doAddPath(directoryPath string) (err error) { 109 var ( 110 isDir = false 111 realPath = "" 112 ) 113 // It firstly checks the resource manager, 114 // and then checks the filesystem for the path. 115 if file := gres.Get(directoryPath); file != nil { 116 realPath = directoryPath 117 isDir = file.FileInfo().IsDir() 118 } else { 119 // Absolute path. 120 realPath = gfile.RealPath(directoryPath) 121 if realPath == "" { 122 // Relative path. 123 a.searchPaths.RLockFunc(func(array []string) { 124 for _, v := range array { 125 if searchedPath, _ := gspath.Search(v, directoryPath); searchedPath != "" { 126 realPath = searchedPath 127 break 128 } 129 } 130 }) 131 } 132 if realPath != "" { 133 isDir = gfile.IsDir(realPath) 134 } 135 } 136 if realPath == "" { 137 buffer := bytes.NewBuffer(nil) 138 if a.searchPaths.Len() > 0 { 139 buffer.WriteString(fmt.Sprintf( 140 `AddPath failed: cannot find directory "%s" in following paths:`, 141 directoryPath, 142 )) 143 a.searchPaths.RLockFunc(func(array []string) { 144 for k, v := range array { 145 buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v)) 146 } 147 }) 148 } else { 149 buffer.WriteString(fmt.Sprintf( 150 `AddPath failed: path "%s" does not exist`, 151 directoryPath, 152 )) 153 } 154 return gerror.New(buffer.String()) 155 } 156 if !isDir { 157 return gerror.NewCodef( 158 gcode.CodeInvalidParameter, 159 `AddPath failed: path "%s" should be directory type`, 160 directoryPath, 161 ) 162 } 163 // Repeated path check. 164 if a.searchPaths.Search(realPath) != -1 { 165 return nil 166 } 167 a.searchPaths.Append(realPath) 168 intlog.Print(context.TODO(), "AddPath:", realPath) 169 return nil 170 } 171 172 // GetPaths returns the searching directory path array of current configuration manager. 173 func (a *AdapterFile) GetPaths() []string { 174 return a.searchPaths.Slice() 175 } 176 177 // doGetFilePath returns the absolute configuration file path for the given filename by `fileNameOrPath`. 178 // The `fileNameOrPath` can be either a file name or the file path. 179 func (a *AdapterFile) doGetFilePath(fileNameOrPath string) (filePath string) { 180 var ( 181 tempPath string 182 resFile *gres.File 183 fileInfo os.FileInfo 184 ) 185 // Searching resource manager. 186 if !gres.IsEmpty() { 187 for _, tryFolder := range resourceTryFolders { 188 tempPath = tryFolder + fileNameOrPath 189 if resFile = gres.Get(tempPath); resFile != nil { 190 fileInfo, _ = resFile.Stat() 191 if fileInfo != nil && !fileInfo.IsDir() { 192 filePath = resFile.Name() 193 return 194 } 195 } 196 } 197 a.searchPaths.RLockFunc(func(array []string) { 198 for _, searchPath := range array { 199 for _, tryFolder := range resourceTryFolders { 200 tempPath = searchPath + tryFolder + fileNameOrPath 201 if resFile = gres.Get(tempPath); resFile != nil { 202 fileInfo, _ = resFile.Stat() 203 if fileInfo != nil && !fileInfo.IsDir() { 204 filePath = resFile.Name() 205 return 206 } 207 } 208 } 209 } 210 }) 211 } 212 213 a.autoCheckAndAddMainPkgPathToSearchPaths() 214 215 // Searching local file system. 216 if filePath == "" { 217 a.searchPaths.RLockFunc(func(array []string) { 218 for _, searchPath := range array { 219 searchPath = gstr.TrimRight(searchPath, `\/`) 220 for _, tryFolder := range localSystemTryFolders { 221 relativePath := gstr.TrimRight( 222 gfile.Join(tryFolder, fileNameOrPath), 223 `\/`, 224 ) 225 if filePath, _ = gspath.Search(searchPath, relativePath); filePath != "" && 226 !gfile.IsDir(filePath) { 227 return 228 } 229 } 230 } 231 }) 232 } 233 // The `fileNameOrPath` can be a file path. 234 if filePath == "" { 235 if filePath = gfile.RealPath(fileNameOrPath); filePath != "" && !gfile.IsDir(filePath) { 236 return 237 } 238 } 239 return 240 } 241 242 // GetFilePath returns the absolute configuration file path for the given filename by `file`. 243 // If `file` is not passed, it returns the configuration file path of the default name. 244 // It returns an empty `path` string and an error if the given `file` does not exist. 245 func (a *AdapterFile) GetFilePath(fileNameOrPath ...string) (filePath string, err error) { 246 var ( 247 fileExtName string 248 tempFileNameOrPath string 249 usedFileNameOrPath = a.defaultFileNameOrPath 250 ) 251 if len(fileNameOrPath) > 0 { 252 usedFileNameOrPath = fileNameOrPath[0] 253 } 254 fileExtName = gfile.ExtName(usedFileNameOrPath) 255 if filePath = a.doGetFilePath(usedFileNameOrPath); (filePath == "" || gfile.IsDir(filePath)) && 256 !gstr.InArray(supportedFileTypes, fileExtName) { 257 // If it's not using default configuration or its configuration file is not available, 258 // it searches the possible configuration file according to the name and all supported 259 // file types. 260 for _, fileType := range supportedFileTypes { 261 tempFileNameOrPath = fmt.Sprintf(`%s.%s`, usedFileNameOrPath, fileType) 262 if filePath = a.doGetFilePath(tempFileNameOrPath); filePath != "" { 263 break 264 } 265 } 266 } 267 // If it cannot find the filePath of `file`, it formats and returns a detailed error. 268 if filePath == "" { 269 var buffer = bytes.NewBuffer(nil) 270 if a.searchPaths.Len() > 0 { 271 if !gstr.InArray(supportedFileTypes, fileExtName) { 272 buffer.WriteString(fmt.Sprintf( 273 `possible config files "%s" or "%s" not found in resource manager or following system searching paths:`, 274 usedFileNameOrPath, fmt.Sprintf(`%s.%s`, usedFileNameOrPath, gstr.Join(supportedFileTypes, "/")), 275 )) 276 } else { 277 buffer.WriteString(fmt.Sprintf( 278 `specified config file "%s" not found in resource manager or following system searching paths:`, 279 usedFileNameOrPath, 280 )) 281 } 282 a.searchPaths.RLockFunc(func(array []string) { 283 index := 1 284 for _, searchPath := range array { 285 searchPath = gstr.TrimRight(searchPath, `\/`) 286 for _, tryFolder := range localSystemTryFolders { 287 buffer.WriteString(fmt.Sprintf( 288 "\n%d. %s", 289 index, gfile.Join(searchPath, tryFolder), 290 )) 291 index++ 292 } 293 } 294 }) 295 } else { 296 buffer.WriteString(fmt.Sprintf( 297 `cannot find config file "%s" with no filePath configured`, 298 usedFileNameOrPath, 299 )) 300 } 301 err = gerror.NewCode(gcode.CodeNotFound, buffer.String()) 302 } 303 return 304 }