github.com/wangyougui/gf/v2@v2.6.5/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/wangyougui/gf.
     6  
     7  package gcfg
     8  
     9  import (
    10  	"bytes"
    11  	"context"
    12  	"fmt"
    13  	"os"
    14  
    15  	"github.com/wangyougui/gf/v2/errors/gcode"
    16  	"github.com/wangyougui/gf/v2/errors/gerror"
    17  	"github.com/wangyougui/gf/v2/internal/intlog"
    18  	"github.com/wangyougui/gf/v2/os/gfile"
    19  	"github.com/wangyougui/gf/v2/os/gres"
    20  	"github.com/wangyougui/gf/v2/os/gspath"
    21  	"github.com/wangyougui/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 `file`.
   178  // If `file` is not passed, it returns the configuration file path of the default name.
   179  // It returns an empty `path` string and an error if the given `file` does not exist.
   180  func (a *AdapterFile) doGetFilePath(fileName string) (filePath string) {
   181  	var (
   182  		tempPath string
   183  		resFile  *gres.File
   184  		fileInfo os.FileInfo
   185  	)
   186  	// Searching resource manager.
   187  	if !gres.IsEmpty() {
   188  		for _, tryFolder := range resourceTryFolders {
   189  			tempPath = tryFolder + fileName
   190  			if resFile = gres.Get(tempPath); resFile != nil {
   191  				fileInfo, _ = resFile.Stat()
   192  				if fileInfo != nil && !fileInfo.IsDir() {
   193  					filePath = resFile.Name()
   194  					return
   195  				}
   196  			}
   197  		}
   198  		a.searchPaths.RLockFunc(func(array []string) {
   199  			for _, searchPath := range array {
   200  				for _, tryFolder := range resourceTryFolders {
   201  					tempPath = searchPath + tryFolder + fileName
   202  					if resFile = gres.Get(tempPath); resFile != nil {
   203  						fileInfo, _ = resFile.Stat()
   204  						if fileInfo != nil && !fileInfo.IsDir() {
   205  							filePath = resFile.Name()
   206  							return
   207  						}
   208  					}
   209  				}
   210  			}
   211  		})
   212  	}
   213  
   214  	a.autoCheckAndAddMainPkgPathToSearchPaths()
   215  
   216  	// Searching local file system.
   217  	if filePath == "" {
   218  		// Absolute path.
   219  		if filePath = gfile.RealPath(fileName); filePath != "" && !gfile.IsDir(filePath) {
   220  			return
   221  		}
   222  		a.searchPaths.RLockFunc(func(array []string) {
   223  			for _, searchPath := range array {
   224  				searchPath = gstr.TrimRight(searchPath, `\/`)
   225  				for _, tryFolder := range localSystemTryFolders {
   226  					relativePath := gstr.TrimRight(
   227  						gfile.Join(tryFolder, fileName),
   228  						`\/`,
   229  					)
   230  					if filePath, _ = gspath.Search(searchPath, relativePath); filePath != "" &&
   231  						!gfile.IsDir(filePath) {
   232  						return
   233  					}
   234  				}
   235  			}
   236  		})
   237  	}
   238  	return
   239  }
   240  
   241  // GetFilePath returns the absolute configuration file path for the given filename by `file`.
   242  // If `file` is not passed, it returns the configuration file path of the default name.
   243  // It returns an empty `path` string and an error if the given `file` does not exist.
   244  func (a *AdapterFile) GetFilePath(fileName ...string) (filePath string, err error) {
   245  	var (
   246  		fileExtName  string
   247  		tempFileName string
   248  		usedFileName = a.defaultName
   249  	)
   250  	if len(fileName) > 0 {
   251  		usedFileName = fileName[0]
   252  	}
   253  	fileExtName = gfile.ExtName(usedFileName)
   254  	if filePath = a.doGetFilePath(usedFileName); (filePath == "" || gfile.IsDir(filePath)) && !gstr.InArray(supportedFileTypes, fileExtName) {
   255  		// If it's not using default configuration or its configuration file is not available,
   256  		// it searches the possible configuration file according to the name and all supported
   257  		// file types.
   258  		for _, fileType := range supportedFileTypes {
   259  			tempFileName = fmt.Sprintf(`%s.%s`, usedFileName, fileType)
   260  			if filePath = a.doGetFilePath(tempFileName); filePath != "" {
   261  				break
   262  			}
   263  		}
   264  	}
   265  	// If it cannot find the filePath of `file`, it formats and returns a detailed error.
   266  	if filePath == "" {
   267  		var buffer = bytes.NewBuffer(nil)
   268  		if a.searchPaths.Len() > 0 {
   269  			if !gstr.InArray(supportedFileTypes, fileExtName) {
   270  				buffer.WriteString(fmt.Sprintf(
   271  					`possible config files "%s" or "%s" not found in resource manager or following system searching paths:`,
   272  					usedFileName, fmt.Sprintf(`%s.%s`, usedFileName, gstr.Join(supportedFileTypes, "/")),
   273  				))
   274  			} else {
   275  				buffer.WriteString(fmt.Sprintf(
   276  					`specified config file "%s" not found in resource manager or following system searching paths:`,
   277  					usedFileName,
   278  				))
   279  			}
   280  			a.searchPaths.RLockFunc(func(array []string) {
   281  				index := 1
   282  				for _, searchPath := range array {
   283  					searchPath = gstr.TrimRight(searchPath, `\/`)
   284  					for _, tryFolder := range localSystemTryFolders {
   285  						buffer.WriteString(fmt.Sprintf(
   286  							"\n%d. %s",
   287  							index, gfile.Join(searchPath, tryFolder),
   288  						))
   289  						index++
   290  					}
   291  				}
   292  			})
   293  		} else {
   294  			buffer.WriteString(fmt.Sprintf(`cannot find config file "%s" with no filePath configured`, usedFileName))
   295  		}
   296  		err = gerror.NewCode(gcode.CodeNotFound, buffer.String())
   297  	}
   298  	return
   299  }