mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +08:00
92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package gfile
|
|
|
|
import (
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/gogf/gf/v2/text/gregex"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
)
|
|
|
|
var (
|
|
// goRootForFilter is used for stack filtering purpose.
|
|
goRootForFilter = runtime.GOROOT()
|
|
)
|
|
|
|
func init() {
|
|
if goRootForFilter != "" {
|
|
goRootForFilter = strings.ReplaceAll(goRootForFilter, "\\", "/")
|
|
}
|
|
}
|
|
|
|
// MainPkgPath returns absolute file path of package main,
|
|
// which contains the entrance function main.
|
|
//
|
|
// It's only available in develop environment.
|
|
//
|
|
// Note1: Only valid for source development environments,
|
|
// IE only valid for systems that generate this executable.
|
|
//
|
|
// Note2: When the method is called for the first time, if it is in an asynchronous goroutine,
|
|
// the method may not get the main package path.
|
|
func MainPkgPath() string {
|
|
// It is only for source development environments.
|
|
if goRootForFilter == "" {
|
|
return ""
|
|
}
|
|
path := mainPkgPath.Val()
|
|
if path != "" {
|
|
return path
|
|
}
|
|
var lastFile string
|
|
for i := 1; i < 10000; i++ {
|
|
if pc, file, _, ok := runtime.Caller(i); ok {
|
|
if goRootForFilter != "" && len(file) >= len(goRootForFilter) && file[0:len(goRootForFilter)] == goRootForFilter {
|
|
continue
|
|
}
|
|
if Ext(file) != ".go" {
|
|
continue
|
|
}
|
|
lastFile = file
|
|
// Check if it is called in package initialization function,
|
|
// in which it here cannot retrieve main package path,
|
|
// it so just returns that can make next check.
|
|
if fn := runtime.FuncForPC(pc); fn != nil {
|
|
array := gstr.Split(fn.Name(), ".")
|
|
if array[0] != "main" {
|
|
continue
|
|
}
|
|
}
|
|
if gregex.IsMatchString(`package\s+main\s+`, GetContents(file)) {
|
|
mainPkgPath.Set(Dir(file))
|
|
return Dir(file)
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
// If it still cannot find the path of the package main,
|
|
// it recursively searches the directory and its parents directory of the last go file.
|
|
// It's usually necessary for uint testing cases of business project.
|
|
if lastFile != "" {
|
|
for path = Dir(lastFile); len(path) > 1 && Exists(path) && path[len(path)-1] != os.PathSeparator; {
|
|
files, _ := ScanDir(path, "*.go")
|
|
for _, v := range files {
|
|
if gregex.IsMatchString(`package\s+main\s+`, GetContents(v)) {
|
|
mainPkgPath.Set(path)
|
|
return path
|
|
}
|
|
}
|
|
path = Dir(path)
|
|
}
|
|
}
|
|
return ""
|
|
}
|