Skip to content

Commit

Permalink
Merge pull request #57 from xushiwei/req
Browse files Browse the repository at this point in the history
gopmod: DepMods
  • Loading branch information
xushiwei committed Feb 10, 2024
2 parents 03f041a + f119de6 commit 3cc7ed4
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 47 deletions.
70 changes: 70 additions & 0 deletions gopmod/gopmod_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package gopmod

import (
"log"
"runtime"
"testing"

"github.com/goplus/mod/modload/modtest"
)

func TestLookup(t *testing.T) {
mod := New(modtest.GopClass(t))
if modv, ok := mod.LookupDepMod("github.com/qiniu/x"); !ok || modv.Version != "v1.13.2" {
t.Fatal("mod.LookupDepMod:", modv)
}
if pkg, err := mod.Lookup("fmt"); err != nil || pkg.ModPath != "" || pkg.ModDir != runtime.GOROOT()+"/src" {
t.Fatal("mod.Lookup fmt:", pkg.ModPath, pkg.ModDir, "err:", err)
}
if pkg, err := mod.Lookup("github.com/goplus/community/foo"); err != nil || pkg.ModPath != "github.com/goplus/community" {
t.Fatal("mod.Lookup github.com/goplus/community/foo:", pkg.ModPath, pkg.ModDir, "err:", err)
}
if _, err := mod.Lookup("github.com/qiniu/y/mockhttp"); err == nil || err.Error() != `no required module provides package github.com/qiniu/y/mockhttp; to add it:
gop get github.com/qiniu/y/mockhttp` {
t.Fatal("mod.Lookup github.com/qiniu/y/mockhttp:", err)
}
if pkg, err := mod.Lookup("github.com/qiniu/x/mockhttp"); err != nil || pkg.ModPath != "github.com/qiniu/x" {
t.Fatal("mod.Lookup github.com/qiniu/x/mockhttp:", pkg.ModPath, pkg.ModDir, "err:", err)
}
defer func() {
if e := recover(); e == nil {
log.Fatal("mod.Lookup: no panic?")
}
}()
mod.Lookup("")
}

func TestPkgType(t *testing.T) {
mod := New(modtest.GopClass(t))
if mod.IsPkgtStandard("github.com/qiniu/x") {
t.Fatal("mod.IsPkgtStandard: true?")
}
if !mod.IsPkgtStandard("fmt") {
t.Fatal("mod.IsPkgtStandard: false?")
}
if pt := mod.PkgType(""); pt != PkgtInvalid {
t.Fatal("mod.PkgType:", pt)
}
if pt := mod.PkgType("./fmt"); pt != PkgtLocal {
t.Fatal("mod.PkgType ./fmt:", pt)
}
if pt := mod.PkgType("github.com/goplus/community/foo"); pt != PkgtModule {
t.Fatal("mod.PkgType github.com/goplus/community/foo:", pt)
}
}
63 changes: 18 additions & 45 deletions gopmod/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"log"
"path/filepath"
"runtime"
"sort"
"strings"
"syscall"

Expand All @@ -34,15 +33,19 @@ import (

// -----------------------------------------------------------------------------

type depmodInfo struct {
path string
real module.Version
}

type Module struct {
modload.Module
projects map[string]*Project // ext -> project
depmods []depmodInfo
depmods_ map[string]module.Version
}

// DepMods returns all depended modules.
// If a depended module path is replace to be a local path, it will be canonical to an absolute path.
func (p *Module) DepMods() map[string]module.Version {
if p.depmods_ == nil {
p.depmods_ = p.Module.DepMods()
}
return p.depmods_
}

// PkgType specifies a package type.
Expand Down Expand Up @@ -119,12 +122,12 @@ func (p *Module) Lookup(pkgPath string) (pkg *Package, err error) {
// 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) (pkg *Package, err error) {
for _, m := range p.depmods {
if isPkgInMod(pkgPath, m.path) {
if modDir, e := modcache.Path(m.real); e == nil {
modPath := m.path
for path, real := range p.DepMods() {
if isPkgInMod(pkgPath, path) {
if modDir, e := modcache.Path(real); e == nil {
modPath := path
dir := modDir + pkgPath[len(modPath):]
pkg = &Package{Type: PkgtExtern, Real: m.real, ModPath: modPath, ModDir: modDir, Dir: dir}
pkg = &Package{Type: PkgtExtern, Real: real, ModPath: modPath, ModDir: modDir, Dir: dir}
} else {
err = e
}
Expand All @@ -138,45 +141,15 @@ func (p *Module) lookupExternPkg(pkgPath string) (pkg *Package, err error) {
// LookupDepMod lookups a depended module.
// If modVer.Path is replace to be a local path, it will be canonical to an absolute path.
func (p *Module) LookupDepMod(modPath string) (modVer module.Version, ok bool) {
for _, m := range p.depmods {
if m.path == modPath {
modVer, ok = m.real, true
break
}
}
deps := p.DepMods()
modVer, ok = deps[modPath]
return
}

// IsGopMod returns if this module is a Go+ module or not.
func (p *Module) IsGopMod() bool {
const gopPkgPath = "github.com/goplus/gop"
_, file := filepath.Split(p.Modfile())
if file == "gop.mod" {
return true
}
if _, ok := p.LookupDepMod(gopPkgPath); ok {
return true
}
return p.Path() == gopPkgPath
}

func getDepMods(mod modload.Module) []depmodInfo {
depmods := mod.DepMods()
ret := make([]depmodInfo, 0, len(depmods))
for path, m := range depmods {
ret = append(ret, depmodInfo{path: path, real: m})
}
sort.Slice(ret, func(i, j int) bool {
return ret[i].path > ret[j].path
})
return ret
}

// New creates a module from a modload.Module instance.
func New(mod modload.Module) *Module {
projects := make(map[string]*Project)
depmods := getDepMods(mod)
return &Module{projects: projects, depmods: depmods, Module: mod}
return &Module{projects: projects, Module: mod}
}

// Load loads a module from a local directory.
Expand Down
6 changes: 4 additions & 2 deletions modload/modtest/modtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func Load(t *testing.T, gomodText, gopmodText string, errMsg string) modload.Mod
return mod
}

func GopClass(t *testing.T) {
func GopClass(t *testing.T) modload.Module {
const gomodText = `
module github.com/goplus/community
Expand All @@ -60,9 +60,10 @@ require (
if n := len(mod.Opt.ClassMods); n != 2 {
t.Fatal("len(mod.Opt.Import):", n)
}
return mod
}

func Import(t *testing.T) {
func Import(t *testing.T) modload.Module {
const gomodText = `
module github.com/goplus/yap
Expand All @@ -82,4 +83,5 @@ import yauth github.com/goplus/yap/ytest/auth
if n := len(mod.Opt.Projects); n != 2 {
t.Fatal("len(mod.Opt.Projects):", n)
}
return mod
}

0 comments on commit 3cc7ed4

Please sign in to comment.