1
0
mirror of https://github.com/gogf/gf.git synced 2025-04-05 11:18:50 +08:00

os/gcfg: fix file searching issue always returning the configuration file of pwd (#3592)

This commit is contained in:
John Guo 2024-05-22 21:14:16 +08:00 committed by GitHub
parent 1e8f4287af
commit 2e471662f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 71 additions and 72 deletions

View File

@ -25,10 +25,10 @@ import (
// AdapterFile implements interface Adapter using file. // AdapterFile implements interface Adapter using file.
type AdapterFile struct { type AdapterFile struct {
defaultName string // Default configuration file name. defaultFileNameOrPath string // Default configuration file name or file path.
searchPaths *garray.StrArray // Searching path array. searchPaths *garray.StrArray // Searching path array.
jsonMap *gmap.StrAnyMap // The pared JSON objects for configuration files. jsonMap *gmap.StrAnyMap // The pared JSON objects for configuration files.
violenceCheck bool // Whether it does violence check in value index searching. It affects the performance when set true(false in default). violenceCheck bool // Whether it does violence check in value index searching. It affects the performance when set true(false in default).
} }
const ( const (
@ -53,23 +53,23 @@ var (
// NewAdapterFile returns a new configuration management object. // NewAdapterFile returns a new configuration management object.
// The parameter `file` specifies the default configuration file name for reading. // The parameter `file` specifies the default configuration file name for reading.
func NewAdapterFile(file ...string) (*AdapterFile, error) { func NewAdapterFile(fileNameOrPath ...string) (*AdapterFile, error) {
var ( var (
err error err error
name = DefaultConfigFileName usedFileNameOrPath = DefaultConfigFileName
) )
if len(file) > 0 { if len(fileNameOrPath) > 0 {
name = file[0] usedFileNameOrPath = fileNameOrPath[0]
} else { } else {
// Custom default configuration file name from command line or environment. // Custom default configuration file name from command line or environment.
if customFile := command.GetOptWithEnv(commandEnvKeyForFile); customFile != "" { if customFile := command.GetOptWithEnv(commandEnvKeyForFile); customFile != "" {
name = customFile usedFileNameOrPath = customFile
} }
} }
config := &AdapterFile{ config := &AdapterFile{
defaultName: name, defaultFileNameOrPath: usedFileNameOrPath,
searchPaths: garray.NewStrArray(true), searchPaths: garray.NewStrArray(true),
jsonMap: gmap.NewStrAnyMap(true), jsonMap: gmap.NewStrAnyMap(true),
} }
// Customized dir path from env/cmd. // Customized dir path from env/cmd.
if customPath := command.GetOptWithEnv(commandEnvKeyForPath); customPath != "" { if customPath := command.GetOptWithEnv(commandEnvKeyForPath); customPath != "" {
@ -120,13 +120,13 @@ func (a *AdapterFile) SetViolenceCheck(check bool) {
} }
// SetFileName sets the default configuration file name. // SetFileName sets the default configuration file name.
func (a *AdapterFile) SetFileName(name string) { func (a *AdapterFile) SetFileName(fileNameOrPath string) {
a.defaultName = name a.defaultFileNameOrPath = fileNameOrPath
} }
// GetFileName returns the default configuration file name. // GetFileName returns the default configuration file name.
func (a *AdapterFile) GetFileName() string { func (a *AdapterFile) GetFileName() string {
return a.defaultName return a.defaultFileNameOrPath
} }
// Get retrieves and returns value by specified `pattern`. // Get retrieves and returns value by specified `pattern`.
@ -200,7 +200,7 @@ func (a *AdapterFile) Dump() {
// Available checks and returns whether configuration of given `file` is available. // Available checks and returns whether configuration of given `file` is available.
func (a *AdapterFile) Available(ctx context.Context, fileName ...string) bool { func (a *AdapterFile) Available(ctx context.Context, fileName ...string) bool {
checkFileName := gutil.GetOrDefaultStr(a.defaultName, fileName...) checkFileName := gutil.GetOrDefaultStr(a.defaultFileNameOrPath, fileName...)
// Custom configuration content exists. // Custom configuration content exists.
if a.GetContent(checkFileName) != "" { if a.GetContent(checkFileName) != "" {
return true return true
@ -227,26 +227,26 @@ func (a *AdapterFile) autoCheckAndAddMainPkgPathToSearchPaths() {
// getJson returns a *gjson.Json object for the specified `file` content. // getJson returns a *gjson.Json object for the specified `file` content.
// It would print error if file reading fails. It returns nil if any error occurs. // It would print error if file reading fails. It returns nil if any error occurs.
func (a *AdapterFile) getJson(fileName ...string) (configJson *gjson.Json, err error) { func (a *AdapterFile) getJson(fileNameOrPath ...string) (configJson *gjson.Json, err error) {
var ( var (
usedFileName = a.defaultName usedFileNameOrPath = a.defaultFileNameOrPath
) )
if len(fileName) > 0 && fileName[0] != "" { if len(fileNameOrPath) > 0 && fileNameOrPath[0] != "" {
usedFileName = fileName[0] usedFileNameOrPath = fileNameOrPath[0]
} else { } else {
usedFileName = a.defaultName usedFileNameOrPath = a.defaultFileNameOrPath
} }
// It uses json map to cache specified configuration file content. // It uses json map to cache specified configuration file content.
result := a.jsonMap.GetOrSetFuncLock(usedFileName, func() interface{} { result := a.jsonMap.GetOrSetFuncLock(usedFileNameOrPath, func() interface{} {
var ( var (
content string content string
filePath string filePath string
) )
// The configured content can be any kind of data type different from its file type. // The configured content can be any kind of data type different from its file type.
isFromConfigContent := true isFromConfigContent := true
if content = a.GetContent(usedFileName); content == "" { if content = a.GetContent(usedFileNameOrPath); content == "" {
isFromConfigContent = false isFromConfigContent = false
filePath, err = a.GetFilePath(usedFileName) filePath, err = a.GetFilePath(usedFileNameOrPath)
if err != nil { if err != nil {
return nil return nil
} }
@ -279,7 +279,7 @@ func (a *AdapterFile) getJson(fileName ...string) (configJson *gjson.Json, err e
// any changes of this file will refresh its cache in Config object. // any changes of this file will refresh its cache in Config object.
if filePath != "" && !gres.Contains(filePath) { if filePath != "" && !gres.Contains(filePath) {
_, err = gfsnotify.Add(filePath, func(event *gfsnotify.Event) { _, err = gfsnotify.Add(filePath, func(event *gfsnotify.Event) {
a.jsonMap.Remove(usedFileName) a.jsonMap.Remove(usedFileNameOrPath)
}) })
if err != nil { if err != nil {
return nil return nil

View File

@ -14,58 +14,58 @@ import (
// SetContent sets customized configuration content for specified `file`. // SetContent sets customized configuration content for specified `file`.
// The `file` is unnecessary param, default is DefaultConfigFile. // The `file` is unnecessary param, default is DefaultConfigFile.
func (a *AdapterFile) SetContent(content string, file ...string) { func (a *AdapterFile) SetContent(content string, fileNameOrPath ...string) {
name := DefaultConfigFileName var usedFileNameOrPath = DefaultConfigFileName
if len(file) > 0 { if len(fileNameOrPath) > 0 {
name = file[0] usedFileNameOrPath = fileNameOrPath[0]
} }
// Clear file cache for instances which cached `name`. // Clear file cache for instances which cached `name`.
localInstances.LockFunc(func(m map[string]interface{}) { localInstances.LockFunc(func(m map[string]interface{}) {
if customConfigContentMap.Contains(name) { if customConfigContentMap.Contains(usedFileNameOrPath) {
for _, v := range m { for _, v := range m {
if configInstance, ok := v.(*Config); ok { if configInstance, ok := v.(*Config); ok {
if fileConfig, ok := configInstance.GetAdapter().(*AdapterFile); ok { if fileConfig, ok := configInstance.GetAdapter().(*AdapterFile); ok {
fileConfig.jsonMap.Remove(name) fileConfig.jsonMap.Remove(usedFileNameOrPath)
} }
} }
} }
} }
customConfigContentMap.Set(name, content) customConfigContentMap.Set(usedFileNameOrPath, content)
}) })
} }
// GetContent returns customized configuration content for specified `file`. // GetContent returns customized configuration content for specified `file`.
// The `file` is unnecessary param, default is DefaultConfigFile. // The `file` is unnecessary param, default is DefaultConfigFile.
func (a *AdapterFile) GetContent(file ...string) string { func (a *AdapterFile) GetContent(fileNameOrPath ...string) string {
name := DefaultConfigFileName var usedFileNameOrPath = DefaultConfigFileName
if len(file) > 0 { if len(fileNameOrPath) > 0 {
name = file[0] usedFileNameOrPath = fileNameOrPath[0]
} }
return customConfigContentMap.Get(name) return customConfigContentMap.Get(usedFileNameOrPath)
} }
// RemoveContent removes the global configuration with specified `file`. // RemoveContent removes the global configuration with specified `file`.
// If `name` is not passed, it removes configuration of the default group name. // If `name` is not passed, it removes configuration of the default group name.
func (a *AdapterFile) RemoveContent(file ...string) { func (a *AdapterFile) RemoveContent(fileNameOrPath ...string) {
name := DefaultConfigFileName var usedFileNameOrPath = DefaultConfigFileName
if len(file) > 0 { if len(fileNameOrPath) > 0 {
name = file[0] usedFileNameOrPath = fileNameOrPath[0]
} }
// Clear file cache for instances which cached `name`. // Clear file cache for instances which cached `name`.
localInstances.LockFunc(func(m map[string]interface{}) { localInstances.LockFunc(func(m map[string]interface{}) {
if customConfigContentMap.Contains(name) { if customConfigContentMap.Contains(usedFileNameOrPath) {
for _, v := range m { for _, v := range m {
if configInstance, ok := v.(*Config); ok { if configInstance, ok := v.(*Config); ok {
if fileConfig, ok := configInstance.GetAdapter().(*AdapterFile); ok { if fileConfig, ok := configInstance.GetAdapter().(*AdapterFile); ok {
fileConfig.jsonMap.Remove(name) fileConfig.jsonMap.Remove(usedFileNameOrPath)
} }
} }
} }
customConfigContentMap.Remove(name) customConfigContentMap.Remove(usedFileNameOrPath)
} }
}) })
intlog.Printf(context.TODO(), `RemoveContent: %s`, name) intlog.Printf(context.TODO(), `RemoveContent: %s`, usedFileNameOrPath)
} }
// ClearContent removes all global configuration contents. // ClearContent removes all global configuration contents.

View File

@ -174,10 +174,9 @@ func (a *AdapterFile) GetPaths() []string {
return a.searchPaths.Slice() return a.searchPaths.Slice()
} }
// doGetFilePath returns the absolute configuration file path for the given filename by `file`. // doGetFilePath returns the absolute configuration file path for the given filename by `fileNameOrPath`.
// If `file` is not passed, it returns the configuration file path of the default name. // The `fileNameOrPath` can be either a file name or the file path.
// It returns an empty `path` string and an error if the given `file` does not exist. func (a *AdapterFile) doGetFilePath(fileNameOrPath string) (filePath string) {
func (a *AdapterFile) doGetFilePath(fileName string) (filePath string) {
var ( var (
tempPath string tempPath string
resFile *gres.File resFile *gres.File
@ -186,7 +185,7 @@ func (a *AdapterFile) doGetFilePath(fileName string) (filePath string) {
// Searching resource manager. // Searching resource manager.
if !gres.IsEmpty() { if !gres.IsEmpty() {
for _, tryFolder := range resourceTryFolders { for _, tryFolder := range resourceTryFolders {
tempPath = tryFolder + fileName tempPath = tryFolder + fileNameOrPath
if resFile = gres.Get(tempPath); resFile != nil { if resFile = gres.Get(tempPath); resFile != nil {
fileInfo, _ = resFile.Stat() fileInfo, _ = resFile.Stat()
if fileInfo != nil && !fileInfo.IsDir() { if fileInfo != nil && !fileInfo.IsDir() {
@ -198,7 +197,7 @@ func (a *AdapterFile) doGetFilePath(fileName string) (filePath string) {
a.searchPaths.RLockFunc(func(array []string) { a.searchPaths.RLockFunc(func(array []string) {
for _, searchPath := range array { for _, searchPath := range array {
for _, tryFolder := range resourceTryFolders { for _, tryFolder := range resourceTryFolders {
tempPath = searchPath + tryFolder + fileName tempPath = searchPath + tryFolder + fileNameOrPath
if resFile = gres.Get(tempPath); resFile != nil { if resFile = gres.Get(tempPath); resFile != nil {
fileInfo, _ = resFile.Stat() fileInfo, _ = resFile.Stat()
if fileInfo != nil && !fileInfo.IsDir() { if fileInfo != nil && !fileInfo.IsDir() {
@ -215,16 +214,12 @@ func (a *AdapterFile) doGetFilePath(fileName string) (filePath string) {
// Searching local file system. // Searching local file system.
if filePath == "" { if filePath == "" {
// Absolute path.
/*if filePath = gfile.RealPath(fileName); filePath != "" && !gfile.IsDir(filePath) {
return
}*/
a.searchPaths.RLockFunc(func(array []string) { a.searchPaths.RLockFunc(func(array []string) {
for _, searchPath := range array { for _, searchPath := range array {
searchPath = gstr.TrimRight(searchPath, `\/`) searchPath = gstr.TrimRight(searchPath, `\/`)
for _, tryFolder := range localSystemTryFolders { for _, tryFolder := range localSystemTryFolders {
relativePath := gstr.TrimRight( relativePath := gstr.TrimRight(
gfile.Join(tryFolder, fileName), gfile.Join(tryFolder, fileNameOrPath),
`\/`, `\/`,
) )
if filePath, _ = gspath.Search(searchPath, relativePath); filePath != "" && if filePath, _ = gspath.Search(searchPath, relativePath); filePath != "" &&
@ -235,9 +230,9 @@ func (a *AdapterFile) doGetFilePath(fileName string) (filePath string) {
} }
}) })
} }
// The `fileNameOrPath` can be a file path.
if filePath == "" { if filePath == "" {
// Absolute path. if filePath = gfile.RealPath(fileNameOrPath); filePath != "" && !gfile.IsDir(filePath) {
if filePath = gfile.RealPath(fileName); filePath != "" && !gfile.IsDir(filePath) {
return return
} }
} }
@ -247,23 +242,24 @@ func (a *AdapterFile) doGetFilePath(fileName string) (filePath string) {
// GetFilePath returns the absolute configuration file path for the given filename by `file`. // GetFilePath returns the absolute configuration file path for the given filename by `file`.
// If `file` is not passed, it returns the configuration file path of the default name. // If `file` is not passed, it returns the configuration file path of the default name.
// It returns an empty `path` string and an error if the given `file` does not exist. // It returns an empty `path` string and an error if the given `file` does not exist.
func (a *AdapterFile) GetFilePath(fileName ...string) (filePath string, err error) { func (a *AdapterFile) GetFilePath(fileNameOrPath ...string) (filePath string, err error) {
var ( var (
fileExtName string fileExtName string
tempFileName string tempFileNameOrPath string
usedFileName = a.defaultName usedFileNameOrPath = a.defaultFileNameOrPath
) )
if len(fileName) > 0 { if len(fileNameOrPath) > 0 {
usedFileName = fileName[0] usedFileNameOrPath = fileNameOrPath[0]
} }
fileExtName = gfile.ExtName(usedFileName) fileExtName = gfile.ExtName(usedFileNameOrPath)
if filePath = a.doGetFilePath(usedFileName); (filePath == "" || gfile.IsDir(filePath)) && !gstr.InArray(supportedFileTypes, fileExtName) { if filePath = a.doGetFilePath(usedFileNameOrPath); (filePath == "" || gfile.IsDir(filePath)) &&
!gstr.InArray(supportedFileTypes, fileExtName) {
// If it's not using default configuration or its configuration file is not available, // If it's not using default configuration or its configuration file is not available,
// it searches the possible configuration file according to the name and all supported // it searches the possible configuration file according to the name and all supported
// file types. // file types.
for _, fileType := range supportedFileTypes { for _, fileType := range supportedFileTypes {
tempFileName = fmt.Sprintf(`%s.%s`, usedFileName, fileType) tempFileNameOrPath = fmt.Sprintf(`%s.%s`, usedFileNameOrPath, fileType)
if filePath = a.doGetFilePath(tempFileName); filePath != "" { if filePath = a.doGetFilePath(tempFileNameOrPath); filePath != "" {
break break
} }
} }
@ -275,12 +271,12 @@ func (a *AdapterFile) GetFilePath(fileName ...string) (filePath string, err erro
if !gstr.InArray(supportedFileTypes, fileExtName) { if !gstr.InArray(supportedFileTypes, fileExtName) {
buffer.WriteString(fmt.Sprintf( buffer.WriteString(fmt.Sprintf(
`possible config files "%s" or "%s" not found in resource manager or following system searching paths:`, `possible config files "%s" or "%s" not found in resource manager or following system searching paths:`,
usedFileName, fmt.Sprintf(`%s.%s`, usedFileName, gstr.Join(supportedFileTypes, "/")), usedFileNameOrPath, fmt.Sprintf(`%s.%s`, usedFileNameOrPath, gstr.Join(supportedFileTypes, "/")),
)) ))
} else { } else {
buffer.WriteString(fmt.Sprintf( buffer.WriteString(fmt.Sprintf(
`specified config file "%s" not found in resource manager or following system searching paths:`, `specified config file "%s" not found in resource manager or following system searching paths:`,
usedFileName, usedFileNameOrPath,
)) ))
} }
a.searchPaths.RLockFunc(func(array []string) { a.searchPaths.RLockFunc(func(array []string) {
@ -297,7 +293,10 @@ func (a *AdapterFile) GetFilePath(fileName ...string) (filePath string, err erro
} }
}) })
} else { } else {
buffer.WriteString(fmt.Sprintf(`cannot find config file "%s" with no filePath configured`, usedFileName)) buffer.WriteString(fmt.Sprintf(
`cannot find config file "%s" with no filePath configured`,
usedFileNameOrPath,
))
} }
err = gerror.NewCode(gcode.CodeNotFound, buffer.String()) err = gerror.NewCode(gcode.CodeNotFound, buffer.String())
} }