Skip to content

Commit

Permalink
Merge pull request #63 from xushiwei/req
Browse files Browse the repository at this point in the history
modload: SaveWithGopMod
  • Loading branch information
xushiwei authored Feb 11, 2024
2 parents 1626453 + a13e1f5 commit 25ea24f
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 98 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
*.out

go.work*
.gop/
2 changes: 1 addition & 1 deletion gopmod/classfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var (
SpxProject = &Project{
Ext: ".spx",
Class: "Game",
Works: []*Class{{Ext: ".spx", Class: "Sprite"}},
Works: []*modfile.Class{{Ext: ".spx", Class: "Sprite"}},
PkgPaths: []string{"github.com/goplus/spx", "math"},
}
TestProject = &Project{
Expand Down
141 changes: 44 additions & 97 deletions modload/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"strings"

"github.com/goplus/mod"
"github.com/goplus/mod/env"
"github.com/goplus/mod/modfile"
"github.com/qiniu/x/errors"
"golang.org/x/mod/module"
Expand Down Expand Up @@ -54,6 +55,14 @@ func (p Module) Modfile() string {
return ""
}

func (p Module) workFile() string {
if syn := p.Syntax; syn != nil {
dir, _ := filepath.Split(syn.Name)
return dir + "go.work"
}
return ""
}

// Root returns absolute root path of this module.
func (p Module) Root() string {
if syn := p.Syntax; syn != nil {
Expand Down Expand Up @@ -115,6 +124,12 @@ func Create(dir string, modPath, goVer, gopVer string) (p Module, err error) {
return Module{}, fmt.Errorf("gop: %s already exists", gopmod)
}

if goVer == "" {
goVer = defaultGoVer
}
if gopVer == "" {
gopVer = defaultGopVer
}
mod := newGoMod(gomod, modPath, goVer)
opt := newGopMod(gopmod, gopVer)
return Module{mod, opt}, nil
Expand Down Expand Up @@ -285,115 +300,47 @@ func (p Module) Save() (err error) {
return
}

/*
const (
gopMod = "github.com/goplus/gop"
)
// UpdateGoMod updates the go.mod file.
func (p Module) UpdateGoMod(env *env.Gop, checkChanged bool) error {
gopmod := p.Modfile()
dir, file := filepath.Split(gopmod)
if file == "go.mod" {
return nil
}
gomod := dir + "go.mod"
if checkChanged && notChanged(gomod, gopmod) {
return nil
}
return p.saveGoMod(gomod, env)
}
func (p Module) saveGoMod(gomod string, env *env.Gop) error {
gof := p.convToGoMod(env)
data, err := gof.Format()
if err == nil {
err = os.WriteFile(gomod, data, 0644)
}
return err
}
func (p Module) convToGoMod(env *env.Gop) *gomodfile.File {
copy := p.File.File
copy.Syntax = cloneGoFileSyntax(copy.Syntax)
addRequireIfNotExist(&copy, gopMod, env.Version)
addReplaceIfNotExist(&copy, gopMod, "", env.Root, "")
return &copy
}
func addRequireIfNotExist(f *gomodfile.File, path, vers string) {
for _, r := range f.Require {
if r.Mod.Path == path {
return
}
}
f.AddNewRequire(path, vers, false)
}
func addReplaceIfNotExist(f *gomodfile.File, oldPath, oldVers, newPath, newVers string) {
for _, r := range f.Replace {
if r.Old.Path == oldPath && (oldVers == "" || r.Old.Version == oldVers) {
return
}
// SaveWithGopMod adds `require github.com/goplus/gop` and saves all
// changes of this module.
func (p Module) SaveWithGopMod(gop *env.Gop, flags int) (err error) {
gopVer := getGopVer(gop)
p.requireGop(gop, gopVer, flags)
if err = p.Save(); err != nil {
return
}
f.AddReplace(oldPath, oldVers, newPath, newVers)
}

func notChanged(target, src string) bool {
fiTarget, err := os.Stat(target)
var work *gomodfile.WorkFile
var workFile = p.workFile()
b, err := os.ReadFile(workFile)
if err != nil {
return false
}
fiSrc, err := os.Stat(src)
if err != nil {
return false
}
return fiTarget.ModTime().After(fiSrc.ModTime())
}
// -----------------------------------------------------------------------------
func cloneGoFileSyntax(syn *modfile.FileSyntax) *modfile.FileSyntax {
stmt := make([]modfile.Expr, 0, len(syn.Stmt))
for _, e := range syn.Stmt {
if isGopOrDeletedExpr(e) {
continue
if os.IsNotExist(err) {
b = []byte(`go ` + p.Go.Version)
} else {
return
}
stmt = append(stmt, cloneExpr(e))
}
return &modfile.FileSyntax{
Name: syn.Name,
Comments: syn.Comments,
Stmt: stmt,
}
}
func cloneExpr(e modfile.Expr) modfile.Expr {
if v, ok := e.(*modfile.LineBlock); ok {
copy := *v
return &copy
var fixed bool
fix := fixVersion(&fixed)
if work, err = gomodfile.ParseWork(workFile, b, fix); err != nil {
return
}
return e
work.AddReplace("github.com/goplus/gop", gopVer, gop.Root, "")
return os.WriteFile(workFile, gomodfile.Format(work.Syntax), 0666)
}

func isGopOrDeletedExpr(e modfile.Expr) bool {
switch verb := getVerb(e); verb {
case "", "gop", "register", "project", "class":
return true
}
return false
// requireGop adds require for the github.com/goplus/gop module.
func (p Module) requireGop(gop *env.Gop, gopVer string, flags int) {
p.File.AddRequire("github.com/goplus/gop", gopVer)
// TODO: AddRequire "github.com/qiniu/x" if necessary
}

func getVerb(e modfile.Expr) string {
if line, ok := e.(*modfile.Line); ok {
if token := line.Token; len(token) > 0 {
return token[0]
}
return "" // deleted line
func getGopVer(gop *env.Gop) string {
ver := gop.Version
if pos := strings.IndexByte(ver, ' '); pos > 0 { // v1.2.0 devel
ver = ver[:pos]
}
return e.(*modfile.LineBlock).Token[0]
return ver
}
*/

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

Expand Down
75 changes: 75 additions & 0 deletions modload/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ package modload

import (
"encoding/json"
"os"
"runtime"
"testing"

"github.com/goplus/mod/env"
"github.com/goplus/mod/modfile"
gomodfile "golang.org/x/mod/modfile"
)
Expand Down Expand Up @@ -131,3 +133,76 @@ replace github.com/goplus/yap v0.7.2 => ../
}
}
}

func TestSaveDefault(t *testing.T) {
if v := Default.workFile(); v != "" {
t.Fatal("Default.workFile:", v)
}
if err := Default.Save(); err != ErrSaveDefault {
t.Fatal("Default.Save:", err)
}
}

func TestSave(t *testing.T) {
dir := ".gop/_tempdir"
os.RemoveAll(dir)
os.MkdirAll(dir, 0777)
mod, err := Create(dir, "github.com/foo/bar", "", "")
if err != nil {
t.Fatal("Create:", err)
}
if err = mod.AddRequire("github.com/goplus/yap", "v0.5.0", true); err != nil {
t.Fatal("mod.AddRequire:", err)
}
mod.Save()

mod, err = Load(dir)
if err != nil {
t.Fatal("Load:", err)
}
if err = mod.SaveWithGopMod(&env.Gop{Version: "v1.2.0 devel", Root: "/foo/bar/gop"}, 0); err != nil {
t.Fatal("mod.SaveWithGopMod:", err)
}
if b, err := mod.File.Format(); err != nil {
t.Fatal("Format:", err)
} else if v := string(b); v != `module github.com/foo/bar
go 1.18
require (
github.com/goplus/yap v0.5.0 //gop:class
github.com/goplus/gop v1.2.0
)
` {
t.Fatal("SaveWithGopMod:", v)
}
b, err := os.ReadFile(mod.workFile())
if err != nil {
t.Fatal("read workFile:", err)
}
if v := string(b); v != `go 1.18
replace github.com/goplus/gop v1.2.0 => /foo/bar/gop
` {
t.Fatal("workFile:", v)
}
mod.Opt.Projects = append(mod.Opt.Projects, spxProject)
mod.Save()
b, err = os.ReadFile(mod.Opt.Syntax.Name)
if err != nil {
t.Fatal("read gop.mod:", err)
}
if v := string(b); v != `gop 1.2
` {
t.Fatal("gop.mod:", v)
}
}

var (
spxProject = &modfile.Project{
Ext: ".spx",
Class: "Game",
Works: []*modfile.Class{{Ext: ".spx", Class: "Sprite"}},
PkgPaths: []string{"github.com/goplus/spx", "math"},
}
)

0 comments on commit 25ea24f

Please sign in to comment.