156 lines
3.1 KiB
Go
156 lines
3.1 KiB
Go
package gomod
|
||
|
||
import (
|
||
"bufio"
|
||
"errors"
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
"regexp"
|
||
"strings"
|
||
|
||
"golang.org/x/mod/modfile"
|
||
)
|
||
|
||
var goMod *GoMod
|
||
|
||
type GoMod struct {
|
||
file *modfile.File
|
||
modules map[string]ModuleInfo
|
||
}
|
||
|
||
type ModuleInfo struct {
|
||
Name string
|
||
Version string
|
||
Path string
|
||
}
|
||
|
||
// ParseGoMod 解析当前目录下的go.mod文件
|
||
func Parse(modPath string) error {
|
||
// 查找当前目录下的go.mod文件
|
||
// 读取文件内容
|
||
content, err := os.ReadFile(modPath)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 使用官方包解析go.mod
|
||
f, err := modfile.Parse(modPath, content, nil)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
goMod = &GoMod{file: f, modules: make(map[string]ModuleInfo)}
|
||
|
||
for _, require := range f.Require {
|
||
if require.Indirect {
|
||
continue
|
||
}
|
||
|
||
name, err := getPackageName(require.Mod.Path, require.Mod.Version)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
|
||
goMod.modules[require.Mod.Path] = ModuleInfo{
|
||
Name: name,
|
||
Version: require.Mod.Version,
|
||
Path: require.Mod.Path,
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// GetModuleName 获取模块名
|
||
func GetModuleName() string {
|
||
return goMod.file.Module.Mod.Path
|
||
}
|
||
|
||
// GetModuleVersion 获取模块版本
|
||
func GetModuleVersion() string {
|
||
return goMod.file.Module.Mod.Version
|
||
}
|
||
|
||
func GetPackageModuleName(pkg string) string {
|
||
if module, ok := goMod.modules[pkg]; ok {
|
||
return module.Name
|
||
}
|
||
|
||
return filepath.Base(pkg)
|
||
}
|
||
|
||
// GetPackageModuleName 获取包的真实包名
|
||
func getPackageName(pkg, version string) (string, error) {
|
||
gopath := os.Getenv("GOPATH")
|
||
if gopath == "" {
|
||
gopath = filepath.Join(os.Getenv("HOME"), "go")
|
||
}
|
||
|
||
pkgPath := fmt.Sprintf("%s@%s", pkg, version)
|
||
// 构建包的本地路径
|
||
pkgLocalPath := filepath.Join(gopath, "pkg", "mod", pkgPath)
|
||
|
||
// 获取目录下任意一个非_test.go文件,读取他的package name
|
||
files, err := filepath.Glob(filepath.Join(pkgLocalPath, "*.go"))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
packagePattern := regexp.MustCompile(`^package\s+(\w+)$`)
|
||
getFilePackageName := func(file string) (string, error) {
|
||
// 读取文件内容
|
||
f, err := os.Open(file)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
defer f.Close()
|
||
|
||
scanner := bufio.NewScanner(f)
|
||
for scanner.Scan() {
|
||
line := scanner.Text()
|
||
if matches := packagePattern.FindStringSubmatch(line); matches != nil {
|
||
return matches[1], nil
|
||
}
|
||
}
|
||
return "", errors.New("no match")
|
||
}
|
||
|
||
if len(files) > 0 {
|
||
for _, file := range files {
|
||
if strings.HasSuffix(file, "_test.go") {
|
||
continue
|
||
}
|
||
|
||
if name, err := getFilePackageName(file); err == nil {
|
||
return name, nil
|
||
}
|
||
}
|
||
}
|
||
// 读取go.mod 文件内容
|
||
modFile := filepath.Join(pkgLocalPath, "go.mod")
|
||
content, err := os.ReadFile(modFile)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
f, err := modfile.Parse(modFile, content, nil)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
path := f.Module.Mod.Path
|
||
|
||
// 获取包名
|
||
path, name := filepath.Split(path)
|
||
versionPattern := regexp.MustCompile(`^v\d+$`)
|
||
if versionPattern.MatchString(name) {
|
||
_, name = filepath.Split(strings.TrimSuffix(path, "/"))
|
||
}
|
||
|
||
if strings.Contains(name, "-") {
|
||
name = strings.ReplaceAll(name, "-", "")
|
||
}
|
||
|
||
return name, nil
|
||
}
|