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  }