diff --git a/gopmod/module.go b/gopmod/module.go index 157f7bc..b3b5957 100644 --- a/gopmod/module.go +++ b/gopmod/module.go @@ -24,6 +24,7 @@ import ( "strings" "syscall" + "github.com/goplus/mod" "github.com/goplus/mod/modcache" "github.com/goplus/mod/modfetch" "github.com/goplus/mod/modload" @@ -101,7 +102,7 @@ func (p *Module) Lookup(pkgPath string) (pkg *Package, err error) { dir := modDir + pkgPath[len(modPath):] pkg = &Package{Type: PkgtModule, ModPath: modPath, ModDir: modDir, Dir: dir} case PkgtExtern: - if modPath, modVer, ok := p.LookupExternPkg(pkgPath); ok { + if modPath, modVer, ok := p.lookupExternPkg(pkgPath); ok { if modDir, e := modcache.Path(modVer); e == nil { dir := modDir + pkgPath[len(modPath):] pkg = &Package{Type: PkgtExtern, ModPath: modPath, ModDir: modDir, Dir: dir} @@ -117,9 +118,9 @@ func (p *Module) Lookup(pkgPath string) (pkg *Package, err error) { return } -// LookupExternPkg lookups a external package from depended modules. +// lookupExternPkg lookups a external package from depended modules. // If modVer.Path is replace to be a local path, it will be canonical to an absolute path. -func (p *Module) LookupExternPkg(pkgPath string) (modPath string, modVer module.Version, ok bool) { +func (p *Module) lookupExternPkg(pkgPath string) (modPath string, modVer module.Version, ok bool) { for _, m := range p.depmods { if isPkgInMod(pkgPath, m.path) { modPath, modVer, ok = m.path, m.real, true @@ -175,8 +176,8 @@ func New(mod modload.Module) *Module { // Load loads a module from a local dir. // If we only want to load a Go modfile, pass env parameter as nil. -func Load(dir string) (*Module, error) { - mod, err := modload.Load(dir, 0) +func Load(dir string, mode mod.Mode) (*Module, error) { + mod, err := modload.Load(dir, mode) if err != nil { return nil, err } @@ -185,8 +186,8 @@ func Load(dir string) (*Module, error) { // LoadMod loads a module from a versioned module path. // If we only want to load a Go modfile, pass env parameter as nil. -func LoadMod(mod module.Version) (p *Module, err error) { - p, err = loadModFrom(mod) +func LoadMod(mod module.Version, mode mod.Mode) (p *Module, err error) { + p, err = loadModFrom(mod, mode) if err != syscall.ENOENT { return } @@ -194,15 +195,15 @@ func LoadMod(mod module.Version) (p *Module, err error) { if err != nil { return } - return loadModFrom(mod) + return loadModFrom(mod, mode) } -func loadModFrom(mod module.Version) (p *Module, err error) { +func loadModFrom(mod module.Version, mode mod.Mode) (p *Module, err error) { dir, err := modcache.Path(mod) if err != nil { return } - return Load(dir) + return Load(dir, mode) } // ----------------------------------------------------------------------------- diff --git a/mod.go b/mod.go index a6c8c61..17ff88e 100644 --- a/mod.go +++ b/mod.go @@ -28,12 +28,14 @@ import ( type Mode int const ( - GoModOnly Mode = 1 + GoModOnly Mode = 1 + GopModOnly Mode = 2 ) // GOPMOD checks the modfile in this dir or its ancestors. // If mode == 0, it checks both gop.mod and go.mod // If mode == GoModOnly, it checks go.mod +// If mode == GopModOnly, it checks gop.mod func GOPMOD(dir string, mode Mode) (file string, err error) { if dir == "" { dir = "." @@ -48,9 +50,11 @@ func GOPMOD(dir string, mode Mode) (file string, err error) { return } } - file = filepath.Join(dir, "go.mod") - if fi, e := os.Lstat(file); e == nil && !fi.IsDir() { - return + if mode != GopModOnly { + file = filepath.Join(dir, "go.mod") + if fi, e := os.Lstat(file); e == nil && !fi.IsDir() { + return + } } if dir, file = filepath.Split(strings.TrimRight(dir, "/\\")); file == "" { break diff --git a/modfetch/fetch.go b/modfetch/fetch.go index 18e251d..beabb13 100644 --- a/modfetch/fetch.go +++ b/modfetch/fetch.go @@ -33,9 +33,57 @@ import ( // ----------------------------------------------------------------------------- +// GetPkg downloads the module that contains pkgPath to GOMODCACHE. +func GetPkg(pkgPath, modBase string) (modVer module.Version, relPath string, err error) { + modPath, relPath := Split(pkgPath, modBase) + modVer, err = Get(modPath) + return +} + +// Split splits a pkgPath into modPath and its relPath to module root. +func Split(pkgPath, modBase string) (modPath, relPath string) { + if modBase != "" && strings.HasPrefix(pkgPath, modBase) { + n := len(modBase) + if len(pkgPath) == n { + return modBase, "" + } + if pkgPath[n] == '/' { + return modBase, pkgPath[n+1:] + } + } + parts := strings.SplitN(pkgPath, "/", 4) + if strings.Index(parts[0], ".") < 0 { // standard package + return "", pkgPath + } + switch parts[0] { + case ".", "..": // local package + return modBase, pkgPath + case "github.com": + if len(parts) > 3 { + relPath = parts[3] + if pos := strings.IndexByte(relPath, '@'); pos > 0 { + parts[2] += relPath[pos:] + relPath = relPath[:pos] + } + modPath = strings.Join(parts[:3], "/") + return + } + } + panic("TODO: modfetch.Split - unexpected pkgPath") +} + +// ----------------------------------------------------------------------------- + +var ( + errEmptyModPath = errors.New("empty module path") +) + // Get downloads a modPath to GOMODCACHE. -// func Get(modPath string, noCache ...bool) (mod module.Version, err error) { + if modPath == "" { + err = errEmptyModPath + return + } if noCache == nil || !noCache[0] { mod, err = getFromCache(modPath) if err != syscall.ENOENT { diff --git a/modload/module.go b/modload/module.go index 6bc0171..0bf2d4d 100644 --- a/modload/module.go +++ b/modload/module.go @@ -119,14 +119,8 @@ func fixVersion(fixed *bool) modfile.VersionFixer { } } -type Mode = mod.Mode - -const ( - GoModOnly = mod.GoModOnly -) - // Load loads a module from `dir`. -func Load(dir string, mode Mode) (p Module, err error) { +func Load(dir string, mode mod.Mode) (p Module, err error) { gopmod, err := mod.GOPMOD(dir, mode) if err != nil { return