From 6c702b9cfcf2939b4e8b6d33a52540088d0bb308 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Wed, 6 Nov 2024 00:13:09 +0100 Subject: [PATCH 01/51] chore: explicitely remove require support Signed-off-by: Norman Meier --- gnovm/cmd/gno/mod.go | 24 +---- gnovm/pkg/doc/dirs.go | 25 ----- gnovm/pkg/gnomod/file.go | 118 +---------------------- gnovm/pkg/gnomod/file_test.go | 142 ---------------------------- gnovm/pkg/gnomod/gnomod.go | 36 ++++--- gnovm/pkg/gnomod/parse.go | 20 +--- gnovm/pkg/gnomod/parse_test.go | 2 +- gnovm/pkg/gnomod/pkg.go | 52 +++++++--- gnovm/pkg/gnomod/pkg_test.go | 142 +++------------------------- gnovm/pkg/gnomod/preprocess.go | 6 +- gnovm/pkg/gnomod/read_test.go | 167 --------------------------------- 11 files changed, 78 insertions(+), 656 deletions(-) delete mode 100644 gnovm/pkg/gnomod/file_test.go diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 03b2bb348a8..625a67b323d 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -177,9 +177,7 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { } // fetch dependencies - if err := gnoMod.FetchDeps(gnomod.GetGnoModPath(), cfg.remote, cfg.verbose); err != nil { - return fmt.Errorf("fetch: %w", err) - } + panic("not implemented") gomod, err := gnomod.GnoToGoMod(*gnoMod) if err != nil { @@ -276,26 +274,6 @@ func modTidyOnce(cfg *modTidyCfg, wd, pkgdir string, io commands.IO) error { return err } - // Drop all existing requires - for _, r := range gm.Require { - gm.DropRequire(r.Mod.Path) - } - - imports, err := getGnoPackageImports(pkgdir) - if err != nil { - return err - } - for _, im := range imports { - // skip if importpath is modulepath - if im == gm.Module.Mod.Path { - continue - } - gm.AddRequire(im, "v0.0.0-latest") - if cfg.verbose { - io.ErrPrintfln(" %s", im) - } - } - gm.Write(fname) return nil } diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index 19d312f6826..48c51dfb27a 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -60,37 +60,12 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { dir: mdir, importPath: gm.Module.Mod.Path, }) - roots = append(roots, getGnoModDirs(gm)...) } go d.walk(roots) return d } -func getGnoModDirs(gm *gnomod.File) []bfsDir { - // cmd/go makes use of the go list command, we don't have that here. - - dirs := make([]bfsDir, 0, len(gm.Require)) - for _, r := range gm.Require { - mv := gm.Resolve(r) - path := gnomod.PackageDir("", mv) - if _, err := os.Stat(path); err != nil { - // only give directories which actually exist and don't give - // an error when accessing - if !os.IsNotExist(err) { - log.Println("open source directories from gno.mod:", err) - } - continue - } - dirs = append(dirs, bfsDir{ - importPath: mv.Path, - dir: path, - }) - } - - return dirs -} - // Reset puts the scan back at the beginning. func (d *bfsDirs) Reset() { d.offset = 0 diff --git a/gnovm/pkg/gnomod/file.go b/gnovm/pkg/gnomod/file.go index b6ee95acac8..71f01b6b071 100644 --- a/gnovm/pkg/gnomod/file.go +++ b/gnovm/pkg/gnomod/file.go @@ -12,12 +12,8 @@ package gnomod import ( "errors" "fmt" - "log" "os" - "path/filepath" - "strings" - gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "golang.org/x/mod/modfile" "golang.org/x/mod/module" ) @@ -27,51 +23,11 @@ type File struct { Draft bool Module *modfile.Module Go *modfile.Go - Require []*modfile.Require Replace []*modfile.Replace Syntax *modfile.FileSyntax } -// AddRequire sets the first require line for path to version vers, -// preserving any existing comments for that line and removing all -// other lines for path. -// -// If no line currently exists for path, AddRequire adds a new line -// at the end of the last require block. -func (f *File) AddRequire(path, vers string) error { - need := true - for _, r := range f.Require { - if r.Mod.Path == path { - if need { - r.Mod.Version = vers - updateLine(r.Syntax, "require", modfile.AutoQuote(path), vers) - need = false - } else { - markLineAsRemoved(r.Syntax) - *r = modfile.Require{} - } - } - } - - if need { - f.AddNewRequire(path, vers, false) - } - return nil -} - -// AddNewRequire adds a new require line for path at version vers at the end of -// the last require block, regardless of any existing require lines for path. -func (f *File) AddNewRequire(path, vers string, indirect bool) { - line := addLine(f.Syntax, nil, "require", modfile.AutoQuote(path), vers) - r := &modfile.Require{ - Mod: module.Version{Path: path, Version: vers}, - Syntax: line, - } - setIndirect(r, indirect) - f.Require = append(f.Require, r) -} - func (f *File) AddModuleStmt(path string) error { if f.Syntax == nil { f.Syntax = new(modfile.FileSyntax) @@ -107,16 +63,6 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { return addReplace(f.Syntax, &f.Replace, oldPath, oldVers, newPath, newVers) } -func (f *File) DropRequire(path string) error { - for _, r := range f.Require { - if r.Mod.Path == path { - markLineAsRemoved(r.Syntax) - *r = modfile.Require{} - } - } - return nil -} - func (f *File) DropReplace(oldPath, oldVers string) error { for _, r := range f.Replace { if r.Old.Path == oldPath && r.Old.Version == oldVers { @@ -146,68 +92,6 @@ func (f *File) Resolve(r *modfile.Require) module.Version { return r.Mod } -// FetchDeps fetches and writes gno.mod packages -// in GOPATH/pkg/gnomod/ -func (f *File) FetchDeps(path string, remote string, verbose bool) error { - for _, r := range f.Require { - mod := f.Resolve(r) - if r.Mod.Path != mod.Path { - if modfile.IsDirectoryPath(mod.Path) { - continue - } - } - indirect := "" - if r.Indirect { - indirect = "// indirect" - } - - _, err := os.Stat(PackageDir(path, mod)) - if !os.IsNotExist(err) { - if verbose { - log.Println("cached", mod.Path, indirect) - } - continue - } - if verbose { - log.Println("fetching", mod.Path, indirect) - } - requirements, err := writePackage(remote, path, mod.Path) - if err != nil { - return fmt.Errorf("writepackage: %w", err) - } - - modFile := new(File) - modFile.AddModuleStmt(mod.Path) - for _, req := range requirements { - path := req[1 : len(req)-1] // trim leading and trailing `"` - if strings.HasSuffix(path, modFile.Module.Mod.Path) { - continue - } - - if !gno.IsStdlib(path) { - modFile.AddNewRequire(path, "v0.0.0-latest", true) - } - } - - err = modFile.FetchDeps(path, remote, verbose) - if err != nil { - return err - } - goMod, err := GnoToGoMod(*modFile) - if err != nil { - return err - } - pkgPath := PackageDir(path, mod) - goModFilePath := filepath.Join(pkgPath, "go.mod") - err = goMod.Write(goModFilePath) - if err != nil { - return err - } - } - - return nil -} - // writes file to the given absolute file path func (f *File) Write(fname string) error { f.Syntax.Cleanup() @@ -220,5 +104,5 @@ func (f *File) Write(fname string) error { } func (f *File) Sanitize() { - removeDups(f.Syntax, &f.Require, &f.Replace) + removeDups(f.Syntax, &f.Replace) } diff --git a/gnovm/pkg/gnomod/file_test.go b/gnovm/pkg/gnomod/file_test.go deleted file mode 100644 index a64c2794a65..00000000000 --- a/gnovm/pkg/gnomod/file_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package gnomod - -import ( - "bytes" - "log" - "os" - "path/filepath" - "testing" - - "github.com/gnolang/gno/tm2/pkg/testutils" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/mod/modfile" - "golang.org/x/mod/module" -) - -const testRemote string = "gno.land:26657" // XXX(race condition): test with a local node so that this test is consistent with git and not with a deploy - -func TestFetchDeps(t *testing.T) { - for _, tc := range []struct { - desc string - modFile File - errorShouldContain string - requirements []string - stdOutContains []string - cachedStdOutContains []string - }{ - { - desc: "not_exists", - modFile: File{ - Module: &modfile.Module{ - Mod: module.Version{ - Path: "testFetchDeps", - }, - }, - Require: []*modfile.Require{ - { - Mod: module.Version{ - Path: "gno.land/p/demo/does_not_exists", - Version: "v0.0.0", - }, - }, - }, - }, - errorShouldContain: "querychain (gno.land/p/demo/does_not_exists)", - }, { - desc: "fetch_gno.land/p/demo/avl", - modFile: File{ - Module: &modfile.Module{ - Mod: module.Version{ - Path: "testFetchDeps", - }, - }, - Require: []*modfile.Require{ - { - Mod: module.Version{ - Path: "gno.land/p/demo/avl", - Version: "v0.0.0", - }, - }, - }, - }, - requirements: []string{"avl"}, - stdOutContains: []string{ - "fetching gno.land/p/demo/avl", - }, - cachedStdOutContains: []string{ - "cached gno.land/p/demo/avl", - }, - }, { - desc: "fetch_gno.land/p/demo/blog6", - modFile: File{ - Module: &modfile.Module{ - Mod: module.Version{ - Path: "testFetchDeps", - }, - }, - Require: []*modfile.Require{ - { - Mod: module.Version{ - Path: "gno.land/p/demo/blog", - Version: "v0.0.0", - }, - }, - }, - }, - requirements: []string{"avl", "blog", "ufmt", "mux"}, - stdOutContains: []string{ - "fetching gno.land/p/demo/blog", - "fetching gno.land/p/demo/avl // indirect", - "fetching gno.land/p/demo/ufmt // indirect", - }, - cachedStdOutContains: []string{ - "cached gno.land/p/demo/blog", - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - var buf bytes.Buffer - log.SetOutput(&buf) - defer func() { - log.SetOutput(os.Stderr) - }() - - // Create test dir - dirPath, cleanUpFn := testutils.NewTestCaseDir(t) - assert.NotNil(t, dirPath) - defer cleanUpFn() - - // Fetching dependencies - err := tc.modFile.FetchDeps(dirPath, testRemote, true) - if tc.errorShouldContain != "" { - require.ErrorContains(t, err, tc.errorShouldContain) - } else { - require.Nil(t, err) - - // Read dir - entries, err := os.ReadDir(filepath.Join(dirPath, "gno.land", "p", "demo")) - require.Nil(t, err) - - // Check dir entries - assert.Equal(t, len(tc.requirements), len(entries)) - for _, e := range entries { - assert.Contains(t, tc.requirements, e.Name()) - } - - // Check logs - for _, c := range tc.stdOutContains { - assert.Contains(t, buf.String(), c) - } - - buf.Reset() - - // Try fetching again. Should be cached - tc.modFile.FetchDeps(dirPath, testRemote, true) - for _, c := range tc.cachedStdOutContains { - assert.Contains(t, buf.String(), c) - } - } - }) - } -} diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 553bb32f4b5..29f85eb185f 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -89,28 +89,34 @@ func writePackage(remote, basePath, pkgPath string) (requirements []string, err func GnoToGoMod(f File) (*File, error) { // TODO(morgan): good candidate to move to pkg/transpiler. - gnoModPath := GetGnoModPath() + // gnoModPath := GetGnoModPath() if !gnolang.IsStdlib(f.Module.Mod.Path) { f.AddModuleStmt(transpiler.TranspileImportPath(f.Module.Mod.Path)) } - for i := range f.Require { - mod, replaced := isReplaced(f.Require[i].Mod, f.Replace) - if replaced { - if modfile.IsDirectoryPath(mod.Path) { - continue + /* + + // FIXME: not sure how to port this + + for i := range f.Require { + mod, replaced := isReplaced(f.Require[i].Mod, f.Replace) + if replaced { + if modfile.IsDirectoryPath(mod.Path) { + continue + } } + path := f.Require[i].Mod.Path + if !gnolang.IsStdlib(path) { + // Add dependency with a modified import path + f.AddRequire(transpiler.TranspileImportPath(path), f.Require[i].Mod.Version) + } + f.AddReplace(path, f.Require[i].Mod.Version, filepath.Join(gnoModPath, path), "") + // Remove the old require since the new dependency was added above + f.DropRequire(path) } - path := f.Require[i].Mod.Path - if !gnolang.IsStdlib(path) { - // Add dependency with a modified import path - f.AddRequire(transpiler.TranspileImportPath(path), f.Require[i].Mod.Version) - } - f.AddReplace(path, f.Require[i].Mod.Version, filepath.Join(gnoModPath, path), "") - // Remove the old require since the new dependency was added above - f.DropRequire(path) - } + + */ // Remove replacements that are not replaced by directories. // diff --git a/gnovm/pkg/gnomod/parse.go b/gnovm/pkg/gnomod/parse.go index a6314d5729f..7f656dc7840 100644 --- a/gnovm/pkg/gnomod/parse.go +++ b/gnovm/pkg/gnomod/parse.go @@ -181,24 +181,8 @@ func (f *File) add(errs *modfile.ErrorList, block *modfile.LineBlock, line *modf f.Module.Mod = module.Version{Path: s} case "require": - if len(args) != 2 { - errorf("usage: %s module/path v1.2.3", verb) - return - } - s, err := parseString(&args[0]) - if err != nil { - errorf("invalid quoted string: %v", err) - return - } - v, err := parseVersion(verb, s, &args[1]) - if err != nil { - wrapError(err) - return - } - f.Require = append(f.Require, &modfile.Require{ - Mod: module.Version{Path: s, Version: v}, - Syntax: line, - }) + errorf("require is not supported by gno") + return case "replace": replace, wrappederr := parseReplace(f.Syntax.Name, line, verb, args) diff --git a/gnovm/pkg/gnomod/parse_test.go b/gnovm/pkg/gnomod/parse_test.go index 61aaa83482b..f266a1d065a 100644 --- a/gnovm/pkg/gnomod/parse_test.go +++ b/gnovm/pkg/gnomod/parse_test.go @@ -203,7 +203,7 @@ func TestParseGnoMod(t *testing.T) { desc: "error validating gno.mod", modData: `require bar v0.0.0`, modPath: filepath.Join(pkgDir, "gno.mod"), - errShouldContain: "error validating gno.mod file at", + errShouldContain: "require is not supported by gno", }, } { t.Run(tc.desc, func(t *testing.T) { diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index f6fe7f60301..252b0c6b37c 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -2,17 +2,20 @@ package gnomod import ( "fmt" + "go/parser" + gotoken "go/token" "io/fs" "os" "path/filepath" + "slices" "strings" ) type Pkg struct { - Dir string // absolute path to package dir - Name string // package name - Requires []string // dependencies - Draft bool // whether the package is a draft + Dir string // absolute path to package dir + Name string // package name + Imports []string + Draft bool // whether the package is a draft } type SubPkg struct { @@ -60,10 +63,10 @@ func visitPackage(pkg Pkg, pkgs []Pkg, visited, onStack map[string]bool, sortedP onStack[pkg.Name] = true // Visit package's dependencies - for _, req := range pkg.Requires { + for _, imp := range pkg.Imports { found := false for _, p := range pkgs { - if p.Name != req { + if p.Name != imp { continue } if err := visitPackage(p, pkgs, visited, onStack, sortedPkgs); err != nil { @@ -73,7 +76,7 @@ func visitPackage(pkg Pkg, pkgs []Pkg, visited, onStack map[string]bool, sortedP break } if !found { - return fmt.Errorf("missing dependency '%s' for package '%s'", req, pkg.Name) + return fmt.Errorf("missing dependency '%s' for package '%s'", imp, pkg.Name) } } @@ -115,12 +118,35 @@ func ListPkgs(root string) (PkgList, error) { Dir: path, Name: gnoMod.Module.Mod.Path, Draft: gnoMod.Draft, - Requires: func() []string { - var reqs []string - for _, req := range gnoMod.Require { - reqs = append(reqs, req.Mod.Path) + Imports: func() []string { + dir, err := os.ReadDir(path) + if err != nil { + return nil } - return reqs + resMap := map[string]struct{}{} + for _, f := range dir { + filename := f.Name() + if f.IsDir() || !strings.HasSuffix(filename, ".gno") { + continue + } + fileSet := gotoken.NewFileSet() + gnoFile, err := parser.ParseFile(fileSet, filepath.Join(path, filename), nil, parser.ImportsOnly) + if err != nil { + continue + } + for _, importSpec := range gnoFile.Imports { + val := strings.TrimSuffix(strings.TrimPrefix(importSpec.Path.Value, `"`), `"`) + resMap[val] = struct{}{} + } + } + res := make([]string, len(resMap)) + i := 0 + for imp := range resMap { + res[i] = imp + i++ + } + slices.Sort(res) + return res }(), }) return nil @@ -144,7 +170,7 @@ func (sp SortedPkgList) GetNonDraftPkgs() SortedPkgList { continue } dependsOnDraft := false - for _, req := range pkg.Requires { + for _, req := range pkg.Imports { if draft[req] { dependsOnDraft = true draft[pkg.Name] = true diff --git a/gnovm/pkg/gnomod/pkg_test.go b/gnovm/pkg/gnomod/pkg_test.go index 587a0bb8f81..7c3035a4b7b 100644 --- a/gnovm/pkg/gnomod/pkg_test.go +++ b/gnovm/pkg/gnomod/pkg_test.go @@ -47,12 +47,6 @@ func TestListAndNonDraftPkgs(t *testing.T) { "foo", `module foo`, }, - { - "bar", - `module bar - - require foo v0.0.0`, - }, { "baz", `module baz`, @@ -64,121 +58,8 @@ func TestListAndNonDraftPkgs(t *testing.T) { module qux`, }, }, - outListPkgs: []string{"foo", "bar", "baz", "qux"}, - outNonDraftPkgs: []string{"foo", "bar", "baz"}, - }, - { - desc: "package directly depends on draft package", - in: []struct{ name, modfile string }{ - { - "foo", - `// Draft - - module foo`, - }, - { - "bar", - `module bar - require foo v0.0.0`, - }, - { - "baz", - `module baz`, - }, - }, - outListPkgs: []string{"foo", "bar", "baz"}, - outNonDraftPkgs: []string{"baz"}, - }, - { - desc: "package indirectly depends on draft package", - in: []struct{ name, modfile string }{ - { - "foo", - `// Draft - - module foo`, - }, - { - "bar", - `module bar - - require foo v0.0.0`, - }, - { - "baz", - `module baz - - require bar v0.0.0`, - }, - { - "qux", - `module qux`, - }, - }, - outListPkgs: []string{"foo", "bar", "baz", "qux"}, - outNonDraftPkgs: []string{"qux"}, - }, - { - desc: "package indirectly depends on draft package (multiple levels - 1)", - in: []struct{ name, modfile string }{ - { - "foo", - `// Draft - - module foo`, - }, - { - "bar", - `module bar - - require foo v0.0.0`, - }, - { - "baz", - `module baz - - require bar v0.0.0`, - }, - { - "qux", - `module qux - - require baz v0.0.0`, - }, - }, - outListPkgs: []string{"foo", "bar", "baz", "qux"}, - outNonDraftPkgs: []string{}, - }, - { - desc: "package indirectly depends on draft package (multiple levels - 2)", - in: []struct{ name, modfile string }{ - { - "foo", - `// Draft - - module foo`, - }, - { - "bar", - `module bar - - require qux v0.0.0`, - }, - { - "baz", - `module baz - - require foo v0.0.0`, - }, - { - "qux", - `module qux - - require baz v0.0.0`, - }, - }, - outListPkgs: []string{"foo", "bar", "baz", "qux"}, - outNonDraftPkgs: []string{}, + outListPkgs: []string{"foo", "baz", "qux"}, + outNonDraftPkgs: []string{"foo", "baz"}, }, } { t.Run(tc.desc, func(t *testing.T) { @@ -224,6 +105,7 @@ func createGnoModPkg(t *testing.T, dirPath, pkgName, modData string) { // Create gno.mod err = os.WriteFile(filepath.Join(pkgDirPath, "gno.mod"), []byte(modData), 0o644) + require.NoError(t, err) } func TestSortPkgs(t *testing.T) { @@ -240,30 +122,30 @@ func TestSortPkgs(t *testing.T) { }, { desc: "no_dependencies", in: []Pkg{ - {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{}}, - {Name: "pkg2", Dir: "/path/to/pkg2", Requires: []string{}}, - {Name: "pkg3", Dir: "/path/to/pkg3", Requires: []string{}}, + {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{}}, + {Name: "pkg2", Dir: "/path/to/pkg2", Imports: []string{}}, + {Name: "pkg3", Dir: "/path/to/pkg3", Imports: []string{}}, }, expected: []string{"pkg1", "pkg2", "pkg3"}, }, { desc: "circular_dependencies", in: []Pkg{ - {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{"pkg2"}}, - {Name: "pkg2", Dir: "/path/to/pkg2", Requires: []string{"pkg1"}}, + {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{"pkg2"}}, + {Name: "pkg2", Dir: "/path/to/pkg2", Imports: []string{"pkg1"}}, }, shouldErr: true, }, { desc: "missing_dependencies", in: []Pkg{ - {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{"pkg2"}}, + {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{"pkg2"}}, }, shouldErr: true, }, { desc: "valid_dependencies", in: []Pkg{ - {Name: "pkg1", Dir: "/path/to/pkg1", Requires: []string{"pkg2"}}, - {Name: "pkg2", Dir: "/path/to/pkg2", Requires: []string{"pkg3"}}, - {Name: "pkg3", Dir: "/path/to/pkg3", Requires: []string{}}, + {Name: "pkg1", Dir: "/path/to/pkg1", Imports: []string{"pkg2"}}, + {Name: "pkg2", Dir: "/path/to/pkg2", Imports: []string{"pkg3"}}, + {Name: "pkg3", Dir: "/path/to/pkg3", Imports: []string{}}, }, expected: []string{"pkg3", "pkg2", "pkg1"}, }, diff --git a/gnovm/pkg/gnomod/preprocess.go b/gnovm/pkg/gnomod/preprocess.go index ec1faaa5c29..b78c91e3678 100644 --- a/gnovm/pkg/gnomod/preprocess.go +++ b/gnovm/pkg/gnomod/preprocess.go @@ -6,11 +6,7 @@ import ( "golang.org/x/mod/semver" ) -func removeDups(syntax *modfile.FileSyntax, require *[]*modfile.Require, replace *[]*modfile.Replace) { - if require != nil { - purged := removeRequireDups(require) - cleanSyntaxTree(syntax, purged) - } +func removeDups(syntax *modfile.FileSyntax, replace *[]*modfile.Replace) { if replace != nil { purged := removeReplaceDups(replace) cleanSyntaxTree(syntax, purged) diff --git a/gnovm/pkg/gnomod/read_test.go b/gnovm/pkg/gnomod/read_test.go index cf3b6f59076..d9c35205a51 100644 --- a/gnovm/pkg/gnomod/read_test.go +++ b/gnovm/pkg/gnomod/read_test.go @@ -210,85 +210,6 @@ comments before "// e" } } -var addRequireTests = []struct { - desc string - in string - path string - vers string - out string -}{ - { - `existing`, - ` - module m - require x.y/z v1.2.3 - `, - "x.y/z", "v1.5.6", - ` - module m - require x.y/z v1.5.6 - `, - }, - { - `existing2`, - ` - module m - require ( - x.y/z v1.2.3 // first - x.z/a v0.1.0 // first-a - ) - require x.y/z v1.4.5 // second - require ( - x.y/z v1.6.7 // third - x.z/a v0.2.0 // third-a - ) - `, - "x.y/z", "v1.8.9", - ` - module m - - require ( - x.y/z v1.8.9 // first - x.z/a v0.1.0 // first-a - ) - - require x.z/a v0.2.0 // third-a - `, - }, - { - `new`, - ` - module m - require x.y/z v1.2.3 - `, - "x.y/w", "v1.5.6", - ` - module m - require ( - x.y/z v1.2.3 - x.y/w v1.5.6 - ) - `, - }, - { - `new2`, - ` - module m - require x.y/z v1.2.3 - require x.y/q/v2 v2.3.4 - `, - "x.y/w", "v1.5.6", - ` - module m - require x.y/z v1.2.3 - require ( - x.y/q/v2 v2.3.4 - x.y/w v1.5.6 - ) - `, - }, -} - var addModuleStmtTests = []struct { desc string in string @@ -299,12 +220,10 @@ var addModuleStmtTests = []struct { `existing`, ` module m - require x.y/z v1.2.3 `, "n", ` module n - require x.y/z v1.2.3 `, }, { @@ -330,7 +249,6 @@ var addReplaceTests = []struct { `replace_with_module`, ` module m - require x.y/z v1.2.3 `, "x.y/z", "v1.5.6", @@ -338,7 +256,6 @@ var addReplaceTests = []struct { "v1.5.6", ` module m - require x.y/z v1.2.3 replace x.y/z v1.5.6 => a.b/c v1.5.6 `, }, @@ -346,7 +263,6 @@ var addReplaceTests = []struct { `replace_with_dir`, ` module m - require x.y/z v1.2.3 `, "x.y/z", "v1.5.6", @@ -354,66 +270,11 @@ var addReplaceTests = []struct { "", ` module m - require x.y/z v1.2.3 replace x.y/z v1.5.6 => /path/to/dir `, }, } -var dropRequireTests = []struct { - desc string - in string - path string - out string -}{ - { - `existing`, - ` - module m - require x.y/z v1.2.3 - `, - "x.y/z", - ` - module m - `, - }, - { - `existing2`, - ` - module m - require ( - x.y/z v1.2.3 // first - x.z/a v0.1.0 // first-a - ) - require x.y/z v1.4.5 // second - require ( - x.y/z v1.6.7 // third - x.z/a v0.2.0 // third-a - ) - `, - "x.y/z", - ` - module m - - require x.z/a v0.1.0 // first-a - - require x.z/a v0.2.0 // third-a - `, - }, - { - `not_exists`, - ` - module m - require x.y/z v1.2.3 - `, - "a.b/c", - ` - module m - require x.y/z v1.2.3 - `, - }, -} - var dropReplaceTests = []struct { desc string in string @@ -425,7 +286,6 @@ var dropReplaceTests = []struct { `existing`, ` module m - require x.y/z v1.2.3 replace x.y/z v1.2.3 => a.b/c v1.5.6 `, @@ -433,14 +293,12 @@ var dropReplaceTests = []struct { "v1.2.3", ` module m - require x.y/z v1.2.3 `, }, { `not_exists`, ` module m - require x.y/z v1.2.3 replace x.y/z v1.2.3 => a.b/c v1.5.6 `, @@ -448,25 +306,12 @@ var dropReplaceTests = []struct { "v3.2.1", ` module m - require x.y/z v1.2.3 replace x.y/z v1.2.3 => a.b/c v1.5.6 `, }, } -func TestAddRequire(t *testing.T) { - for _, tt := range addRequireTests { - t.Run(tt.desc, func(t *testing.T) { - testEdit(t, tt.in, tt.out, func(f *File) error { - err := f.AddRequire(tt.path, tt.vers) - f.Syntax.Cleanup() - return err - }) - }) - } -} - func TestAddModuleStmt(t *testing.T) { for _, tt := range addModuleStmtTests { t.Run(tt.desc, func(t *testing.T) { @@ -491,18 +336,6 @@ func TestAddReplace(t *testing.T) { } } -func TestDropRequire(t *testing.T) { - for _, tt := range dropRequireTests { - t.Run(tt.desc, func(t *testing.T) { - testEdit(t, tt.in, tt.out, func(f *File) error { - err := f.DropRequire(tt.path) - f.Syntax.Cleanup() - return err - }) - }) - } -} - func TestDropReplace(t *testing.T) { for _, tt := range dropReplaceTests { t.Run(tt.desc, func(t *testing.T) { From 946f9e381f2f1f1f0d3a18f84bbbe13eb089f354 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Wed, 6 Nov 2024 04:44:38 +0100 Subject: [PATCH 02/51] chore: finish remove require (+ tmp move utils to load package but should be reverted) Signed-off-by: Norman Meier --- contribs/gnogenesis/go.mod | 1 - contribs/gnogenesis/go.sum | 2 - .../pkg/integration/testing_integration.go | 9 - gnovm/cmd/gno/fmt.go | 5 +- gnovm/cmd/gno/lint.go | 3 +- gnovm/cmd/gno/mod.go | 11 - gnovm/cmd/gno/run.go | 3 +- gnovm/cmd/gno/test.go | 3 +- gnovm/cmd/gno/transpile.go | 3 +- gnovm/cmd/gno/util.go | 216 ------------- gnovm/cmd/gno/util_test.go | 287 ----------------- gnovm/pkg/gnomod/file.go | 8 +- gnovm/pkg/gnomod/gnomod.go | 73 ----- gnovm/pkg/gnomod/parse.go | 2 +- gnovm/pkg/gnomod/preprocess.go | 31 -- gnovm/pkg/gnomod/preprocess_test.go | 127 -------- gnovm/pkg/gnomod/read.go | 42 --- gnovm/pkg/load/load.go | 223 +++++++++++++ gnovm/pkg/load/match_test.go | 297 ++++++++++++++++++ misc/loop/go.mod | 1 - 20 files changed, 536 insertions(+), 811 deletions(-) create mode 100644 gnovm/pkg/load/load.go create mode 100644 gnovm/pkg/load/match_test.go diff --git a/contribs/gnogenesis/go.mod b/contribs/gnogenesis/go.mod index 393fed0725d..b777cc6e5eb 100644 --- a/contribs/gnogenesis/go.mod +++ b/contribs/gnogenesis/go.mod @@ -53,7 +53,6 @@ require ( golang.org/x/sys v0.24.0 // indirect golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect - golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/contribs/gnogenesis/go.sum b/contribs/gnogenesis/go.sum index f3161e47bad..3c6127ac216 100644 --- a/contribs/gnogenesis/go.sum +++ b/contribs/gnogenesis/go.sum @@ -195,8 +195,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 56b298e4541..9d530d6bc9f 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -742,9 +742,6 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { // Override package info with mod infos currentPkg.Name = gm.Module.Mod.Path currentPkg.Draft = gm.Draft - for _, req := range gm.Require { - currentPkg.Requires = append(currentPkg.Requires, req.Mod.Path) - } } if currentPkg.Draft { @@ -755,12 +752,6 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { continue } pl.add(currentPkg) - - // Add requirements to the queue - for _, pkgPath := range currentPkg.Requires { - fullPath := filepath.Join(modroot, pkgPath) - queue = append(queue, gnomod.Pkg{Dir: fullPath}) - } } return nil diff --git a/gnovm/cmd/gno/fmt.go b/gnovm/cmd/gno/fmt.go index de6c28c4df0..8e28039f341 100644 --- a/gnovm/cmd/gno/fmt.go +++ b/gnovm/cmd/gno/fmt.go @@ -16,6 +16,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnofmt" + "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/rogpeppe/go-internal/diff" ) @@ -94,12 +95,12 @@ func execFmt(cfg *fmtCfg, args []string, io commands.IO) error { return flag.ErrHelp } - paths, err := targetsFromPatterns(args) + paths, err := load.TargetsFromPatterns(args) if err != nil { return fmt.Errorf("unable to get targets paths from patterns: %w", err) } - files, err := gnoFilesFromArgs(paths) + files, err := load.GnoFilesFromArgs(paths) if err != nil { return fmt.Errorf("unable to gather gno files: %w", err) } diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index c6008117f13..87bc6e6f7c7 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -14,6 +14,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" osm "github.com/gnolang/gno/tm2/pkg/os" @@ -63,7 +64,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { rootDir = gnoenv.RootDir() } - pkgPaths, err := gnoPackagesFromArgsRecursively(args) + pkgPaths, err := load.GnoPackagesFromArgsRecursively(args) if err != nil { return fmt.Errorf("list packages from args: %w", err) } diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 625a67b323d..7edc3c8bc2c 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -179,17 +179,6 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { // fetch dependencies panic("not implemented") - gomod, err := gnomod.GnoToGoMod(*gnoMod) - if err != nil { - return fmt.Errorf("sanitize: %w", err) - } - - // write go.mod file - err = gomod.Write(filepath.Join(path, "go.mod")) - if err != nil { - return fmt.Errorf("write go.mod file: %w", err) - } - return nil } diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index f174c2b4cc5..59b5bc8b17a 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -12,6 +12,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/std" @@ -181,7 +182,7 @@ func listNonTestFiles(dir string) ([]string, error) { fn := make([]string, 0, len(fs)) for _, f := range fs { n := f.Name() - if isGnoFile(f) && + if load.IsGnoFile(f) && !strings.HasSuffix(n, "_test.gno") && !strings.HasSuffix(n, "_filetest.gno") { fn = append(fn, filepath.Join(dir, n)) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index d54b12f6a4f..229521c399c 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -22,6 +22,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/gnovm/tests" teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" "github.com/gnolang/gno/tm2/pkg/commands" @@ -171,7 +172,7 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { cfg.rootDir = gnoenv.RootDir() } - paths, err := targetsFromPatterns(args) + paths, err := load.TargetsFromPatterns(args) if err != nil { return fmt.Errorf("list targets from patterns: %w", err) } diff --git a/gnovm/cmd/gno/transpile.go b/gnovm/cmd/gno/transpile.go index 1e3081ca2b0..a74b096b3d2 100644 --- a/gnovm/cmd/gno/transpile.go +++ b/gnovm/cmd/gno/transpile.go @@ -18,6 +18,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/gnovm/pkg/transpiler" "github.com/gnolang/gno/tm2/pkg/commands" ) @@ -134,7 +135,7 @@ func execTranspile(cfg *transpileCfg, args []string, io commands.IO) error { } // transpile .gno packages and files. - paths, err := gnoFilesFromArgsRecursively(args) + paths, err := load.GnoFilesFromArgsRecursively(args) if err != nil { return fmt.Errorf("list paths: %w", err) } diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index 90aedd5d27a..899cbd03895 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -3,232 +3,16 @@ package main import ( "fmt" "io" - "io/fs" "os" "path/filepath" - "regexp" - "strings" "time" ) -func isGnoFile(f fs.DirEntry) bool { - name := f.Name() - return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".gno") && !f.IsDir() -} - func isFileExist(path string) bool { _, err := os.Stat(path) return err == nil } -func gnoFilesFromArgsRecursively(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - if isGnoFile(fs.FileInfoToDirEntry(info)) { - paths = append(paths, ensurePathPrefix(argPath)) - } - - continue - } - - // Gather package paths from the directory - err = walkDirForGnoFiles(argPath, func(path string) { - paths = append(paths, ensurePathPrefix(path)) - }) - if err != nil { - return nil, fmt.Errorf("unable to walk dir: %w", err) - } - } - - return paths, nil -} - -func gnoFilesFromArgs(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - if isGnoFile(fs.FileInfoToDirEntry(info)) { - paths = append(paths, ensurePathPrefix(argPath)) - } - continue - } - - files, err := os.ReadDir(argPath) - if err != nil { - return nil, err - } - for _, f := range files { - if isGnoFile(f) { - path := filepath.Join(argPath, f.Name()) - paths = append(paths, ensurePathPrefix(path)) - } - } - } - - return paths, nil -} - -func ensurePathPrefix(path string) string { - if filepath.IsAbs(path) { - return path - } - - // cannot use path.Join or filepath.Join, because we need - // to ensure that ./ is the prefix to pass to go build. - // if not absolute. - return "." + string(filepath.Separator) + path -} - -func walkDirForGnoFiles(root string, addPath func(path string)) error { - visited := make(map[string]struct{}) - - walkFn := func(currPath string, f fs.DirEntry, err error) error { - if err != nil { - return fmt.Errorf("%s: walk dir: %w", root, err) - } - - if f.IsDir() || !isGnoFile(f) { - return nil - } - - parentDir := filepath.Dir(currPath) - if _, found := visited[parentDir]; found { - return nil - } - - visited[parentDir] = struct{}{} - - addPath(parentDir) - - return nil - } - - return filepath.WalkDir(root, walkFn) -} - -func gnoPackagesFromArgsRecursively(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - paths = append(paths, ensurePathPrefix(argPath)) - - continue - } - - // Gather package paths from the directory - err = walkDirForGnoFiles(argPath, func(path string) { - paths = append(paths, ensurePathPrefix(path)) - }) - if err != nil { - return nil, fmt.Errorf("unable to walk dir: %w", err) - } - } - - return paths, nil -} - -// targetsFromPatterns returns a list of target paths that match the patterns. -// Each pattern can represent a file or a directory, and if the pattern -// includes "/...", the "..." is treated as a wildcard, matching any string. -// Intended to be used by gno commands such as `gno test`. -func targetsFromPatterns(patterns []string) ([]string, error) { - paths := []string{} - for _, p := range patterns { - var match func(string) bool - patternLookup := false - dirToSearch := p - - // Check if the pattern includes `/...` - if strings.Contains(p, "/...") { - index := strings.Index(p, "/...") - if index != -1 { - dirToSearch = p[:index] // Extract the directory path to search - } - match = matchPattern(strings.TrimPrefix(p, "./")) - patternLookup = true - } - - info, err := os.Stat(dirToSearch) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - // If the pattern is a file or a directory - // without `/...`, add it to the list. - if !info.IsDir() || !patternLookup { - paths = append(paths, p) - continue - } - - // the pattern is a dir containing `/...`, walk the dir recursively and - // look for directories containing at least one .gno file and match pattern. - visited := map[string]bool{} // used to run the builder only once per folder. - err = filepath.WalkDir(dirToSearch, func(curpath string, f fs.DirEntry, err error) error { - if err != nil { - return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) - } - // Skip directories and non ".gno" files. - if f.IsDir() || !isGnoFile(f) { - return nil - } - - parentDir := filepath.Dir(curpath) - if _, found := visited[parentDir]; found { - return nil - } - - visited[parentDir] = true - if match(parentDir) { - paths = append(paths, parentDir) - } - - return nil - }) - if err != nil { - return nil, err - } - } - return paths, nil -} - -// matchPattern(pattern)(name) reports whether -// name matches pattern. Pattern is a limited glob -// pattern in which '...' means 'any string' and there -// is no other special syntax. -// Simplified version of go source's matchPatternInternal -// (see $GOROOT/src/cmd/internal/pkgpattern) -func matchPattern(pattern string) func(name string) bool { - re := regexp.QuoteMeta(pattern) - re = strings.Replace(re, `\.\.\.`, `.*`, -1) - // Special case: foo/... matches foo too. - if strings.HasSuffix(re, `/.*`) { - re = re[:len(re)-len(`/.*`)] + `(/.*)?` - } - reg := regexp.MustCompile(`^` + re + `$`) - return func(name string) bool { - return reg.MatchString(name) - } -} - func fmtDuration(d time.Duration) string { return fmt.Sprintf("%.2fs", d.Seconds()) } diff --git a/gnovm/cmd/gno/util_test.go b/gnovm/cmd/gno/util_test.go index a92c924e272..68e4557fb12 100644 --- a/gnovm/cmd/gno/util_test.go +++ b/gnovm/cmd/gno/util_test.go @@ -9,293 +9,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestMatchPattern(t *testing.T) { - tests := []struct { - pattern string - names []string - expected []bool - }{ - { - pattern: "foo", - names: []string{"foo", "bar", "baz", "foo/bar"}, - expected: []bool{true, false, false, false}, - }, - { - pattern: "foo/...", - names: []string{"foo", "foo/bar", "foo/bar/baz", "bar", "baz"}, - expected: []bool{true, true, true, false, false}, - }, - { - pattern: "foo/bar/...", - names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, - expected: []bool{true, true, false, false, false}, - }, - { - pattern: "foo/.../baz", - names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, - expected: []bool{false, true, false, false, false}, - }, - { - pattern: "foo/.../baz/...", - names: []string{"foo/bar/baz", "foo/baz/bar", "foo/bar/baz/qux", "foo/baz/bar/qux"}, - expected: []bool{true, false, true, false}, - }, - { - pattern: "...", - names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, - expected: []bool{true, true, true, true, true}, - }, - { - pattern: ".../bar", - names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, - expected: []bool{false, false, false, true, false}, - }, - } - - for _, test := range tests { - t.Run(test.pattern, func(t *testing.T) { - matchFunc := matchPattern(test.pattern) - for i, name := range test.names { - res := matchFunc(name) - assert.Equal(t, test.expected[i], res, "Expected: %v, Got: %v", test.expected[i], res) - } - }) - } -} - -func TestTargetsFromPatterns(t *testing.T) { - tmpDir := t.TempDir() - createGnoPackages(t, tmpDir) - - for _, tc := range []struct { - desc string - in, expected []string - errorShouldContain string - }{ - { - desc: "valid1", - in: []string{ - tmpDir, - }, - expected: []string{ - tmpDir, - }, - }, - { - desc: "valid2", - in: []string{ - tmpDir + "/foo", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - }, - }, - { - desc: "valid_recursive1", - in: []string{ - tmpDir + "/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "baz"), - filepath.Join(tmpDir, "foo", "qux"), - filepath.Join(tmpDir, "bar", "quux"), - filepath.Join(tmpDir, "foo", "qux", "corge"), - }, - }, - { - desc: "valid_recursive2", - in: []string{ - tmpDir + "/foo/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "foo", "qux"), - filepath.Join(tmpDir, "foo", "qux", "corge"), - }, - }, - { - desc: "valid_recursive2", - in: []string{ - tmpDir + "/.../qux", - }, - expected: []string{ - filepath.Join(tmpDir, "foo", "qux"), - }, - }, - { - desc: "valid_recursive3", - in: []string{ - tmpDir + "/.../qux/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo", "qux"), - filepath.Join(tmpDir, "foo", "qux", "corge"), - }, - }, - { - desc: "multiple_input", - in: []string{ - tmpDir + "/foo", - tmpDir + "/bar", - tmpDir + "/baz", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "baz"), - }, - }, - { - desc: "mixed_input1", - in: []string{ - tmpDir + "/foo", - tmpDir + "/bar/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "bar", "quux"), - }, - }, - { - desc: "mixed_input2", - in: []string{ - tmpDir + "/foo", - tmpDir + "/bar/...", - tmpDir + "/baz/baz.gno", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "bar", "quux"), - filepath.Join(tmpDir, "baz", "baz.gno"), - }, - }, - { - desc: "not_exists1", - in: []string{ - tmpDir + "/notexists", // dir path - }, - errorShouldContain: "no such file or directory", - }, - { - desc: "not_exists2", - in: []string{ - tmpDir + "/foo/bar.gno", // file path - }, - errorShouldContain: "no such file or directory", - }, - { - desc: "not_exists3", // mixed - in: []string{ - tmpDir + "/foo", // exists - tmpDir + "/notexists", // not exists - }, - errorShouldContain: "no such file or directory", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - targets, err := targetsFromPatterns(tc.in) - if tc.errorShouldContain != "" { - assert.ErrorContains(t, err, tc.errorShouldContain) - return - } - assert.NoError(t, err) - require.Equal(t, len(tc.expected), len(targets)) - for _, tr := range targets { - assert.Contains(t, tc.expected, tr) - } - }) - } -} - -func createGnoPackages(t *testing.T, tmpDir string) { - t.Helper() - - type file struct { - name, data string - } - // Gno pkgs to create - pkgs := []struct { - dir string - files []file - }{ - // pkg 'foo', 'bar' and 'baz' - { - dir: filepath.Join(tmpDir, "foo"), - files: []file{ - { - name: "foo.gno", - data: `package foo`, - }, - }, - }, - { - dir: filepath.Join(tmpDir, "bar"), - files: []file{ - { - name: "bar.gno", - data: `package bar`, - }, - }, - }, - { - dir: filepath.Join(tmpDir, "baz"), - files: []file{ - { - name: "baz.gno", - data: `package baz`, - }, - }, - }, - - // pkg inside 'foo' pkg - { - dir: filepath.Join(tmpDir, "foo", "qux"), - files: []file{ - { - name: "qux.gno", - data: `package qux`, - }, - }, - }, - - // pkg inside 'bar' pkg - { - dir: filepath.Join(tmpDir, "bar", "quux"), - files: []file{ - { - name: "quux.gno", - data: `package quux`, - }, - }, - }, - - // pkg inside 'foo/qux' pkg - { - dir: filepath.Join(tmpDir, "foo", "qux", "corge"), - files: []file{ - { - name: "corge.gno", - data: `package corge`, - }, - }, - }, - } - - // Create pkgs - for _, p := range pkgs { - err := os.MkdirAll(p.dir, 0o700) - require.NoError(t, err) - for _, f := range p.files { - err = os.WriteFile(filepath.Join(p.dir, f.name), []byte(f.data), 0o644) - require.NoError(t, err) - } - } -} - func TestResolvePath(t *testing.T) { t.Parallel() diff --git a/gnovm/pkg/gnomod/file.go b/gnovm/pkg/gnomod/file.go index 71f01b6b071..5e313a9af5a 100644 --- a/gnovm/pkg/gnomod/file.go +++ b/gnovm/pkg/gnomod/file.go @@ -82,14 +82,14 @@ func (f *File) Validate() error { return nil } -// Resolve takes a Require directive from File and returns any adequate replacement +// Resolve takes a module version and returns any adequate replacement // following the Replace directives. -func (f *File) Resolve(r *modfile.Require) module.Version { - mod, replaced := isReplaced(r.Mod, f.Replace) +func (f *File) Resolve(m module.Version) module.Version { + mod, replaced := isReplaced(m, f.Replace) if replaced { return mod } - return r.Mod + return m } // writes file to the given absolute file path diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 29f85eb185f..c8e09ef520a 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -12,7 +12,6 @@ import ( "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/transpiler" "golang.org/x/mod/modfile" "golang.org/x/mod/module" ) @@ -84,78 +83,6 @@ func writePackage(remote, basePath, pkgPath string) (requirements []string, err return removeDuplicateStr(requirements), nil } -// GnoToGoMod make necessary modifications in the gno.mod -// and return go.mod file. -func GnoToGoMod(f File) (*File, error) { - // TODO(morgan): good candidate to move to pkg/transpiler. - - // gnoModPath := GetGnoModPath() - - if !gnolang.IsStdlib(f.Module.Mod.Path) { - f.AddModuleStmt(transpiler.TranspileImportPath(f.Module.Mod.Path)) - } - - /* - - // FIXME: not sure how to port this - - for i := range f.Require { - mod, replaced := isReplaced(f.Require[i].Mod, f.Replace) - if replaced { - if modfile.IsDirectoryPath(mod.Path) { - continue - } - } - path := f.Require[i].Mod.Path - if !gnolang.IsStdlib(path) { - // Add dependency with a modified import path - f.AddRequire(transpiler.TranspileImportPath(path), f.Require[i].Mod.Version) - } - f.AddReplace(path, f.Require[i].Mod.Version, filepath.Join(gnoModPath, path), "") - // Remove the old require since the new dependency was added above - f.DropRequire(path) - } - - */ - - // Remove replacements that are not replaced by directories. - // - // Explanation: - // By this stage every replacement should be replace by dir. - // If not replaced by dir, remove it. - // - // e.g: - // - // ``` - // require ( - // gno.land/p/demo/avl v1.2.3 - // ) - // - // replace ( - // gno.land/p/demo/avl v1.2.3 => gno.land/p/demo/avl v3.2.1 - // ) - // ``` - // - // In above case we will fetch `gno.land/p/demo/avl v3.2.1` and - // replace will look something like: - // - // ``` - // replace ( - // gno.land/p/demo/avl v1.2.3 => gno.land/p/demo/avl v3.2.1 - // gno.land/p/demo/avl v3.2.1 => /path/to/avl/version/v3.2.1 - // ) - // ``` - // - // Remove `gno.land/p/demo/avl v1.2.3 => gno.land/p/demo/avl v3.2.1`. - for _, r := range f.Replace { - if !modfile.IsDirectoryPath(r.New.Path) { - f.DropReplace(r.Old.Path, r.Old.Version) - } - } - - return &f, nil -} - func CreateGnoModFile(rootDir, modPath string) error { if !filepath.IsAbs(rootDir) { return fmt.Errorf("dir %q is not absolute", rootDir) diff --git a/gnovm/pkg/gnomod/parse.go b/gnovm/pkg/gnomod/parse.go index 7f656dc7840..b44a1f1a6c9 100644 --- a/gnovm/pkg/gnomod/parse.go +++ b/gnovm/pkg/gnomod/parse.go @@ -181,7 +181,7 @@ func (f *File) add(errs *modfile.ErrorList, block *modfile.LineBlock, line *modf f.Module.Mod = module.Version{Path: s} case "require": - errorf("require is not supported by gno") + // ignore requires as it's not supported by gno return case "replace": diff --git a/gnovm/pkg/gnomod/preprocess.go b/gnovm/pkg/gnomod/preprocess.go index b78c91e3678..df6910f769b 100644 --- a/gnovm/pkg/gnomod/preprocess.go +++ b/gnovm/pkg/gnomod/preprocess.go @@ -3,7 +3,6 @@ package gnomod import ( "golang.org/x/mod/modfile" "golang.org/x/mod/module" - "golang.org/x/mod/semver" ) func removeDups(syntax *modfile.FileSyntax, replace *[]*modfile.Replace) { @@ -13,36 +12,6 @@ func removeDups(syntax *modfile.FileSyntax, replace *[]*modfile.Replace) { } } -// removeRequireDups removes duplicate requirements. -// Requirements with higher version takes priority. -func removeRequireDups(require *[]*modfile.Require) map[*modfile.Line]bool { - purge := make(map[*modfile.Line]bool) - - keepRequire := make(map[string]string) - for _, r := range *require { - if v, ok := keepRequire[r.Mod.Path]; ok { - if semver.Compare(r.Mod.Version, v) == 1 { - keepRequire[r.Mod.Path] = r.Mod.Version - } - continue - } - keepRequire[r.Mod.Path] = r.Mod.Version - } - var req []*modfile.Require - added := make(map[string]bool) - for _, r := range *require { - if v, ok := keepRequire[r.Mod.Path]; ok && !added[r.Mod.Path] && v == r.Mod.Version { - req = append(req, r) - added[r.Mod.Path] = true - continue - } - purge[r.Syntax] = true - } - *require = req - - return purge -} - // removeReplaceDups removes duplicate replacements. // Later replacements take priority over earlier ones. func removeReplaceDups(replace *[]*modfile.Replace) map[*modfile.Line]bool { diff --git a/gnovm/pkg/gnomod/preprocess_test.go b/gnovm/pkg/gnomod/preprocess_test.go index 28f42d740e3..6e0a890763c 100644 --- a/gnovm/pkg/gnomod/preprocess_test.go +++ b/gnovm/pkg/gnomod/preprocess_test.go @@ -8,133 +8,6 @@ import ( "golang.org/x/mod/module" ) -func TestRemoveRequireDups(t *testing.T) { - for _, tc := range []struct { - desc string - in []*modfile.Require - expected []*modfile.Require - }{ - { - desc: "no_duplicate", - in: []*modfile.Require{ - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.0.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/z", - Version: "v1.1.0", - }, - }, - }, - expected: []*modfile.Require{ - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.0.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/z", - Version: "v1.1.0", - }, - }, - }, - }, - { - desc: "one_duplicate", - in: []*modfile.Require{ - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.0.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.0.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/z", - Version: "v1.1.0", - }, - }, - }, - expected: []*modfile.Require{ - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.0.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/z", - Version: "v1.1.0", - }, - }, - }, - }, - { - desc: "multiple_duplicate", - in: []*modfile.Require{ - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.0.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.0.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/z", - Version: "v1.1.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.2.0", - }, - }, - }, - expected: []*modfile.Require{ - { - Mod: module.Version{ - Path: "x.y/z", - Version: "v1.1.0", - }, - }, - { - Mod: module.Version{ - Path: "x.y/w", - Version: "v1.2.0", - }, - }, - }, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - in := tc.in - removeRequireDups(&in) - - assert.Equal(t, tc.expected, in) - }) - } -} - func TestRemoveReplaceDups(t *testing.T) { for _, tc := range []struct { desc string diff --git a/gnovm/pkg/gnomod/read.go b/gnovm/pkg/gnomod/read.go index d6d771429d3..23a98dc6ae9 100644 --- a/gnovm/pkg/gnomod/read.go +++ b/gnovm/pkg/gnomod/read.go @@ -862,48 +862,6 @@ func updateLine(line *modfile.Line, tokens ...string) { line.Token = tokens } -// setIndirect sets line to have (or not have) a "// indirect" comment. -func setIndirect(r *modfile.Require, indirect bool) { - r.Indirect = indirect - line := r.Syntax - if isIndirect(line) == indirect { - return - } - if indirect { - // Adding comment. - if len(line.Suffix) == 0 { - // New comment. - line.Suffix = []modfile.Comment{{Token: "// indirect", Suffix: true}} - return - } - - com := &line.Suffix[0] - text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash))) - if text == "" { - // Empty comment. - com.Token = "// indirect" - return - } - - // Insert at beginning of existing comment. - com.Token = "// indirect; " + text - return - } - - // Removing comment. - f := strings.TrimSpace(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) - if f == "indirect" { - // Remove whole comment. - line.Suffix = nil - return - } - - // Remove comment prefix. - com := &line.Suffix[0] - i := strings.Index(com.Token, "indirect;") - com.Token = "//" + com.Token[i+len("indirect;"):] -} - // isIndirect reports whether line has a "// indirect" comment, // meaning it is in go.mod only for its effect on indirect dependencies, // so that it can be dropped entirely once the effective version of the diff --git a/gnovm/pkg/load/load.go b/gnovm/pkg/load/load.go new file mode 100644 index 00000000000..6fd6150d4a1 --- /dev/null +++ b/gnovm/pkg/load/load.go @@ -0,0 +1,223 @@ +package load + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + "regexp" + "strings" +) + +func IsGnoFile(f fs.DirEntry) bool { + name := f.Name() + return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".gno") && !f.IsDir() +} + +func GnoFilesFromArgsRecursively(args []string) ([]string, error) { + var paths []string + + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + if IsGnoFile(fs.FileInfoToDirEntry(info)) { + paths = append(paths, ensurePathPrefix(argPath)) + } + + continue + } + + // Gather package paths from the directory + err = walkDirForGnoFiles(argPath, func(path string) { + paths = append(paths, ensurePathPrefix(path)) + }) + if err != nil { + return nil, fmt.Errorf("unable to walk dir: %w", err) + } + } + + return paths, nil +} + +func GnoFilesFromArgs(args []string) ([]string, error) { + var paths []string + + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + if IsGnoFile(fs.FileInfoToDirEntry(info)) { + paths = append(paths, ensurePathPrefix(argPath)) + } + continue + } + + files, err := os.ReadDir(argPath) + if err != nil { + return nil, err + } + for _, f := range files { + if IsGnoFile(f) { + path := filepath.Join(argPath, f.Name()) + paths = append(paths, ensurePathPrefix(path)) + } + } + } + + return paths, nil +} + +func ensurePathPrefix(path string) string { + if filepath.IsAbs(path) { + return path + } + + // cannot use path.Join or filepath.Join, because we need + // to ensure that ./ is the prefix to pass to go build. + // if not absolute. + return "." + string(filepath.Separator) + path +} + +func walkDirForGnoFiles(root string, addPath func(path string)) error { + visited := make(map[string]struct{}) + + walkFn := func(currPath string, f fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("%s: walk dir: %w", root, err) + } + + if f.IsDir() || !IsGnoFile(f) { + return nil + } + + parentDir := filepath.Dir(currPath) + if _, found := visited[parentDir]; found { + return nil + } + + visited[parentDir] = struct{}{} + + addPath(parentDir) + + return nil + } + + return filepath.WalkDir(root, walkFn) +} + +func GnoPackagesFromArgsRecursively(args []string) ([]string, error) { + var paths []string + + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + paths = append(paths, ensurePathPrefix(argPath)) + + continue + } + + // Gather package paths from the directory + err = walkDirForGnoFiles(argPath, func(path string) { + paths = append(paths, ensurePathPrefix(path)) + }) + if err != nil { + return nil, fmt.Errorf("unable to walk dir: %w", err) + } + } + + return paths, nil +} + +// targetsFromPatterns returns a list of target paths that match the patterns. +// Each pattern can represent a file or a directory, and if the pattern +// includes "/...", the "..." is treated as a wildcard, matching any string. +// Intended to be used by gno commands such as `gno test`. +func TargetsFromPatterns(patterns []string) ([]string, error) { + paths := []string{} + for _, p := range patterns { + var match func(string) bool + patternLookup := false + dirToSearch := p + + // Check if the pattern includes `/...` + if strings.Contains(p, "/...") { + index := strings.Index(p, "/...") + if index != -1 { + dirToSearch = p[:index] // Extract the directory path to search + } + match = matchPattern(strings.TrimPrefix(p, "./")) + patternLookup = true + } + + info, err := os.Stat(dirToSearch) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + // If the pattern is a file or a directory + // without `/...`, add it to the list. + if !info.IsDir() || !patternLookup { + paths = append(paths, p) + continue + } + + // the pattern is a dir containing `/...`, walk the dir recursively and + // look for directories containing at least one .gno file and match pattern. + visited := map[string]bool{} // used to run the builder only once per folder. + err = filepath.WalkDir(dirToSearch, func(curpath string, f fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) + } + // Skip directories and non ".gno" files. + if f.IsDir() || !IsGnoFile(f) { + return nil + } + + parentDir := filepath.Dir(curpath) + if _, found := visited[parentDir]; found { + return nil + } + + visited[parentDir] = true + if match(parentDir) { + paths = append(paths, parentDir) + } + + return nil + }) + if err != nil { + return nil, err + } + } + return paths, nil +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Simplified version of go source's matchPatternInternal +// (see $GOROOT/src/cmd/internal/pkgpattern) +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return func(name string) bool { + return reg.MatchString(name) + } +} diff --git a/gnovm/pkg/load/match_test.go b/gnovm/pkg/load/match_test.go new file mode 100644 index 00000000000..5845e3a5af1 --- /dev/null +++ b/gnovm/pkg/load/match_test.go @@ -0,0 +1,297 @@ +package load + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMatchPattern(t *testing.T) { + tests := []struct { + pattern string + names []string + expected []bool + }{ + { + pattern: "foo", + names: []string{"foo", "bar", "baz", "foo/bar"}, + expected: []bool{true, false, false, false}, + }, + { + pattern: "foo/...", + names: []string{"foo", "foo/bar", "foo/bar/baz", "bar", "baz"}, + expected: []bool{true, true, true, false, false}, + }, + { + pattern: "foo/bar/...", + names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, + expected: []bool{true, true, false, false, false}, + }, + { + pattern: "foo/.../baz", + names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, + expected: []bool{false, true, false, false, false}, + }, + { + pattern: "foo/.../baz/...", + names: []string{"foo/bar/baz", "foo/baz/bar", "foo/bar/baz/qux", "foo/baz/bar/qux"}, + expected: []bool{true, false, true, false}, + }, + { + pattern: "...", + names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, + expected: []bool{true, true, true, true, true}, + }, + { + pattern: ".../bar", + names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, + expected: []bool{false, false, false, true, false}, + }, + } + + for _, test := range tests { + t.Run(test.pattern, func(t *testing.T) { + matchFunc := matchPattern(test.pattern) + for i, name := range test.names { + res := matchFunc(name) + assert.Equal(t, test.expected[i], res, "Expected: %v, Got: %v", test.expected[i], res) + } + }) + } +} + +func TestTargetsFromPatterns(t *testing.T) { + tmpDir := t.TempDir() + createGnoPackages(t, tmpDir) + + for _, tc := range []struct { + desc string + in, expected []string + errorShouldContain string + }{ + { + desc: "valid1", + in: []string{ + tmpDir, + }, + expected: []string{ + tmpDir, + }, + }, + { + desc: "valid2", + in: []string{ + tmpDir + "/foo", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + }, + }, + { + desc: "valid_recursive1", + in: []string{ + tmpDir + "/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "baz"), + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "bar", "quux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "valid_recursive2", + in: []string{ + tmpDir + "/foo/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "valid_recursive2", + in: []string{ + tmpDir + "/.../qux", + }, + expected: []string{ + filepath.Join(tmpDir, "foo", "qux"), + }, + }, + { + desc: "valid_recursive3", + in: []string{ + tmpDir + "/.../qux/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "multiple_input", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar", + tmpDir + "/baz", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "baz"), + }, + }, + { + desc: "mixed_input1", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "bar", "quux"), + }, + }, + { + desc: "mixed_input2", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar/...", + tmpDir + "/baz/baz.gno", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "bar", "quux"), + filepath.Join(tmpDir, "baz", "baz.gno"), + }, + }, + { + desc: "not_exists1", + in: []string{ + tmpDir + "/notexists", // dir path + }, + errorShouldContain: "no such file or directory", + }, + { + desc: "not_exists2", + in: []string{ + tmpDir + "/foo/bar.gno", // file path + }, + errorShouldContain: "no such file or directory", + }, + { + desc: "not_exists3", // mixed + in: []string{ + tmpDir + "/foo", // exists + tmpDir + "/notexists", // not exists + }, + errorShouldContain: "no such file or directory", + }, + } { + t.Run(tc.desc, func(t *testing.T) { + targets, err := TargetsFromPatterns(tc.in) + if tc.errorShouldContain != "" { + assert.ErrorContains(t, err, tc.errorShouldContain) + return + } + assert.NoError(t, err) + require.Equal(t, len(tc.expected), len(targets)) + for _, tr := range targets { + assert.Contains(t, tc.expected, tr) + } + }) + } +} + +func createGnoPackages(t *testing.T, tmpDir string) { + t.Helper() + + type file struct { + name, data string + } + // Gno pkgs to create + pkgs := []struct { + dir string + files []file + }{ + // pkg 'foo', 'bar' and 'baz' + { + dir: filepath.Join(tmpDir, "foo"), + files: []file{ + { + name: "foo.gno", + data: `package foo`, + }, + }, + }, + { + dir: filepath.Join(tmpDir, "bar"), + files: []file{ + { + name: "bar.gno", + data: `package bar`, + }, + }, + }, + { + dir: filepath.Join(tmpDir, "baz"), + files: []file{ + { + name: "baz.gno", + data: `package baz`, + }, + }, + }, + + // pkg inside 'foo' pkg + { + dir: filepath.Join(tmpDir, "foo", "qux"), + files: []file{ + { + name: "qux.gno", + data: `package qux`, + }, + }, + }, + + // pkg inside 'bar' pkg + { + dir: filepath.Join(tmpDir, "bar", "quux"), + files: []file{ + { + name: "quux.gno", + data: `package quux`, + }, + }, + }, + + // pkg inside 'foo/qux' pkg + { + dir: filepath.Join(tmpDir, "foo", "qux", "corge"), + files: []file{ + { + name: "corge.gno", + data: `package corge`, + }, + }, + }, + } + + // Create pkgs + for _, p := range pkgs { + err := os.MkdirAll(p.dir, 0o700) + require.NoError(t, err) + for _, f := range p.files { + err = os.WriteFile(filepath.Join(p.dir, f.name), []byte(f.data), 0o644) + require.NoError(t, err) + } + } +} diff --git a/misc/loop/go.mod b/misc/loop/go.mod index 9fc5bfb2d57..6d09ca3da18 100644 --- a/misc/loop/go.mod +++ b/misc/loop/go.mod @@ -75,7 +75,6 @@ require ( golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect From 773c548bba9bdbdc5cd3f5b77d068719e17fa36d Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Wed, 6 Nov 2024 05:27:12 +0100 Subject: [PATCH 03/51] feat: mod download without require Signed-off-by: Norman Meier --- gnovm/cmd/gno/mod.go | 26 ++++++++++++++++++++++++-- gnovm/pkg/gnomodfetch/gnomodfetch.go | 14 ++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 gnovm/pkg/gnomodfetch/gnomodfetch.go diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 7edc3c8bc2c..f5a5f6fee77 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -11,7 +11,10 @@ import ( "sort" "strings" + "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/gnomodfetch" + "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "go.uber.org/multierr" @@ -176,8 +179,27 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { return fmt.Errorf("validate: %w", err) } - // fetch dependencies - panic("not implemented") + gnoFiles, err := load.GnoFilesFromArgsRecursively([]string{path}) + if err != nil { + return fmt.Errorf("get gno files: %w", err) + } + + modsDest := filepath.Join(gnoenv.HomeDir(), "pkg", "mod") + + for _, f := range gnoFiles { + fset := token.NewFileSet() + parsed, err := parser.ParseFile(fset, f, nil, parser.ImportsOnly) + if err != nil { + continue + } + + for _, imp := range parsed.Imports { + pkgPath := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, "\""), "\"") + if err := gnomodfetch.Fetch(pkgPath, filepath.Join(modsDest, pkgPath)); err != nil { + io.ErrPrintfln("fetch %q: %w", pkgPath, err) + } + } + } return nil } diff --git a/gnovm/pkg/gnomodfetch/gnomodfetch.go b/gnovm/pkg/gnomodfetch/gnomodfetch.go new file mode 100644 index 00000000000..b63b75fed83 --- /dev/null +++ b/gnovm/pkg/gnomodfetch/gnomodfetch.go @@ -0,0 +1,14 @@ +package gnomodfetch + +import "fmt" + +func Fetch(pkgPath string, dst string) error { + if FetchFn != nil { + return FetchFn(pkgPath, dst) + } + + return fmt.Errorf("not implemented") +} + +// FetchFn allows to override default Fetch behavior, this is mostly useful for testing +var FetchFn func(pkgPath string, dst string) error From ccf8bb89cfa8267103cab822a4ac21cad20a5962 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Wed, 6 Nov 2024 23:14:16 +0100 Subject: [PATCH 04/51] feat: module download without require Signed-off-by: Norman Meier --- gnovm/cmd/gno/main_test.go | 117 +++++++++++++- gnovm/cmd/gno/mod.go | 21 ++- gnovm/cmd/gno/mod_test.go | 68 ++++---- gnovm/cmd/gno/transpile.go | 2 +- gnovm/pkg/gnomod/parse_test.go | 7 +- gnovm/pkg/gnomod/read.go | 6 - gnovm/pkg/gnomodfetch/gnomodfetch.go | 149 +++++++++++++++++- gnovm/pkg/load/load.go | 44 +++++- .../integ/invalid_module_version1/gno.mod | 5 - .../integ/invalid_module_version2/gno.mod | 5 - gnovm/tests/integ/replace_with_dir/gno.mod | 4 - .../integ/replace_with_invalid_module/gno.mod | 6 +- .../replace_with_invalid_module/main.gno | 7 + gnovm/tests/integ/replace_with_module/gno.mod | 6 +- .../tests/integ/replace_with_module/main.gno | 7 + .../integ/require_invalid_module/gno.mod | 6 +- .../integ/require_invalid_module/main.gno | 7 + .../tests/integ/require_remote_module/gno.mod | 4 - gnovm/tests/integ/require_std_lib/gno.mod | 1 + gnovm/tests/integ/require_std_lib/main.gno | 7 + gnovm/tests/integ/valid2/gno.mod | 2 - 21 files changed, 389 insertions(+), 92 deletions(-) delete mode 100644 gnovm/tests/integ/invalid_module_version1/gno.mod delete mode 100644 gnovm/tests/integ/invalid_module_version2/gno.mod create mode 100644 gnovm/tests/integ/replace_with_invalid_module/main.gno create mode 100644 gnovm/tests/integ/replace_with_module/main.gno create mode 100644 gnovm/tests/integ/require_invalid_module/main.gno create mode 100644 gnovm/tests/integ/require_std_lib/gno.mod create mode 100644 gnovm/tests/integ/require_std_lib/main.gno diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 069c42db379..45c82f8c5ff 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -3,15 +3,22 @@ package main import ( "bytes" "context" + "encoding/json" "fmt" "os" "path/filepath" "strings" "testing" - "github.com/stretchr/testify/require" - + "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnomodfetch" + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" + types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/stretchr/testify/require" ) func TestMain_Gno(t *testing.T) { @@ -26,6 +33,7 @@ type testMainCase struct { args []string testDir string simulateExternalRepo bool + tmpGnoHome bool // for the following FooContain+FooBe expected couples, if both are empty, // then the test suite will require that the "got" is not empty. @@ -42,6 +50,68 @@ type testMainCase struct { func testMainCaseRun(t *testing.T, tc []testMainCase) { t.Helper() + { + gnomodfetch.Client = client.NewRPCClient(&mockClient{ + sendRequestFn: func(ctx context.Context, r types.RPCRequest) (*types.RPCResponse, error) { + params := struct { + Path string `json:"path"` + Data []byte `json:"data"` + }{} + if err := json.Unmarshal(r.Params, ¶ms); err != nil { + return nil, fmt.Errorf("failed to unmarshal params: %w", err) + } + path := params.Path + if path != "vm/qfile" { + return nil, fmt.Errorf("unexpected call to %q", path) + } + data := string(params.Data) + + examplesDir := filepath.Join(gnoenv.RootDir(), "examples") + target := filepath.Join(examplesDir, data) + + res := ctypes.ResultABCIQuery{} + + finfo, err := os.Stat(target) + if os.IsNotExist(err) { + res.Response = sdk.ABCIResponseQueryFromError(fmt.Errorf("package %q is not available", data)) + return &types.RPCResponse{ + Result: amino.MustMarshalJSON(res), + }, nil + } else if err != nil { + return nil, fmt.Errorf("failed to stat %q: %w", data, err) + } + + if finfo.IsDir() { + entries, err := os.ReadDir(target) + if err != nil { + return nil, fmt.Errorf("failed to get package %q: %w", data, err) + } + files := []string{} + for _, entry := range entries { + if !entry.IsDir() { + files = append(files, entry.Name()) + } + } + res.Response.Data = []byte(strings.Join(files, "\n")) + } else { + content, err := os.ReadFile(target) + if err != nil { + return nil, fmt.Errorf("failed to get file %q: %w", data, err) + } + res.Response.Data = content + } + + return &types.RPCResponse{ + Result: amino.MustMarshalJSON(res), + }, nil + + }, + }) + t.Cleanup(func() { + gnomodfetch.Client = nil + }) + } + workingDir, err := os.Getwd() require.Nil(t, err) @@ -58,6 +128,13 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { mockOut := bytes.NewBufferString("") mockErr := bytes.NewBufferString("") + if test.tmpGnoHome { + gnohome, err := os.MkdirTemp(os.TempDir(), "gnotesthome") + require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(gnohome) }) + t.Setenv("GNOHOME", gnohome) + } + checkOutputs := func(t *testing.T) { t.Helper() @@ -142,3 +219,39 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { }) } } + +type ( + sendRequestDelegate func(context.Context, types.RPCRequest) (*types.RPCResponse, error) + sendBatchDelegate func(context.Context, types.RPCRequests) (types.RPCResponses, error) + closeDelegate func() error +) + +type mockClient struct { + sendRequestFn sendRequestDelegate + sendBatchFn sendBatchDelegate + closeFn closeDelegate +} + +func (m *mockClient) SendRequest(ctx context.Context, request types.RPCRequest) (*types.RPCResponse, error) { + if m.sendRequestFn != nil { + return m.sendRequestFn(ctx, request) + } + + return nil, nil +} + +func (m *mockClient) SendBatch(ctx context.Context, requests types.RPCRequests) (types.RPCResponses, error) { + if m.sendBatchFn != nil { + return m.sendBatchFn(ctx, requests) + } + + return nil, nil +} + +func (m *mockClient) Close() error { + if m.closeFn != nil { + return m.closeFn() + } + + return nil +} diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index f5a5f6fee77..50a793ac66f 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -11,13 +11,13 @@ import ( "sort" "strings" - "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/gnomodfetch" "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "go.uber.org/multierr" + "golang.org/x/mod/module" ) func newModCmd(io commands.IO) *commands.Command { @@ -184,8 +184,6 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { return fmt.Errorf("get gno files: %w", err) } - modsDest := filepath.Join(gnoenv.HomeDir(), "pkg", "mod") - for _, f := range gnoFiles { fset := token.NewFileSet() parsed, err := parser.ParseFile(fset, f, nil, parser.ImportsOnly) @@ -194,9 +192,20 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { } for _, imp := range parsed.Imports { - pkgPath := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, "\""), "\"") - if err := gnomodfetch.Fetch(pkgPath, filepath.Join(modsDest, pkgPath)); err != nil { - io.ErrPrintfln("fetch %q: %w", pkgPath, err) + importPkgPath := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, "\""), "\"") + + if !strings.ContainsRune(importPkgPath, '.') { + // std lib, ignore + continue + } + + resolved := gnoMod.Resolve(module.Version{Path: importPkgPath}) + resolvedPkgPath := resolved.Path + + // TODO: don't fetch local + + if err := gnomodfetch.FetchPackagesRecursively(io, resolvedPkgPath, gnoMod); err != nil { + return fmt.Errorf("fetch: %w", err) } } } diff --git a/gnovm/cmd/gno/mod_test.go b/gnovm/cmd/gno/mod_test.go index d35ab311b6c..e1152ee0876 100644 --- a/gnovm/cmd/gno/mod_test.go +++ b/gnovm/cmd/gno/mod_test.go @@ -21,63 +21,70 @@ func TestModApp(t *testing.T) { args: []string{"mod", "download"}, testDir: "../../tests/integ/empty_dir", simulateExternalRepo: true, + tmpGnoHome: true, errShouldBe: "gno.mod not found", }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/empty_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, errShouldBe: "validate: requires module", }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/invalid_module_name", simulateExternalRepo: true, + tmpGnoHome: true, errShouldContain: "usage: module module/path", }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/minimalist_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/require_remote_module", simulateExternalRepo: true, + tmpGnoHome: true, + stderrShouldContain: "gno: downloading gno.land/p/demo/avl", }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/require_invalid_module", simulateExternalRepo: true, - errShouldContain: "fetch: writepackage: querychain", + tmpGnoHome: true, + stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", + errShouldContain: "fetch: failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", }, { args: []string{"mod", "download"}, - testDir: "../../tests/integ/invalid_module_version1", + testDir: "../../tests/integ/require_std_lib", simulateExternalRepo: true, - errShouldContain: "usage: require module/path v1.2.3", - }, - { - args: []string{"mod", "download"}, - testDir: "../../tests/integ/invalid_module_version2", - simulateExternalRepo: true, - errShouldContain: "invalid: must be of the form v1.2.3", + tmpGnoHome: true, }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/replace_with_dir", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/replace_with_module", simulateExternalRepo: true, + tmpGnoHome: true, + stderrShouldContain: "gno: downloading gno.land/p/demo/users", }, { args: []string{"mod", "download"}, testDir: "../../tests/integ/replace_with_invalid_module", simulateExternalRepo: true, - errShouldContain: "fetch: writepackage: querychain", + tmpGnoHome: true, + stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", + errShouldContain: "fetch: failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", }, // test `gno mod init` with no module name @@ -85,35 +92,41 @@ func TestModApp(t *testing.T) { args: []string{"mod", "init"}, testDir: "../../tests/integ/valid1", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "init"}, testDir: "../../tests/integ/empty_dir", simulateExternalRepo: true, + tmpGnoHome: true, errShouldBe: "create gno.mod file: cannot determine package name", }, { args: []string{"mod", "init"}, testDir: "../../tests/integ/empty_gno1", simulateExternalRepo: true, + tmpGnoHome: true, recoverShouldContain: "expected 'package', found 'EOF'", }, { args: []string{"mod", "init"}, testDir: "../../tests/integ/empty_gno2", simulateExternalRepo: true, + tmpGnoHome: true, recoverShouldContain: "expected 'package', found 'EOF'", }, { args: []string{"mod", "init"}, testDir: "../../tests/integ/empty_gno3", simulateExternalRepo: true, + tmpGnoHome: true, recoverShouldContain: "expected 'package', found 'EOF'", }, { args: []string{"mod", "init"}, testDir: "../../tests/integ/empty_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, errShouldBe: "create gno.mod file: gno.mod file already exists", }, @@ -122,26 +135,31 @@ func TestModApp(t *testing.T) { args: []string{"mod", "init", "gno.land/p/demo/foo"}, testDir: "../../tests/integ/empty_dir", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "init", "gno.land/p/demo/foo"}, testDir: "../../tests/integ/empty_gno1", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "init", "gno.land/p/demo/foo"}, testDir: "../../tests/integ/empty_gno2", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "init", "gno.land/p/demo/foo"}, testDir: "../../tests/integ/empty_gno3", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "init", "gno.land/p/demo/foo"}, testDir: "../../tests/integ/empty_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, errShouldBe: "create gno.mod file: gno.mod file already exists", }, @@ -150,40 +168,33 @@ func TestModApp(t *testing.T) { args: []string{"mod", "tidy", "arg1"}, testDir: "../../tests/integ/minimalist_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, errShouldContain: "flag: help requested", }, { args: []string{"mod", "tidy"}, testDir: "../../tests/integ/empty_dir", simulateExternalRepo: true, + tmpGnoHome: true, errShouldContain: "could not read gno.mod file", }, - { - args: []string{"mod", "tidy"}, - testDir: "../../tests/integ/invalid_module_version1", - simulateExternalRepo: true, - errShouldContain: "error parsing gno.mod file at", - }, { args: []string{"mod", "tidy"}, testDir: "../../tests/integ/minimalist_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "tidy"}, testDir: "../../tests/integ/require_remote_module", simulateExternalRepo: true, + tmpGnoHome: true, }, { args: []string{"mod", "tidy"}, testDir: "../../tests/integ/valid2", simulateExternalRepo: true, - }, - { - args: []string{"mod", "tidy"}, - testDir: "../../tests/integ/invalid_gno_file", - simulateExternalRepo: true, - errShouldContain: "expected 'package', found packag", + tmpGnoHome: true, }, // test `gno mod why` @@ -191,30 +202,28 @@ func TestModApp(t *testing.T) { args: []string{"mod", "why"}, testDir: "../../tests/integ/minimalist_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, errShouldContain: "flag: help requested", }, { args: []string{"mod", "why", "std"}, testDir: "../../tests/integ/empty_dir", simulateExternalRepo: true, + tmpGnoHome: true, errShouldContain: "could not read gno.mod file", }, - { - args: []string{"mod", "why", "std"}, - testDir: "../../tests/integ/invalid_module_version1", - simulateExternalRepo: true, - errShouldContain: "error parsing gno.mod file at", - }, { args: []string{"mod", "why", "std"}, testDir: "../../tests/integ/invalid_gno_file", simulateExternalRepo: true, + tmpGnoHome: true, errShouldContain: "expected 'package', found packag", }, { args: []string{"mod", "why", "std"}, testDir: "../../tests/integ/minimalist_gnomod", simulateExternalRepo: true, + tmpGnoHome: true, stdoutShouldBe: `# std (module minim does not need package std) `, @@ -223,6 +232,7 @@ func TestModApp(t *testing.T) { args: []string{"mod", "why", "std"}, testDir: "../../tests/integ/require_remote_module", simulateExternalRepo: true, + tmpGnoHome: true, stdoutShouldBe: `# std (module gno.land/tests/importavl does not need package std) `, @@ -231,6 +241,7 @@ func TestModApp(t *testing.T) { args: []string{"mod", "why", "std", "gno.land/p/demo/avl"}, testDir: "../../tests/integ/valid2", simulateExternalRepo: true, + tmpGnoHome: true, stdoutShouldBe: `# std (module gno.land/p/integ/valid does not need package std) @@ -239,6 +250,7 @@ valid.gno `, }, } + testMainCaseRun(t, tc) } diff --git a/gnovm/cmd/gno/transpile.go b/gnovm/cmd/gno/transpile.go index a74b096b3d2..4706bae8f14 100644 --- a/gnovm/cmd/gno/transpile.go +++ b/gnovm/cmd/gno/transpile.go @@ -135,7 +135,7 @@ func execTranspile(cfg *transpileCfg, args []string, io commands.IO) error { } // transpile .gno packages and files. - paths, err := load.GnoFilesFromArgsRecursively(args) + paths, err := load.GnoDirsFromArgsRecursively(args) if err != nil { return fmt.Errorf("list paths: %w", err) } diff --git a/gnovm/pkg/gnomod/parse_test.go b/gnovm/pkg/gnomod/parse_test.go index f266a1d065a..4dd89159d13 100644 --- a/gnovm/pkg/gnomod/parse_test.go +++ b/gnovm/pkg/gnomod/parse_test.go @@ -200,10 +200,9 @@ func TestParseGnoMod(t *testing.T) { errShouldContain: "error parsing gno.mod file at", }, { - desc: "error validating gno.mod", - modData: `require bar v0.0.0`, - modPath: filepath.Join(pkgDir, "gno.mod"), - errShouldContain: "require is not supported by gno", + desc: "error validating gno.mod", + modData: `require bar v0.0.0`, + modPath: filepath.Join(pkgDir, "gno.mod"), }, } { t.Run(tc.desc, func(t *testing.T) { diff --git a/gnovm/pkg/gnomod/read.go b/gnovm/pkg/gnomod/read.go index 23a98dc6ae9..7bfbca69d18 100644 --- a/gnovm/pkg/gnomod/read.go +++ b/gnovm/pkg/gnomod/read.go @@ -770,12 +770,6 @@ func parseReplace(filename string, line *modfile.Line, verb string, args []strin } nv := "" if len(args) == arrow+2 { - if !modfile.IsDirectoryPath(ns) { - if strings.Contains(ns, "@") { - return nil, errorf("replacement module must match format 'path version', not 'path@version'") - } - return nil, errorf("replacement module without version must be directory path (rooted or starting with . or ..)") - } if filepath.Separator == '/' && strings.Contains(ns, `\`) { return nil, errorf("replacement directory appears to be Windows path (on a non-windows system)") } diff --git a/gnovm/pkg/gnomodfetch/gnomodfetch.go b/gnovm/pkg/gnomodfetch/gnomodfetch.go index b63b75fed83..1dd12dc23f4 100644 --- a/gnovm/pkg/gnomodfetch/gnomodfetch.go +++ b/gnovm/pkg/gnomodfetch/gnomodfetch.go @@ -1,14 +1,149 @@ package gnomodfetch -import "fmt" +import ( + "fmt" + "go/parser" + "go/token" + "net/url" + "os" + "path" + "path/filepath" + "strings" -func Fetch(pkgPath string, dst string) error { - if FetchFn != nil { - return FetchFn(pkgPath, dst) + "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/load" + tm2client "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/errors" + "golang.org/x/mod/module" +) + +func FetchPackage(io commands.IO, pkgPath string, dst string) error { + modFilePath := filepath.Join(dst, "gno.mod") + + if _, err := os.Stat(modFilePath); err == nil { + // modfile exists in modcache, do nothing + return nil + } else if !os.IsNotExist(err) { + return fmt.Errorf("failed to stat downloaded module %q at %q: %w", pkgPath, dst, err) + } + + io.ErrPrintfln("gno: downloading %s", pkgPath) + + client := Client + if client == nil { + // create client from pkgpath + parts := strings.Split(pkgPath, "/") + if len(parts) < 1 { + return fmt.Errorf("bad pkg path %q", pkgPath) + } + // XXX: retrieve host/port from r/sys/zones. + rpcURL := (&url.URL{ + Scheme: "https", + Host: "rpc." + parts[0] + ":443", + }).String() + tmClient, err := tm2client.NewHTTPClient(rpcURL) + if err != nil { + return fmt.Errorf("failed to instantiate tm2 client with remote %q: %w", rpcURL, err) + } + defer tmClient.Close() + client = tmClient + } + + // fetch files + data, err := qfile(client, pkgPath) + if err != nil { + return fmt.Errorf("failed to query files list for pkg %q: %w", pkgPath, err) + } + if err := os.MkdirAll(dst, 0o744); err != nil { + return fmt.Errorf("failed to create cache dir for %q at %q: %w", pkgPath, dst, err) + } + files := strings.Split(string(data), "\n") + for _, file := range files { + filePath := path.Join(pkgPath, file) + data, err := qfile(client, filePath) + if err != nil { + return fmt.Errorf("failed to query package file %q: %w", filePath, err) + } + dst := filepath.Join(dst, file) + if err := os.WriteFile(dst, data, 0o644); err != nil { + return fmt.Errorf("failed to write file at %q: %w", dst, err) + } + } + + // write gno.mod + if err := os.WriteFile(modFilePath, []byte("module "+pkgPath+"\n"), 0o644); err != nil { + return fmt.Errorf("failed to write modfile at %q: %w", modFilePath, err) + } + + return nil +} + +func FetchPackagesRecursively(io commands.IO, pkgPath string, gnoMod *gnomod.File) error { + dst := filepath.Join(gnoenv.HomeDir(), "pkg", "mod", pkgPath) + + modFilePath := filepath.Join(dst, "gno.mod") + + if _, err := os.Stat(modFilePath); err == nil { + // modfile exists in modcache, do nothing + return nil + } else if !os.IsNotExist(err) { + return fmt.Errorf("failed to stat downloaded module %q at %q: %w", pkgPath, dst, err) } - return fmt.Errorf("not implemented") + if err := FetchPackage(io, pkgPath, dst); err != nil { + return err + } + + gnoFiles, err := load.GnoFilesFromArgs([]string{dst}) + if err != nil { + return err + } + + for _, f := range gnoFiles { + fset := token.NewFileSet() + parsed, err := parser.ParseFile(fset, f, nil, parser.ImportsOnly) + if err != nil { + continue + } + + for _, imp := range parsed.Imports { + importPkgPath := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, "\""), "\"") + + if !strings.ContainsRune(importPkgPath, '.') { + // std lib, ignore + continue + } + + resolved := gnoMod.Resolve(module.Version{Path: importPkgPath}) + resolvedPkgPath := resolved.Path + + // TODO: don't fetch local + + if err := FetchPackagesRecursively(io, resolvedPkgPath, gnoMod); err != nil { + return fmt.Errorf("fetch: %w", err) + } + } + } + + return nil } -// FetchFn allows to override default Fetch behavior, this is mostly useful for testing -var FetchFn func(pkgPath string, dst string) error +var Client tm2client.Client + +// not using gno client due to cyclic dep +func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { + path := "vm/qfile" + data := []byte(pkgPath) + + qres, err := tmClient.ABCIQuery(path, data) + if err != nil { + return nil, errors.Wrap(err, "query qfile") + } + if qres.Response.Error != nil { + return nil, errors.Wrap(qres.Response.Error, "QFile failed: log:%s", qres.Response.Log) + } + + return qres.Response.Data, nil +} diff --git a/gnovm/pkg/load/load.go b/gnovm/pkg/load/load.go index 6fd6150d4a1..4c878552995 100644 --- a/gnovm/pkg/load/load.go +++ b/gnovm/pkg/load/load.go @@ -17,6 +17,44 @@ func IsGnoFile(f fs.DirEntry) bool { func GnoFilesFromArgsRecursively(args []string) ([]string, error) { var paths []string + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + if IsGnoFile(fs.FileInfoToDirEntry(info)) { + paths = append(paths, ensurePathPrefix(argPath)) + } + + continue + } + + err = walkDirForGnoDirs(argPath, func(path string) { + dir := ensurePathPrefix(path) + files, err := os.ReadDir(dir) + if err != nil { + return + } + for _, f := range files { + if IsGnoFile(f) { + path := filepath.Join(dir, f.Name()) + paths = append(paths, ensurePathPrefix(path)) + } + } + }) + if err != nil { + return nil, fmt.Errorf("unable to walk dir: %w", err) + } + } + + return paths, nil +} + +func GnoDirsFromArgsRecursively(args []string) ([]string, error) { + var paths []string + for _, argPath := range args { info, err := os.Stat(argPath) if err != nil { @@ -32,7 +70,7 @@ func GnoFilesFromArgsRecursively(args []string) ([]string, error) { } // Gather package paths from the directory - err = walkDirForGnoFiles(argPath, func(path string) { + err = walkDirForGnoDirs(argPath, func(path string) { paths = append(paths, ensurePathPrefix(path)) }) if err != nil { @@ -85,7 +123,7 @@ func ensurePathPrefix(path string) string { return "." + string(filepath.Separator) + path } -func walkDirForGnoFiles(root string, addPath func(path string)) error { +func walkDirForGnoDirs(root string, addPath func(path string)) error { visited := make(map[string]struct{}) walkFn := func(currPath string, f fs.DirEntry, err error) error { @@ -128,7 +166,7 @@ func GnoPackagesFromArgsRecursively(args []string) ([]string, error) { } // Gather package paths from the directory - err = walkDirForGnoFiles(argPath, func(path string) { + err = walkDirForGnoDirs(argPath, func(path string) { paths = append(paths, ensurePathPrefix(path)) }) if err != nil { diff --git a/gnovm/tests/integ/invalid_module_version1/gno.mod b/gnovm/tests/integ/invalid_module_version1/gno.mod deleted file mode 100644 index e4c64e3106f..00000000000 --- a/gnovm/tests/integ/invalid_module_version1/gno.mod +++ /dev/null @@ -1,5 +0,0 @@ -module tmp - -require ( - "gno.land/p/demo/avl" //missing version -) diff --git a/gnovm/tests/integ/invalid_module_version2/gno.mod b/gnovm/tests/integ/invalid_module_version2/gno.mod deleted file mode 100644 index 0a3088b454a..00000000000 --- a/gnovm/tests/integ/invalid_module_version2/gno.mod +++ /dev/null @@ -1,5 +0,0 @@ -module tmp - -require ( - "gno.land/p/demo/avl" version-2 //invalid versioning -) diff --git a/gnovm/tests/integ/replace_with_dir/gno.mod b/gnovm/tests/integ/replace_with_dir/gno.mod index 6a7b1b664c8..69ae753a58a 100644 --- a/gnovm/tests/integ/replace_with_dir/gno.mod +++ b/gnovm/tests/integ/replace_with_dir/gno.mod @@ -1,9 +1,5 @@ module gno.land/tests/replaceavl -require ( - "gno.land/p/demo/notexists" v0.0.0 -) - replace ( "gno.land/p/demo/notexists" => /path/to/dir ) diff --git a/gnovm/tests/integ/replace_with_invalid_module/gno.mod b/gnovm/tests/integ/replace_with_invalid_module/gno.mod index ee90787ff0e..2a9527da7d6 100644 --- a/gnovm/tests/integ/replace_with_invalid_module/gno.mod +++ b/gnovm/tests/integ/replace_with_invalid_module/gno.mod @@ -1,9 +1,5 @@ module gno.land/tests/replaceavl -require ( - "gno.land/p/demo/avl" v0.0.0 -) - replace ( - "gno.land/p/demo/avl" => "gno.land/p/demo/avlll" v0.0.0 + "gno.land/p/demo/avl" => "gno.land/p/demo/notexists" ) diff --git a/gnovm/tests/integ/replace_with_invalid_module/main.gno b/gnovm/tests/integ/replace_with_invalid_module/main.gno new file mode 100644 index 00000000000..7f78497fa02 --- /dev/null +++ b/gnovm/tests/integ/replace_with_invalid_module/main.gno @@ -0,0 +1,7 @@ +package main + +import ( + "gno.land/p/demo/avl" +) + +var foo = avl.Bar diff --git a/gnovm/tests/integ/replace_with_module/gno.mod b/gnovm/tests/integ/replace_with_module/gno.mod index 09c77df7a95..de730c90a53 100644 --- a/gnovm/tests/integ/replace_with_module/gno.mod +++ b/gnovm/tests/integ/replace_with_module/gno.mod @@ -1,9 +1,5 @@ module gno.land/tests/replaceavl -require ( - "gno.land/p/demo/avl" v0.0.2 -) - replace ( - "gno.land/p/demo/avl" v0.0.2 => "gno.land/p/demo/avl" v1.0.0 + "gno.land/p/demo/avl" => "gno.land/p/demo/users" ) diff --git a/gnovm/tests/integ/replace_with_module/main.gno b/gnovm/tests/integ/replace_with_module/main.gno new file mode 100644 index 00000000000..7f78497fa02 --- /dev/null +++ b/gnovm/tests/integ/replace_with_module/main.gno @@ -0,0 +1,7 @@ +package main + +import ( + "gno.land/p/demo/avl" +) + +var foo = avl.Bar diff --git a/gnovm/tests/integ/require_invalid_module/gno.mod b/gnovm/tests/integ/require_invalid_module/gno.mod index f0b455f128b..f10dff8c8d5 100644 --- a/gnovm/tests/integ/require_invalid_module/gno.mod +++ b/gnovm/tests/integ/require_invalid_module/gno.mod @@ -1,5 +1 @@ -module gno.land/tests/reqinvalidmodule - -require ( - "gno.land/p/demo/notexists" v1.2.3 -) +module gno.land/tests/reqinvalidmodule \ No newline at end of file diff --git a/gnovm/tests/integ/require_invalid_module/main.gno b/gnovm/tests/integ/require_invalid_module/main.gno new file mode 100644 index 00000000000..703ec65ee5a --- /dev/null +++ b/gnovm/tests/integ/require_invalid_module/main.gno @@ -0,0 +1,7 @@ +package main + +import ( + "gno.land/p/demo/notexists" +) + +var foo = notexists.Bar diff --git a/gnovm/tests/integ/require_remote_module/gno.mod b/gnovm/tests/integ/require_remote_module/gno.mod index 4823c72585d..946f41398ba 100644 --- a/gnovm/tests/integ/require_remote_module/gno.mod +++ b/gnovm/tests/integ/require_remote_module/gno.mod @@ -1,5 +1 @@ module gno.land/tests/importavl - -require ( - "gno.land/p/demo/avl" v0.0.0 -) diff --git a/gnovm/tests/integ/require_std_lib/gno.mod b/gnovm/tests/integ/require_std_lib/gno.mod new file mode 100644 index 00000000000..f10dff8c8d5 --- /dev/null +++ b/gnovm/tests/integ/require_std_lib/gno.mod @@ -0,0 +1 @@ +module gno.land/tests/reqinvalidmodule \ No newline at end of file diff --git a/gnovm/tests/integ/require_std_lib/main.gno b/gnovm/tests/integ/require_std_lib/main.gno new file mode 100644 index 00000000000..920d238cccc --- /dev/null +++ b/gnovm/tests/integ/require_std_lib/main.gno @@ -0,0 +1,7 @@ +package main + +import ( + "std" +) + +var foo std.Address diff --git a/gnovm/tests/integ/valid2/gno.mod b/gnovm/tests/integ/valid2/gno.mod index 98a5a0dacc1..3eaaa374994 100644 --- a/gnovm/tests/integ/valid2/gno.mod +++ b/gnovm/tests/integ/valid2/gno.mod @@ -1,3 +1 @@ module gno.land/p/integ/valid - -require gno.land/p/demo/avl v0.0.0-latest From 14be54fc6df4b9f3f104c5a3a7cd91804be6093a Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 7 Nov 2024 01:22:41 +0100 Subject: [PATCH 05/51] chore: refactor Signed-off-by: Norman Meier --- gnovm/cmd/gno/clean.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gnovm/cmd/gno/clean.go b/gnovm/cmd/gno/clean.go index 19a73c51794..a6b7b636efb 100644 --- a/gnovm/cmd/gno/clean.go +++ b/gnovm/cmd/gno/clean.go @@ -9,7 +9,6 @@ import ( "path/filepath" "strings" - "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/tm2/pkg/commands" ) @@ -64,6 +63,18 @@ func execClean(cfg *cleanCfg, args []string, io commands.IO) error { return flag.ErrHelp } + if cfg.modCache { + modCacheDir := gnomod.GetGnoModPath() + if !cfg.dryRun { + if err := os.RemoveAll(modCacheDir); err != nil { + return err + } + } + if cfg.dryRun || cfg.verbose { + io.Println("rm -rf", modCacheDir) + } + } + path, err := os.Getwd() if err != nil { return err @@ -81,17 +92,6 @@ func execClean(cfg *cleanCfg, args []string, io commands.IO) error { return err } - if cfg.modCache { - modCacheDir := filepath.Join(gnoenv.HomeDir(), "pkg", "mod") - if !cfg.dryRun { - if err := os.RemoveAll(modCacheDir); err != nil { - return err - } - } - if cfg.dryRun || cfg.verbose { - io.Println("rm -rf", modCacheDir) - } - } return nil } From 78ecedb05ef9be3e5d9b523fb6ace3663eb1fa25 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 7 Nov 2024 01:23:05 +0100 Subject: [PATCH 06/51] chore: remove unused writePackage func Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/gnomod.go | 50 -------------------------------------- 1 file changed, 50 deletions(-) diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index c8e09ef520a..6b77e4be309 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -3,13 +3,10 @@ package gnomod import ( "errors" "fmt" - "go/parser" - gotoken "go/token" "os" "path/filepath" "strings" - "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnolang" "golang.org/x/mod/modfile" @@ -36,53 +33,6 @@ func PackageDir(root string, v module.Version) string { return filepath.Join(root, v.Path) } -func writePackage(remote, basePath, pkgPath string) (requirements []string, err error) { - res, err := queryChain(remote, queryPathFile, []byte(pkgPath)) - if err != nil { - return nil, fmt.Errorf("querychain (%s): %w", pkgPath, err) - } - - dirPath, fileName := gnovm.SplitFilepath(pkgPath) - if fileName == "" { - // Is Dir - // Create Dir if not exists - dirPath := filepath.Join(basePath, dirPath) - if _, err = os.Stat(dirPath); os.IsNotExist(err) { - if err = os.MkdirAll(dirPath, 0o755); err != nil { - return nil, fmt.Errorf("mkdir %q: %w", dirPath, err) - } - } - - files := strings.Split(string(res.Data), "\n") - for _, file := range files { - reqs, err := writePackage(remote, basePath, filepath.Join(pkgPath, file)) - if err != nil { - return nil, fmt.Errorf("writepackage: %w", err) - } - requirements = append(requirements, reqs...) - } - } else { - // Is File - // Transpile and write generated go file - file, err := parser.ParseFile(gotoken.NewFileSet(), fileName, res.Data, parser.ImportsOnly) - if err != nil { - return nil, fmt.Errorf("parse gno file: %w", err) - } - for _, i := range file.Imports { - requirements = append(requirements, i.Path.Value) - } - - // Write file - fileNameWithPath := filepath.Join(basePath, dirPath, fileName) - err = os.WriteFile(fileNameWithPath, res.Data, 0o644) - if err != nil { - return nil, fmt.Errorf("writefile %q: %w", fileNameWithPath, err) - } - } - - return removeDuplicateStr(requirements), nil -} - func CreateGnoModFile(rootDir, modPath string) error { if !filepath.IsAbs(rootDir) { return fmt.Errorf("dir %q is not absolute", rootDir) From 70cfde50135906529cc8b04d077d7531b4a2aab7 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 7 Nov 2024 01:23:20 +0100 Subject: [PATCH 07/51] chore: use PackageDir helper Signed-off-by: Norman Meier --- gnovm/pkg/gnomodfetch/gnomodfetch.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gnovm/pkg/gnomodfetch/gnomodfetch.go b/gnovm/pkg/gnomodfetch/gnomodfetch.go index 1dd12dc23f4..d125ae1b466 100644 --- a/gnovm/pkg/gnomodfetch/gnomodfetch.go +++ b/gnovm/pkg/gnomodfetch/gnomodfetch.go @@ -10,7 +10,6 @@ import ( "path/filepath" "strings" - "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/load" tm2client "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" @@ -81,7 +80,7 @@ func FetchPackage(io commands.IO, pkgPath string, dst string) error { } func FetchPackagesRecursively(io commands.IO, pkgPath string, gnoMod *gnomod.File) error { - dst := filepath.Join(gnoenv.HomeDir(), "pkg", "mod", pkgPath) + dst := gnomod.PackageDir("", module.Version{Path: pkgPath}) modFilePath := filepath.Join(dst, "gno.mod") From 13a1e21e324c04f92ff79812716479c3fdafb44a Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 8 Nov 2024 20:48:27 +0100 Subject: [PATCH 08/51] fix: doc imports without require Signed-off-by: Norman Meier --- gnovm/cmd/gno/mod.go | 68 +----------- gnovm/cmd/gno/mod_test.go | 122 --------------------- gnovm/pkg/doc/dirs.go | 35 ++++++ gnovm/pkg/doc/dirs_test.go | 15 ++- gnovm/pkg/doc/testdata/dirsmod/a.gno | 9 ++ gnovm/pkg/doc/testdata/dirsmod/gno.mod | 6 +- gnovm/pkg/load/imports.go | 101 +++++++++++++++++ gnovm/pkg/load/imports_test.go | 145 +++++++++++++++++++++++++ 8 files changed, 303 insertions(+), 198 deletions(-) create mode 100644 gnovm/pkg/doc/testdata/dirsmod/a.gno create mode 100644 gnovm/pkg/load/imports.go create mode 100644 gnovm/pkg/load/imports_test.go diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 50a793ac66f..95534dc9026 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -8,7 +8,6 @@ import ( "go/token" "os" "path/filepath" - "sort" "strings" "github.com/gnolang/gno/gnovm/pkg/gnomod" @@ -364,7 +363,7 @@ func getImportToFilesMap(pkgPath string) (map[string][]string, error) { if strings.HasSuffix(filename, "_filetest.gno") { continue } - imports, err := getGnoFileImports(filepath.Join(pkgPath, filename)) + imports, err := load.GetGnoFileImports(filepath.Join(pkgPath, filename)) if err != nil { return nil, err } @@ -375,68 +374,3 @@ func getImportToFilesMap(pkgPath string) (map[string][]string, error) { } return m, nil } - -// getGnoPackageImports returns the list of gno imports from a given path. -// Note: It ignores subdirs. Since right now we are still deciding on -// how to handle subdirs. -// See: -// - https://github.com/gnolang/gno/issues/1024 -// - https://github.com/gnolang/gno/issues/852 -// -// TODO: move this to better location. -func getGnoPackageImports(path string) ([]string, error) { - entries, err := os.ReadDir(path) - if err != nil { - return nil, err - } - - allImports := make([]string, 0) - seen := make(map[string]struct{}) - for _, e := range entries { - filename := e.Name() - if ext := filepath.Ext(filename); ext != ".gno" { - continue - } - if strings.HasSuffix(filename, "_filetest.gno") { - continue - } - imports, err := getGnoFileImports(filepath.Join(path, filename)) - if err != nil { - return nil, err - } - for _, im := range imports { - if !strings.HasPrefix(im, "gno.land/") { - continue - } - if _, ok := seen[im]; ok { - continue - } - allImports = append(allImports, im) - seen[im] = struct{}{} - } - } - sort.Strings(allImports) - - return allImports, nil -} - -func getGnoFileImports(fname string) ([]string, error) { - if !strings.HasSuffix(fname, ".gno") { - return nil, fmt.Errorf("not a gno file: %q", fname) - } - data, err := os.ReadFile(fname) - if err != nil { - return nil, err - } - fs := token.NewFileSet() - f, err := parser.ParseFile(fs, fname, data, parser.ImportsOnly) - if err != nil { - return nil, err - } - res := make([]string, 0) - for _, im := range f.Imports { - importPath := strings.TrimPrefix(strings.TrimSuffix(im.Path.Value, `"`), `"`) - res = append(res, importPath) - } - return res, nil -} diff --git a/gnovm/cmd/gno/mod_test.go b/gnovm/cmd/gno/mod_test.go index bd36287bc6f..1e2842ff182 100644 --- a/gnovm/cmd/gno/mod_test.go +++ b/gnovm/cmd/gno/mod_test.go @@ -1,12 +1,7 @@ package main import ( - "os" - "path/filepath" "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestModApp(t *testing.T) { @@ -221,120 +216,3 @@ valid.gno testMainCaseRun(t, tc) } - -func TestGetGnoImports(t *testing.T) { - workingDir, err := os.Getwd() - require.NoError(t, err) - - // create external dir - tmpDir, cleanUpFn := createTmpDir(t) - defer cleanUpFn() - - // cd to tmp directory - os.Chdir(tmpDir) - defer os.Chdir(workingDir) - - files := []struct { - name, data string - }{ - { - name: "file1.gno", - data: ` - package tmp - - import ( - "std" - - "gno.land/p/demo/pkg1" - ) - `, - }, - { - name: "file2.gno", - data: ` - package tmp - - import ( - "gno.land/p/demo/pkg1" - "gno.land/p/demo/pkg2" - ) - `, - }, - { - name: "file1_test.gno", - data: ` - package tmp - - import ( - "testing" - - "gno.land/p/demo/testpkg" - ) - `, - }, - { - name: "z_0_filetest.gno", - data: ` - package main - - import ( - "gno.land/p/demo/filetestpkg" - ) - `, - }, - - // subpkg files - { - name: filepath.Join("subtmp", "file1.gno"), - data: ` - package subtmp - - import ( - "std" - - "gno.land/p/demo/subpkg1" - ) - `, - }, - { - name: filepath.Join("subtmp", "file2.gno"), - data: ` - package subtmp - - import ( - "gno.land/p/demo/subpkg1" - "gno.land/p/demo/subpkg2" - ) - `, - }, - } - - // Expected list of imports - // - ignore subdirs - // - ignore duplicate - // - ignore *_filetest.gno - // - should be sorted - expected := []string{ - "gno.land/p/demo/pkg1", - "gno.land/p/demo/pkg2", - "gno.land/p/demo/testpkg", - } - - // Create subpkg dir - err = os.Mkdir("subtmp", 0o700) - require.NoError(t, err) - - // Create files - for _, f := range files { - err = os.WriteFile(f.name, []byte(f.data), 0o644) - require.NoError(t, err) - } - - imports, err := getGnoPackageImports(tmpDir) - require.NoError(t, err) - - require.Equal(t, len(expected), len(imports)) - for i := range imports { - assert.Equal(t, expected[i], imports[i]) - } -} diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index 48c51dfb27a..78f03252811 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -5,6 +5,7 @@ package doc import ( + "fmt" "log" "os" "path" @@ -13,6 +14,8 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/load" + "golang.org/x/mod/module" ) // A bfsDir describes a directory holding code by specifying @@ -60,12 +63,44 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { dir: mdir, importPath: gm.Module.Mod.Path, }) + roots = append(roots, getGnoModDirs(gm, mdir)...) } go d.walk(roots) return d } +func getGnoModDirs(gm *gnomod.File, root string) []bfsDir { + // cmd/go makes use of the go list command, we don't have that here. + + imports, err := load.GetGnoPackageImportsRecursive(root) + if err != nil { + log.Println("get imports at", root, ":", err) + return nil + } + + dirs := make([]bfsDir, 0, len(imports)) + for _, r := range imports { + mv := gm.Resolve(module.Version{Path: r}) + path := gnomod.PackageDir("", mv) + if _, err := os.Stat(path); err != nil { + fmt.Printf("ignoring inexistent path %q for pkg %q\n", path, r) + // only give directories which actually exist and don't give + // an error when accessing + if !os.IsNotExist(err) { + log.Println("open source directories from import:", err) + } + continue + } + dirs = append(dirs, bfsDir{ + importPath: mv.Path, + dir: path, + }) + } + + return dirs +} + // Reset puts the scan back at the beginning. func (d *bfsDirs) Reset() { d.offset = 0 diff --git a/gnovm/pkg/doc/dirs_test.go b/gnovm/pkg/doc/dirs_test.go index 8659f3cbfcb..88c5f837f9a 100644 --- a/gnovm/pkg/doc/dirs_test.go +++ b/gnovm/pkg/doc/dirs_test.go @@ -63,17 +63,24 @@ func TestNewDirs_invalidModDir(t *testing.T) { func tNewDirs(t *testing.T) (string, *bfsDirs) { t.Helper() - // modify GNO_HOME to testdata/dirsdep -- this allows us to test + // modify GNOHOME to testdata/dirsdep -- this allows us to test // dependency lookup by dirs. - old, ex := os.LookupEnv("GNO_HOME") + oldLegacy, exLegacy := os.LookupEnv("GNO_HOME") + old, ex := os.LookupEnv("GNOHOME") os.Setenv("GNO_HOME", wdJoin(t, "testdata/dirsdep")) + os.Setenv("GNOHOME", wdJoin(t, "testdata/dirsdep")) t.Cleanup(func() { - if ex { - os.Setenv("GNO_HOME", old) + if exLegacy { + os.Setenv("GNO_HOME", oldLegacy) } else { os.Unsetenv("GNO_HOME") } + if ex { + os.Setenv("GNOHOME", old) + } else { + os.Unsetenv("GNOHOME") + } }) return wdJoin(t, "testdata"), diff --git a/gnovm/pkg/doc/testdata/dirsmod/a.gno b/gnovm/pkg/doc/testdata/dirsmod/a.gno new file mode 100644 index 00000000000..ee57c47dff5 --- /dev/null +++ b/gnovm/pkg/doc/testdata/dirsmod/a.gno @@ -0,0 +1,9 @@ +package dirsmod + +import ( + "dirs.mod/dep" +) + +func foo() { + dep.Bar() +} diff --git a/gnovm/pkg/doc/testdata/dirsmod/gno.mod b/gnovm/pkg/doc/testdata/dirsmod/gno.mod index 6c8008b958c..34d825571cc 100644 --- a/gnovm/pkg/doc/testdata/dirsmod/gno.mod +++ b/gnovm/pkg/doc/testdata/dirsmod/gno.mod @@ -1,5 +1 @@ -module dirs.mod/prefix - -require ( - dirs.mod/dep v0.0.0 -) +module dirs.mod/prefix \ No newline at end of file diff --git a/gnovm/pkg/load/imports.go b/gnovm/pkg/load/imports.go new file mode 100644 index 00000000000..d5c5196c0d0 --- /dev/null +++ b/gnovm/pkg/load/imports.go @@ -0,0 +1,101 @@ +package load + +import ( + "fmt" + "go/parser" + "go/token" + "os" + "path/filepath" + "slices" + "sort" + "strings" +) + +func GetGnoPackageImportsRecursive(root string) ([]string, error) { + res, err := GetGnoPackageImports(root) + _ = err + + entries, err := os.ReadDir(root) + _ = err + + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + sub, err := GetGnoPackageImportsRecursive(filepath.Join(root, entry.Name())) + if err != nil { + continue + } + + for _, imp := range sub { + if !slices.Contains(res, imp) { + res = append(res, imp) + } + } + } + + sort.Strings(res) + + return res, nil +} + +// GetGnoPackageImports returns the list of gno imports from a given path. +// Note: It ignores subdirs. Since right now we are still deciding on +// how to handle subdirs. +// See: +// - https://github.com/gnolang/gno/issues/1024 +// - https://github.com/gnolang/gno/issues/852 +func GetGnoPackageImports(path string) ([]string, error) { + entries, err := os.ReadDir(path) + if err != nil { + return nil, err + } + + allImports := make([]string, 0) + seen := make(map[string]struct{}) + for _, e := range entries { + filename := e.Name() + if ext := filepath.Ext(filename); ext != ".gno" { + continue + } + if strings.HasSuffix(filename, "_filetest.gno") { + continue + } + imports, err := GetGnoFileImports(filepath.Join(path, filename)) + if err != nil { + return nil, err + } + for _, im := range imports { + if _, ok := seen[im]; ok { + continue + } + allImports = append(allImports, im) + seen[im] = struct{}{} + } + } + sort.Strings(allImports) + + return allImports, nil +} + +func GetGnoFileImports(fname string) ([]string, error) { + if !strings.HasSuffix(fname, ".gno") { + return nil, fmt.Errorf("not a gno file: %q", fname) + } + data, err := os.ReadFile(fname) + if err != nil { + return nil, err + } + fs := token.NewFileSet() + f, err := parser.ParseFile(fs, fname, data, parser.ImportsOnly) + if err != nil { + return nil, err + } + res := make([]string, 0) + for _, im := range f.Imports { + importPath := strings.TrimPrefix(strings.TrimSuffix(im.Path.Value, `"`), `"`) + res = append(res, importPath) + } + return res, nil +} diff --git a/gnovm/pkg/load/imports_test.go b/gnovm/pkg/load/imports_test.go new file mode 100644 index 00000000000..42e9c3524fd --- /dev/null +++ b/gnovm/pkg/load/imports_test.go @@ -0,0 +1,145 @@ +package load + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetGnoImports(t *testing.T) { + workingDir, err := os.Getwd() + require.NoError(t, err) + + // create external dir + tmpDir, cleanUpFn := createTmpDir(t) + defer cleanUpFn() + + // cd to tmp directory + os.Chdir(tmpDir) + defer os.Chdir(workingDir) + + files := []struct { + name, data string + }{ + { + name: "file1.gno", + data: ` + package tmp + + import ( + "std" + + "gno.land/p/demo/pkg1" + ) + `, + }, + { + name: "file2.gno", + data: ` + package tmp + + import ( + "gno.land/p/demo/pkg1" + "gno.land/p/demo/pkg2" + ) + `, + }, + { + name: "file1_test.gno", + data: ` + package tmp + + import ( + "testing" + + "gno.land/p/demo/testpkg" + ) + `, + }, + { + name: "z_0_filetest.gno", + data: ` + package main + + import ( + "gno.land/p/demo/filetestpkg" + ) + `, + }, + + // subpkg files + { + name: filepath.Join("subtmp", "file1.gno"), + data: ` + package subtmp + + import ( + "std" + + "gno.land/p/demo/subpkg1" + ) + `, + }, + { + name: filepath.Join("subtmp", "file2.gno"), + data: ` + package subtmp + + import ( + "gno.land/p/demo/subpkg1" + "gno.land/p/demo/subpkg2" + ) + `, + }, + } + + // Expected list of imports + // - ignore subdirs + // - ignore duplicate + // - ignore *_filetest.gno + // - should be sorted + expected := []string{ + "gno.land/p/demo/pkg1", + "gno.land/p/demo/pkg2", + "gno.land/p/demo/testpkg", + } + + // Create subpkg dir + err = os.Mkdir("subtmp", 0o700) + require.NoError(t, err) + + // Create files + for _, f := range files { + err = os.WriteFile(f.name, []byte(f.data), 0o644) + require.NoError(t, err) + } + + imports, err := GetGnoPackageImports(tmpDir) + require.NoError(t, err) + + require.Equal(t, len(expected), len(imports)) + for i := range imports { + assert.Equal(t, expected[i], imports[i]) + } +} + +func createTmpDir(t *testing.T) (string, func()) { + t.Helper() + + tmpDir, err := os.MkdirTemp("", "gno-mod-test") + if err != nil { + t.Error("Failed to create tmp dir for mod:", err) + } + + cleanUpFn := func() { + err := os.RemoveAll(tmpDir) + if err != nil { + t.Logf("Failed to clean up test %s: %v", t.Name(), err) + } + } + + return tmpDir, cleanUpFn +} From 77d696d89073ff42b7d00b6b86d4bd81524f54f2 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 8 Nov 2024 21:28:24 +0100 Subject: [PATCH 09/51] chore: fix tests Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/parse_test.go | 7 ++++--- gnovm/pkg/load/imports_test.go | 8 +++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/gnovm/pkg/gnomod/parse_test.go b/gnovm/pkg/gnomod/parse_test.go index 4dd89159d13..35861fb4c55 100644 --- a/gnovm/pkg/gnomod/parse_test.go +++ b/gnovm/pkg/gnomod/parse_test.go @@ -200,9 +200,10 @@ func TestParseGnoMod(t *testing.T) { errShouldContain: "error parsing gno.mod file at", }, { - desc: "error validating gno.mod", - modData: `require bar v0.0.0`, - modPath: filepath.Join(pkgDir, "gno.mod"), + desc: "error validating gno.mod", + modData: `require bar v0.0.0`, + modPath: filepath.Join(pkgDir, "gno.mod"), + errShouldContain: "requires module", }, } { t.Run(tc.desc, func(t *testing.T) { diff --git a/gnovm/pkg/load/imports_test.go b/gnovm/pkg/load/imports_test.go index 42e9c3524fd..5e44ce7d0b9 100644 --- a/gnovm/pkg/load/imports_test.go +++ b/gnovm/pkg/load/imports_test.go @@ -5,7 +5,6 @@ import ( "path/filepath" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -105,6 +104,8 @@ func TestGetGnoImports(t *testing.T) { "gno.land/p/demo/pkg1", "gno.land/p/demo/pkg2", "gno.land/p/demo/testpkg", + "std", + "testing", } // Create subpkg dir @@ -120,10 +121,7 @@ func TestGetGnoImports(t *testing.T) { imports, err := GetGnoPackageImports(tmpDir) require.NoError(t, err) - require.Equal(t, len(expected), len(imports)) - for i := range imports { - assert.Equal(t, expected[i], imports[i]) - } + require.Equal(t, expected, imports) } func createTmpDir(t *testing.T) (string, func()) { From 43afcc93039d190084b0d865975608504ad351af Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 8 Nov 2024 22:15:33 +0100 Subject: [PATCH 10/51] fix: txtar loader Signed-off-by: Norman Meier --- .../pkg/integration/testing_integration.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 9d530d6bc9f..052ab3b9c0d 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -19,7 +19,9 @@ import ( "github.com/gnolang/gno/gno.land/pkg/log" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/tm2/pkg/bft/node" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" @@ -742,6 +744,17 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { // Override package info with mod infos currentPkg.Name = gm.Module.Mod.Path currentPkg.Draft = gm.Draft + + imports, err := load.GetGnoPackageImports(currentPkg.Dir) + if err != nil { + return fmt.Errorf("unable to load package imports in %q: %w", currentPkg.Dir, err) + } + for _, imp := range imports { + if gno.IsStdlib(imp) { + continue + } + currentPkg.Imports = append(currentPkg.Imports, imp) + } } if currentPkg.Draft { @@ -752,6 +765,12 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { continue } pl.add(currentPkg) + + // Add requirements to the queue + for _, pkgPath := range currentPkg.Imports { + fullPath := filepath.Join(modroot, pkgPath) + queue = append(queue, gnomod.Pkg{Dir: fullPath}) + } } return nil From 89ca16457f8fbcbed53dd4293e5618a4b11a44ad Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 8 Nov 2024 22:37:21 +0100 Subject: [PATCH 11/51] chore: forbid require Signed-off-by: Norman Meier --- examples/gno.land/p/demo/acl/gno.mod | 6 ------ examples/gno.land/p/demo/avl/pager/gno.mod | 6 ------ examples/gno.land/p/demo/avlhelpers/gno.mod | 1 - examples/gno.land/p/demo/blog/gno.mod | 5 ----- examples/gno.land/p/demo/dao/gno.mod | 1 - examples/gno.land/p/demo/dom/gno.mod | 1 - examples/gno.land/p/demo/fqname/gno.mod | 1 - .../gno.land/p/demo/gnorkle/agent/gno.mod | 4 ---- .../p/demo/gnorkle/feeds/static/gno.mod | 11 ----------- .../gno.land/p/demo/gnorkle/gnorkle/gno.mod | 7 ------- .../p/demo/gnorkle/ingesters/single/gno.mod | 6 ------ .../gno.land/p/demo/gnorkle/message/gno.mod | 1 - .../p/demo/gnorkle/storage/simple/gno.mod | 7 ------- examples/gno.land/p/demo/grc/grc1155/gno.mod | 5 ----- examples/gno.land/p/demo/grc/grc20/gno.mod | 7 ------- examples/gno.land/p/demo/grc/grc721/gno.mod | 6 ------ examples/gno.land/p/demo/grc/grc777/gno.mod | 1 - examples/gno.land/p/demo/groups/gno.mod | 4 ---- examples/gno.land/p/demo/int256/gno.mod | 1 - examples/gno.land/p/demo/json/gno.mod | 1 - .../gno.land/p/demo/math_eval/int32/gno.mod | 1 - examples/gno.land/p/demo/membstore/gno.mod | 7 ------- examples/gno.land/p/demo/memeland/gno.mod | 8 -------- examples/gno.land/p/demo/microblog/gno.mod | 4 ---- .../p/demo/ownable/exts/authorizable/gno.mod | 7 ------- examples/gno.land/p/demo/ownable/gno.mod | 4 ---- examples/gno.land/p/demo/pausable/gno.mod | 4 ---- examples/gno.land/p/demo/seqid/gno.mod | 1 - examples/gno.land/p/demo/simpledao/gno.mod | 10 ---------- .../p/demo/subscription/lifetime/gno.mod | 6 ------ .../p/demo/subscription/recurring/gno.mod | 6 ------ examples/gno.land/p/demo/svg/gno.mod | 1 - examples/gno.land/p/demo/tamagotchi/gno.mod | 1 - examples/gno.land/p/demo/tests/gno.mod | 5 ----- examples/gno.land/p/demo/todolist/gno.mod | 4 ---- examples/gno.land/p/demo/uassert/gno.mod | 1 - examples/gno.land/p/demo/urequire/gno.mod | 1 - examples/gno.land/p/demo/watchdog/gno.mod | 1 - examples/gno.land/p/gov/executor/gno.mod | 5 ----- examples/gno.land/p/moul/helplink/gno.mod | 4 ---- .../gno.land/p/moul/printfdebugging/gno.mod | 1 - examples/gno.land/p/moul/txlink/gno.mod | 1 - examples/gno.land/p/nt/poa/gno.mod | 8 -------- examples/gno.land/r/demo/art/gnoface/gno.mod | 5 ----- .../gno.land/r/demo/art/millipede/gno.mod | 4 ---- examples/gno.land/r/demo/bar20/gno.mod | 6 ------ examples/gno.land/r/demo/boards/gno.mod | 5 ----- examples/gno.land/r/demo/daoweb/gno.mod | 5 ----- examples/gno.land/r/demo/disperse/gno.mod | 1 - examples/gno.land/r/demo/echo/gno.mod | 1 - examples/gno.land/r/demo/foo1155/gno.mod | 6 ------ examples/gno.land/r/demo/foo20/gno.mod | 9 --------- examples/gno.land/r/demo/foo721/gno.mod | 6 ------ .../gno.land/r/demo/games/dice_roller/gno.mod | 9 --------- .../gno.land/r/demo/games/shifumi/gno.mod | 5 ----- examples/gno.land/r/demo/grc20factory/gno.mod | 7 ------- examples/gno.land/r/demo/groups/gno.mod | 4 ---- examples/gno.land/r/demo/keystore/gno.mod | 6 ------ examples/gno.land/r/demo/math_eval/gno.mod | 4 ---- examples/gno.land/r/demo/memeland/gno.mod | 1 - examples/gno.land/r/demo/microblog/gno.mod | 7 ------- examples/gno.land/r/demo/nft/gno.mod | 4 ---- examples/gno.land/r/demo/profile/gno.mod | 7 ------- .../gno.land/r/demo/releases_example/gno.mod | 1 - examples/gno.land/r/demo/tamagotchi/gno.mod | 4 ---- .../gno.land/r/demo/tests/crossrealm/gno.mod | 4 ---- examples/gno.land/r/demo/tests/gno.mod | 4 ---- examples/gno.land/r/demo/tests_foo/gno.mod | 1 - examples/gno.land/r/demo/todolist/gno.mod | 7 ------- examples/gno.land/r/demo/types/gno.mod | 1 - examples/gno.land/r/demo/ui/gno.mod | 4 ---- examples/gno.land/r/demo/userbook/gno.mod | 6 ------ examples/gno.land/r/demo/users/gno.mod | 7 ------- examples/gno.land/r/demo/wugnot/gno.mod | 6 ------ examples/gno.land/r/gnoland/blog/gno.mod | 6 ------ examples/gno.land/r/gnoland/events/gno.mod | 7 ------- examples/gno.land/r/gnoland/faucet/gno.mod | 5 ----- examples/gno.land/r/gnoland/ghverify/gno.mod | 7 ------- examples/gno.land/r/gnoland/home/gno.mod | 7 ------- examples/gno.land/r/gnoland/monit/gno.mod | 6 ------ examples/gno.land/r/gnoland/pages/gno.mod | 4 ---- .../gno.land/r/gnoland/valopers/v2/gno.mod | 10 ---------- examples/gno.land/r/gov/dao/bridge/gno.mod | 9 --------- examples/gno.land/r/gov/dao/v2/gno.mod | 8 -------- examples/gno.land/r/leon/home/gno.mod | 6 ------ examples/gno.land/r/manfred/home/gno.mod | 1 - examples/gno.land/r/manfred/present/gno.mod | 4 ---- examples/gno.land/r/morgan/guestbook/gno.mod | 5 ----- examples/gno.land/r/stefann/home/gno.mod | 7 ------- examples/gno.land/r/stefann/registry/gno.mod | 1 - examples/gno.land/r/sys/users/gno.mod | 4 ---- examples/gno.land/r/sys/validators/v2/gno.mod | 11 ----------- examples/gno.land/r/x/manfred_outfmt/gno.mod | 1 - gnovm/pkg/gnomod/parse.go | 6 +----- gnovm/pkg/gnomod/parse_test.go | 19 ++++++++++++++++--- 95 files changed, 17 insertions(+), 437 deletions(-) diff --git a/examples/gno.land/p/demo/acl/gno.mod b/examples/gno.land/p/demo/acl/gno.mod index 15d9f078048..48010dc0536 100644 --- a/examples/gno.land/p/demo/acl/gno.mod +++ b/examples/gno.land/p/demo/acl/gno.mod @@ -1,8 +1,2 @@ module gno.land/p/demo/acl -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/avl/pager/gno.mod b/examples/gno.land/p/demo/avl/pager/gno.mod index 59c961d73f2..785e67cb125 100644 --- a/examples/gno.land/p/demo/avl/pager/gno.mod +++ b/examples/gno.land/p/demo/avl/pager/gno.mod @@ -1,8 +1,2 @@ module gno.land/p/demo/avl/pager -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/avlhelpers/gno.mod b/examples/gno.land/p/demo/avlhelpers/gno.mod index 559f60975cf..0d5a22959ea 100644 --- a/examples/gno.land/p/demo/avlhelpers/gno.mod +++ b/examples/gno.land/p/demo/avlhelpers/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/avlhelpers -require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/p/demo/blog/gno.mod b/examples/gno.land/p/demo/blog/gno.mod index 65f58e7a0f6..fa42570f5f9 100644 --- a/examples/gno.land/p/demo/blog/gno.mod +++ b/examples/gno.land/p/demo/blog/gno.mod @@ -1,7 +1,2 @@ module gno.land/p/demo/blog -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/mux v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/dao/gno.mod b/examples/gno.land/p/demo/dao/gno.mod index ecbab2f7692..107b400286d 100644 --- a/examples/gno.land/p/demo/dao/gno.mod +++ b/examples/gno.land/p/demo/dao/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/dao -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/dom/gno.mod b/examples/gno.land/p/demo/dom/gno.mod index 83ca827cf66..2ce66f123d8 100644 --- a/examples/gno.land/p/demo/dom/gno.mod +++ b/examples/gno.land/p/demo/dom/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/dom -require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/p/demo/fqname/gno.mod b/examples/gno.land/p/demo/fqname/gno.mod index 1282e262303..f9684cb824b 100644 --- a/examples/gno.land/p/demo/fqname/gno.mod +++ b/examples/gno.land/p/demo/fqname/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/fqname -require gno.land/p/demo/uassert v0.0.0-latest diff --git a/examples/gno.land/p/demo/gnorkle/agent/gno.mod b/examples/gno.land/p/demo/gnorkle/agent/gno.mod index 093ca9cf38e..be54d8c850f 100644 --- a/examples/gno.land/p/demo/gnorkle/agent/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/agent/gno.mod @@ -1,6 +1,2 @@ module gno.land/p/demo/gnorkle/agent -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod b/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod index c651c62cb1b..69b58cf85f1 100644 --- a/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod @@ -1,13 +1,2 @@ module gno.land/p/demo/gnorkle/feeds/static -require ( - gno.land/p/demo/gnorkle/feed v0.0.0-latest - gno.land/p/demo/gnorkle/gnorkle v0.0.0-latest - gno.land/p/demo/gnorkle/ingester v0.0.0-latest - gno.land/p/demo/gnorkle/ingesters/single v0.0.0-latest - gno.land/p/demo/gnorkle/message v0.0.0-latest - gno.land/p/demo/gnorkle/storage/simple v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod b/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod index 88fb202863f..77cff50c11e 100644 --- a/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod @@ -1,9 +1,2 @@ module gno.land/p/demo/gnorkle/gnorkle -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/gnorkle/agent v0.0.0-latest - gno.land/p/demo/gnorkle/feed v0.0.0-latest - gno.land/p/demo/gnorkle/ingester v0.0.0-latest - gno.land/p/demo/gnorkle/message v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod b/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod index 71120966a0c..e9454c65385 100644 --- a/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod @@ -1,8 +1,2 @@ module gno.land/p/demo/gnorkle/ingesters/single -require ( - gno.land/p/demo/gnorkle/gnorkle v0.0.0-latest - gno.land/p/demo/gnorkle/ingester v0.0.0-latest - gno.land/p/demo/gnorkle/storage/simple v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/gnorkle/message/gno.mod b/examples/gno.land/p/demo/gnorkle/message/gno.mod index 4baad40ef86..fdff0ee63f2 100644 --- a/examples/gno.land/p/demo/gnorkle/message/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/message/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/gnorkle/message -require gno.land/p/demo/uassert v0.0.0-latest diff --git a/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod b/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod index cd673a8771c..d37382264ee 100644 --- a/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod @@ -1,9 +1,2 @@ module gno.land/p/demo/gnorkle/storage/simple -require ( - gno.land/p/demo/gnorkle/feed v0.0.0-latest - gno.land/p/demo/gnorkle/storage v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/grc/grc1155/gno.mod b/examples/gno.land/p/demo/grc/grc1155/gno.mod index d6db0700146..24cc267c662 100644 --- a/examples/gno.land/p/demo/grc/grc1155/gno.mod +++ b/examples/gno.land/p/demo/grc/grc1155/gno.mod @@ -1,7 +1,2 @@ module gno.land/p/demo/grc/grc1155 -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/grc/grc20/gno.mod b/examples/gno.land/p/demo/grc/grc20/gno.mod index e872d80ec12..6400797762e 100644 --- a/examples/gno.land/p/demo/grc/grc20/gno.mod +++ b/examples/gno.land/p/demo/grc/grc20/gno.mod @@ -1,9 +1,2 @@ module gno.land/p/demo/grc/grc20 -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/grc/exts v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/grc/grc721/gno.mod b/examples/gno.land/p/demo/grc/grc721/gno.mod index 9e1d6f56ffc..4dc957f19f5 100644 --- a/examples/gno.land/p/demo/grc/grc721/gno.mod +++ b/examples/gno.land/p/demo/grc/grc721/gno.mod @@ -1,8 +1,2 @@ module gno.land/p/demo/grc/grc721 -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/grc/grc777/gno.mod b/examples/gno.land/p/demo/grc/grc777/gno.mod index 9fbf2f2b7cd..698bf465c9a 100644 --- a/examples/gno.land/p/demo/grc/grc777/gno.mod +++ b/examples/gno.land/p/demo/grc/grc777/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/grc/grc777 -require gno.land/p/demo/grc/exts v0.0.0-latest diff --git a/examples/gno.land/p/demo/groups/gno.mod b/examples/gno.land/p/demo/groups/gno.mod index f0749e3f411..437e5504196 100644 --- a/examples/gno.land/p/demo/groups/gno.mod +++ b/examples/gno.land/p/demo/groups/gno.mod @@ -1,6 +1,2 @@ module gno.land/p/demo/groups -require ( - gno.land/p/demo/rat v0.0.0-latest - gno.land/r/demo/boards v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/int256/gno.mod b/examples/gno.land/p/demo/int256/gno.mod index ef906c83c93..5dba413c025 100644 --- a/examples/gno.land/p/demo/int256/gno.mod +++ b/examples/gno.land/p/demo/int256/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/int256 -require gno.land/p/demo/uint256 v0.0.0-latest diff --git a/examples/gno.land/p/demo/json/gno.mod b/examples/gno.land/p/demo/json/gno.mod index ef794458c56..549a1d9739a 100644 --- a/examples/gno.land/p/demo/json/gno.mod +++ b/examples/gno.land/p/demo/json/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/json -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/math_eval/int32/gno.mod b/examples/gno.land/p/demo/math_eval/int32/gno.mod index de57497a699..2157ad2f1d2 100644 --- a/examples/gno.land/p/demo/math_eval/int32/gno.mod +++ b/examples/gno.land/p/demo/math_eval/int32/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/math_eval/int32 -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/membstore/gno.mod b/examples/gno.land/p/demo/membstore/gno.mod index da22a8dcae4..1e30257e2fb 100644 --- a/examples/gno.land/p/demo/membstore/gno.mod +++ b/examples/gno.land/p/demo/membstore/gno.mod @@ -1,9 +1,2 @@ module gno.land/p/demo/membstore -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/memeland/gno.mod b/examples/gno.land/p/demo/memeland/gno.mod index 66f22d1ccee..283867d7dcd 100644 --- a/examples/gno.land/p/demo/memeland/gno.mod +++ b/examples/gno.land/p/demo/memeland/gno.mod @@ -1,10 +1,2 @@ module gno.land/p/demo/memeland -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/microblog/gno.mod b/examples/gno.land/p/demo/microblog/gno.mod index 9bbcfa19e31..f77774d1484 100644 --- a/examples/gno.land/p/demo/microblog/gno.mod +++ b/examples/gno.land/p/demo/microblog/gno.mod @@ -1,6 +1,2 @@ module gno.land/p/demo/microblog -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod b/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod index f36823f3f71..d270555de06 100644 --- a/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod +++ b/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod @@ -1,9 +1,2 @@ module gno.land/p/demo/ownable/exts/authorizable -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/ownable/gno.mod b/examples/gno.land/p/demo/ownable/gno.mod index 00f7812f6f5..f81528a1715 100644 --- a/examples/gno.land/p/demo/ownable/gno.mod +++ b/examples/gno.land/p/demo/ownable/gno.mod @@ -1,6 +1,2 @@ module gno.land/p/demo/ownable -require ( - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/pausable/gno.mod b/examples/gno.land/p/demo/pausable/gno.mod index 156875f7d85..108dae847b9 100644 --- a/examples/gno.land/p/demo/pausable/gno.mod +++ b/examples/gno.land/p/demo/pausable/gno.mod @@ -1,6 +1,2 @@ module gno.land/p/demo/pausable -require ( - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/seqid/gno.mod b/examples/gno.land/p/demo/seqid/gno.mod index d1390012c3c..4f4cd1f8a5a 100644 --- a/examples/gno.land/p/demo/seqid/gno.mod +++ b/examples/gno.land/p/demo/seqid/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/seqid -require gno.land/p/demo/cford32 v0.0.0-latest diff --git a/examples/gno.land/p/demo/simpledao/gno.mod b/examples/gno.land/p/demo/simpledao/gno.mod index f6f14f379ec..4ddaa9f13ec 100644 --- a/examples/gno.land/p/demo/simpledao/gno.mod +++ b/examples/gno.land/p/demo/simpledao/gno.mod @@ -1,12 +1,2 @@ module gno.land/p/demo/simpledao -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/dao v0.0.0-latest - gno.land/p/demo/membstore v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/subscription/lifetime/gno.mod b/examples/gno.land/p/demo/subscription/lifetime/gno.mod index 0084aa714c5..8d7a2e7c38e 100644 --- a/examples/gno.land/p/demo/subscription/lifetime/gno.mod +++ b/examples/gno.land/p/demo/subscription/lifetime/gno.mod @@ -1,8 +1,2 @@ module gno.land/p/demo/subscription/lifetime -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/subscription/recurring/gno.mod b/examples/gno.land/p/demo/subscription/recurring/gno.mod index d3cf8a044f8..96beb72dc31 100644 --- a/examples/gno.land/p/demo/subscription/recurring/gno.mod +++ b/examples/gno.land/p/demo/subscription/recurring/gno.mod @@ -1,8 +1,2 @@ module gno.land/p/demo/subscription/recurring -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/svg/gno.mod b/examples/gno.land/p/demo/svg/gno.mod index 0af7ba0636d..ac804476fc3 100644 --- a/examples/gno.land/p/demo/svg/gno.mod +++ b/examples/gno.land/p/demo/svg/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/svg -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/tamagotchi/gno.mod b/examples/gno.land/p/demo/tamagotchi/gno.mod index 58441284a6b..bd17bd19a74 100644 --- a/examples/gno.land/p/demo/tamagotchi/gno.mod +++ b/examples/gno.land/p/demo/tamagotchi/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/tamagotchi -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/tests/gno.mod b/examples/gno.land/p/demo/tests/gno.mod index d3d796f76f8..8c76f3f7519 100644 --- a/examples/gno.land/p/demo/tests/gno.mod +++ b/examples/gno.land/p/demo/tests/gno.mod @@ -1,7 +1,2 @@ module gno.land/p/demo/tests -require ( - gno.land/p/demo/tests/subtests v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/r/demo/tests v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/todolist/gno.mod b/examples/gno.land/p/demo/todolist/gno.mod index bbccf357e3b..f44b3d9e459 100644 --- a/examples/gno.land/p/demo/todolist/gno.mod +++ b/examples/gno.land/p/demo/todolist/gno.mod @@ -1,6 +1,2 @@ module gno.land/p/demo/todolist -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest -) diff --git a/examples/gno.land/p/demo/uassert/gno.mod b/examples/gno.land/p/demo/uassert/gno.mod index f22276564bf..d8ba2f865ee 100644 --- a/examples/gno.land/p/demo/uassert/gno.mod +++ b/examples/gno.land/p/demo/uassert/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/uassert -require gno.land/p/demo/diff v0.0.0-latest diff --git a/examples/gno.land/p/demo/urequire/gno.mod b/examples/gno.land/p/demo/urequire/gno.mod index 9689a2222ac..6120cc45db1 100644 --- a/examples/gno.land/p/demo/urequire/gno.mod +++ b/examples/gno.land/p/demo/urequire/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/urequire -require gno.land/p/demo/uassert v0.0.0-latest diff --git a/examples/gno.land/p/demo/watchdog/gno.mod b/examples/gno.land/p/demo/watchdog/gno.mod index 29005441401..a7e91a9aeae 100644 --- a/examples/gno.land/p/demo/watchdog/gno.mod +++ b/examples/gno.land/p/demo/watchdog/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/watchdog -require gno.land/p/demo/uassert v0.0.0-latest diff --git a/examples/gno.land/p/gov/executor/gno.mod b/examples/gno.land/p/gov/executor/gno.mod index 99f2ab3610b..43f8bed4bdc 100644 --- a/examples/gno.land/p/gov/executor/gno.mod +++ b/examples/gno.land/p/gov/executor/gno.mod @@ -1,7 +1,2 @@ module gno.land/p/gov/executor -require ( - gno.land/p/demo/context v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/p/moul/helplink/gno.mod b/examples/gno.land/p/moul/helplink/gno.mod index 1b106749260..93dcb4da1eb 100644 --- a/examples/gno.land/p/moul/helplink/gno.mod +++ b/examples/gno.land/p/moul/helplink/gno.mod @@ -1,6 +1,2 @@ module gno.land/p/moul/helplink -require ( - gno.land/p/demo/urequire v0.0.0-latest - gno.land/p/moul/txlink v0.0.0-latest -) diff --git a/examples/gno.land/p/moul/printfdebugging/gno.mod b/examples/gno.land/p/moul/printfdebugging/gno.mod index 2cf6aa09e61..e2ffd627bc2 100644 --- a/examples/gno.land/p/moul/printfdebugging/gno.mod +++ b/examples/gno.land/p/moul/printfdebugging/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/demo/printfdebugging -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/moul/txlink/gno.mod b/examples/gno.land/p/moul/txlink/gno.mod index 6110464316f..4095169389d 100644 --- a/examples/gno.land/p/moul/txlink/gno.mod +++ b/examples/gno.land/p/moul/txlink/gno.mod @@ -1,3 +1,2 @@ module gno.land/p/moul/txlink -require gno.land/p/demo/urequire v0.0.0-latest diff --git a/examples/gno.land/p/nt/poa/gno.mod b/examples/gno.land/p/nt/poa/gno.mod index 5c1b75eb05a..2cf88fcb49f 100644 --- a/examples/gno.land/p/nt/poa/gno.mod +++ b/examples/gno.land/p/nt/poa/gno.mod @@ -1,10 +1,2 @@ module gno.land/p/nt/poa -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest - gno.land/p/sys/validators v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/art/gnoface/gno.mod b/examples/gno.land/r/demo/art/gnoface/gno.mod index 072c98f3bd6..47a7b452b7b 100644 --- a/examples/gno.land/r/demo/art/gnoface/gno.mod +++ b/examples/gno.land/r/demo/art/gnoface/gno.mod @@ -1,7 +1,2 @@ module gno.land/r/demo/art/gnoface -require ( - gno.land/p/demo/entropy v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/art/millipede/gno.mod b/examples/gno.land/r/demo/art/millipede/gno.mod index 7cd604206fa..4d12356936f 100644 --- a/examples/gno.land/r/demo/art/millipede/gno.mod +++ b/examples/gno.land/r/demo/art/millipede/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/art/millipede -require ( - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/bar20/gno.mod b/examples/gno.land/r/demo/bar20/gno.mod index 2ec82d7be0b..5f078cc124c 100644 --- a/examples/gno.land/r/demo/bar20/gno.mod +++ b/examples/gno.land/r/demo/bar20/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/demo/bar20 -require ( - gno.land/p/demo/grc/grc20 v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/boards/gno.mod b/examples/gno.land/r/demo/boards/gno.mod index 24fea7ce853..2212876335b 100644 --- a/examples/gno.land/r/demo/boards/gno.mod +++ b/examples/gno.land/r/demo/boards/gno.mod @@ -1,7 +1,2 @@ module gno.land/r/demo/boards -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/moul/txlink v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/daoweb/gno.mod b/examples/gno.land/r/demo/daoweb/gno.mod index bc781b311dc..504ba6df0de 100644 --- a/examples/gno.land/r/demo/daoweb/gno.mod +++ b/examples/gno.land/r/demo/daoweb/gno.mod @@ -1,7 +1,2 @@ module gno.land/r/demo/daoweb -require ( - gno.land/p/demo/dao v0.0.0-latest - gno.land/p/demo/json v0.0.0-latest - gno.land/r/gov/dao/bridge v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/disperse/gno.mod b/examples/gno.land/r/demo/disperse/gno.mod index 0ba9c88810a..c739eed9d06 100644 --- a/examples/gno.land/r/demo/disperse/gno.mod +++ b/examples/gno.land/r/demo/disperse/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/demo/disperse -require gno.land/r/demo/grc20factory v0.0.0-latest diff --git a/examples/gno.land/r/demo/echo/gno.mod b/examples/gno.land/r/demo/echo/gno.mod index 4ca5ccab6e0..7f93ddcd0d5 100644 --- a/examples/gno.land/r/demo/echo/gno.mod +++ b/examples/gno.land/r/demo/echo/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/demo/echo -require gno.land/p/demo/urequire v0.0.0-latest diff --git a/examples/gno.land/r/demo/foo1155/gno.mod b/examples/gno.land/r/demo/foo1155/gno.mod index 0a405c5b4a2..9611ab03c71 100644 --- a/examples/gno.land/r/demo/foo1155/gno.mod +++ b/examples/gno.land/r/demo/foo1155/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/demo/foo1155 -require ( - gno.land/p/demo/grc/grc1155 v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/users v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/foo20/gno.mod b/examples/gno.land/r/demo/foo20/gno.mod index 4035f9b1200..6297a2b21ab 100644 --- a/examples/gno.land/r/demo/foo20/gno.mod +++ b/examples/gno.land/r/demo/foo20/gno.mod @@ -1,11 +1,2 @@ module gno.land/r/demo/foo20 -require ( - gno.land/p/demo/grc/grc20 v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/users v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/foo721/gno.mod b/examples/gno.land/r/demo/foo721/gno.mod index e013677379d..fda752e2efc 100644 --- a/examples/gno.land/r/demo/foo721/gno.mod +++ b/examples/gno.land/r/demo/foo721/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/demo/foo721 -require ( - gno.land/p/demo/grc/grc721 v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/users v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/games/dice_roller/gno.mod b/examples/gno.land/r/demo/games/dice_roller/gno.mod index 75c6473fa3e..44f4264e891 100644 --- a/examples/gno.land/r/demo/games/dice_roller/gno.mod +++ b/examples/gno.land/r/demo/games/dice_roller/gno.mod @@ -1,11 +1,2 @@ module gno.land/r/demo/games/dice_roller -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/entropy v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/games/shifumi/gno.mod b/examples/gno.land/r/demo/games/shifumi/gno.mod index 7a4fc173d3d..8489aecff28 100644 --- a/examples/gno.land/r/demo/games/shifumi/gno.mod +++ b/examples/gno.land/r/demo/games/shifumi/gno.mod @@ -1,7 +1,2 @@ module gno.land/r/demo/games/shifumi -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/grc20factory/gno.mod b/examples/gno.land/r/demo/grc20factory/gno.mod index 8d0fbd0c46b..ca1b6adc29d 100644 --- a/examples/gno.land/r/demo/grc20factory/gno.mod +++ b/examples/gno.land/r/demo/grc20factory/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/demo/grc20factory -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/grc/grc20 v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/groups/gno.mod b/examples/gno.land/r/demo/groups/gno.mod index fc6756e13e2..34991b9781f 100644 --- a/examples/gno.land/r/demo/groups/gno.mod +++ b/examples/gno.land/r/demo/groups/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/groups -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/keystore/gno.mod b/examples/gno.land/r/demo/keystore/gno.mod index 49b0f3494a4..32d0f52bf7a 100644 --- a/examples/gno.land/r/demo/keystore/gno.mod +++ b/examples/gno.land/r/demo/keystore/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/demo/keystore -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/math_eval/gno.mod b/examples/gno.land/r/demo/math_eval/gno.mod index 0e3fcfe6e9b..f581a37cfed 100644 --- a/examples/gno.land/r/demo/math_eval/gno.mod +++ b/examples/gno.land/r/demo/math_eval/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/math_eval -require ( - gno.land/p/demo/math_eval/int32 v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/memeland/gno.mod b/examples/gno.land/r/demo/memeland/gno.mod index 5c73379519b..194c5d3c2ee 100644 --- a/examples/gno.land/r/demo/memeland/gno.mod +++ b/examples/gno.land/r/demo/memeland/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/demo/memeland -require gno.land/p/demo/memeland v0.0.0-latest diff --git a/examples/gno.land/r/demo/microblog/gno.mod b/examples/gno.land/r/demo/microblog/gno.mod index 26349e481d4..b7359e953c0 100644 --- a/examples/gno.land/r/demo/microblog/gno.mod +++ b/examples/gno.land/r/demo/microblog/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/demo/microblog -require ( - gno.land/p/demo/microblog v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/nft/gno.mod b/examples/gno.land/r/demo/nft/gno.mod index 89e0055be51..a2fa32c1079 100644 --- a/examples/gno.land/r/demo/nft/gno.mod +++ b/examples/gno.land/r/demo/nft/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/nft -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/grc/grc721 v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/profile/gno.mod b/examples/gno.land/r/demo/profile/gno.mod index e7feac5d680..0c56e34f8c1 100644 --- a/examples/gno.land/r/demo/profile/gno.mod +++ b/examples/gno.land/r/demo/profile/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/demo/profile -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/mux v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/releases_example/gno.mod b/examples/gno.land/r/demo/releases_example/gno.mod index 22f640fe797..4afb2415a20 100644 --- a/examples/gno.land/r/demo/releases_example/gno.mod +++ b/examples/gno.land/r/demo/releases_example/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/demo/releases_example -require gno.land/p/demo/releases v0.0.0-latest diff --git a/examples/gno.land/r/demo/tamagotchi/gno.mod b/examples/gno.land/r/demo/tamagotchi/gno.mod index b7a2deea2c2..3db4e417f75 100644 --- a/examples/gno.land/r/demo/tamagotchi/gno.mod +++ b/examples/gno.land/r/demo/tamagotchi/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/tamagotchi -require ( - gno.land/p/demo/tamagotchi v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/tests/crossrealm/gno.mod b/examples/gno.land/r/demo/tests/crossrealm/gno.mod index 71a89ec2ec5..44dfffefb29 100644 --- a/examples/gno.land/r/demo/tests/crossrealm/gno.mod +++ b/examples/gno.land/r/demo/tests/crossrealm/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/tests/crossrealm -require ( - gno.land/p/demo/tests/p_crossrealm v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/tests/gno.mod b/examples/gno.land/r/demo/tests/gno.mod index c51571e7d04..f039a08638f 100644 --- a/examples/gno.land/r/demo/tests/gno.mod +++ b/examples/gno.land/r/demo/tests/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/tests -require ( - gno.land/p/demo/nestedpkg v0.0.0-latest - gno.land/r/demo/tests/subtests v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/tests_foo/gno.mod b/examples/gno.land/r/demo/tests_foo/gno.mod index 226271ae4b0..e953ecf239e 100644 --- a/examples/gno.land/r/demo/tests_foo/gno.mod +++ b/examples/gno.land/r/demo/tests_foo/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/demo/tests_foo -require gno.land/r/demo/tests v0.0.0-latest diff --git a/examples/gno.land/r/demo/todolist/gno.mod b/examples/gno.land/r/demo/todolist/gno.mod index 36909859a6f..4ab7dcde7b3 100644 --- a/examples/gno.land/r/demo/todolist/gno.mod +++ b/examples/gno.land/r/demo/todolist/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/demo/todolist -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest - gno.land/p/demo/todolist v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/types/gno.mod b/examples/gno.land/r/demo/types/gno.mod index 0e86e5d5676..ea2771c63e1 100644 --- a/examples/gno.land/r/demo/types/gno.mod +++ b/examples/gno.land/r/demo/types/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/demo/types -require gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/r/demo/ui/gno.mod b/examples/gno.land/r/demo/ui/gno.mod index 0ef5d9dd40e..b37c6d5bc09 100644 --- a/examples/gno.land/r/demo/ui/gno.mod +++ b/examples/gno.land/r/demo/ui/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/demo/ui -require ( - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ui v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/userbook/gno.mod b/examples/gno.land/r/demo/userbook/gno.mod index 213586d12ee..fe64702a8d2 100644 --- a/examples/gno.land/r/demo/userbook/gno.mod +++ b/examples/gno.land/r/demo/userbook/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/demo/userbook -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/mux v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/users/gno.mod b/examples/gno.land/r/demo/users/gno.mod index f2f88a0f993..b4b901192cc 100644 --- a/examples/gno.land/r/demo/users/gno.mod +++ b/examples/gno.land/r/demo/users/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/demo/users -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/avl/pager v0.0.0-latest - gno.land/p/demo/avlhelpers v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/wugnot/gno.mod b/examples/gno.land/r/demo/wugnot/gno.mod index f076e90e068..4e48a37e650 100644 --- a/examples/gno.land/r/demo/wugnot/gno.mod +++ b/examples/gno.land/r/demo/wugnot/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/demo/wugnot -require ( - gno.land/p/demo/grc/grc20 v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/users v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/blog/gno.mod b/examples/gno.land/r/gnoland/blog/gno.mod index 8a4c5851b4c..03240bf9809 100644 --- a/examples/gno.land/r/gnoland/blog/gno.mod +++ b/examples/gno.land/r/gnoland/blog/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/gnoland/blog -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/blog v0.0.0-latest - gno.land/p/demo/dao v0.0.0-latest - gno.land/r/gov/dao/bridge v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/events/gno.mod b/examples/gno.land/r/gnoland/events/gno.mod index bd3e4652b04..84872196b1a 100644 --- a/examples/gno.land/r/gnoland/events/gno.mod +++ b/examples/gno.land/r/gnoland/events/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/gnoland/events -require ( - gno.land/p/demo/ownable/exts/authorizable v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/faucet/gno.mod b/examples/gno.land/r/gnoland/faucet/gno.mod index 693b0e795cf..ebfa55279bb 100644 --- a/examples/gno.land/r/gnoland/faucet/gno.mod +++ b/examples/gno.land/r/gnoland/faucet/gno.mod @@ -1,7 +1,2 @@ module gno.land/r/gnoland/faucet -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/ghverify/gno.mod b/examples/gno.land/r/gnoland/ghverify/gno.mod index 386bd9293d2..7e93f513cde 100644 --- a/examples/gno.land/r/gnoland/ghverify/gno.mod +++ b/examples/gno.land/r/gnoland/ghverify/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/gnoland/ghverify -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/gnorkle/feeds/static v0.0.0-latest - gno.land/p/demo/gnorkle/gnorkle v0.0.0-latest - gno.land/p/demo/gnorkle/message v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/home/gno.mod b/examples/gno.land/r/gnoland/home/gno.mod index c208ad421c9..44eb4817093 100644 --- a/examples/gno.land/r/gnoland/home/gno.mod +++ b/examples/gno.land/r/gnoland/home/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/gnoland/home -require ( - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/ui v0.0.0-latest - gno.land/r/gnoland/blog v0.0.0-latest - gno.land/r/gnoland/events v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/monit/gno.mod b/examples/gno.land/r/gnoland/monit/gno.mod index e67fdaa7d71..8578a55a5ec 100644 --- a/examples/gno.land/r/gnoland/monit/gno.mod +++ b/examples/gno.land/r/gnoland/monit/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/gnoland/monit -require ( - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/demo/watchdog v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/pages/gno.mod b/examples/gno.land/r/gnoland/pages/gno.mod index 31e9ad2c85b..aa3a0f5a78b 100644 --- a/examples/gno.land/r/gnoland/pages/gno.mod +++ b/examples/gno.land/r/gnoland/pages/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/gnoland/pages -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/blog v0.0.0-latest -) diff --git a/examples/gno.land/r/gnoland/valopers/v2/gno.mod b/examples/gno.land/r/gnoland/valopers/v2/gno.mod index 099a8406db4..fa17b097c4b 100644 --- a/examples/gno.land/r/gnoland/valopers/v2/gno.mod +++ b/examples/gno.land/r/gnoland/valopers/v2/gno.mod @@ -1,12 +1,2 @@ module gno.land/r/gnoland/valopers/v2 -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/dao v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/sys/validators v0.0.0-latest - gno.land/r/gov/dao/bridge v0.0.0-latest - gno.land/r/sys/validators/v2 v0.0.0-latest -) diff --git a/examples/gno.land/r/gov/dao/bridge/gno.mod b/examples/gno.land/r/gov/dao/bridge/gno.mod index 3382557573a..c539434a0cc 100644 --- a/examples/gno.land/r/gov/dao/bridge/gno.mod +++ b/examples/gno.land/r/gov/dao/bridge/gno.mod @@ -1,11 +1,2 @@ module gno.land/r/gov/dao/bridge -require ( - gno.land/p/demo/dao v0.0.0-latest - gno.land/p/demo/membstore v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest - gno.land/r/gov/dao/v2 v0.0.0-latest -) diff --git a/examples/gno.land/r/gov/dao/v2/gno.mod b/examples/gno.land/r/gov/dao/v2/gno.mod index bc379bf18df..57ab433b7c4 100644 --- a/examples/gno.land/r/gov/dao/v2/gno.mod +++ b/examples/gno.land/r/gov/dao/v2/gno.mod @@ -1,10 +1,2 @@ module gno.land/r/gov/dao/v2 -require ( - gno.land/p/demo/combinederr v0.0.0-latest - gno.land/p/demo/dao v0.0.0-latest - gno.land/p/demo/membstore v0.0.0-latest - gno.land/p/demo/simpledao v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/gov/executor v0.0.0-latest -) diff --git a/examples/gno.land/r/leon/home/gno.mod b/examples/gno.land/r/leon/home/gno.mod index 48cf64a9d0a..2b884ec1723 100644 --- a/examples/gno.land/r/leon/home/gno.mod +++ b/examples/gno.land/r/leon/home/gno.mod @@ -1,8 +1,2 @@ module gno.land/r/leon/home -require ( - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/r/demo/art/gnoface v0.0.0-latest - gno.land/r/demo/art/millipede v0.0.0-latest - gno.land/r/leon/config v0.0.0-latest -) diff --git a/examples/gno.land/r/manfred/home/gno.mod b/examples/gno.land/r/manfred/home/gno.mod index 6e7aac70cc7..cd6a56b786d 100644 --- a/examples/gno.land/r/manfred/home/gno.mod +++ b/examples/gno.land/r/manfred/home/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/manfred/home -require gno.land/r/manfred/config v0.0.0-latest diff --git a/examples/gno.land/r/manfred/present/gno.mod b/examples/gno.land/r/manfred/present/gno.mod index 5d50447e0e0..32dc0482f43 100644 --- a/examples/gno.land/r/manfred/present/gno.mod +++ b/examples/gno.land/r/manfred/present/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/manfred/present -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/blog v0.0.0-latest -) diff --git a/examples/gno.land/r/morgan/guestbook/gno.mod b/examples/gno.land/r/morgan/guestbook/gno.mod index 2591643d33d..6b1ebdd46f2 100644 --- a/examples/gno.land/r/morgan/guestbook/gno.mod +++ b/examples/gno.land/r/morgan/guestbook/gno.mod @@ -1,7 +1,2 @@ module gno.land/r/morgan/guestbook -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest -) diff --git a/examples/gno.land/r/stefann/home/gno.mod b/examples/gno.land/r/stefann/home/gno.mod index dd556e7f817..034684ff6c5 100644 --- a/examples/gno.land/r/stefann/home/gno.mod +++ b/examples/gno.land/r/stefann/home/gno.mod @@ -1,9 +1,2 @@ module gno.land/r/stefann/home -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/r/stefann/registry v0.0.0-latest -) diff --git a/examples/gno.land/r/stefann/registry/gno.mod b/examples/gno.land/r/stefann/registry/gno.mod index 5ed3e4916e2..8e956ac45da 100644 --- a/examples/gno.land/r/stefann/registry/gno.mod +++ b/examples/gno.land/r/stefann/registry/gno.mod @@ -1,3 +1,2 @@ module gno.land/r/stefann/registry -require gno.land/p/demo/ownable v0.0.0-latest diff --git a/examples/gno.land/r/sys/users/gno.mod b/examples/gno.land/r/sys/users/gno.mod index 774a364a272..b5fe21a3b9c 100644 --- a/examples/gno.land/r/sys/users/gno.mod +++ b/examples/gno.land/r/sys/users/gno.mod @@ -1,6 +1,2 @@ module gno.land/r/sys/users -require ( - gno.land/p/demo/ownable v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/sys/validators/v2/gno.mod b/examples/gno.land/r/sys/validators/v2/gno.mod index db94a208902..63903cf20b1 100644 --- a/examples/gno.land/r/sys/validators/v2/gno.mod +++ b/examples/gno.land/r/sys/validators/v2/gno.mod @@ -1,13 +1,2 @@ module gno.land/r/sys/validators/v2 -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/dao v0.0.0-latest - gno.land/p/demo/seqid v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/uassert v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/nt/poa v0.0.0-latest - gno.land/p/sys/validators v0.0.0-latest - gno.land/r/gov/dao/bridge v0.0.0-latest -) diff --git a/examples/gno.land/r/x/manfred_outfmt/gno.mod b/examples/gno.land/r/x/manfred_outfmt/gno.mod index 7044f0f72b3..c6d2c15d592 100644 --- a/examples/gno.land/r/x/manfred_outfmt/gno.mod +++ b/examples/gno.land/r/x/manfred_outfmt/gno.mod @@ -2,4 +2,3 @@ module gno.land/r/x/manfred_outfmt -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/gnovm/pkg/gnomod/parse.go b/gnovm/pkg/gnomod/parse.go index b44a1f1a6c9..e3a3fbcaeea 100644 --- a/gnovm/pkg/gnomod/parse.go +++ b/gnovm/pkg/gnomod/parse.go @@ -105,7 +105,7 @@ func Parse(file string, data []byte) (*File, error) { Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), }) continue - case "module", "require", "replace": + case "module", "replace": for _, l := range x.Line { f.add(&errs, x, l, x.Token[0], l.Token) } @@ -180,10 +180,6 @@ func (f *File) add(errs *modfile.ErrorList, block *modfile.LineBlock, line *modf } f.Module.Mod = module.Version{Path: s} - case "require": - // ignore requires as it's not supported by gno - return - case "replace": replace, wrappederr := parseReplace(f.Syntax.Name, line, verb, args) if wrappederr != nil { diff --git a/gnovm/pkg/gnomod/parse_test.go b/gnovm/pkg/gnomod/parse_test.go index 35861fb4c55..ec54c6424fc 100644 --- a/gnovm/pkg/gnomod/parse_test.go +++ b/gnovm/pkg/gnomod/parse_test.go @@ -194,17 +194,30 @@ func TestParseGnoMod(t *testing.T) { modPath: filepath.Join(pkgDir, "gno.mod"), }, { - desc: "error parsing gno.mod", + desc: "valid gno.mod file with replace", + modData: `module foo + replace bar => ../bar`, + modPath: filepath.Join(pkgDir, "gno.mod"), + }, + { + desc: "error bad module directive", modData: `module foo v0.0.0`, modPath: filepath.Join(pkgDir, "gno.mod"), errShouldContain: "error parsing gno.mod file at", }, { - desc: "error validating gno.mod", - modData: `require bar v0.0.0`, + desc: "error gno.mod without module", + modData: `replace bar => ../bar`, modPath: filepath.Join(pkgDir, "gno.mod"), errShouldContain: "requires module", }, + { + desc: "error gno.mod with require", + modData: `module foo + require bar v0.0.0`, + modPath: filepath.Join(pkgDir, "gno.mod"), + errShouldContain: "unknown directive: require", + }, } { t.Run(tc.desc, func(t *testing.T) { // Create test dir From 409bb3c0884d1c57a0682bce545405ae725e278d Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 8 Nov 2024 22:38:56 +0100 Subject: [PATCH 12/51] chore: tidy Signed-off-by: Norman Meier --- examples/gno.land/p/demo/acl/gno.mod | 1 - examples/gno.land/p/demo/avl/pager/gno.mod | 1 - examples/gno.land/p/demo/avlhelpers/gno.mod | 1 - examples/gno.land/p/demo/blog/gno.mod | 1 - examples/gno.land/p/demo/dao/gno.mod | 1 - examples/gno.land/p/demo/dom/gno.mod | 1 - examples/gno.land/p/demo/fqname/gno.mod | 1 - examples/gno.land/p/demo/gnorkle/agent/gno.mod | 1 - examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod | 1 - examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod | 1 - examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod | 1 - examples/gno.land/p/demo/gnorkle/message/gno.mod | 1 - examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod | 1 - examples/gno.land/p/demo/grc/grc1155/gno.mod | 1 - examples/gno.land/p/demo/grc/grc20/gno.mod | 1 - examples/gno.land/p/demo/grc/grc721/gno.mod | 1 - examples/gno.land/p/demo/grc/grc777/gno.mod | 1 - examples/gno.land/p/demo/groups/gno.mod | 1 - examples/gno.land/p/demo/int256/gno.mod | 1 - examples/gno.land/p/demo/json/gno.mod | 1 - examples/gno.land/p/demo/math_eval/int32/gno.mod | 1 - examples/gno.land/p/demo/membstore/gno.mod | 1 - examples/gno.land/p/demo/memeland/gno.mod | 1 - examples/gno.land/p/demo/microblog/gno.mod | 1 - examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod | 1 - examples/gno.land/p/demo/ownable/gno.mod | 1 - examples/gno.land/p/demo/pausable/gno.mod | 1 - examples/gno.land/p/demo/seqid/gno.mod | 1 - examples/gno.land/p/demo/simpledao/gno.mod | 1 - examples/gno.land/p/demo/subscription/lifetime/gno.mod | 1 - examples/gno.land/p/demo/subscription/recurring/gno.mod | 1 - examples/gno.land/p/demo/svg/gno.mod | 1 - examples/gno.land/p/demo/tamagotchi/gno.mod | 1 - examples/gno.land/p/demo/tests/gno.mod | 1 - examples/gno.land/p/demo/todolist/gno.mod | 1 - examples/gno.land/p/demo/uassert/gno.mod | 1 - examples/gno.land/p/demo/urequire/gno.mod | 1 - examples/gno.land/p/demo/watchdog/gno.mod | 1 - examples/gno.land/p/gov/executor/gno.mod | 1 - examples/gno.land/p/moul/helplink/gno.mod | 1 - examples/gno.land/p/moul/printfdebugging/gno.mod | 1 - examples/gno.land/p/moul/txlink/gno.mod | 1 - examples/gno.land/p/nt/poa/gno.mod | 1 - examples/gno.land/r/demo/art/gnoface/gno.mod | 1 - examples/gno.land/r/demo/art/millipede/gno.mod | 1 - examples/gno.land/r/demo/bar20/gno.mod | 1 - examples/gno.land/r/demo/boards/gno.mod | 1 - examples/gno.land/r/demo/daoweb/gno.mod | 1 - examples/gno.land/r/demo/disperse/gno.mod | 1 - examples/gno.land/r/demo/echo/gno.mod | 1 - examples/gno.land/r/demo/foo1155/gno.mod | 1 - examples/gno.land/r/demo/foo20/gno.mod | 1 - examples/gno.land/r/demo/foo721/gno.mod | 1 - examples/gno.land/r/demo/games/dice_roller/gno.mod | 1 - examples/gno.land/r/demo/games/shifumi/gno.mod | 1 - examples/gno.land/r/demo/grc20factory/gno.mod | 1 - examples/gno.land/r/demo/groups/gno.mod | 1 - examples/gno.land/r/demo/keystore/gno.mod | 1 - examples/gno.land/r/demo/math_eval/gno.mod | 1 - examples/gno.land/r/demo/memeland/gno.mod | 1 - examples/gno.land/r/demo/microblog/gno.mod | 1 - examples/gno.land/r/demo/nft/gno.mod | 1 - examples/gno.land/r/demo/profile/gno.mod | 1 - examples/gno.land/r/demo/releases_example/gno.mod | 1 - examples/gno.land/r/demo/tamagotchi/gno.mod | 1 - examples/gno.land/r/demo/tests/crossrealm/gno.mod | 1 - examples/gno.land/r/demo/tests/gno.mod | 1 - examples/gno.land/r/demo/tests_foo/gno.mod | 1 - examples/gno.land/r/demo/todolist/gno.mod | 1 - examples/gno.land/r/demo/types/gno.mod | 1 - examples/gno.land/r/demo/ui/gno.mod | 1 - examples/gno.land/r/demo/userbook/gno.mod | 1 - examples/gno.land/r/demo/users/gno.mod | 1 - examples/gno.land/r/demo/wugnot/gno.mod | 1 - examples/gno.land/r/gnoland/blog/gno.mod | 1 - examples/gno.land/r/gnoland/events/gno.mod | 1 - examples/gno.land/r/gnoland/faucet/gno.mod | 1 - examples/gno.land/r/gnoland/ghverify/gno.mod | 1 - examples/gno.land/r/gnoland/home/gno.mod | 1 - examples/gno.land/r/gnoland/monit/gno.mod | 1 - examples/gno.land/r/gnoland/pages/gno.mod | 1 - examples/gno.land/r/gnoland/valopers/v2/gno.mod | 1 - examples/gno.land/r/gov/dao/bridge/gno.mod | 1 - examples/gno.land/r/gov/dao/v2/gno.mod | 1 - examples/gno.land/r/leon/home/gno.mod | 1 - examples/gno.land/r/manfred/home/gno.mod | 1 - examples/gno.land/r/manfred/present/gno.mod | 1 - examples/gno.land/r/morgan/guestbook/gno.mod | 1 - examples/gno.land/r/stefann/home/gno.mod | 1 - examples/gno.land/r/stefann/registry/gno.mod | 1 - examples/gno.land/r/sys/users/gno.mod | 1 - examples/gno.land/r/sys/validators/v2/gno.mod | 1 - examples/gno.land/r/x/manfred_outfmt/gno.mod | 1 - 93 files changed, 93 deletions(-) diff --git a/examples/gno.land/p/demo/acl/gno.mod b/examples/gno.land/p/demo/acl/gno.mod index 48010dc0536..04fbf9043c4 100644 --- a/examples/gno.land/p/demo/acl/gno.mod +++ b/examples/gno.land/p/demo/acl/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/acl - diff --git a/examples/gno.land/p/demo/avl/pager/gno.mod b/examples/gno.land/p/demo/avl/pager/gno.mod index 785e67cb125..020b809b208 100644 --- a/examples/gno.land/p/demo/avl/pager/gno.mod +++ b/examples/gno.land/p/demo/avl/pager/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/avl/pager - diff --git a/examples/gno.land/p/demo/avlhelpers/gno.mod b/examples/gno.land/p/demo/avlhelpers/gno.mod index 0d5a22959ea..5adffd13a43 100644 --- a/examples/gno.land/p/demo/avlhelpers/gno.mod +++ b/examples/gno.land/p/demo/avlhelpers/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/avlhelpers - diff --git a/examples/gno.land/p/demo/blog/gno.mod b/examples/gno.land/p/demo/blog/gno.mod index fa42570f5f9..e4e3def299b 100644 --- a/examples/gno.land/p/demo/blog/gno.mod +++ b/examples/gno.land/p/demo/blog/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/blog - diff --git a/examples/gno.land/p/demo/dao/gno.mod b/examples/gno.land/p/demo/dao/gno.mod index 107b400286d..fbb23299116 100644 --- a/examples/gno.land/p/demo/dao/gno.mod +++ b/examples/gno.land/p/demo/dao/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/dao - diff --git a/examples/gno.land/p/demo/dom/gno.mod b/examples/gno.land/p/demo/dom/gno.mod index 2ce66f123d8..bd8bba14d06 100644 --- a/examples/gno.land/p/demo/dom/gno.mod +++ b/examples/gno.land/p/demo/dom/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/dom - diff --git a/examples/gno.land/p/demo/fqname/gno.mod b/examples/gno.land/p/demo/fqname/gno.mod index f9684cb824b..afee55e0b7b 100644 --- a/examples/gno.land/p/demo/fqname/gno.mod +++ b/examples/gno.land/p/demo/fqname/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/fqname - diff --git a/examples/gno.land/p/demo/gnorkle/agent/gno.mod b/examples/gno.land/p/demo/gnorkle/agent/gno.mod index be54d8c850f..e784354c35e 100644 --- a/examples/gno.land/p/demo/gnorkle/agent/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/agent/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/gnorkle/agent - diff --git a/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod b/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod index 69b58cf85f1..05363a3cd06 100644 --- a/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/feeds/static/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/gnorkle/feeds/static - diff --git a/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod b/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod index 77cff50c11e..ce2c2c3706d 100644 --- a/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/gnorkle/gnorkle - diff --git a/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod b/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod index e9454c65385..8cf5a9a30d8 100644 --- a/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/ingesters/single/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/gnorkle/ingesters/single - diff --git a/examples/gno.land/p/demo/gnorkle/message/gno.mod b/examples/gno.land/p/demo/gnorkle/message/gno.mod index fdff0ee63f2..5544d0eb873 100644 --- a/examples/gno.land/p/demo/gnorkle/message/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/message/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/gnorkle/message - diff --git a/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod b/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod index d37382264ee..b842e2b514c 100644 --- a/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/storage/simple/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/gnorkle/storage/simple - diff --git a/examples/gno.land/p/demo/grc/grc1155/gno.mod b/examples/gno.land/p/demo/grc/grc1155/gno.mod index 24cc267c662..1c3ec6360eb 100644 --- a/examples/gno.land/p/demo/grc/grc1155/gno.mod +++ b/examples/gno.land/p/demo/grc/grc1155/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/grc/grc1155 - diff --git a/examples/gno.land/p/demo/grc/grc20/gno.mod b/examples/gno.land/p/demo/grc/grc20/gno.mod index 6400797762e..37377b32e73 100644 --- a/examples/gno.land/p/demo/grc/grc20/gno.mod +++ b/examples/gno.land/p/demo/grc/grc20/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/grc/grc20 - diff --git a/examples/gno.land/p/demo/grc/grc721/gno.mod b/examples/gno.land/p/demo/grc/grc721/gno.mod index 4dc957f19f5..f27caee5282 100644 --- a/examples/gno.land/p/demo/grc/grc721/gno.mod +++ b/examples/gno.land/p/demo/grc/grc721/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/grc/grc721 - diff --git a/examples/gno.land/p/demo/grc/grc777/gno.mod b/examples/gno.land/p/demo/grc/grc777/gno.mod index 698bf465c9a..da5c762b2ec 100644 --- a/examples/gno.land/p/demo/grc/grc777/gno.mod +++ b/examples/gno.land/p/demo/grc/grc777/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/grc/grc777 - diff --git a/examples/gno.land/p/demo/groups/gno.mod b/examples/gno.land/p/demo/groups/gno.mod index 437e5504196..d33df3866fa 100644 --- a/examples/gno.land/p/demo/groups/gno.mod +++ b/examples/gno.land/p/demo/groups/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/groups - diff --git a/examples/gno.land/p/demo/int256/gno.mod b/examples/gno.land/p/demo/int256/gno.mod index 5dba413c025..33fb0bc4e72 100644 --- a/examples/gno.land/p/demo/int256/gno.mod +++ b/examples/gno.land/p/demo/int256/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/int256 - diff --git a/examples/gno.land/p/demo/json/gno.mod b/examples/gno.land/p/demo/json/gno.mod index 549a1d9739a..831fa56c0f9 100644 --- a/examples/gno.land/p/demo/json/gno.mod +++ b/examples/gno.land/p/demo/json/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/json - diff --git a/examples/gno.land/p/demo/math_eval/int32/gno.mod b/examples/gno.land/p/demo/math_eval/int32/gno.mod index 2157ad2f1d2..c4e4bc8f454 100644 --- a/examples/gno.land/p/demo/math_eval/int32/gno.mod +++ b/examples/gno.land/p/demo/math_eval/int32/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/math_eval/int32 - diff --git a/examples/gno.land/p/demo/membstore/gno.mod b/examples/gno.land/p/demo/membstore/gno.mod index 1e30257e2fb..007e7a5d883 100644 --- a/examples/gno.land/p/demo/membstore/gno.mod +++ b/examples/gno.land/p/demo/membstore/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/membstore - diff --git a/examples/gno.land/p/demo/memeland/gno.mod b/examples/gno.land/p/demo/memeland/gno.mod index 283867d7dcd..06cc8fbf487 100644 --- a/examples/gno.land/p/demo/memeland/gno.mod +++ b/examples/gno.land/p/demo/memeland/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/memeland - diff --git a/examples/gno.land/p/demo/microblog/gno.mod b/examples/gno.land/p/demo/microblog/gno.mod index f77774d1484..a285ef5f903 100644 --- a/examples/gno.land/p/demo/microblog/gno.mod +++ b/examples/gno.land/p/demo/microblog/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/microblog - diff --git a/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod b/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod index d270555de06..0e8be79f130 100644 --- a/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod +++ b/examples/gno.land/p/demo/ownable/exts/authorizable/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/ownable/exts/authorizable - diff --git a/examples/gno.land/p/demo/ownable/gno.mod b/examples/gno.land/p/demo/ownable/gno.mod index f81528a1715..9a9abb1e661 100644 --- a/examples/gno.land/p/demo/ownable/gno.mod +++ b/examples/gno.land/p/demo/ownable/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/ownable - diff --git a/examples/gno.land/p/demo/pausable/gno.mod b/examples/gno.land/p/demo/pausable/gno.mod index 108dae847b9..a741342eb84 100644 --- a/examples/gno.land/p/demo/pausable/gno.mod +++ b/examples/gno.land/p/demo/pausable/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/pausable - diff --git a/examples/gno.land/p/demo/seqid/gno.mod b/examples/gno.land/p/demo/seqid/gno.mod index 4f4cd1f8a5a..63e6a1fb551 100644 --- a/examples/gno.land/p/demo/seqid/gno.mod +++ b/examples/gno.land/p/demo/seqid/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/seqid - diff --git a/examples/gno.land/p/demo/simpledao/gno.mod b/examples/gno.land/p/demo/simpledao/gno.mod index 4ddaa9f13ec..51de621cbec 100644 --- a/examples/gno.land/p/demo/simpledao/gno.mod +++ b/examples/gno.land/p/demo/simpledao/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/simpledao - diff --git a/examples/gno.land/p/demo/subscription/lifetime/gno.mod b/examples/gno.land/p/demo/subscription/lifetime/gno.mod index 8d7a2e7c38e..59b6c1cf001 100644 --- a/examples/gno.land/p/demo/subscription/lifetime/gno.mod +++ b/examples/gno.land/p/demo/subscription/lifetime/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/subscription/lifetime - diff --git a/examples/gno.land/p/demo/subscription/recurring/gno.mod b/examples/gno.land/p/demo/subscription/recurring/gno.mod index 96beb72dc31..356402978b5 100644 --- a/examples/gno.land/p/demo/subscription/recurring/gno.mod +++ b/examples/gno.land/p/demo/subscription/recurring/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/subscription/recurring - diff --git a/examples/gno.land/p/demo/svg/gno.mod b/examples/gno.land/p/demo/svg/gno.mod index ac804476fc3..b9dd7f47434 100644 --- a/examples/gno.land/p/demo/svg/gno.mod +++ b/examples/gno.land/p/demo/svg/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/svg - diff --git a/examples/gno.land/p/demo/tamagotchi/gno.mod b/examples/gno.land/p/demo/tamagotchi/gno.mod index bd17bd19a74..a9c6026629e 100644 --- a/examples/gno.land/p/demo/tamagotchi/gno.mod +++ b/examples/gno.land/p/demo/tamagotchi/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/tamagotchi - diff --git a/examples/gno.land/p/demo/tests/gno.mod b/examples/gno.land/p/demo/tests/gno.mod index 8c76f3f7519..a342a726f61 100644 --- a/examples/gno.land/p/demo/tests/gno.mod +++ b/examples/gno.land/p/demo/tests/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/tests - diff --git a/examples/gno.land/p/demo/todolist/gno.mod b/examples/gno.land/p/demo/todolist/gno.mod index f44b3d9e459..46d21bf0bc0 100644 --- a/examples/gno.land/p/demo/todolist/gno.mod +++ b/examples/gno.land/p/demo/todolist/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/todolist - diff --git a/examples/gno.land/p/demo/uassert/gno.mod b/examples/gno.land/p/demo/uassert/gno.mod index d8ba2f865ee..a70e7db825d 100644 --- a/examples/gno.land/p/demo/uassert/gno.mod +++ b/examples/gno.land/p/demo/uassert/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/uassert - diff --git a/examples/gno.land/p/demo/urequire/gno.mod b/examples/gno.land/p/demo/urequire/gno.mod index 6120cc45db1..e5336b2c80d 100644 --- a/examples/gno.land/p/demo/urequire/gno.mod +++ b/examples/gno.land/p/demo/urequire/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/urequire - diff --git a/examples/gno.land/p/demo/watchdog/gno.mod b/examples/gno.land/p/demo/watchdog/gno.mod index a7e91a9aeae..96fba14451b 100644 --- a/examples/gno.land/p/demo/watchdog/gno.mod +++ b/examples/gno.land/p/demo/watchdog/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/watchdog - diff --git a/examples/gno.land/p/gov/executor/gno.mod b/examples/gno.land/p/gov/executor/gno.mod index 43f8bed4bdc..5dbb6f7f85e 100644 --- a/examples/gno.land/p/gov/executor/gno.mod +++ b/examples/gno.land/p/gov/executor/gno.mod @@ -1,2 +1 @@ module gno.land/p/gov/executor - diff --git a/examples/gno.land/p/moul/helplink/gno.mod b/examples/gno.land/p/moul/helplink/gno.mod index 93dcb4da1eb..cb070b79d6a 100644 --- a/examples/gno.land/p/moul/helplink/gno.mod +++ b/examples/gno.land/p/moul/helplink/gno.mod @@ -1,2 +1 @@ module gno.land/p/moul/helplink - diff --git a/examples/gno.land/p/moul/printfdebugging/gno.mod b/examples/gno.land/p/moul/printfdebugging/gno.mod index e2ffd627bc2..4b8d0f3256c 100644 --- a/examples/gno.land/p/moul/printfdebugging/gno.mod +++ b/examples/gno.land/p/moul/printfdebugging/gno.mod @@ -1,2 +1 @@ module gno.land/p/demo/printfdebugging - diff --git a/examples/gno.land/p/moul/txlink/gno.mod b/examples/gno.land/p/moul/txlink/gno.mod index 4095169389d..ed16b8b74fd 100644 --- a/examples/gno.land/p/moul/txlink/gno.mod +++ b/examples/gno.land/p/moul/txlink/gno.mod @@ -1,2 +1 @@ module gno.land/p/moul/txlink - diff --git a/examples/gno.land/p/nt/poa/gno.mod b/examples/gno.land/p/nt/poa/gno.mod index 2cf88fcb49f..965eeb56aed 100644 --- a/examples/gno.land/p/nt/poa/gno.mod +++ b/examples/gno.land/p/nt/poa/gno.mod @@ -1,2 +1 @@ module gno.land/p/nt/poa - diff --git a/examples/gno.land/r/demo/art/gnoface/gno.mod b/examples/gno.land/r/demo/art/gnoface/gno.mod index 47a7b452b7b..9465af6216a 100644 --- a/examples/gno.land/r/demo/art/gnoface/gno.mod +++ b/examples/gno.land/r/demo/art/gnoface/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/art/gnoface - diff --git a/examples/gno.land/r/demo/art/millipede/gno.mod b/examples/gno.land/r/demo/art/millipede/gno.mod index 4d12356936f..3e5177efdcd 100644 --- a/examples/gno.land/r/demo/art/millipede/gno.mod +++ b/examples/gno.land/r/demo/art/millipede/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/art/millipede - diff --git a/examples/gno.land/r/demo/bar20/gno.mod b/examples/gno.land/r/demo/bar20/gno.mod index 5f078cc124c..e8ede1ea44f 100644 --- a/examples/gno.land/r/demo/bar20/gno.mod +++ b/examples/gno.land/r/demo/bar20/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/bar20 - diff --git a/examples/gno.land/r/demo/boards/gno.mod b/examples/gno.land/r/demo/boards/gno.mod index 2212876335b..dffb96740fc 100644 --- a/examples/gno.land/r/demo/boards/gno.mod +++ b/examples/gno.land/r/demo/boards/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/boards - diff --git a/examples/gno.land/r/demo/daoweb/gno.mod b/examples/gno.land/r/demo/daoweb/gno.mod index 504ba6df0de..74ae149cdb6 100644 --- a/examples/gno.land/r/demo/daoweb/gno.mod +++ b/examples/gno.land/r/demo/daoweb/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/daoweb - diff --git a/examples/gno.land/r/demo/disperse/gno.mod b/examples/gno.land/r/demo/disperse/gno.mod index c739eed9d06..06e81884dfa 100644 --- a/examples/gno.land/r/demo/disperse/gno.mod +++ b/examples/gno.land/r/demo/disperse/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/disperse - diff --git a/examples/gno.land/r/demo/echo/gno.mod b/examples/gno.land/r/demo/echo/gno.mod index 7f93ddcd0d5..f07d78943d1 100644 --- a/examples/gno.land/r/demo/echo/gno.mod +++ b/examples/gno.land/r/demo/echo/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/echo - diff --git a/examples/gno.land/r/demo/foo1155/gno.mod b/examples/gno.land/r/demo/foo1155/gno.mod index 9611ab03c71..eae12bcd1e3 100644 --- a/examples/gno.land/r/demo/foo1155/gno.mod +++ b/examples/gno.land/r/demo/foo1155/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/foo1155 - diff --git a/examples/gno.land/r/demo/foo20/gno.mod b/examples/gno.land/r/demo/foo20/gno.mod index 6297a2b21ab..79dea556e78 100644 --- a/examples/gno.land/r/demo/foo20/gno.mod +++ b/examples/gno.land/r/demo/foo20/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/foo20 - diff --git a/examples/gno.land/r/demo/foo721/gno.mod b/examples/gno.land/r/demo/foo721/gno.mod index fda752e2efc..4779f2fc467 100644 --- a/examples/gno.land/r/demo/foo721/gno.mod +++ b/examples/gno.land/r/demo/foo721/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/foo721 - diff --git a/examples/gno.land/r/demo/games/dice_roller/gno.mod b/examples/gno.land/r/demo/games/dice_roller/gno.mod index 44f4264e891..3aae9cbe791 100644 --- a/examples/gno.land/r/demo/games/dice_roller/gno.mod +++ b/examples/gno.land/r/demo/games/dice_roller/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/games/dice_roller - diff --git a/examples/gno.land/r/demo/games/shifumi/gno.mod b/examples/gno.land/r/demo/games/shifumi/gno.mod index 8489aecff28..e6a428090a9 100644 --- a/examples/gno.land/r/demo/games/shifumi/gno.mod +++ b/examples/gno.land/r/demo/games/shifumi/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/games/shifumi - diff --git a/examples/gno.land/r/demo/grc20factory/gno.mod b/examples/gno.land/r/demo/grc20factory/gno.mod index ca1b6adc29d..f89ee5872a5 100644 --- a/examples/gno.land/r/demo/grc20factory/gno.mod +++ b/examples/gno.land/r/demo/grc20factory/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/grc20factory - diff --git a/examples/gno.land/r/demo/groups/gno.mod b/examples/gno.land/r/demo/groups/gno.mod index 34991b9781f..6f715471ced 100644 --- a/examples/gno.land/r/demo/groups/gno.mod +++ b/examples/gno.land/r/demo/groups/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/groups - diff --git a/examples/gno.land/r/demo/keystore/gno.mod b/examples/gno.land/r/demo/keystore/gno.mod index 32d0f52bf7a..cd07d24adf6 100644 --- a/examples/gno.land/r/demo/keystore/gno.mod +++ b/examples/gno.land/r/demo/keystore/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/keystore - diff --git a/examples/gno.land/r/demo/math_eval/gno.mod b/examples/gno.land/r/demo/math_eval/gno.mod index f581a37cfed..c797becfa7d 100644 --- a/examples/gno.land/r/demo/math_eval/gno.mod +++ b/examples/gno.land/r/demo/math_eval/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/math_eval - diff --git a/examples/gno.land/r/demo/memeland/gno.mod b/examples/gno.land/r/demo/memeland/gno.mod index 194c5d3c2ee..0ccb353659f 100644 --- a/examples/gno.land/r/demo/memeland/gno.mod +++ b/examples/gno.land/r/demo/memeland/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/memeland - diff --git a/examples/gno.land/r/demo/microblog/gno.mod b/examples/gno.land/r/demo/microblog/gno.mod index b7359e953c0..a622200b76d 100644 --- a/examples/gno.land/r/demo/microblog/gno.mod +++ b/examples/gno.land/r/demo/microblog/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/microblog - diff --git a/examples/gno.land/r/demo/nft/gno.mod b/examples/gno.land/r/demo/nft/gno.mod index a2fa32c1079..ad760d186ab 100644 --- a/examples/gno.land/r/demo/nft/gno.mod +++ b/examples/gno.land/r/demo/nft/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/nft - diff --git a/examples/gno.land/r/demo/profile/gno.mod b/examples/gno.land/r/demo/profile/gno.mod index 0c56e34f8c1..3e875672a99 100644 --- a/examples/gno.land/r/demo/profile/gno.mod +++ b/examples/gno.land/r/demo/profile/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/profile - diff --git a/examples/gno.land/r/demo/releases_example/gno.mod b/examples/gno.land/r/demo/releases_example/gno.mod index 4afb2415a20..0dc5d6561dc 100644 --- a/examples/gno.land/r/demo/releases_example/gno.mod +++ b/examples/gno.land/r/demo/releases_example/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/releases_example - diff --git a/examples/gno.land/r/demo/tamagotchi/gno.mod b/examples/gno.land/r/demo/tamagotchi/gno.mod index 3db4e417f75..bccf4841666 100644 --- a/examples/gno.land/r/demo/tamagotchi/gno.mod +++ b/examples/gno.land/r/demo/tamagotchi/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/tamagotchi - diff --git a/examples/gno.land/r/demo/tests/crossrealm/gno.mod b/examples/gno.land/r/demo/tests/crossrealm/gno.mod index 44dfffefb29..2f7f217d288 100644 --- a/examples/gno.land/r/demo/tests/crossrealm/gno.mod +++ b/examples/gno.land/r/demo/tests/crossrealm/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/tests/crossrealm - diff --git a/examples/gno.land/r/demo/tests/gno.mod b/examples/gno.land/r/demo/tests/gno.mod index f039a08638f..f04aa5cf7bd 100644 --- a/examples/gno.land/r/demo/tests/gno.mod +++ b/examples/gno.land/r/demo/tests/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/tests - diff --git a/examples/gno.land/r/demo/tests_foo/gno.mod b/examples/gno.land/r/demo/tests_foo/gno.mod index e953ecf239e..e5a00113181 100644 --- a/examples/gno.land/r/demo/tests_foo/gno.mod +++ b/examples/gno.land/r/demo/tests_foo/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/tests_foo - diff --git a/examples/gno.land/r/demo/todolist/gno.mod b/examples/gno.land/r/demo/todolist/gno.mod index 4ab7dcde7b3..acd336f1724 100644 --- a/examples/gno.land/r/demo/todolist/gno.mod +++ b/examples/gno.land/r/demo/todolist/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/todolist - diff --git a/examples/gno.land/r/demo/types/gno.mod b/examples/gno.land/r/demo/types/gno.mod index ea2771c63e1..c24f7ddbc93 100644 --- a/examples/gno.land/r/demo/types/gno.mod +++ b/examples/gno.land/r/demo/types/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/types - diff --git a/examples/gno.land/r/demo/ui/gno.mod b/examples/gno.land/r/demo/ui/gno.mod index b37c6d5bc09..591b0b93190 100644 --- a/examples/gno.land/r/demo/ui/gno.mod +++ b/examples/gno.land/r/demo/ui/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/ui - diff --git a/examples/gno.land/r/demo/userbook/gno.mod b/examples/gno.land/r/demo/userbook/gno.mod index fe64702a8d2..bb709a39ed7 100644 --- a/examples/gno.land/r/demo/userbook/gno.mod +++ b/examples/gno.land/r/demo/userbook/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/userbook - diff --git a/examples/gno.land/r/demo/users/gno.mod b/examples/gno.land/r/demo/users/gno.mod index b4b901192cc..4d7fd15d1cd 100644 --- a/examples/gno.land/r/demo/users/gno.mod +++ b/examples/gno.land/r/demo/users/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/users - diff --git a/examples/gno.land/r/demo/wugnot/gno.mod b/examples/gno.land/r/demo/wugnot/gno.mod index 4e48a37e650..12b6baa7ae2 100644 --- a/examples/gno.land/r/demo/wugnot/gno.mod +++ b/examples/gno.land/r/demo/wugnot/gno.mod @@ -1,2 +1 @@ module gno.land/r/demo/wugnot - diff --git a/examples/gno.land/r/gnoland/blog/gno.mod b/examples/gno.land/r/gnoland/blog/gno.mod index 03240bf9809..b510867c485 100644 --- a/examples/gno.land/r/gnoland/blog/gno.mod +++ b/examples/gno.land/r/gnoland/blog/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/blog - diff --git a/examples/gno.land/r/gnoland/events/gno.mod b/examples/gno.land/r/gnoland/events/gno.mod index 84872196b1a..50aa3d8fc27 100644 --- a/examples/gno.land/r/gnoland/events/gno.mod +++ b/examples/gno.land/r/gnoland/events/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/events - diff --git a/examples/gno.land/r/gnoland/faucet/gno.mod b/examples/gno.land/r/gnoland/faucet/gno.mod index ebfa55279bb..6193d111e4f 100644 --- a/examples/gno.land/r/gnoland/faucet/gno.mod +++ b/examples/gno.land/r/gnoland/faucet/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/faucet - diff --git a/examples/gno.land/r/gnoland/ghverify/gno.mod b/examples/gno.land/r/gnoland/ghverify/gno.mod index 7e93f513cde..8ffdec663f7 100644 --- a/examples/gno.land/r/gnoland/ghverify/gno.mod +++ b/examples/gno.land/r/gnoland/ghverify/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/ghverify - diff --git a/examples/gno.land/r/gnoland/home/gno.mod b/examples/gno.land/r/gnoland/home/gno.mod index 44eb4817093..09eb0eb19e1 100644 --- a/examples/gno.land/r/gnoland/home/gno.mod +++ b/examples/gno.land/r/gnoland/home/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/home - diff --git a/examples/gno.land/r/gnoland/monit/gno.mod b/examples/gno.land/r/gnoland/monit/gno.mod index 8578a55a5ec..6086a3fa21f 100644 --- a/examples/gno.land/r/gnoland/monit/gno.mod +++ b/examples/gno.land/r/gnoland/monit/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/monit - diff --git a/examples/gno.land/r/gnoland/pages/gno.mod b/examples/gno.land/r/gnoland/pages/gno.mod index aa3a0f5a78b..e041fd948bc 100644 --- a/examples/gno.land/r/gnoland/pages/gno.mod +++ b/examples/gno.land/r/gnoland/pages/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/pages - diff --git a/examples/gno.land/r/gnoland/valopers/v2/gno.mod b/examples/gno.land/r/gnoland/valopers/v2/gno.mod index fa17b097c4b..064fe6d811e 100644 --- a/examples/gno.land/r/gnoland/valopers/v2/gno.mod +++ b/examples/gno.land/r/gnoland/valopers/v2/gno.mod @@ -1,2 +1 @@ module gno.land/r/gnoland/valopers/v2 - diff --git a/examples/gno.land/r/gov/dao/bridge/gno.mod b/examples/gno.land/r/gov/dao/bridge/gno.mod index c539434a0cc..9f472eaa464 100644 --- a/examples/gno.land/r/gov/dao/bridge/gno.mod +++ b/examples/gno.land/r/gov/dao/bridge/gno.mod @@ -1,2 +1 @@ module gno.land/r/gov/dao/bridge - diff --git a/examples/gno.land/r/gov/dao/v2/gno.mod b/examples/gno.land/r/gov/dao/v2/gno.mod index 57ab433b7c4..4daf8c600a1 100644 --- a/examples/gno.land/r/gov/dao/v2/gno.mod +++ b/examples/gno.land/r/gov/dao/v2/gno.mod @@ -1,2 +1 @@ module gno.land/r/gov/dao/v2 - diff --git a/examples/gno.land/r/leon/home/gno.mod b/examples/gno.land/r/leon/home/gno.mod index 2b884ec1723..56fea265e29 100644 --- a/examples/gno.land/r/leon/home/gno.mod +++ b/examples/gno.land/r/leon/home/gno.mod @@ -1,2 +1 @@ module gno.land/r/leon/home - diff --git a/examples/gno.land/r/manfred/home/gno.mod b/examples/gno.land/r/manfred/home/gno.mod index cd6a56b786d..2efefe1824f 100644 --- a/examples/gno.land/r/manfred/home/gno.mod +++ b/examples/gno.land/r/manfred/home/gno.mod @@ -1,2 +1 @@ module gno.land/r/manfred/home - diff --git a/examples/gno.land/r/manfred/present/gno.mod b/examples/gno.land/r/manfred/present/gno.mod index 32dc0482f43..6e15ff6cf5a 100644 --- a/examples/gno.land/r/manfred/present/gno.mod +++ b/examples/gno.land/r/manfred/present/gno.mod @@ -1,2 +1 @@ module gno.land/r/manfred/present - diff --git a/examples/gno.land/r/morgan/guestbook/gno.mod b/examples/gno.land/r/morgan/guestbook/gno.mod index 6b1ebdd46f2..ac63a4cf8cd 100644 --- a/examples/gno.land/r/morgan/guestbook/gno.mod +++ b/examples/gno.land/r/morgan/guestbook/gno.mod @@ -1,2 +1 @@ module gno.land/r/morgan/guestbook - diff --git a/examples/gno.land/r/stefann/home/gno.mod b/examples/gno.land/r/stefann/home/gno.mod index 034684ff6c5..89071aa70fb 100644 --- a/examples/gno.land/r/stefann/home/gno.mod +++ b/examples/gno.land/r/stefann/home/gno.mod @@ -1,2 +1 @@ module gno.land/r/stefann/home - diff --git a/examples/gno.land/r/stefann/registry/gno.mod b/examples/gno.land/r/stefann/registry/gno.mod index 8e956ac45da..7ef0c32030f 100644 --- a/examples/gno.land/r/stefann/registry/gno.mod +++ b/examples/gno.land/r/stefann/registry/gno.mod @@ -1,2 +1 @@ module gno.land/r/stefann/registry - diff --git a/examples/gno.land/r/sys/users/gno.mod b/examples/gno.land/r/sys/users/gno.mod index b5fe21a3b9c..e5e84a49faf 100644 --- a/examples/gno.land/r/sys/users/gno.mod +++ b/examples/gno.land/r/sys/users/gno.mod @@ -1,2 +1 @@ module gno.land/r/sys/users - diff --git a/examples/gno.land/r/sys/validators/v2/gno.mod b/examples/gno.land/r/sys/validators/v2/gno.mod index 63903cf20b1..beae6e95d34 100644 --- a/examples/gno.land/r/sys/validators/v2/gno.mod +++ b/examples/gno.land/r/sys/validators/v2/gno.mod @@ -1,2 +1 @@ module gno.land/r/sys/validators/v2 - diff --git a/examples/gno.land/r/x/manfred_outfmt/gno.mod b/examples/gno.land/r/x/manfred_outfmt/gno.mod index c6d2c15d592..e8165d847c9 100644 --- a/examples/gno.land/r/x/manfred_outfmt/gno.mod +++ b/examples/gno.land/r/x/manfred_outfmt/gno.mod @@ -1,4 +1,3 @@ // Draft module gno.land/r/x/manfred_outfmt - From a411efa9730cdd35a961be17ce7532df73fda690 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 8 Nov 2024 23:02:48 +0100 Subject: [PATCH 13/51] chore: fmt Signed-off-by: Norman Meier --- gnovm/cmd/gno/main_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 4976dc0ac75..278bae17ad6 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -104,7 +104,6 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { return &types.RPCResponse{ Result: amino.MustMarshalJSON(res), }, nil - }, }) t.Cleanup(func() { From 4bc99980c4aa064cbc61be50051a7921d00048b4 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 8 Nov 2024 23:03:46 +0100 Subject: [PATCH 14/51] chore: remove debug artifact Signed-off-by: Norman Meier --- gnovm/pkg/doc/dirs.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index 78f03252811..dc8a4f3b69f 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -5,7 +5,6 @@ package doc import ( - "fmt" "log" "os" "path" @@ -84,7 +83,6 @@ func getGnoModDirs(gm *gnomod.File, root string) []bfsDir { mv := gm.Resolve(module.Version{Path: r}) path := gnomod.PackageDir("", mv) if _, err := os.Stat(path); err != nil { - fmt.Printf("ignoring inexistent path %q for pkg %q\n", path, r) // only give directories which actually exist and don't give // an error when accessing if !os.IsNotExist(err) { From 3e2450eb541564472c4c5ed05199543f5adbcafc Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Sat, 9 Nov 2024 00:09:26 +0100 Subject: [PATCH 15/51] chore: cleaner examples client' Signed-off-by: Norman Meier --- gnovm/cmd/gno/main_test.go | 142 +++++++++++++++---------------------- 1 file changed, 58 insertions(+), 84 deletions(-) diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 278bae17ad6..04771c96000 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -50,66 +51,11 @@ type testMainCase struct { func testMainCaseRun(t *testing.T, tc []testMainCase) { t.Helper() - { - gnomodfetch.Client = client.NewRPCClient(&mockClient{ - sendRequestFn: func(ctx context.Context, r types.RPCRequest) (*types.RPCResponse, error) { - params := struct { - Path string `json:"path"` - Data []byte `json:"data"` - }{} - if err := json.Unmarshal(r.Params, ¶ms); err != nil { - return nil, fmt.Errorf("failed to unmarshal params: %w", err) - } - path := params.Path - if path != "vm/qfile" { - return nil, fmt.Errorf("unexpected call to %q", path) - } - data := string(params.Data) - - examplesDir := filepath.Join(gnoenv.RootDir(), "examples") - target := filepath.Join(examplesDir, data) - - res := ctypes.ResultABCIQuery{} - - finfo, err := os.Stat(target) - if os.IsNotExist(err) { - res.Response = sdk.ABCIResponseQueryFromError(fmt.Errorf("package %q is not available", data)) - return &types.RPCResponse{ - Result: amino.MustMarshalJSON(res), - }, nil - } else if err != nil { - return nil, fmt.Errorf("failed to stat %q: %w", data, err) - } - - if finfo.IsDir() { - entries, err := os.ReadDir(target) - if err != nil { - return nil, fmt.Errorf("failed to get package %q: %w", data, err) - } - files := []string{} - for _, entry := range entries { - if !entry.IsDir() { - files = append(files, entry.Name()) - } - } - res.Response.Data = []byte(strings.Join(files, "\n")) - } else { - content, err := os.ReadFile(target) - if err != nil { - return nil, fmt.Errorf("failed to get file %q: %w", data, err) - } - res.Response.Data = content - } - - return &types.RPCResponse{ - Result: amino.MustMarshalJSON(res), - }, nil - }, - }) - t.Cleanup(func() { - gnomodfetch.Client = nil - }) - } + oldClient := gnomodfetch.Client + gnomodfetch.Client = client.NewRPCClient(&examplesMockClient{}) + t.Cleanup(func() { + gnomodfetch.Client = oldClient + }) workingDir, err := os.Getwd() require.Nil(t, err) @@ -219,38 +165,66 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { } } -type ( - sendRequestDelegate func(context.Context, types.RPCRequest) (*types.RPCResponse, error) - sendBatchDelegate func(context.Context, types.RPCRequests) (types.RPCResponses, error) - closeDelegate func() error -) +type examplesMockClient struct{} -type mockClient struct { - sendRequestFn sendRequestDelegate - sendBatchFn sendBatchDelegate - closeFn closeDelegate -} - -func (m *mockClient) SendRequest(ctx context.Context, request types.RPCRequest) (*types.RPCResponse, error) { - if m.sendRequestFn != nil { - return m.sendRequestFn(ctx, request) +func (m *examplesMockClient) SendRequest(ctx context.Context, request types.RPCRequest) (*types.RPCResponse, error) { + params := struct { + Path string `json:"path"` + Data []byte `json:"data"` + }{} + if err := json.Unmarshal(request.Params, ¶ms); err != nil { + return nil, fmt.Errorf("failed to unmarshal params: %w", err) + } + path := params.Path + if path != "vm/qfile" { + return nil, fmt.Errorf("unexpected call to %q", path) } + data := string(params.Data) - return nil, nil -} + examplesDir := filepath.Join(gnoenv.RootDir(), "examples") + target := filepath.Join(examplesDir, data) -func (m *mockClient) SendBatch(ctx context.Context, requests types.RPCRequests) (types.RPCResponses, error) { - if m.sendBatchFn != nil { - return m.sendBatchFn(ctx, requests) + res := ctypes.ResultABCIQuery{} + + finfo, err := os.Stat(target) + if os.IsNotExist(err) { + res.Response = sdk.ABCIResponseQueryFromError(fmt.Errorf("package %q is not available", data)) + return &types.RPCResponse{ + Result: amino.MustMarshalJSON(res), + }, nil + } else if err != nil { + return nil, fmt.Errorf("failed to stat %q: %w", data, err) + } + + if finfo.IsDir() { + entries, err := os.ReadDir(target) + if err != nil { + return nil, fmt.Errorf("failed to get package %q: %w", data, err) + } + files := []string{} + for _, entry := range entries { + if !entry.IsDir() { + files = append(files, entry.Name()) + } + } + res.Response.Data = []byte(strings.Join(files, "\n")) + } else { + content, err := os.ReadFile(target) + if err != nil { + return nil, fmt.Errorf("failed to get file %q: %w", data, err) + } + res.Response.Data = content } - return nil, nil + return &types.RPCResponse{ + Result: amino.MustMarshalJSON(res), + }, nil } -func (m *mockClient) Close() error { - if m.closeFn != nil { - return m.closeFn() - } +func (m *examplesMockClient) SendBatch(ctx context.Context, requests types.RPCRequests) (types.RPCResponses, error) { + return nil, errors.New("not implemented") +} +func (m *examplesMockClient) Close() error { return nil } From 2ced616d2b90e3c763c4e26bb003d61c4466b04b Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Sat, 9 Nov 2024 00:13:14 +0100 Subject: [PATCH 16/51] chore: go mod tidy Signed-off-by: Norman Meier --- contribs/gnomigrate/go.mod | 1 - contribs/gnomigrate/go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/contribs/gnomigrate/go.mod b/contribs/gnomigrate/go.mod index c492ae7c818..a81c2de4ba0 100644 --- a/contribs/gnomigrate/go.mod +++ b/contribs/gnomigrate/go.mod @@ -48,7 +48,6 @@ require ( golang.org/x/sys v0.24.0 // indirect golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect - golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/contribs/gnomigrate/go.sum b/contribs/gnomigrate/go.sum index f3161e47bad..3c6127ac216 100644 --- a/contribs/gnomigrate/go.sum +++ b/contribs/gnomigrate/go.sum @@ -195,8 +195,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 39241023b4d7328e15906f255ccfe6e02949ab5e Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 06:16:49 +0100 Subject: [PATCH 17/51] chore: refacto Signed-off-by: Norman Meier --- .../pkg/integration/testing_integration.go | 4 +- gnovm/cmd/gno/fmt.go | 6 +- gnovm/cmd/gno/lint.go | 4 +- gnovm/cmd/gno/mod.go | 38 +------- gnovm/cmd/gno/run.go | 4 +- gnovm/cmd/gno/test.go | 4 +- gnovm/cmd/gno/transpile.go | 4 +- gnovm/pkg/doc/dirs.go | 4 +- gnovm/pkg/gnolang/helpers.go | 6 ++ gnovm/pkg/{load => gnoload}/imports.go | 2 +- gnovm/pkg/{load => gnoload}/imports_test.go | 2 +- gnovm/pkg/{load/load.go => gnoload/match.go} | 18 ++-- gnovm/pkg/{load => gnoload}/match_test.go | 2 +- gnovm/pkg/gnomod/file.go | 3 + gnovm/pkg/gnomod/gnomod.go | 6 +- gnovm/pkg/gnomodfetch/gnomodfetch.go | 88 +++++++------------ 16 files changed, 75 insertions(+), 120 deletions(-) rename gnovm/pkg/{load => gnoload}/imports.go (99%) rename gnovm/pkg/{load => gnoload}/imports_test.go (99%) rename gnovm/pkg/{load/load.go => gnoload/match.go} (94%) rename gnovm/pkg/{load => gnoload}/match_test.go (99%) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 052ab3b9c0d..1054b65ea84 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -20,8 +20,8 @@ import ( "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/tm2/pkg/bft/node" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" @@ -745,7 +745,7 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { currentPkg.Name = gm.Module.Mod.Path currentPkg.Draft = gm.Draft - imports, err := load.GetGnoPackageImports(currentPkg.Dir) + imports, err := gnoload.GetGnoPackageImports(currentPkg.Dir) if err != nil { return fmt.Errorf("unable to load package imports in %q: %w", currentPkg.Dir, err) } diff --git a/gnovm/cmd/gno/fmt.go b/gnovm/cmd/gno/fmt.go index 8e28039f341..c32952cf474 100644 --- a/gnovm/cmd/gno/fmt.go +++ b/gnovm/cmd/gno/fmt.go @@ -16,7 +16,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnofmt" - "github.com/gnolang/gno/gnovm/pkg/load" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/rogpeppe/go-internal/diff" ) @@ -95,12 +95,12 @@ func execFmt(cfg *fmtCfg, args []string, io commands.IO) error { return flag.ErrHelp } - paths, err := load.TargetsFromPatterns(args) + paths, err := gnoload.TargetsFromPatterns(args) if err != nil { return fmt.Errorf("unable to get targets paths from patterns: %w", err) } - files, err := load.GnoFilesFromArgs(paths) + files, err := gnoload.GnoFilesFromArgs(paths) if err != nil { return fmt.Errorf("unable to gather gno files: %w", err) } diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index 87bc6e6f7c7..662de32909c 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -14,7 +14,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/load" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" osm "github.com/gnolang/gno/tm2/pkg/os" @@ -64,7 +64,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { rootDir = gnoenv.RootDir() } - pkgPaths, err := load.GnoPackagesFromArgsRecursively(args) + pkgPaths, err := gnoload.GnoPackagesFromArgsRecursively(args) if err != nil { return fmt.Errorf("list packages from args: %w", err) } diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 95534dc9026..f3daa07f1c0 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -4,19 +4,16 @@ import ( "context" "flag" "fmt" - "go/parser" - "go/token" "os" "path/filepath" "strings" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/gnomodfetch" - "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "go.uber.org/multierr" - "golang.org/x/mod/module" ) func newModCmd(io commands.IO) *commands.Command { @@ -178,35 +175,8 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { return fmt.Errorf("validate: %w", err) } - gnoFiles, err := load.GnoFilesFromArgsRecursively([]string{path}) - if err != nil { - return fmt.Errorf("get gno files: %w", err) - } - - for _, f := range gnoFiles { - fset := token.NewFileSet() - parsed, err := parser.ParseFile(fset, f, nil, parser.ImportsOnly) - if err != nil { - continue - } - - for _, imp := range parsed.Imports { - importPkgPath := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, "\""), "\"") - - if !strings.ContainsRune(importPkgPath, '.') { - // std lib, ignore - continue - } - - resolved := gnoMod.Resolve(module.Version{Path: importPkgPath}) - resolvedPkgPath := resolved.Path - - // TODO: don't fetch local - - if err := gnomodfetch.FetchPackagesRecursively(io, resolvedPkgPath, gnoMod); err != nil { - return fmt.Errorf("fetch: %w", err) - } - } + if err := gnomodfetch.FetchPackageImportsRecursively(io, path, gnoMod); err != nil { + return err } return nil @@ -363,7 +333,7 @@ func getImportToFilesMap(pkgPath string) (map[string][]string, error) { if strings.HasSuffix(filename, "_filetest.gno") { continue } - imports, err := load.GetGnoFileImports(filepath.Join(pkgPath, filename)) + imports, err := gnoload.GetGnoFileImports(filepath.Join(pkgPath, filename)) if err != nil { return nil, err } diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index 59b5bc8b17a..31e6d002061 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -12,7 +12,7 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/load" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/std" @@ -182,7 +182,7 @@ func listNonTestFiles(dir string) ([]string, error) { fn := make([]string, 0, len(fs)) for _, f := range fs { n := f.Name() - if load.IsGnoFile(f) && + if gnoload.DirEntryIsGnoFile(f) && !strings.HasSuffix(n, "_test.gno") && !strings.HasSuffix(n, "_filetest.gno") { fn = append(fn, filepath.Join(dir, n)) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 229521c399c..ddbf35d79c1 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -21,8 +21,8 @@ import ( "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/gnovm/tests" teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" "github.com/gnolang/gno/tm2/pkg/commands" @@ -172,7 +172,7 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { cfg.rootDir = gnoenv.RootDir() } - paths, err := load.TargetsFromPatterns(args) + paths, err := gnoload.TargetsFromPatterns(args) if err != nil { return fmt.Errorf("list targets from patterns: %w", err) } diff --git a/gnovm/cmd/gno/transpile.go b/gnovm/cmd/gno/transpile.go index 4706bae8f14..c550744c5e6 100644 --- a/gnovm/cmd/gno/transpile.go +++ b/gnovm/cmd/gno/transpile.go @@ -17,8 +17,8 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/gnovm/pkg/load" "github.com/gnolang/gno/gnovm/pkg/transpiler" "github.com/gnolang/gno/tm2/pkg/commands" ) @@ -135,7 +135,7 @@ func execTranspile(cfg *transpileCfg, args []string, io commands.IO) error { } // transpile .gno packages and files. - paths, err := load.GnoDirsFromArgsRecursively(args) + paths, err := gnoload.GnoDirsFromArgsRecursively(args) if err != nil { return fmt.Errorf("list paths: %w", err) } diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index dc8a4f3b69f..348550c7cdc 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -12,8 +12,8 @@ import ( "sort" "strings" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/gnovm/pkg/load" "golang.org/x/mod/module" ) @@ -72,7 +72,7 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { func getGnoModDirs(gm *gnomod.File, root string) []bfsDir { // cmd/go makes use of the go list command, we don't have that here. - imports, err := load.GetGnoPackageImportsRecursive(root) + imports, err := gnoload.GetGnoPackageImportsRecursive(root) if err != nil { log.Println("get imports at", root, ":", err) return nil diff --git a/gnovm/pkg/gnolang/helpers.go b/gnovm/pkg/gnolang/helpers.go index c6f7e696ea4..50678707e0e 100644 --- a/gnovm/pkg/gnolang/helpers.go +++ b/gnovm/pkg/gnolang/helpers.go @@ -2,6 +2,7 @@ package gnolang import ( "fmt" + "path/filepath" "regexp" "strconv" "strings" @@ -35,6 +36,11 @@ func IsStdlib(s string) bool { return !strings.HasPrefix(s, "gno.land/") } +// IsRemotePkgPath determines whether s is a remote pkg path, i.e.: not a filepath nor a standard library +func IsRemotePkgPath(s string) bool { + return !strings.HasPrefix(s, ".") && !filepath.IsAbs(s) && !IsStdlib(s) +} + // ---------------------------------------- // AST Construction (Expr) // These are copied over from go-amino-x, but produces Gno ASTs. diff --git a/gnovm/pkg/load/imports.go b/gnovm/pkg/gnoload/imports.go similarity index 99% rename from gnovm/pkg/load/imports.go rename to gnovm/pkg/gnoload/imports.go index d5c5196c0d0..521377f3990 100644 --- a/gnovm/pkg/load/imports.go +++ b/gnovm/pkg/gnoload/imports.go @@ -1,4 +1,4 @@ -package load +package gnoload import ( "fmt" diff --git a/gnovm/pkg/load/imports_test.go b/gnovm/pkg/gnoload/imports_test.go similarity index 99% rename from gnovm/pkg/load/imports_test.go rename to gnovm/pkg/gnoload/imports_test.go index 5e44ce7d0b9..25f5f68d998 100644 --- a/gnovm/pkg/load/imports_test.go +++ b/gnovm/pkg/gnoload/imports_test.go @@ -1,4 +1,4 @@ -package load +package gnoload import ( "os" diff --git a/gnovm/pkg/load/load.go b/gnovm/pkg/gnoload/match.go similarity index 94% rename from gnovm/pkg/load/load.go rename to gnovm/pkg/gnoload/match.go index 4c878552995..5c5923ad6b3 100644 --- a/gnovm/pkg/load/load.go +++ b/gnovm/pkg/gnoload/match.go @@ -1,4 +1,4 @@ -package load +package gnoload import ( "fmt" @@ -9,7 +9,7 @@ import ( "strings" ) -func IsGnoFile(f fs.DirEntry) bool { +func DirEntryIsGnoFile(f fs.DirEntry) bool { name := f.Name() return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".gno") && !f.IsDir() } @@ -24,7 +24,7 @@ func GnoFilesFromArgsRecursively(args []string) ([]string, error) { } if !info.IsDir() { - if IsGnoFile(fs.FileInfoToDirEntry(info)) { + if DirEntryIsGnoFile(fs.FileInfoToDirEntry(info)) { paths = append(paths, ensurePathPrefix(argPath)) } @@ -38,7 +38,7 @@ func GnoFilesFromArgsRecursively(args []string) ([]string, error) { return } for _, f := range files { - if IsGnoFile(f) { + if DirEntryIsGnoFile(f) { path := filepath.Join(dir, f.Name()) paths = append(paths, ensurePathPrefix(path)) } @@ -62,7 +62,7 @@ func GnoDirsFromArgsRecursively(args []string) ([]string, error) { } if !info.IsDir() { - if IsGnoFile(fs.FileInfoToDirEntry(info)) { + if DirEntryIsGnoFile(fs.FileInfoToDirEntry(info)) { paths = append(paths, ensurePathPrefix(argPath)) } @@ -91,7 +91,7 @@ func GnoFilesFromArgs(args []string) ([]string, error) { } if !info.IsDir() { - if IsGnoFile(fs.FileInfoToDirEntry(info)) { + if DirEntryIsGnoFile(fs.FileInfoToDirEntry(info)) { paths = append(paths, ensurePathPrefix(argPath)) } continue @@ -102,7 +102,7 @@ func GnoFilesFromArgs(args []string) ([]string, error) { return nil, err } for _, f := range files { - if IsGnoFile(f) { + if DirEntryIsGnoFile(f) { path := filepath.Join(argPath, f.Name()) paths = append(paths, ensurePathPrefix(path)) } @@ -131,7 +131,7 @@ func walkDirForGnoDirs(root string, addPath func(path string)) error { return fmt.Errorf("%s: walk dir: %w", root, err) } - if f.IsDir() || !IsGnoFile(f) { + if f.IsDir() || !DirEntryIsGnoFile(f) { return nil } @@ -218,7 +218,7 @@ func TargetsFromPatterns(patterns []string) ([]string, error) { return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) } // Skip directories and non ".gno" files. - if f.IsDir() || !IsGnoFile(f) { + if f.IsDir() || !DirEntryIsGnoFile(f) { return nil } diff --git a/gnovm/pkg/load/match_test.go b/gnovm/pkg/gnoload/match_test.go similarity index 99% rename from gnovm/pkg/load/match_test.go rename to gnovm/pkg/gnoload/match_test.go index 5845e3a5af1..1b43925935f 100644 --- a/gnovm/pkg/load/match_test.go +++ b/gnovm/pkg/gnoload/match_test.go @@ -1,4 +1,4 @@ -package load +package gnoload import ( "os" diff --git a/gnovm/pkg/gnomod/file.go b/gnovm/pkg/gnomod/file.go index 5e313a9af5a..a1c77b51e45 100644 --- a/gnovm/pkg/gnomod/file.go +++ b/gnovm/pkg/gnomod/file.go @@ -85,6 +85,9 @@ func (f *File) Validate() error { // Resolve takes a module version and returns any adequate replacement // following the Replace directives. func (f *File) Resolve(m module.Version) module.Version { + if f == nil { + return m + } mod, replaced := isReplaced(m, f.Replace) if replaced { return mod diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 82a4bbea5cb..726d9ba2bc0 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -23,14 +23,10 @@ func ModCachePath() string { // PackageDir resolves a given module.Version to the path on the filesystem. // If root is dir, it is defaulted to the value of [ModCachePath]. func PackageDir(root string, v module.Version) string { - // This is also used internally exactly like filepath.Join; but we'll keep - // the calls centralized to make sure we can change the path centrally should - // we start including the module version in the path. - if root == "" { root = ModCachePath() } - return filepath.Join(root, v.Path) + return filepath.Join(root, filepath.FromSlash(v.Path)) } func CreateGnoModFile(rootDir, modPath string) error { diff --git a/gnovm/pkg/gnomodfetch/gnomodfetch.go b/gnovm/pkg/gnomodfetch/gnomodfetch.go index d125ae1b466..8e882d99698 100644 --- a/gnovm/pkg/gnomodfetch/gnomodfetch.go +++ b/gnovm/pkg/gnomodfetch/gnomodfetch.go @@ -2,22 +2,49 @@ package gnomodfetch import ( "fmt" - "go/parser" - "go/token" "net/url" "os" "path" "path/filepath" "strings" + "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/gnovm/pkg/load" tm2client "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "golang.org/x/mod/module" ) +func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomod.File) error { + imports, err := gnoload.GetGnoPackageImports(pkgDir) + if err != nil { + return fmt.Errorf("read imports at %q: %w", pkgDir, err) + } + + for _, pkgPath := range imports { + resolved := gnoMod.Resolve(module.Version{Path: pkgPath}) + resolvedPkgPath := resolved.Path + + if !gnolang.IsRemotePkgPath(resolvedPkgPath) { + continue + } + + depDir := gnomod.PackageDir("", module.Version{Path: resolvedPkgPath}) + + if err := FetchPackage(io, resolvedPkgPath, depDir); err != nil { + return fmt.Errorf("fetch import %q of %q: %w", resolvedPkgPath, pkgDir, err) + } + + if err := FetchPackageImportsRecursively(io, depDir, gnoMod); err != nil { + return err + } + } + + return nil +} + func FetchPackage(io commands.IO, pkgPath string, dst string) error { modFilePath := filepath.Join(dst, "gno.mod") @@ -71,7 +98,10 @@ func FetchPackage(io commands.IO, pkgPath string, dst string) error { } } - // write gno.mod + // We need to write a marker file for each downloaded package. + // For example: if you first download gno.land/r/foo/bar then download gno.land/r/foo, + // we need to know that gno.land/r/foo is not downloaded. + // We do this by checking for the presence of gno.land/r/foo/gno.mod if err := os.WriteFile(modFilePath, []byte("module "+pkgPath+"\n"), 0o644); err != nil { return fmt.Errorf("failed to write modfile at %q: %w", modFilePath, err) } @@ -79,56 +109,6 @@ func FetchPackage(io commands.IO, pkgPath string, dst string) error { return nil } -func FetchPackagesRecursively(io commands.IO, pkgPath string, gnoMod *gnomod.File) error { - dst := gnomod.PackageDir("", module.Version{Path: pkgPath}) - - modFilePath := filepath.Join(dst, "gno.mod") - - if _, err := os.Stat(modFilePath); err == nil { - // modfile exists in modcache, do nothing - return nil - } else if !os.IsNotExist(err) { - return fmt.Errorf("failed to stat downloaded module %q at %q: %w", pkgPath, dst, err) - } - - if err := FetchPackage(io, pkgPath, dst); err != nil { - return err - } - - gnoFiles, err := load.GnoFilesFromArgs([]string{dst}) - if err != nil { - return err - } - - for _, f := range gnoFiles { - fset := token.NewFileSet() - parsed, err := parser.ParseFile(fset, f, nil, parser.ImportsOnly) - if err != nil { - continue - } - - for _, imp := range parsed.Imports { - importPkgPath := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, "\""), "\"") - - if !strings.ContainsRune(importPkgPath, '.') { - // std lib, ignore - continue - } - - resolved := gnoMod.Resolve(module.Version{Path: importPkgPath}) - resolvedPkgPath := resolved.Path - - // TODO: don't fetch local - - if err := FetchPackagesRecursively(io, resolvedPkgPath, gnoMod); err != nil { - return fmt.Errorf("fetch: %w", err) - } - } - } - - return nil -} - var Client tm2client.Client // not using gno client due to cyclic dep From eff07fba2df307660b18b8774d8f30352fe9d4d1 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 06:23:47 +0100 Subject: [PATCH 18/51] fix: return errors Signed-off-by: Norman Meier --- gnovm/pkg/gnoload/imports.go | 63 +++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/gnovm/pkg/gnoload/imports.go b/gnovm/pkg/gnoload/imports.go index 521377f3990..03ade128914 100644 --- a/gnovm/pkg/gnoload/imports.go +++ b/gnovm/pkg/gnoload/imports.go @@ -11,35 +11,6 @@ import ( "strings" ) -func GetGnoPackageImportsRecursive(root string) ([]string, error) { - res, err := GetGnoPackageImports(root) - _ = err - - entries, err := os.ReadDir(root) - _ = err - - for _, entry := range entries { - if !entry.IsDir() { - continue - } - - sub, err := GetGnoPackageImportsRecursive(filepath.Join(root, entry.Name())) - if err != nil { - continue - } - - for _, imp := range sub { - if !slices.Contains(res, imp) { - res = append(res, imp) - } - } - } - - sort.Strings(res) - - return res, nil -} - // GetGnoPackageImports returns the list of gno imports from a given path. // Note: It ignores subdirs. Since right now we are still deciding on // how to handle subdirs. @@ -79,6 +50,40 @@ func GetGnoPackageImports(path string) ([]string, error) { return allImports, nil } +// GetGnoPackageImportsRecursive returns the list of gno imports from a given path. +func GetGnoPackageImportsRecursive(root string) ([]string, error) { + res, err := GetGnoPackageImports(root) + if err != nil { + return nil, fmt.Errorf("get imports at %q: %w", root, err) + } + + entries, err := os.ReadDir(root) + if err != nil { + return nil, fmt.Errorf("read dir at %q: %w", root, err) + } + + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + sub, err := GetGnoPackageImportsRecursive(filepath.Join(root, entry.Name())) + if err != nil { + return nil, err + } + + for _, imp := range sub { + if !slices.Contains(res, imp) { + res = append(res, imp) + } + } + } + + sort.Strings(res) + + return res, nil +} + func GetGnoFileImports(fname string) ([]string, error) { if !strings.HasSuffix(fname, ".gno") { return nil, fmt.Errorf("not a gno file: %q", fname) From 9bf675ae5d2feab10aa5570a4e7d5e9ab1706576 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 06:54:14 +0100 Subject: [PATCH 19/51] chore: move / rename Signed-off-by: Norman Meier --- .../pkg/integration/testing_integration.go | 4 +- gnovm/cmd/gno/fmt.go | 6 +- gnovm/cmd/gno/lint.go | 4 +- gnovm/cmd/gno/main_test.go | 8 +- gnovm/cmd/gno/match.go | 95 +++++++++++++++++++ gnovm/{pkg/gnoload => cmd/gno}/match_test.go | 4 +- gnovm/cmd/gno/mod.go | 8 +- gnovm/cmd/gno/mod_test.go | 4 +- gnovm/cmd/gno/run.go | 4 +- gnovm/cmd/gno/test.go | 3 +- gnovm/cmd/gno/transpile.go | 4 +- gnovm/pkg/doc/dirs.go | 35 +++++-- .../match.go => gnofiles/gnofiles.go} | 86 +---------------- gnovm/pkg/{gnoload => gnoimports}/imports.go | 46 ++------- .../{gnoload => gnoimports}/imports_test.go | 4 +- .../gnopkgfetch.go} | 62 ++++++------ 16 files changed, 189 insertions(+), 188 deletions(-) create mode 100644 gnovm/cmd/gno/match.go rename gnovm/{pkg/gnoload => cmd/gno}/match_test.go (98%) rename gnovm/pkg/{gnoload/match.go => gnofiles/gnofiles.go} (59%) rename gnovm/pkg/{gnoload => gnoimports}/imports.go (57%) rename gnovm/pkg/{gnoload => gnoimports}/imports_test.go (97%) rename gnovm/pkg/{gnomodfetch/gnomodfetch.go => gnopkgfetch/gnopkgfetch.go} (93%) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 1054b65ea84..8fcc00a0d28 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -19,8 +19,8 @@ import ( "github.com/gnolang/gno/gno.land/pkg/log" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnoimports" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/tm2/pkg/bft/node" bft "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -745,7 +745,7 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { currentPkg.Name = gm.Module.Mod.Path currentPkg.Draft = gm.Draft - imports, err := gnoload.GetGnoPackageImports(currentPkg.Dir) + imports, err := gnoimports.PackageImports(currentPkg.Dir) if err != nil { return fmt.Errorf("unable to load package imports in %q: %w", currentPkg.Dir, err) } diff --git a/gnovm/cmd/gno/fmt.go b/gnovm/cmd/gno/fmt.go index c32952cf474..8b4079edd3a 100644 --- a/gnovm/cmd/gno/fmt.go +++ b/gnovm/cmd/gno/fmt.go @@ -15,8 +15,8 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnofiles" "github.com/gnolang/gno/gnovm/pkg/gnofmt" - "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/rogpeppe/go-internal/diff" ) @@ -95,12 +95,12 @@ func execFmt(cfg *fmtCfg, args []string, io commands.IO) error { return flag.ErrHelp } - paths, err := gnoload.TargetsFromPatterns(args) + paths, err := targetsFromPatterns(args) if err != nil { return fmt.Errorf("unable to get targets paths from patterns: %w", err) } - files, err := gnoload.GnoFilesFromArgs(paths) + files, err := gnofiles.GnoFilesFromArgs(paths) if err != nil { return fmt.Errorf("unable to gather gno files: %w", err) } diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index 662de32909c..8cddc6cc400 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -13,8 +13,8 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnofiles" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" osm "github.com/gnolang/gno/tm2/pkg/os" @@ -64,7 +64,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { rootDir = gnoenv.RootDir() } - pkgPaths, err := gnoload.GnoPackagesFromArgsRecursively(args) + pkgPaths, err := gnofiles.GnoPackagesFromArgsRecursively(args) if err != nil { return fmt.Errorf("list packages from args: %w", err) } diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 04771c96000..c8535aeb857 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -12,7 +12,7 @@ import ( "testing" "github.com/gnolang/gno/gnovm/pkg/gnoenv" - "github.com/gnolang/gno/gnovm/pkg/gnomodfetch" + "github.com/gnolang/gno/gnovm/pkg/gnopkgfetch" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" @@ -51,10 +51,10 @@ type testMainCase struct { func testMainCaseRun(t *testing.T, tc []testMainCase) { t.Helper() - oldClient := gnomodfetch.Client - gnomodfetch.Client = client.NewRPCClient(&examplesMockClient{}) + oldClient := gnopkgfetch.Client + gnopkgfetch.Client = client.NewRPCClient(&examplesMockClient{}) t.Cleanup(func() { - gnomodfetch.Client = oldClient + gnopkgfetch.Client = oldClient }) workingDir, err := os.Getwd() diff --git a/gnovm/cmd/gno/match.go b/gnovm/cmd/gno/match.go new file mode 100644 index 00000000000..9bee3024403 --- /dev/null +++ b/gnovm/cmd/gno/match.go @@ -0,0 +1,95 @@ +package main + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/gnolang/gno/gnovm/pkg/gnofiles" +) + +// targetsFromPatterns returns a list of target paths that match the patterns. +// Each pattern can represent a file or a directory, and if the pattern +// includes "/...", the "..." is treated as a wildcard, matching any string. +// Intended to be used by gno commands such as `gno test`. +func targetsFromPatterns(patterns []string) ([]string, error) { + paths := []string{} + for _, p := range patterns { + var match func(string) bool + patternLookup := false + dirToSearch := p + + // Check if the pattern includes `/...` + if strings.Contains(p, "/...") { + index := strings.Index(p, "/...") + if index != -1 { + dirToSearch = p[:index] // Extract the directory path to search + } + match = matchPattern(strings.TrimPrefix(p, "./")) + patternLookup = true + } + + info, err := os.Stat(dirToSearch) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + // If the pattern is a file or a directory + // without `/...`, add it to the list. + if !info.IsDir() || !patternLookup { + paths = append(paths, p) + continue + } + + // the pattern is a dir containing `/...`, walk the dir recursively and + // look for directories containing at least one .gno file and match pattern. + visited := map[string]bool{} // used to run the builder only once per folder. + err = filepath.WalkDir(dirToSearch, func(curpath string, f fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) + } + // Skip directories and non ".gno" files. + if f.IsDir() || !gnofiles.DirEntryIsGnoFile(f) { + return nil + } + + parentDir := filepath.Dir(curpath) + if _, found := visited[parentDir]; found { + return nil + } + + visited[parentDir] = true + if match(parentDir) { + paths = append(paths, parentDir) + } + + return nil + }) + if err != nil { + return nil, err + } + } + return paths, nil +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Simplified version of go source's matchPatternInternal +// (see $GOROOT/src/cmd/internal/pkgpattern) +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return func(name string) bool { + return reg.MatchString(name) + } +} diff --git a/gnovm/pkg/gnoload/match_test.go b/gnovm/cmd/gno/match_test.go similarity index 98% rename from gnovm/pkg/gnoload/match_test.go rename to gnovm/cmd/gno/match_test.go index 1b43925935f..9e9659bfe4f 100644 --- a/gnovm/pkg/gnoload/match_test.go +++ b/gnovm/cmd/gno/match_test.go @@ -1,4 +1,4 @@ -package gnoload +package main import ( "os" @@ -197,7 +197,7 @@ func TestTargetsFromPatterns(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - targets, err := TargetsFromPatterns(tc.in) + targets, err := targetsFromPatterns(tc.in) if tc.errorShouldContain != "" { assert.ErrorContains(t, err, tc.errorShouldContain) return diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index f3daa07f1c0..3184bc69012 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -8,9 +8,9 @@ import ( "path/filepath" "strings" - "github.com/gnolang/gno/gnovm/pkg/gnoload" + "github.com/gnolang/gno/gnovm/pkg/gnoimports" "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/gnovm/pkg/gnomodfetch" + "github.com/gnolang/gno/gnovm/pkg/gnopkgfetch" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "go.uber.org/multierr" @@ -175,7 +175,7 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { return fmt.Errorf("validate: %w", err) } - if err := gnomodfetch.FetchPackageImportsRecursively(io, path, gnoMod); err != nil { + if err := gnopkgfetch.FetchPackageImportsRecursively(io, path, gnoMod); err != nil { return err } @@ -333,7 +333,7 @@ func getImportToFilesMap(pkgPath string) (map[string][]string, error) { if strings.HasSuffix(filename, "_filetest.gno") { continue } - imports, err := gnoload.GetGnoFileImports(filepath.Join(pkgPath, filename)) + imports, err := gnoimports.FileImports(filepath.Join(pkgPath, filename)) if err != nil { return nil, err } diff --git a/gnovm/cmd/gno/mod_test.go b/gnovm/cmd/gno/mod_test.go index 1e2842ff182..e06eba6decf 100644 --- a/gnovm/cmd/gno/mod_test.go +++ b/gnovm/cmd/gno/mod_test.go @@ -46,7 +46,7 @@ func TestModApp(t *testing.T) { testDir: "../../tests/integ/require_invalid_module", simulateExternalRepo: true, stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", - errShouldContain: "fetch: failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", + errShouldContain: "failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", }, { args: []string{"mod", "download"}, @@ -69,7 +69,7 @@ func TestModApp(t *testing.T) { testDir: "../../tests/integ/replace_with_invalid_module", simulateExternalRepo: true, stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", - errShouldContain: "fetch: failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", + errShouldContain: "failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", }, // test `gno mod init` with no module name diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index 31e6d002061..fcc99b1baed 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -11,8 +11,8 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" + "github.com/gnolang/gno/gnovm/pkg/gnofiles" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/std" @@ -182,7 +182,7 @@ func listNonTestFiles(dir string) ([]string, error) { fn := make([]string, 0, len(fs)) for _, f := range fs { n := f.Name() - if gnoload.DirEntryIsGnoFile(f) && + if gnofiles.DirEntryIsGnoFile(f) && !strings.HasSuffix(n, "_test.gno") && !strings.HasSuffix(n, "_filetest.gno") { fn = append(fn, filepath.Join(dir, n)) diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index ddbf35d79c1..d54b12f6a4f 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -21,7 +21,6 @@ import ( "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/tests" teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" @@ -172,7 +171,7 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { cfg.rootDir = gnoenv.RootDir() } - paths, err := gnoload.TargetsFromPatterns(args) + paths, err := targetsFromPatterns(args) if err != nil { return fmt.Errorf("list targets from patterns: %w", err) } diff --git a/gnovm/cmd/gno/transpile.go b/gnovm/cmd/gno/transpile.go index c550744c5e6..81621c6378b 100644 --- a/gnovm/cmd/gno/transpile.go +++ b/gnovm/cmd/gno/transpile.go @@ -17,7 +17,7 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" - "github.com/gnolang/gno/gnovm/pkg/gnoload" + "github.com/gnolang/gno/gnovm/pkg/gnofiles" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/transpiler" "github.com/gnolang/gno/tm2/pkg/commands" @@ -135,7 +135,7 @@ func execTranspile(cfg *transpileCfg, args []string, io commands.IO) error { } // transpile .gno packages and files. - paths, err := gnoload.GnoDirsFromArgsRecursively(args) + paths, err := gnofiles.GnoDirsFromArgsRecursively(args) if err != nil { return fmt.Errorf("list paths: %w", err) } diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index 348550c7cdc..039341d9e45 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -9,10 +9,11 @@ import ( "os" "path" "path/filepath" + "slices" "sort" "strings" - "github.com/gnolang/gno/gnovm/pkg/gnoload" + "github.com/gnolang/gno/gnovm/pkg/gnoimports" "github.com/gnolang/gno/gnovm/pkg/gnomod" "golang.org/x/mod/module" ) @@ -72,11 +73,7 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { func getGnoModDirs(gm *gnomod.File, root string) []bfsDir { // cmd/go makes use of the go list command, we don't have that here. - imports, err := gnoload.GetGnoPackageImportsRecursive(root) - if err != nil { - log.Println("get imports at", root, ":", err) - return nil - } + imports := packageImportsRecursive(root) dirs := make([]bfsDir, 0, len(imports)) for _, r := range imports { @@ -99,6 +96,32 @@ func getGnoModDirs(gm *gnomod.File, root string) []bfsDir { return dirs } +func packageImportsRecursive(root string) []string { + res, err := gnoimports.PackageImports(root) + _ = err + + entries, err := os.ReadDir(root) + _ = err + + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + sub := packageImportsRecursive(filepath.Join(root, entry.Name())) + + for _, imp := range sub { + if !slices.Contains(res, imp) { + res = append(res, imp) + } + } + } + + sort.Strings(res) + + return res +} + // Reset puts the scan back at the beginning. func (d *bfsDirs) Reset() { d.offset = 0 diff --git a/gnovm/pkg/gnoload/match.go b/gnovm/pkg/gnofiles/gnofiles.go similarity index 59% rename from gnovm/pkg/gnoload/match.go rename to gnovm/pkg/gnofiles/gnofiles.go index 5c5923ad6b3..5a7d273f832 100644 --- a/gnovm/pkg/gnoload/match.go +++ b/gnovm/pkg/gnofiles/gnofiles.go @@ -1,11 +1,10 @@ -package gnoload +package gnofiles import ( "fmt" "io/fs" "os" "path/filepath" - "regexp" "strings" ) @@ -176,86 +175,3 @@ func GnoPackagesFromArgsRecursively(args []string) ([]string, error) { return paths, nil } - -// targetsFromPatterns returns a list of target paths that match the patterns. -// Each pattern can represent a file or a directory, and if the pattern -// includes "/...", the "..." is treated as a wildcard, matching any string. -// Intended to be used by gno commands such as `gno test`. -func TargetsFromPatterns(patterns []string) ([]string, error) { - paths := []string{} - for _, p := range patterns { - var match func(string) bool - patternLookup := false - dirToSearch := p - - // Check if the pattern includes `/...` - if strings.Contains(p, "/...") { - index := strings.Index(p, "/...") - if index != -1 { - dirToSearch = p[:index] // Extract the directory path to search - } - match = matchPattern(strings.TrimPrefix(p, "./")) - patternLookup = true - } - - info, err := os.Stat(dirToSearch) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - // If the pattern is a file or a directory - // without `/...`, add it to the list. - if !info.IsDir() || !patternLookup { - paths = append(paths, p) - continue - } - - // the pattern is a dir containing `/...`, walk the dir recursively and - // look for directories containing at least one .gno file and match pattern. - visited := map[string]bool{} // used to run the builder only once per folder. - err = filepath.WalkDir(dirToSearch, func(curpath string, f fs.DirEntry, err error) error { - if err != nil { - return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) - } - // Skip directories and non ".gno" files. - if f.IsDir() || !DirEntryIsGnoFile(f) { - return nil - } - - parentDir := filepath.Dir(curpath) - if _, found := visited[parentDir]; found { - return nil - } - - visited[parentDir] = true - if match(parentDir) { - paths = append(paths, parentDir) - } - - return nil - }) - if err != nil { - return nil, err - } - } - return paths, nil -} - -// matchPattern(pattern)(name) reports whether -// name matches pattern. Pattern is a limited glob -// pattern in which '...' means 'any string' and there -// is no other special syntax. -// Simplified version of go source's matchPatternInternal -// (see $GOROOT/src/cmd/internal/pkgpattern) -func matchPattern(pattern string) func(name string) bool { - re := regexp.QuoteMeta(pattern) - re = strings.Replace(re, `\.\.\.`, `.*`, -1) - // Special case: foo/... matches foo too. - if strings.HasSuffix(re, `/.*`) { - re = re[:len(re)-len(`/.*`)] + `(/.*)?` - } - reg := regexp.MustCompile(`^` + re + `$`) - return func(name string) bool { - return reg.MatchString(name) - } -} diff --git a/gnovm/pkg/gnoload/imports.go b/gnovm/pkg/gnoimports/imports.go similarity index 57% rename from gnovm/pkg/gnoload/imports.go rename to gnovm/pkg/gnoimports/imports.go index 03ade128914..8a33f5ae52c 100644 --- a/gnovm/pkg/gnoload/imports.go +++ b/gnovm/pkg/gnoimports/imports.go @@ -1,4 +1,4 @@ -package gnoload +package gnoimports import ( "fmt" @@ -6,18 +6,17 @@ import ( "go/token" "os" "path/filepath" - "slices" "sort" "strings" ) -// GetGnoPackageImports returns the list of gno imports from a given path. +// PackageImports returns the list of gno imports from a given path. // Note: It ignores subdirs. Since right now we are still deciding on // how to handle subdirs. // See: // - https://github.com/gnolang/gno/issues/1024 // - https://github.com/gnolang/gno/issues/852 -func GetGnoPackageImports(path string) ([]string, error) { +func PackageImports(path string) ([]string, error) { entries, err := os.ReadDir(path) if err != nil { return nil, err @@ -33,7 +32,7 @@ func GetGnoPackageImports(path string) ([]string, error) { if strings.HasSuffix(filename, "_filetest.gno") { continue } - imports, err := GetGnoFileImports(filepath.Join(path, filename)) + imports, err := FileImports(filepath.Join(path, filename)) if err != nil { return nil, err } @@ -50,41 +49,8 @@ func GetGnoPackageImports(path string) ([]string, error) { return allImports, nil } -// GetGnoPackageImportsRecursive returns the list of gno imports from a given path. -func GetGnoPackageImportsRecursive(root string) ([]string, error) { - res, err := GetGnoPackageImports(root) - if err != nil { - return nil, fmt.Errorf("get imports at %q: %w", root, err) - } - - entries, err := os.ReadDir(root) - if err != nil { - return nil, fmt.Errorf("read dir at %q: %w", root, err) - } - - for _, entry := range entries { - if !entry.IsDir() { - continue - } - - sub, err := GetGnoPackageImportsRecursive(filepath.Join(root, entry.Name())) - if err != nil { - return nil, err - } - - for _, imp := range sub { - if !slices.Contains(res, imp) { - res = append(res, imp) - } - } - } - - sort.Strings(res) - - return res, nil -} - -func GetGnoFileImports(fname string) ([]string, error) { +// FileImports returns the list of gno imports in a given file. +func FileImports(fname string) ([]string, error) { if !strings.HasSuffix(fname, ".gno") { return nil, fmt.Errorf("not a gno file: %q", fname) } diff --git a/gnovm/pkg/gnoload/imports_test.go b/gnovm/pkg/gnoimports/imports_test.go similarity index 97% rename from gnovm/pkg/gnoload/imports_test.go rename to gnovm/pkg/gnoimports/imports_test.go index 25f5f68d998..5123c0475ce 100644 --- a/gnovm/pkg/gnoload/imports_test.go +++ b/gnovm/pkg/gnoimports/imports_test.go @@ -1,4 +1,4 @@ -package gnoload +package gnoimports import ( "os" @@ -118,7 +118,7 @@ func TestGetGnoImports(t *testing.T) { require.NoError(t, err) } - imports, err := GetGnoPackageImports(tmpDir) + imports, err := PackageImports(tmpDir) require.NoError(t, err) require.Equal(t, expected, imports) diff --git a/gnovm/pkg/gnomodfetch/gnomodfetch.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go similarity index 93% rename from gnovm/pkg/gnomodfetch/gnomodfetch.go rename to gnovm/pkg/gnopkgfetch/gnopkgfetch.go index 8e882d99698..141cdf0eb1d 100644 --- a/gnovm/pkg/gnomodfetch/gnomodfetch.go +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go @@ -1,4 +1,4 @@ -package gnomodfetch +package gnopkgfetch import ( "fmt" @@ -8,8 +8,8 @@ import ( "path/filepath" "strings" + "github.com/gnolang/gno/gnovm/pkg/gnoimports" "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/pkg/gnoload" "github.com/gnolang/gno/gnovm/pkg/gnomod" tm2client "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" "github.com/gnolang/gno/tm2/pkg/commands" @@ -17,33 +17,9 @@ import ( "golang.org/x/mod/module" ) -func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomod.File) error { - imports, err := gnoload.GetGnoPackageImports(pkgDir) - if err != nil { - return fmt.Errorf("read imports at %q: %w", pkgDir, err) - } - - for _, pkgPath := range imports { - resolved := gnoMod.Resolve(module.Version{Path: pkgPath}) - resolvedPkgPath := resolved.Path - - if !gnolang.IsRemotePkgPath(resolvedPkgPath) { - continue - } - - depDir := gnomod.PackageDir("", module.Version{Path: resolvedPkgPath}) - - if err := FetchPackage(io, resolvedPkgPath, depDir); err != nil { - return fmt.Errorf("fetch import %q of %q: %w", resolvedPkgPath, pkgDir, err) - } - - if err := FetchPackageImportsRecursively(io, depDir, gnoMod); err != nil { - return err - } - } - - return nil -} +// Client allows to override the tendermint client used to fetch packages. +// It is exposed for testing purposes. +var Client tm2client.Client func FetchPackage(io commands.IO, pkgPath string, dst string) error { modFilePath := filepath.Join(dst, "gno.mod") @@ -109,7 +85,33 @@ func FetchPackage(io commands.IO, pkgPath string, dst string) error { return nil } -var Client tm2client.Client +func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomod.File) error { + imports, err := gnoimports.PackageImports(pkgDir) + if err != nil { + return fmt.Errorf("read imports at %q: %w", pkgDir, err) + } + + for _, pkgPath := range imports { + resolved := gnoMod.Resolve(module.Version{Path: pkgPath}) + resolvedPkgPath := resolved.Path + + if !gnolang.IsRemotePkgPath(resolvedPkgPath) { + continue + } + + depDir := gnomod.PackageDir("", module.Version{Path: resolvedPkgPath}) + + if err := FetchPackage(io, resolvedPkgPath, depDir); err != nil { + return fmt.Errorf("fetch import %q of %q: %w", resolvedPkgPath, pkgDir, err) + } + + if err := FetchPackageImportsRecursively(io, depDir, gnoMod); err != nil { + return err + } + } + + return nil +} // not using gno client due to cyclic dep func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { From bee03a08efef7019affcfac16ea49f69d8a966de Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 07:00:24 +0100 Subject: [PATCH 20/51] chore: move back utils Signed-off-by: Norman Meier --- gnovm/cmd/gno/match.go | 95 ------------ gnovm/cmd/gno/match_test.go | 297 ------------------------------------ gnovm/cmd/gno/util.go | 88 +++++++++++ gnovm/cmd/gno/util_test.go | 287 ++++++++++++++++++++++++++++++++++ 4 files changed, 375 insertions(+), 392 deletions(-) delete mode 100644 gnovm/cmd/gno/match.go delete mode 100644 gnovm/cmd/gno/match_test.go diff --git a/gnovm/cmd/gno/match.go b/gnovm/cmd/gno/match.go deleted file mode 100644 index 9bee3024403..00000000000 --- a/gnovm/cmd/gno/match.go +++ /dev/null @@ -1,95 +0,0 @@ -package main - -import ( - "fmt" - "io/fs" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/gnolang/gno/gnovm/pkg/gnofiles" -) - -// targetsFromPatterns returns a list of target paths that match the patterns. -// Each pattern can represent a file or a directory, and if the pattern -// includes "/...", the "..." is treated as a wildcard, matching any string. -// Intended to be used by gno commands such as `gno test`. -func targetsFromPatterns(patterns []string) ([]string, error) { - paths := []string{} - for _, p := range patterns { - var match func(string) bool - patternLookup := false - dirToSearch := p - - // Check if the pattern includes `/...` - if strings.Contains(p, "/...") { - index := strings.Index(p, "/...") - if index != -1 { - dirToSearch = p[:index] // Extract the directory path to search - } - match = matchPattern(strings.TrimPrefix(p, "./")) - patternLookup = true - } - - info, err := os.Stat(dirToSearch) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - // If the pattern is a file or a directory - // without `/...`, add it to the list. - if !info.IsDir() || !patternLookup { - paths = append(paths, p) - continue - } - - // the pattern is a dir containing `/...`, walk the dir recursively and - // look for directories containing at least one .gno file and match pattern. - visited := map[string]bool{} // used to run the builder only once per folder. - err = filepath.WalkDir(dirToSearch, func(curpath string, f fs.DirEntry, err error) error { - if err != nil { - return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) - } - // Skip directories and non ".gno" files. - if f.IsDir() || !gnofiles.DirEntryIsGnoFile(f) { - return nil - } - - parentDir := filepath.Dir(curpath) - if _, found := visited[parentDir]; found { - return nil - } - - visited[parentDir] = true - if match(parentDir) { - paths = append(paths, parentDir) - } - - return nil - }) - if err != nil { - return nil, err - } - } - return paths, nil -} - -// matchPattern(pattern)(name) reports whether -// name matches pattern. Pattern is a limited glob -// pattern in which '...' means 'any string' and there -// is no other special syntax. -// Simplified version of go source's matchPatternInternal -// (see $GOROOT/src/cmd/internal/pkgpattern) -func matchPattern(pattern string) func(name string) bool { - re := regexp.QuoteMeta(pattern) - re = strings.Replace(re, `\.\.\.`, `.*`, -1) - // Special case: foo/... matches foo too. - if strings.HasSuffix(re, `/.*`) { - re = re[:len(re)-len(`/.*`)] + `(/.*)?` - } - reg := regexp.MustCompile(`^` + re + `$`) - return func(name string) bool { - return reg.MatchString(name) - } -} diff --git a/gnovm/cmd/gno/match_test.go b/gnovm/cmd/gno/match_test.go deleted file mode 100644 index 9e9659bfe4f..00000000000 --- a/gnovm/cmd/gno/match_test.go +++ /dev/null @@ -1,297 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestMatchPattern(t *testing.T) { - tests := []struct { - pattern string - names []string - expected []bool - }{ - { - pattern: "foo", - names: []string{"foo", "bar", "baz", "foo/bar"}, - expected: []bool{true, false, false, false}, - }, - { - pattern: "foo/...", - names: []string{"foo", "foo/bar", "foo/bar/baz", "bar", "baz"}, - expected: []bool{true, true, true, false, false}, - }, - { - pattern: "foo/bar/...", - names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, - expected: []bool{true, true, false, false, false}, - }, - { - pattern: "foo/.../baz", - names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, - expected: []bool{false, true, false, false, false}, - }, - { - pattern: "foo/.../baz/...", - names: []string{"foo/bar/baz", "foo/baz/bar", "foo/bar/baz/qux", "foo/baz/bar/qux"}, - expected: []bool{true, false, true, false}, - }, - { - pattern: "...", - names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, - expected: []bool{true, true, true, true, true}, - }, - { - pattern: ".../bar", - names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, - expected: []bool{false, false, false, true, false}, - }, - } - - for _, test := range tests { - t.Run(test.pattern, func(t *testing.T) { - matchFunc := matchPattern(test.pattern) - for i, name := range test.names { - res := matchFunc(name) - assert.Equal(t, test.expected[i], res, "Expected: %v, Got: %v", test.expected[i], res) - } - }) - } -} - -func TestTargetsFromPatterns(t *testing.T) { - tmpDir := t.TempDir() - createGnoPackages(t, tmpDir) - - for _, tc := range []struct { - desc string - in, expected []string - errorShouldContain string - }{ - { - desc: "valid1", - in: []string{ - tmpDir, - }, - expected: []string{ - tmpDir, - }, - }, - { - desc: "valid2", - in: []string{ - tmpDir + "/foo", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - }, - }, - { - desc: "valid_recursive1", - in: []string{ - tmpDir + "/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "baz"), - filepath.Join(tmpDir, "foo", "qux"), - filepath.Join(tmpDir, "bar", "quux"), - filepath.Join(tmpDir, "foo", "qux", "corge"), - }, - }, - { - desc: "valid_recursive2", - in: []string{ - tmpDir + "/foo/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "foo", "qux"), - filepath.Join(tmpDir, "foo", "qux", "corge"), - }, - }, - { - desc: "valid_recursive2", - in: []string{ - tmpDir + "/.../qux", - }, - expected: []string{ - filepath.Join(tmpDir, "foo", "qux"), - }, - }, - { - desc: "valid_recursive3", - in: []string{ - tmpDir + "/.../qux/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo", "qux"), - filepath.Join(tmpDir, "foo", "qux", "corge"), - }, - }, - { - desc: "multiple_input", - in: []string{ - tmpDir + "/foo", - tmpDir + "/bar", - tmpDir + "/baz", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "baz"), - }, - }, - { - desc: "mixed_input1", - in: []string{ - tmpDir + "/foo", - tmpDir + "/bar/...", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "bar", "quux"), - }, - }, - { - desc: "mixed_input2", - in: []string{ - tmpDir + "/foo", - tmpDir + "/bar/...", - tmpDir + "/baz/baz.gno", - }, - expected: []string{ - filepath.Join(tmpDir, "foo"), - filepath.Join(tmpDir, "bar"), - filepath.Join(tmpDir, "bar", "quux"), - filepath.Join(tmpDir, "baz", "baz.gno"), - }, - }, - { - desc: "not_exists1", - in: []string{ - tmpDir + "/notexists", // dir path - }, - errorShouldContain: "no such file or directory", - }, - { - desc: "not_exists2", - in: []string{ - tmpDir + "/foo/bar.gno", // file path - }, - errorShouldContain: "no such file or directory", - }, - { - desc: "not_exists3", // mixed - in: []string{ - tmpDir + "/foo", // exists - tmpDir + "/notexists", // not exists - }, - errorShouldContain: "no such file or directory", - }, - } { - t.Run(tc.desc, func(t *testing.T) { - targets, err := targetsFromPatterns(tc.in) - if tc.errorShouldContain != "" { - assert.ErrorContains(t, err, tc.errorShouldContain) - return - } - assert.NoError(t, err) - require.Equal(t, len(tc.expected), len(targets)) - for _, tr := range targets { - assert.Contains(t, tc.expected, tr) - } - }) - } -} - -func createGnoPackages(t *testing.T, tmpDir string) { - t.Helper() - - type file struct { - name, data string - } - // Gno pkgs to create - pkgs := []struct { - dir string - files []file - }{ - // pkg 'foo', 'bar' and 'baz' - { - dir: filepath.Join(tmpDir, "foo"), - files: []file{ - { - name: "foo.gno", - data: `package foo`, - }, - }, - }, - { - dir: filepath.Join(tmpDir, "bar"), - files: []file{ - { - name: "bar.gno", - data: `package bar`, - }, - }, - }, - { - dir: filepath.Join(tmpDir, "baz"), - files: []file{ - { - name: "baz.gno", - data: `package baz`, - }, - }, - }, - - // pkg inside 'foo' pkg - { - dir: filepath.Join(tmpDir, "foo", "qux"), - files: []file{ - { - name: "qux.gno", - data: `package qux`, - }, - }, - }, - - // pkg inside 'bar' pkg - { - dir: filepath.Join(tmpDir, "bar", "quux"), - files: []file{ - { - name: "quux.gno", - data: `package quux`, - }, - }, - }, - - // pkg inside 'foo/qux' pkg - { - dir: filepath.Join(tmpDir, "foo", "qux", "corge"), - files: []file{ - { - name: "corge.gno", - data: `package corge`, - }, - }, - }, - } - - // Create pkgs - for _, p := range pkgs { - err := os.MkdirAll(p.dir, 0o700) - require.NoError(t, err) - for _, f := range p.files { - err = os.WriteFile(filepath.Join(p.dir, f.name), []byte(f.data), 0o644) - require.NoError(t, err) - } - } -} diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index 899cbd03895..61899c2d760 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -3,9 +3,14 @@ package main import ( "fmt" "io" + "io/fs" "os" "path/filepath" + "regexp" + "strings" "time" + + "github.com/gnolang/gno/gnovm/pkg/gnofiles" ) func isFileExist(path string) bool { @@ -13,6 +18,89 @@ func isFileExist(path string) bool { return err == nil } +// targetsFromPatterns returns a list of target paths that match the patterns. +// Each pattern can represent a file or a directory, and if the pattern +// includes "/...", the "..." is treated as a wildcard, matching any string. +// Intended to be used by gno commands such as `gno test`. +func targetsFromPatterns(patterns []string) ([]string, error) { + paths := []string{} + for _, p := range patterns { + var match func(string) bool + patternLookup := false + dirToSearch := p + + // Check if the pattern includes `/...` + if strings.Contains(p, "/...") { + index := strings.Index(p, "/...") + if index != -1 { + dirToSearch = p[:index] // Extract the directory path to search + } + match = matchPattern(strings.TrimPrefix(p, "./")) + patternLookup = true + } + + info, err := os.Stat(dirToSearch) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + // If the pattern is a file or a directory + // without `/...`, add it to the list. + if !info.IsDir() || !patternLookup { + paths = append(paths, p) + continue + } + + // the pattern is a dir containing `/...`, walk the dir recursively and + // look for directories containing at least one .gno file and match pattern. + visited := map[string]bool{} // used to run the builder only once per folder. + err = filepath.WalkDir(dirToSearch, func(curpath string, f fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) + } + // Skip directories and non ".gno" files. + if f.IsDir() || !gnofiles.DirEntryIsGnoFile(f) { + return nil + } + + parentDir := filepath.Dir(curpath) + if _, found := visited[parentDir]; found { + return nil + } + + visited[parentDir] = true + if match(parentDir) { + paths = append(paths, parentDir) + } + + return nil + }) + if err != nil { + return nil, err + } + } + return paths, nil +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Simplified version of go source's matchPatternInternal +// (see $GOROOT/src/cmd/internal/pkgpattern) +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return func(name string) bool { + return reg.MatchString(name) + } +} + func fmtDuration(d time.Duration) string { return fmt.Sprintf("%.2fs", d.Seconds()) } diff --git a/gnovm/cmd/gno/util_test.go b/gnovm/cmd/gno/util_test.go index 68e4557fb12..a92c924e272 100644 --- a/gnovm/cmd/gno/util_test.go +++ b/gnovm/cmd/gno/util_test.go @@ -9,6 +9,293 @@ import ( "github.com/stretchr/testify/require" ) +func TestMatchPattern(t *testing.T) { + tests := []struct { + pattern string + names []string + expected []bool + }{ + { + pattern: "foo", + names: []string{"foo", "bar", "baz", "foo/bar"}, + expected: []bool{true, false, false, false}, + }, + { + pattern: "foo/...", + names: []string{"foo", "foo/bar", "foo/bar/baz", "bar", "baz"}, + expected: []bool{true, true, true, false, false}, + }, + { + pattern: "foo/bar/...", + names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, + expected: []bool{true, true, false, false, false}, + }, + { + pattern: "foo/.../baz", + names: []string{"foo/bar", "foo/bar/baz", "foo/baz/bar", "foo", "bar"}, + expected: []bool{false, true, false, false, false}, + }, + { + pattern: "foo/.../baz/...", + names: []string{"foo/bar/baz", "foo/baz/bar", "foo/bar/baz/qux", "foo/baz/bar/qux"}, + expected: []bool{true, false, true, false}, + }, + { + pattern: "...", + names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, + expected: []bool{true, true, true, true, true}, + }, + { + pattern: ".../bar", + names: []string{"foo", "bar", "baz", "foo/bar", "foo/bar/baz"}, + expected: []bool{false, false, false, true, false}, + }, + } + + for _, test := range tests { + t.Run(test.pattern, func(t *testing.T) { + matchFunc := matchPattern(test.pattern) + for i, name := range test.names { + res := matchFunc(name) + assert.Equal(t, test.expected[i], res, "Expected: %v, Got: %v", test.expected[i], res) + } + }) + } +} + +func TestTargetsFromPatterns(t *testing.T) { + tmpDir := t.TempDir() + createGnoPackages(t, tmpDir) + + for _, tc := range []struct { + desc string + in, expected []string + errorShouldContain string + }{ + { + desc: "valid1", + in: []string{ + tmpDir, + }, + expected: []string{ + tmpDir, + }, + }, + { + desc: "valid2", + in: []string{ + tmpDir + "/foo", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + }, + }, + { + desc: "valid_recursive1", + in: []string{ + tmpDir + "/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "baz"), + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "bar", "quux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "valid_recursive2", + in: []string{ + tmpDir + "/foo/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "valid_recursive2", + in: []string{ + tmpDir + "/.../qux", + }, + expected: []string{ + filepath.Join(tmpDir, "foo", "qux"), + }, + }, + { + desc: "valid_recursive3", + in: []string{ + tmpDir + "/.../qux/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo", "qux"), + filepath.Join(tmpDir, "foo", "qux", "corge"), + }, + }, + { + desc: "multiple_input", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar", + tmpDir + "/baz", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "baz"), + }, + }, + { + desc: "mixed_input1", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar/...", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "bar", "quux"), + }, + }, + { + desc: "mixed_input2", + in: []string{ + tmpDir + "/foo", + tmpDir + "/bar/...", + tmpDir + "/baz/baz.gno", + }, + expected: []string{ + filepath.Join(tmpDir, "foo"), + filepath.Join(tmpDir, "bar"), + filepath.Join(tmpDir, "bar", "quux"), + filepath.Join(tmpDir, "baz", "baz.gno"), + }, + }, + { + desc: "not_exists1", + in: []string{ + tmpDir + "/notexists", // dir path + }, + errorShouldContain: "no such file or directory", + }, + { + desc: "not_exists2", + in: []string{ + tmpDir + "/foo/bar.gno", // file path + }, + errorShouldContain: "no such file or directory", + }, + { + desc: "not_exists3", // mixed + in: []string{ + tmpDir + "/foo", // exists + tmpDir + "/notexists", // not exists + }, + errorShouldContain: "no such file or directory", + }, + } { + t.Run(tc.desc, func(t *testing.T) { + targets, err := targetsFromPatterns(tc.in) + if tc.errorShouldContain != "" { + assert.ErrorContains(t, err, tc.errorShouldContain) + return + } + assert.NoError(t, err) + require.Equal(t, len(tc.expected), len(targets)) + for _, tr := range targets { + assert.Contains(t, tc.expected, tr) + } + }) + } +} + +func createGnoPackages(t *testing.T, tmpDir string) { + t.Helper() + + type file struct { + name, data string + } + // Gno pkgs to create + pkgs := []struct { + dir string + files []file + }{ + // pkg 'foo', 'bar' and 'baz' + { + dir: filepath.Join(tmpDir, "foo"), + files: []file{ + { + name: "foo.gno", + data: `package foo`, + }, + }, + }, + { + dir: filepath.Join(tmpDir, "bar"), + files: []file{ + { + name: "bar.gno", + data: `package bar`, + }, + }, + }, + { + dir: filepath.Join(tmpDir, "baz"), + files: []file{ + { + name: "baz.gno", + data: `package baz`, + }, + }, + }, + + // pkg inside 'foo' pkg + { + dir: filepath.Join(tmpDir, "foo", "qux"), + files: []file{ + { + name: "qux.gno", + data: `package qux`, + }, + }, + }, + + // pkg inside 'bar' pkg + { + dir: filepath.Join(tmpDir, "bar", "quux"), + files: []file{ + { + name: "quux.gno", + data: `package quux`, + }, + }, + }, + + // pkg inside 'foo/qux' pkg + { + dir: filepath.Join(tmpDir, "foo", "qux", "corge"), + files: []file{ + { + name: "corge.gno", + data: `package corge`, + }, + }, + }, + } + + // Create pkgs + for _, p := range pkgs { + err := os.MkdirAll(p.dir, 0o700) + require.NoError(t, err) + for _, f := range p.files { + err = os.WriteFile(filepath.Join(p.dir, f.name), []byte(f.data), 0o644) + require.NoError(t, err) + } + } +} + func TestResolvePath(t *testing.T) { t.Parallel() From c7498466bf4797d7cf67bb3e6514c690e83fd69d Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 07:14:41 +0100 Subject: [PATCH 21/51] chore: rename funcs and write doc Signed-off-by: Norman Meier --- gnovm/cmd/gno/lint.go | 2 +- gnovm/cmd/gno/transpile.go | 2 +- gnovm/pkg/gnofiles/gnofiles.go | 61 +++++++++++++++------------- gnovm/pkg/gnoimports/imports.go | 4 +- gnovm/pkg/gnopkgfetch/gnopkgfetch.go | 2 + 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index 8cddc6cc400..84f78a46eae 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -64,7 +64,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { rootDir = gnoenv.RootDir() } - pkgPaths, err := gnofiles.GnoPackagesFromArgsRecursively(args) + pkgPaths, err := gnofiles.GnoDirsFromArgsRecursively(args) if err != nil { return fmt.Errorf("list packages from args: %w", err) } diff --git a/gnovm/cmd/gno/transpile.go b/gnovm/cmd/gno/transpile.go index 81621c6378b..c6016cd69f0 100644 --- a/gnovm/cmd/gno/transpile.go +++ b/gnovm/cmd/gno/transpile.go @@ -135,7 +135,7 @@ func execTranspile(cfg *transpileCfg, args []string, io commands.IO) error { } // transpile .gno packages and files. - paths, err := gnofiles.GnoDirsFromArgsRecursively(args) + paths, err := gnofiles.GnoTargetsFromArgs(args) if err != nil { return fmt.Errorf("list paths: %w", err) } diff --git a/gnovm/pkg/gnofiles/gnofiles.go b/gnovm/pkg/gnofiles/gnofiles.go index 5a7d273f832..5ae71872005 100644 --- a/gnovm/pkg/gnofiles/gnofiles.go +++ b/gnovm/pkg/gnofiles/gnofiles.go @@ -8,11 +8,13 @@ import ( "strings" ) +// DirEntryIsGnoFile determines if a given DirEnry is a gno file func DirEntryIsGnoFile(f fs.DirEntry) bool { name := f.Name() return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".gno") && !f.IsDir() } +// GnoFilesFromArgsRecursively returns all gno files present under the given filepaths func GnoFilesFromArgsRecursively(args []string) ([]string, error) { var paths []string @@ -51,7 +53,8 @@ func GnoFilesFromArgsRecursively(args []string) ([]string, error) { return paths, nil } -func GnoDirsFromArgsRecursively(args []string) ([]string, error) { +// GnoTargetsFromArgs returns all gno files and directories containing gno files present in the given filepaths +func GnoTargetsFromArgs(args []string) ([]string, error) { var paths []string for _, argPath := range args { @@ -80,6 +83,7 @@ func GnoDirsFromArgsRecursively(args []string) ([]string, error) { return paths, nil } +// GnoFilesFromArg returns all gno files that are in the given filepaths func GnoFilesFromArgs(args []string) ([]string, error) { var paths []string @@ -111,6 +115,34 @@ func GnoFilesFromArgs(args []string) ([]string, error) { return paths, nil } +// GnoDirsFromArgsRecursively returns all directories containing gno files under the given filepaths +func GnoDirsFromArgsRecursively(args []string) ([]string, error) { + var paths []string + + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + paths = append(paths, ensurePathPrefix(argPath)) + + continue + } + + // Gather package paths from the directory + err = walkDirForGnoDirs(argPath, func(path string) { + paths = append(paths, ensurePathPrefix(path)) + }) + if err != nil { + return nil, fmt.Errorf("unable to walk dir: %w", err) + } + } + + return paths, nil +} + func ensurePathPrefix(path string) string { if filepath.IsAbs(path) { return path @@ -148,30 +180,3 @@ func walkDirForGnoDirs(root string, addPath func(path string)) error { return filepath.WalkDir(root, walkFn) } - -func GnoPackagesFromArgsRecursively(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - paths = append(paths, ensurePathPrefix(argPath)) - - continue - } - - // Gather package paths from the directory - err = walkDirForGnoDirs(argPath, func(path string) { - paths = append(paths, ensurePathPrefix(path)) - }) - if err != nil { - return nil, fmt.Errorf("unable to walk dir: %w", err) - } - } - - return paths, nil -} diff --git a/gnovm/pkg/gnoimports/imports.go b/gnovm/pkg/gnoimports/imports.go index 8a33f5ae52c..4387e163094 100644 --- a/gnovm/pkg/gnoimports/imports.go +++ b/gnovm/pkg/gnoimports/imports.go @@ -8,6 +8,8 @@ import ( "path/filepath" "sort" "strings" + + "github.com/gnolang/gno/gnovm/pkg/gnofiles" ) // PackageImports returns the list of gno imports from a given path. @@ -26,7 +28,7 @@ func PackageImports(path string) ([]string, error) { seen := make(map[string]struct{}) for _, e := range entries { filename := e.Name() - if ext := filepath.Ext(filename); ext != ".gno" { + if !gnofiles.DirEntryIsGnoFile(e) { continue } if strings.HasSuffix(filename, "_filetest.gno") { diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go index 141cdf0eb1d..be2e973601f 100644 --- a/gnovm/pkg/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go @@ -21,6 +21,7 @@ import ( // It is exposed for testing purposes. var Client tm2client.Client +// FetchPackage downloads a remote gno package by pkg path and store it at dst func FetchPackage(io commands.IO, pkgPath string, dst string) error { modFilePath := filepath.Join(dst, "gno.mod") @@ -85,6 +86,7 @@ func FetchPackage(io commands.IO, pkgPath string, dst string) error { return nil } +// FetchPackageImportsRecursively recursively fetches the imports of a local package while following a given gno.mod replace directives func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomod.File) error { imports, err := gnoimports.PackageImports(pkgDir) if err != nil { From 8f320741e6f378ef70920f34c29aa10581743103 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 07:17:36 +0100 Subject: [PATCH 22/51] chore: refacto Signed-off-by: Norman Meier --- gnovm/pkg/gnofiles/gnofiles.go | 39 ----------------- gnovm/pkg/gnopkgfetch/gnopkgfetch.go | 62 ++++++++++++++-------------- 2 files changed, 31 insertions(+), 70 deletions(-) diff --git a/gnovm/pkg/gnofiles/gnofiles.go b/gnovm/pkg/gnofiles/gnofiles.go index 5ae71872005..a78385dd6a4 100644 --- a/gnovm/pkg/gnofiles/gnofiles.go +++ b/gnovm/pkg/gnofiles/gnofiles.go @@ -14,45 +14,6 @@ func DirEntryIsGnoFile(f fs.DirEntry) bool { return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".gno") && !f.IsDir() } -// GnoFilesFromArgsRecursively returns all gno files present under the given filepaths -func GnoFilesFromArgsRecursively(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - if DirEntryIsGnoFile(fs.FileInfoToDirEntry(info)) { - paths = append(paths, ensurePathPrefix(argPath)) - } - - continue - } - - err = walkDirForGnoDirs(argPath, func(path string) { - dir := ensurePathPrefix(path) - files, err := os.ReadDir(dir) - if err != nil { - return - } - for _, f := range files { - if DirEntryIsGnoFile(f) { - path := filepath.Join(dir, f.Name()) - paths = append(paths, ensurePathPrefix(path)) - } - } - }) - if err != nil { - return nil, fmt.Errorf("unable to walk dir: %w", err) - } - } - - return paths, nil -} - // GnoTargetsFromArgs returns all gno files and directories containing gno files present in the given filepaths func GnoTargetsFromArgs(args []string) ([]string, error) { var paths []string diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go index be2e973601f..fe4cbc48a06 100644 --- a/gnovm/pkg/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go @@ -21,8 +21,37 @@ import ( // It is exposed for testing purposes. var Client tm2client.Client -// FetchPackage downloads a remote gno package by pkg path and store it at dst -func FetchPackage(io commands.IO, pkgPath string, dst string) error { +// FetchPackageImportsRecursively recursively fetches the imports of a local package while following a given gno.mod replace directives +func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomod.File) error { + imports, err := gnoimports.PackageImports(pkgDir) + if err != nil { + return fmt.Errorf("read imports at %q: %w", pkgDir, err) + } + + for _, pkgPath := range imports { + resolved := gnoMod.Resolve(module.Version{Path: pkgPath}) + resolvedPkgPath := resolved.Path + + if !gnolang.IsRemotePkgPath(resolvedPkgPath) { + continue + } + + depDir := gnomod.PackageDir("", module.Version{Path: resolvedPkgPath}) + + if err := fetchPackage(io, resolvedPkgPath, depDir); err != nil { + return fmt.Errorf("fetch import %q of %q: %w", resolvedPkgPath, pkgDir, err) + } + + if err := FetchPackageImportsRecursively(io, depDir, gnoMod); err != nil { + return err + } + } + + return nil +} + +// fetchPackage downloads a remote gno package by pkg path and store it at dst +func fetchPackage(io commands.IO, pkgPath string, dst string) error { modFilePath := filepath.Join(dst, "gno.mod") if _, err := os.Stat(modFilePath); err == nil { @@ -86,35 +115,6 @@ func FetchPackage(io commands.IO, pkgPath string, dst string) error { return nil } -// FetchPackageImportsRecursively recursively fetches the imports of a local package while following a given gno.mod replace directives -func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomod.File) error { - imports, err := gnoimports.PackageImports(pkgDir) - if err != nil { - return fmt.Errorf("read imports at %q: %w", pkgDir, err) - } - - for _, pkgPath := range imports { - resolved := gnoMod.Resolve(module.Version{Path: pkgPath}) - resolvedPkgPath := resolved.Path - - if !gnolang.IsRemotePkgPath(resolvedPkgPath) { - continue - } - - depDir := gnomod.PackageDir("", module.Version{Path: resolvedPkgPath}) - - if err := FetchPackage(io, resolvedPkgPath, depDir); err != nil { - return fmt.Errorf("fetch import %q of %q: %w", resolvedPkgPath, pkgDir, err) - } - - if err := FetchPackageImportsRecursively(io, depDir, gnoMod); err != nil { - return err - } - } - - return nil -} - // not using gno client due to cyclic dep func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { path := "vm/qfile" From c353b2116d17f896771c3e38e7f2885152e824c2 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 07:21:53 +0100 Subject: [PATCH 23/51] chore: atomicize Signed-off-by: Norman Meier --- gnovm/cmd/gno/fmt.go | 3 +- gnovm/cmd/gno/lint.go | 3 +- gnovm/cmd/gno/run.go | 3 +- gnovm/cmd/gno/transpile.go | 3 +- gnovm/cmd/gno/util.go | 134 +++++++++++++++++++++++++++++- gnovm/pkg/gnofiles/gnofiles.go | 143 -------------------------------- gnovm/pkg/gnoimports/imports.go | 4 +- 7 files changed, 136 insertions(+), 157 deletions(-) delete mode 100644 gnovm/pkg/gnofiles/gnofiles.go diff --git a/gnovm/cmd/gno/fmt.go b/gnovm/cmd/gno/fmt.go index 8b4079edd3a..de6c28c4df0 100644 --- a/gnovm/cmd/gno/fmt.go +++ b/gnovm/cmd/gno/fmt.go @@ -15,7 +15,6 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" - "github.com/gnolang/gno/gnovm/pkg/gnofiles" "github.com/gnolang/gno/gnovm/pkg/gnofmt" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/rogpeppe/go-internal/diff" @@ -100,7 +99,7 @@ func execFmt(cfg *fmtCfg, args []string, io commands.IO) error { return fmt.Errorf("unable to get targets paths from patterns: %w", err) } - files, err := gnofiles.GnoFilesFromArgs(paths) + files, err := gnoFilesFromArgs(paths) if err != nil { return fmt.Errorf("unable to gather gno files: %w", err) } diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index 84f78a46eae..c6008117f13 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -13,7 +13,6 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" - "github.com/gnolang/gno/gnovm/pkg/gnofiles" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" @@ -64,7 +63,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { rootDir = gnoenv.RootDir() } - pkgPaths, err := gnofiles.GnoDirsFromArgsRecursively(args) + pkgPaths, err := gnoPackagesFromArgsRecursively(args) if err != nil { return fmt.Errorf("list packages from args: %w", err) } diff --git a/gnovm/cmd/gno/run.go b/gnovm/cmd/gno/run.go index fcc99b1baed..f174c2b4cc5 100644 --- a/gnovm/cmd/gno/run.go +++ b/gnovm/cmd/gno/run.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" - "github.com/gnolang/gno/gnovm/pkg/gnofiles" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" @@ -182,7 +181,7 @@ func listNonTestFiles(dir string) ([]string, error) { fn := make([]string, 0, len(fs)) for _, f := range fs { n := f.Name() - if gnofiles.DirEntryIsGnoFile(f) && + if isGnoFile(f) && !strings.HasSuffix(n, "_test.gno") && !strings.HasSuffix(n, "_filetest.gno") { fn = append(fn, filepath.Join(dir, n)) diff --git a/gnovm/cmd/gno/transpile.go b/gnovm/cmd/gno/transpile.go index c6016cd69f0..1e3081ca2b0 100644 --- a/gnovm/cmd/gno/transpile.go +++ b/gnovm/cmd/gno/transpile.go @@ -17,7 +17,6 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoenv" - "github.com/gnolang/gno/gnovm/pkg/gnofiles" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/pkg/transpiler" "github.com/gnolang/gno/tm2/pkg/commands" @@ -135,7 +134,7 @@ func execTranspile(cfg *transpileCfg, args []string, io commands.IO) error { } // transpile .gno packages and files. - paths, err := gnofiles.GnoTargetsFromArgs(args) + paths, err := gnoFilesFromArgsRecursively(args) if err != nil { return fmt.Errorf("list paths: %w", err) } diff --git a/gnovm/cmd/gno/util.go b/gnovm/cmd/gno/util.go index 61899c2d760..90aedd5d27a 100644 --- a/gnovm/cmd/gno/util.go +++ b/gnovm/cmd/gno/util.go @@ -9,15 +9,143 @@ import ( "regexp" "strings" "time" - - "github.com/gnolang/gno/gnovm/pkg/gnofiles" ) +func isGnoFile(f fs.DirEntry) bool { + name := f.Name() + return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".gno") && !f.IsDir() +} + func isFileExist(path string) bool { _, err := os.Stat(path) return err == nil } +func gnoFilesFromArgsRecursively(args []string) ([]string, error) { + var paths []string + + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + if isGnoFile(fs.FileInfoToDirEntry(info)) { + paths = append(paths, ensurePathPrefix(argPath)) + } + + continue + } + + // Gather package paths from the directory + err = walkDirForGnoFiles(argPath, func(path string) { + paths = append(paths, ensurePathPrefix(path)) + }) + if err != nil { + return nil, fmt.Errorf("unable to walk dir: %w", err) + } + } + + return paths, nil +} + +func gnoFilesFromArgs(args []string) ([]string, error) { + var paths []string + + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + if isGnoFile(fs.FileInfoToDirEntry(info)) { + paths = append(paths, ensurePathPrefix(argPath)) + } + continue + } + + files, err := os.ReadDir(argPath) + if err != nil { + return nil, err + } + for _, f := range files { + if isGnoFile(f) { + path := filepath.Join(argPath, f.Name()) + paths = append(paths, ensurePathPrefix(path)) + } + } + } + + return paths, nil +} + +func ensurePathPrefix(path string) string { + if filepath.IsAbs(path) { + return path + } + + // cannot use path.Join or filepath.Join, because we need + // to ensure that ./ is the prefix to pass to go build. + // if not absolute. + return "." + string(filepath.Separator) + path +} + +func walkDirForGnoFiles(root string, addPath func(path string)) error { + visited := make(map[string]struct{}) + + walkFn := func(currPath string, f fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("%s: walk dir: %w", root, err) + } + + if f.IsDir() || !isGnoFile(f) { + return nil + } + + parentDir := filepath.Dir(currPath) + if _, found := visited[parentDir]; found { + return nil + } + + visited[parentDir] = struct{}{} + + addPath(parentDir) + + return nil + } + + return filepath.WalkDir(root, walkFn) +} + +func gnoPackagesFromArgsRecursively(args []string) ([]string, error) { + var paths []string + + for _, argPath := range args { + info, err := os.Stat(argPath) + if err != nil { + return nil, fmt.Errorf("invalid file or package path: %w", err) + } + + if !info.IsDir() { + paths = append(paths, ensurePathPrefix(argPath)) + + continue + } + + // Gather package paths from the directory + err = walkDirForGnoFiles(argPath, func(path string) { + paths = append(paths, ensurePathPrefix(path)) + }) + if err != nil { + return nil, fmt.Errorf("unable to walk dir: %w", err) + } + } + + return paths, nil +} + // targetsFromPatterns returns a list of target paths that match the patterns. // Each pattern can represent a file or a directory, and if the pattern // includes "/...", the "..." is treated as a wildcard, matching any string. @@ -59,7 +187,7 @@ func targetsFromPatterns(patterns []string) ([]string, error) { return fmt.Errorf("%s: walk dir: %w", dirToSearch, err) } // Skip directories and non ".gno" files. - if f.IsDir() || !gnofiles.DirEntryIsGnoFile(f) { + if f.IsDir() || !isGnoFile(f) { return nil } diff --git a/gnovm/pkg/gnofiles/gnofiles.go b/gnovm/pkg/gnofiles/gnofiles.go deleted file mode 100644 index a78385dd6a4..00000000000 --- a/gnovm/pkg/gnofiles/gnofiles.go +++ /dev/null @@ -1,143 +0,0 @@ -package gnofiles - -import ( - "fmt" - "io/fs" - "os" - "path/filepath" - "strings" -) - -// DirEntryIsGnoFile determines if a given DirEnry is a gno file -func DirEntryIsGnoFile(f fs.DirEntry) bool { - name := f.Name() - return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".gno") && !f.IsDir() -} - -// GnoTargetsFromArgs returns all gno files and directories containing gno files present in the given filepaths -func GnoTargetsFromArgs(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - if DirEntryIsGnoFile(fs.FileInfoToDirEntry(info)) { - paths = append(paths, ensurePathPrefix(argPath)) - } - - continue - } - - // Gather package paths from the directory - err = walkDirForGnoDirs(argPath, func(path string) { - paths = append(paths, ensurePathPrefix(path)) - }) - if err != nil { - return nil, fmt.Errorf("unable to walk dir: %w", err) - } - } - - return paths, nil -} - -// GnoFilesFromArg returns all gno files that are in the given filepaths -func GnoFilesFromArgs(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - if DirEntryIsGnoFile(fs.FileInfoToDirEntry(info)) { - paths = append(paths, ensurePathPrefix(argPath)) - } - continue - } - - files, err := os.ReadDir(argPath) - if err != nil { - return nil, err - } - for _, f := range files { - if DirEntryIsGnoFile(f) { - path := filepath.Join(argPath, f.Name()) - paths = append(paths, ensurePathPrefix(path)) - } - } - } - - return paths, nil -} - -// GnoDirsFromArgsRecursively returns all directories containing gno files under the given filepaths -func GnoDirsFromArgsRecursively(args []string) ([]string, error) { - var paths []string - - for _, argPath := range args { - info, err := os.Stat(argPath) - if err != nil { - return nil, fmt.Errorf("invalid file or package path: %w", err) - } - - if !info.IsDir() { - paths = append(paths, ensurePathPrefix(argPath)) - - continue - } - - // Gather package paths from the directory - err = walkDirForGnoDirs(argPath, func(path string) { - paths = append(paths, ensurePathPrefix(path)) - }) - if err != nil { - return nil, fmt.Errorf("unable to walk dir: %w", err) - } - } - - return paths, nil -} - -func ensurePathPrefix(path string) string { - if filepath.IsAbs(path) { - return path - } - - // cannot use path.Join or filepath.Join, because we need - // to ensure that ./ is the prefix to pass to go build. - // if not absolute. - return "." + string(filepath.Separator) + path -} - -func walkDirForGnoDirs(root string, addPath func(path string)) error { - visited := make(map[string]struct{}) - - walkFn := func(currPath string, f fs.DirEntry, err error) error { - if err != nil { - return fmt.Errorf("%s: walk dir: %w", root, err) - } - - if f.IsDir() || !DirEntryIsGnoFile(f) { - return nil - } - - parentDir := filepath.Dir(currPath) - if _, found := visited[parentDir]; found { - return nil - } - - visited[parentDir] = struct{}{} - - addPath(parentDir) - - return nil - } - - return filepath.WalkDir(root, walkFn) -} diff --git a/gnovm/pkg/gnoimports/imports.go b/gnovm/pkg/gnoimports/imports.go index 4387e163094..28b94922627 100644 --- a/gnovm/pkg/gnoimports/imports.go +++ b/gnovm/pkg/gnoimports/imports.go @@ -8,8 +8,6 @@ import ( "path/filepath" "sort" "strings" - - "github.com/gnolang/gno/gnovm/pkg/gnofiles" ) // PackageImports returns the list of gno imports from a given path. @@ -28,7 +26,7 @@ func PackageImports(path string) ([]string, error) { seen := make(map[string]struct{}) for _, e := range entries { filename := e.Name() - if !gnofiles.DirEntryIsGnoFile(e) { + if strings.HasSuffix(filename, ".gno") { continue } if strings.HasSuffix(filename, "_filetest.gno") { From 283b3085cbd0f63fce0c63f55ecb19934fcb9586 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 07:26:17 +0100 Subject: [PATCH 24/51] fix: bad refactor Signed-off-by: Norman Meier --- gnovm/pkg/gnoimports/imports.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnoimports/imports.go b/gnovm/pkg/gnoimports/imports.go index 28b94922627..f0c658f311a 100644 --- a/gnovm/pkg/gnoimports/imports.go +++ b/gnovm/pkg/gnoimports/imports.go @@ -26,7 +26,7 @@ func PackageImports(path string) ([]string, error) { seen := make(map[string]struct{}) for _, e := range entries { filename := e.Name() - if strings.HasSuffix(filename, ".gno") { + if !strings.HasSuffix(filename, ".gno") { continue } if strings.HasSuffix(filename, "_filetest.gno") { From d4f6cad530ead525246a9cb06289127f171c0c8c Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 07:29:28 +0100 Subject: [PATCH 25/51] chore: remove unused funcs Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/fetch.go | 30 ------------------------------ gnovm/pkg/gnomod/gnomod.go | 13 ------------- gnovm/pkg/gnomod/read.go | 12 ------------ 3 files changed, 55 deletions(-) delete mode 100644 gnovm/pkg/gnomod/fetch.go diff --git a/gnovm/pkg/gnomod/fetch.go b/gnovm/pkg/gnomod/fetch.go deleted file mode 100644 index 24aaac2f9d4..00000000000 --- a/gnovm/pkg/gnomod/fetch.go +++ /dev/null @@ -1,30 +0,0 @@ -package gnomod - -import ( - "fmt" - - abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" - "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" -) - -func queryChain(remote string, qpath string, data []byte) (res *abci.ResponseQuery, err error) { - opts2 := client.ABCIQueryOptions{ - // Height: height, XXX - // Prove: false, XXX - } - cli, err := client.NewHTTPClient(remote) - if err != nil { - return nil, err - } - - qres, err := cli.ABCIQueryWithOptions(qpath, data, opts2) - if err != nil { - return nil, err - } - if qres.Response.Error != nil { - fmt.Printf("Log: %s\n", qres.Response.Log) - return nil, qres.Response.Error - } - - return &qres.Response, nil -} diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 726d9ba2bc0..b75fc2f09f3 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -13,8 +13,6 @@ import ( "golang.org/x/mod/module" ) -const queryPathFile = "vm/qfile" - // ModCachePath returns the path for gno modules func ModCachePath() string { return filepath.Join(gnoenv.HomeDir(), "pkg", "mod") @@ -96,14 +94,3 @@ func isReplaced(mod module.Version, repl []*modfile.Replace) (module.Version, bo } return module.Version{}, false } - -func removeDuplicateStr(str []string) (res []string) { - m := make(map[string]struct{}, len(str)) - for _, s := range str { - if _, ok := m[s]; !ok { - m[s] = struct{}{} - res = append(res, s) - } - } - return -} diff --git a/gnovm/pkg/gnomod/read.go b/gnovm/pkg/gnomod/read.go index 7bfbca69d18..bb03ddf6efd 100644 --- a/gnovm/pkg/gnomod/read.go +++ b/gnovm/pkg/gnomod/read.go @@ -856,18 +856,6 @@ func updateLine(line *modfile.Line, tokens ...string) { line.Token = tokens } -// isIndirect reports whether line has a "// indirect" comment, -// meaning it is in go.mod only for its effect on indirect dependencies, -// so that it can be dropped entirely once the effective version of the -// indirect dependency reaches the given minimum version. -func isIndirect(line *modfile.Line) bool { - if len(line.Suffix) == 0 { - return false - } - f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) - return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;") -} - // addLine adds a line containing the given tokens to the file. // // If the first token of the hint matches the first token of the From e1331fde180daa41d713d0eb19d34c33692137d6 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 07:35:40 +0100 Subject: [PATCH 26/51] chore: dedup code Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/pkg.go | 45 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index 252b0c6b37c..1d761ce5354 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -2,13 +2,12 @@ package gnomod import ( "fmt" - "go/parser" - gotoken "go/token" "io/fs" "os" "path/filepath" - "slices" "strings" + + "github.com/gnolang/gno/gnovm/pkg/gnoimports" ) type Pkg struct { @@ -114,40 +113,14 @@ func ListPkgs(root string) (PkgList, error) { return fmt.Errorf("validate: %w", err) } + imports, err := gnoimports.PackageImports(path) + _ = err // get all valid imports while ignoring bad/partial files + pkgs = append(pkgs, Pkg{ - Dir: path, - Name: gnoMod.Module.Mod.Path, - Draft: gnoMod.Draft, - Imports: func() []string { - dir, err := os.ReadDir(path) - if err != nil { - return nil - } - resMap := map[string]struct{}{} - for _, f := range dir { - filename := f.Name() - if f.IsDir() || !strings.HasSuffix(filename, ".gno") { - continue - } - fileSet := gotoken.NewFileSet() - gnoFile, err := parser.ParseFile(fileSet, filepath.Join(path, filename), nil, parser.ImportsOnly) - if err != nil { - continue - } - for _, importSpec := range gnoFile.Imports { - val := strings.TrimSuffix(strings.TrimPrefix(importSpec.Path.Value, `"`), `"`) - resMap[val] = struct{}{} - } - } - res := make([]string, len(resMap)) - i := 0 - for imp := range resMap { - res[i] = imp - i++ - } - slices.Sort(res) - return res - }(), + Dir: path, + Name: gnoMod.Module.Mod.Path, + Draft: gnoMod.Draft, + Imports: imports, }) return nil }) From 965095bdc0a212056b347013d7a1930c20d4d579 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 08:15:19 +0100 Subject: [PATCH 27/51] chore: port test Signed-off-by: Norman Meier --- gnovm/cmd/gno/main_test.go | 78 +----------- gnovm/pkg/gnopkgfetch/gnopkgfetch.go | 8 +- gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go | 123 +++++++++++++++++++ gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go | 97 +++++++++++++++ 4 files changed, 224 insertions(+), 82 deletions(-) create mode 100644 gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go create mode 100644 gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index c8535aeb857..f5dee739700 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -3,22 +3,14 @@ package main import ( "bytes" "context" - "encoding/json" - "errors" "fmt" "os" "path/filepath" "strings" "testing" - "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnopkgfetch" - "github.com/gnolang/gno/tm2/pkg/amino" - "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" - ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" - types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/stretchr/testify/require" ) @@ -51,11 +43,7 @@ type testMainCase struct { func testMainCaseRun(t *testing.T, tc []testMainCase) { t.Helper() - oldClient := gnopkgfetch.Client - gnopkgfetch.Client = client.NewRPCClient(&examplesMockClient{}) - t.Cleanup(func() { - gnopkgfetch.Client = oldClient - }) + gnopkgfetch.InjectExamplesClient(t) workingDir, err := os.Getwd() require.Nil(t, err) @@ -164,67 +152,3 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { }) } } - -type examplesMockClient struct{} - -func (m *examplesMockClient) SendRequest(ctx context.Context, request types.RPCRequest) (*types.RPCResponse, error) { - params := struct { - Path string `json:"path"` - Data []byte `json:"data"` - }{} - if err := json.Unmarshal(request.Params, ¶ms); err != nil { - return nil, fmt.Errorf("failed to unmarshal params: %w", err) - } - path := params.Path - if path != "vm/qfile" { - return nil, fmt.Errorf("unexpected call to %q", path) - } - data := string(params.Data) - - examplesDir := filepath.Join(gnoenv.RootDir(), "examples") - target := filepath.Join(examplesDir, data) - - res := ctypes.ResultABCIQuery{} - - finfo, err := os.Stat(target) - if os.IsNotExist(err) { - res.Response = sdk.ABCIResponseQueryFromError(fmt.Errorf("package %q is not available", data)) - return &types.RPCResponse{ - Result: amino.MustMarshalJSON(res), - }, nil - } else if err != nil { - return nil, fmt.Errorf("failed to stat %q: %w", data, err) - } - - if finfo.IsDir() { - entries, err := os.ReadDir(target) - if err != nil { - return nil, fmt.Errorf("failed to get package %q: %w", data, err) - } - files := []string{} - for _, entry := range entries { - if !entry.IsDir() { - files = append(files, entry.Name()) - } - } - res.Response.Data = []byte(strings.Join(files, "\n")) - } else { - content, err := os.ReadFile(target) - if err != nil { - return nil, fmt.Errorf("failed to get file %q: %w", data, err) - } - res.Response.Data = content - } - - return &types.RPCResponse{ - Result: amino.MustMarshalJSON(res), - }, nil -} - -func (m *examplesMockClient) SendBatch(ctx context.Context, requests types.RPCRequests) (types.RPCResponses, error) { - return nil, errors.New("not implemented") -} - -func (m *examplesMockClient) Close() error { - return nil -} diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go index fe4cbc48a06..97782376619 100644 --- a/gnovm/pkg/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch.go @@ -17,10 +17,6 @@ import ( "golang.org/x/mod/module" ) -// Client allows to override the tendermint client used to fetch packages. -// It is exposed for testing purposes. -var Client tm2client.Client - // FetchPackageImportsRecursively recursively fetches the imports of a local package while following a given gno.mod replace directives func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomod.File) error { imports, err := gnoimports.PackageImports(pkgDir) @@ -63,7 +59,7 @@ func fetchPackage(io commands.IO, pkgPath string, dst string) error { io.ErrPrintfln("gno: downloading %s", pkgPath) - client := Client + client := fetchClient if client == nil { // create client from pkgpath parts := strings.Split(pkgPath, "/") @@ -130,3 +126,5 @@ func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { return qres.Response.Data, nil } + +var fetchClient tm2client.Client diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go new file mode 100644 index 00000000000..d4e03504093 --- /dev/null +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go @@ -0,0 +1,123 @@ +package gnopkgfetch + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/mod/modfile" + "golang.org/x/mod/module" +) + +func TestFetchDeps(t *testing.T) { + for _, tc := range []struct { + desc string + pkgPath string + modFile gnomod.File + errorShouldContain string + requirements []string + ioErrContains []string + }{ + { + desc: "not_exists", + pkgPath: "gno.land/p/demo/does_not_exists", + modFile: gnomod.File{ + Module: &modfile.Module{ + Mod: module.Version{ + Path: "testFetchDeps", + }, + }, + }, + errorShouldContain: "failed to query files list for pkg \"gno.land/p/demo/does_not_exists\": package \"gno.land/p/demo/does_not_exists\" is not available", + }, { + desc: "fetch_gno.land/p/demo/avl", + pkgPath: "gno.land/p/demo/avl", + modFile: gnomod.File{ + Module: &modfile.Module{ + Mod: module.Version{ + Path: "testFetchDeps", + }, + }, + }, + requirements: []string{"avl"}, + ioErrContains: []string{ + "gno: downloading gno.land/p/demo/avl", + }, + }, { + desc: "fetch_gno.land/p/demo/blog6", + pkgPath: "gno.land/p/demo/blog", + modFile: gnomod.File{ + Module: &modfile.Module{ + Mod: module.Version{ + Path: "testFetchDeps", + }, + }, + }, + requirements: []string{"avl", "blog", "ufmt", "mux"}, + ioErrContains: []string{ + "gno: downloading gno.land/p/demo/blog", + "gno: downloading gno.land/p/demo/avl", + "gno: downloading gno.land/p/demo/ufmt", + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + mockErr := bytes.NewBufferString("") + io := commands.NewTestIO() + io.SetErr(commands.WriteNopCloser(mockErr)) + + InjectExamplesClient(t) + + // Create test dir + dirPath, cleanUpFn := testutils.NewTestCaseDir(t) + assert.NotNil(t, dirPath) + defer cleanUpFn() + + err := os.WriteFile(filepath.Join(dirPath, "main.gno"), []byte(fmt.Sprintf("package main\n\n import %q\n", tc.pkgPath)), 0644) + require.NoError(t, err) + + tmpGnoHome, err := os.MkdirTemp(os.TempDir(), "gnotesthome_") + require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(tmpGnoHome) }) + t.Setenv("GNOHOME", tmpGnoHome) + + // gno: downloading dependencies + err = FetchPackageImportsRecursively(io, dirPath, &tc.modFile) + if tc.errorShouldContain != "" { + require.ErrorContains(t, err, tc.errorShouldContain) + } else { + require.Nil(t, err) + + // Read dir + entries, err := os.ReadDir(filepath.Join(tmpGnoHome, "pkg", "mod", "gno.land", "p", "demo")) + require.Nil(t, err) + + // Check dir entries + assert.Equal(t, len(tc.requirements), len(entries)) + for _, e := range entries { + assert.Contains(t, tc.requirements, e.Name()) + } + + // Check logs + for _, c := range tc.ioErrContains { + assert.Contains(t, mockErr.String(), c) + } + + mockErr.Reset() + + // Try gno: downloading again. Should be cached + FetchPackageImportsRecursively(io, dirPath, &tc.modFile) + for _, c := range tc.ioErrContains { + assert.NotContains(t, mockErr.String(), c) + } + } + }) + } +} diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go new file mode 100644 index 00000000000..8e7ceef9553 --- /dev/null +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go @@ -0,0 +1,97 @@ +package gnopkgfetch + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + + "github.com/gnolang/gno/tm2/pkg/amino" + tm2client "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" + types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" + "github.com/gnolang/gno/tm2/pkg/sdk" +) + +func InjectExamplesClient(t *testing.T) { + _, filename, _, ok := runtime.Caller(0) + if !ok { + t.Fatalf("failed to get source path") + } + examplesDir := filepath.Join(filepath.Dir(filename), "..", "..", "..", "examples") + oldClient := fetchClient + fetchClient = tm2client.NewRPCClient(&ExamplesMockClient{examplesRoot: examplesDir}) + t.Cleanup(func() { + fetchClient = oldClient + }) +} + +type ExamplesMockClient struct { + examplesRoot string +} + +func (m *ExamplesMockClient) SendRequest(ctx context.Context, request types.RPCRequest) (*types.RPCResponse, error) { + params := struct { + Path string `json:"path"` + Data []byte `json:"data"` + }{} + if err := json.Unmarshal(request.Params, ¶ms); err != nil { + return nil, fmt.Errorf("failed to unmarshal params: %w", err) + } + path := params.Path + if path != "vm/qfile" { + return nil, fmt.Errorf("unexpected call to %q", path) + } + data := string(params.Data) + + target := filepath.Join(m.examplesRoot, data) + + res := ctypes.ResultABCIQuery{} + + finfo, err := os.Stat(target) + if os.IsNotExist(err) { + res.Response = sdk.ABCIResponseQueryFromError(fmt.Errorf("package %q is not available", data)) + return &types.RPCResponse{ + Result: amino.MustMarshalJSON(res), + }, nil + } else if err != nil { + return nil, fmt.Errorf("failed to stat %q: %w", data, err) + } + + if finfo.IsDir() { + entries, err := os.ReadDir(target) + if err != nil { + return nil, fmt.Errorf("failed to get package %q: %w", data, err) + } + files := []string{} + for _, entry := range entries { + if !entry.IsDir() { + files = append(files, entry.Name()) + } + } + res.Response.Data = []byte(strings.Join(files, "\n")) + } else { + content, err := os.ReadFile(target) + if err != nil { + return nil, fmt.Errorf("failed to get file %q: %w", data, err) + } + res.Response.Data = content + } + + return &types.RPCResponse{ + Result: amino.MustMarshalJSON(res), + }, nil +} + +func (m *ExamplesMockClient) SendBatch(ctx context.Context, requests types.RPCRequests) (types.RPCResponses, error) { + return nil, errors.New("not implemented") +} + +func (m *ExamplesMockClient) Close() error { + return nil +} From 07cccc6602979d43580f9bfce706b031c2096fad Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 08:18:10 +0100 Subject: [PATCH 28/51] chore: add fetch test with replace Signed-off-by: Norman Meier --- gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go index d4e03504093..eddcd008da6 100644 --- a/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go @@ -66,6 +66,24 @@ func TestFetchDeps(t *testing.T) { "gno: downloading gno.land/p/demo/avl", "gno: downloading gno.land/p/demo/ufmt", }, + }, { + desc: "fetch_replace_gno.land/p/demo/avl", + pkgPath: "gno.land/p/demo/replaced_avl", + modFile: gnomod.File{ + Module: &modfile.Module{ + Mod: module.Version{ + Path: "testFetchDeps", + }, + }, + Replace: []*modfile.Replace{{ + Old: module.Version{Path: "gno.land/p/demo/replaced_avl"}, + New: module.Version{Path: "gno.land/p/demo/avl"}, + }}, + }, + requirements: []string{"avl"}, + ioErrContains: []string{ + "gno: downloading gno.land/p/demo/avl", + }, }, } { t.Run(tc.desc, func(t *testing.T) { @@ -112,7 +130,7 @@ func TestFetchDeps(t *testing.T) { mockErr.Reset() - // Try gno: downloading again. Should be cached + // Try fetching again. Should be cached FetchPackageImportsRecursively(io, dirPath, &tc.modFile) for _, c := range tc.ioErrContains { assert.NotContains(t, mockErr.String(), c) From e65600fcdd0616c007f61c34949546d0c6ad43e6 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 08:22:42 +0100 Subject: [PATCH 29/51] chore: more test cases Signed-off-by: Norman Meier --- gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go index eddcd008da6..bc6604a5d38 100644 --- a/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go @@ -84,6 +84,20 @@ func TestFetchDeps(t *testing.T) { ioErrContains: []string{ "gno: downloading gno.land/p/demo/avl", }, + }, { + desc: "fetch_replace_local", + pkgPath: "gno.land/p/demo/foo", + modFile: gnomod.File{ + Module: &modfile.Module{ + Mod: module.Version{ + Path: "testFetchDeps", + }, + }, + Replace: []*modfile.Replace{{ + Old: module.Version{Path: "gno.land/p/demo/foo"}, + New: module.Version{Path: "../local_foo"}, + }}, + }, }, } { t.Run(tc.desc, func(t *testing.T) { @@ -115,7 +129,9 @@ func TestFetchDeps(t *testing.T) { // Read dir entries, err := os.ReadDir(filepath.Join(tmpGnoHome, "pkg", "mod", "gno.land", "p", "demo")) - require.Nil(t, err) + if !os.IsNotExist(err) { + require.Nil(t, err) + } // Check dir entries assert.Equal(t, len(tc.requirements), len(entries)) From 7b385d58f539007aa9249481b5f8602840c569bf Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 08:25:29 +0100 Subject: [PATCH 30/51] chore: unexpose testing client Signed-off-by: Norman Meier --- gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go b/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go index 8e7ceef9553..c40981a7d9d 100644 --- a/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go +++ b/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go @@ -19,23 +19,25 @@ import ( ) func InjectExamplesClient(t *testing.T) { + t.Helper() + _, filename, _, ok := runtime.Caller(0) if !ok { t.Fatalf("failed to get source path") } examplesDir := filepath.Join(filepath.Dir(filename), "..", "..", "..", "examples") oldClient := fetchClient - fetchClient = tm2client.NewRPCClient(&ExamplesMockClient{examplesRoot: examplesDir}) + fetchClient = tm2client.NewRPCClient(&examplesMockClient{examplesRoot: examplesDir}) t.Cleanup(func() { fetchClient = oldClient }) } -type ExamplesMockClient struct { +type examplesMockClient struct { examplesRoot string } -func (m *ExamplesMockClient) SendRequest(ctx context.Context, request types.RPCRequest) (*types.RPCResponse, error) { +func (m *examplesMockClient) SendRequest(ctx context.Context, request types.RPCRequest) (*types.RPCResponse, error) { params := struct { Path string `json:"path"` Data []byte `json:"data"` @@ -88,10 +90,10 @@ func (m *ExamplesMockClient) SendRequest(ctx context.Context, request types.RPCR }, nil } -func (m *ExamplesMockClient) SendBatch(ctx context.Context, requests types.RPCRequests) (types.RPCResponses, error) { +func (m *examplesMockClient) SendBatch(ctx context.Context, requests types.RPCRequests) (types.RPCResponses, error) { return nil, errors.New("not implemented") } -func (m *ExamplesMockClient) Close() error { +func (m *examplesMockClient) Close() error { return nil } From 736d7f649d8dacd1b72e2b1c8e6adab4b7a9d32d Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 09:00:08 +0100 Subject: [PATCH 31/51] fix: remove stdlibs from test imports Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/pkg.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index 1d761ce5354..ffb5237f255 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/gnolang/gno/gnovm/pkg/gnoimports" + "github.com/gnolang/gno/gnovm/pkg/gnolang" ) type Pkg struct { @@ -115,6 +116,7 @@ func ListPkgs(root string) (PkgList, error) { imports, err := gnoimports.PackageImports(path) _ = err // get all valid imports while ignoring bad/partial files + imports = removeStdLibs(imports) pkgs = append(pkgs, Pkg{ Dir: path, @@ -131,6 +133,17 @@ func ListPkgs(root string) (PkgList, error) { return pkgs, nil } +func removeStdLibs(imports []string) []string { + res := []string{} + for _, imp := range imports { + if gnolang.IsStdlib(imp) { + continue + } + res = append(res, imp) + } + return res +} + // GetNonDraftPkgs returns packages that are not draft // and have no direct or indirect draft dependencies. func (sp SortedPkgList) GetNonDraftPkgs() SortedPkgList { From d10eb8af6cdc36d7ec5e1ce1b73a7380857eb2f3 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 14 Nov 2024 19:32:21 +0100 Subject: [PATCH 32/51] chore: bump for CI Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/pkg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index ffb5237f255..25801d68b14 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -115,7 +115,7 @@ func ListPkgs(root string) (PkgList, error) { } imports, err := gnoimports.PackageImports(path) - _ = err // get all valid imports while ignoring bad/partial files + _ = err // get valid imports while ignoring bad/partial files imports = removeStdLibs(imports) pkgs = append(pkgs, Pkg{ From 144c0cc67bf859b4b2725109852bceba5f9075f9 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 15 Nov 2024 07:50:39 +0100 Subject: [PATCH 33/51] fix: remove self from pkg imports Signed-off-by: Norman Meier --- gno.land/pkg/integration/testing_integration.go | 2 +- gnovm/pkg/gnomod/pkg.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index c284b8eaf56..1a46f01e0af 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -751,7 +751,7 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { return fmt.Errorf("unable to load package imports in %q: %w", currentPkg.Dir, err) } for _, imp := range imports { - if gno.IsStdlib(imp) { + if imp == currentPkg.Name || gno.IsStdlib(imp) { continue } currentPkg.Imports = append(currentPkg.Imports, imp) diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index 25801d68b14..9736ca98576 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -116,7 +116,7 @@ func ListPkgs(root string) (PkgList, error) { imports, err := gnoimports.PackageImports(path) _ = err // get valid imports while ignoring bad/partial files - imports = removeStdLibs(imports) + imports = filterImports(gnoMod.Module.Mod.Path, imports) pkgs = append(pkgs, Pkg{ Dir: path, @@ -133,10 +133,11 @@ func ListPkgs(root string) (PkgList, error) { return pkgs, nil } -func removeStdLibs(imports []string) []string { +// filterImports removes self and standard libraries from an import list +func filterImports(pkgPath string, imports []string) []string { res := []string{} for _, imp := range imports { - if gnolang.IsStdlib(imp) { + if imp == pkgPath || gnolang.IsStdlib(imp) { continue } res = append(res, imp) From 485d63e90123680281c24c554901eb195cdd8b27 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Sat, 16 Nov 2024 18:47:48 +0100 Subject: [PATCH 34/51] fix: remove require Signed-off-by: Norman Meier --- examples/gno.land/p/moul/mdtable/gno.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/gno.land/p/moul/mdtable/gno.mod b/examples/gno.land/p/moul/mdtable/gno.mod index 0cea0458895..079c935a874 100644 --- a/examples/gno.land/p/moul/mdtable/gno.mod +++ b/examples/gno.land/p/moul/mdtable/gno.mod @@ -1,3 +1 @@ module gno.land/p/moul/mdtable - -require gno.land/p/demo/urequire v0.0.0-latest From ed89ff6d595310fcbdb5a776facee3610a53f494 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 22 Nov 2024 15:19:57 +0100 Subject: [PATCH 35/51] chore: remove helper present in std Signed-off-by: Norman Meier --- gnovm/pkg/gnoimports/imports_test.go | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/gnovm/pkg/gnoimports/imports_test.go b/gnovm/pkg/gnoimports/imports_test.go index 5123c0475ce..81c639fcabf 100644 --- a/gnovm/pkg/gnoimports/imports_test.go +++ b/gnovm/pkg/gnoimports/imports_test.go @@ -13,8 +13,7 @@ func TestGetGnoImports(t *testing.T) { require.NoError(t, err) // create external dir - tmpDir, cleanUpFn := createTmpDir(t) - defer cleanUpFn() + tmpDir := t.TempDir() // cd to tmp directory os.Chdir(tmpDir) @@ -123,21 +122,3 @@ func TestGetGnoImports(t *testing.T) { require.Equal(t, expected, imports) } - -func createTmpDir(t *testing.T) (string, func()) { - t.Helper() - - tmpDir, err := os.MkdirTemp("", "gno-mod-test") - if err != nil { - t.Error("Failed to create tmp dir for mod:", err) - } - - cleanUpFn := func() { - err := os.RemoveAll(tmpDir) - if err != nil { - t.Logf("Failed to clean up test %s: %v", t.Name(), err) - } - } - - return tmpDir, cleanUpFn -} From 6a2a12c370126949140877ef2a862d5f080489e6 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 22 Nov 2024 15:28:27 +0100 Subject: [PATCH 36/51] chore: optimize slice alloc Signed-off-by: Norman Meier --- gnovm/pkg/gnoimports/imports.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnovm/pkg/gnoimports/imports.go b/gnovm/pkg/gnoimports/imports.go index f0c658f311a..5170958bfc0 100644 --- a/gnovm/pkg/gnoimports/imports.go +++ b/gnovm/pkg/gnoimports/imports.go @@ -63,10 +63,10 @@ func FileImports(fname string) ([]string, error) { if err != nil { return nil, err } - res := make([]string, 0) - for _, im := range f.Imports { + res := make([]string, len(f.Imports)) + for i, im := range f.Imports { importPath := strings.TrimPrefix(strings.TrimSuffix(im.Path.Value, `"`), `"`) - res = append(res, importPath) + res[i] = importPath } return res, nil } From 6aea21eb83212d5620e5b9acfde96bdec5e5413d Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 22 Nov 2024 15:38:16 +0100 Subject: [PATCH 37/51] chore: refacto import filter Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/pkg.go | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index 9736ca98576..36098074775 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -5,6 +5,7 @@ import ( "io/fs" "os" "path/filepath" + "slices" "strings" "github.com/gnolang/gno/gnovm/pkg/gnoimports" @@ -115,8 +116,12 @@ func ListPkgs(root string) (PkgList, error) { } imports, err := gnoimports.PackageImports(path) - _ = err // get valid imports while ignoring bad/partial files - imports = filterImports(gnoMod.Module.Mod.Path, imports) + _ = err // ignore error to get valid imports while ignoring bad/partial files + + // remove self and standard libraries from imports + _ = slices.DeleteFunc(imports, func(imp string) bool { + return imp == gnoMod.Module.Mod.Path || gnolang.IsStdlib(imp) + }) pkgs = append(pkgs, Pkg{ Dir: path, @@ -133,18 +138,6 @@ func ListPkgs(root string) (PkgList, error) { return pkgs, nil } -// filterImports removes self and standard libraries from an import list -func filterImports(pkgPath string, imports []string) []string { - res := []string{} - for _, imp := range imports { - if imp == pkgPath || gnolang.IsStdlib(imp) { - continue - } - res = append(res, imp) - } - return res -} - // GetNonDraftPkgs returns packages that are not draft // and have no direct or indirect draft dependencies. func (sp SortedPkgList) GetNonDraftPkgs() SortedPkgList { From 7bbd0da7e26a6f1ac1a65422b132f694248167f5 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 22 Nov 2024 15:46:00 +0100 Subject: [PATCH 38/51] chore: gnovm/pkg/gnopkgfetch -> gnovm/cmd/gno/internal/gnopkgfetch Signed-off-by: Norman Meier --- gnovm/{pkg => cmd/gno/internal}/gnopkgfetch/gnopkgfetch.go | 0 gnovm/{pkg => cmd/gno/internal}/gnopkgfetch/gnopkgfetch_test.go | 0 .../gno/internal}/gnopkgfetch/gnopkgfetch_testing.go | 0 gnovm/cmd/gno/main_test.go | 2 +- gnovm/cmd/gno/mod.go | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) rename gnovm/{pkg => cmd/gno/internal}/gnopkgfetch/gnopkgfetch.go (100%) rename gnovm/{pkg => cmd/gno/internal}/gnopkgfetch/gnopkgfetch_test.go (100%) rename gnovm/{pkg => cmd/gno/internal}/gnopkgfetch/gnopkgfetch_testing.go (100%) diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go similarity index 100% rename from gnovm/pkg/gnopkgfetch/gnopkgfetch.go rename to gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_test.go similarity index 100% rename from gnovm/pkg/gnopkgfetch/gnopkgfetch_test.go rename to gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_test.go diff --git a/gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go similarity index 100% rename from gnovm/pkg/gnopkgfetch/gnopkgfetch_testing.go rename to gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index f5dee739700..4864a4e91e0 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "github.com/gnolang/gno/gnovm/pkg/gnopkgfetch" + "github.com/gnolang/gno/gnovm/cmd/gno/internal/gnopkgfetch" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/stretchr/testify/require" ) diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 3184bc69012..1a59eccecb1 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -8,9 +8,9 @@ import ( "path/filepath" "strings" + "github.com/gnolang/gno/gnovm/cmd/gno/internal/gnopkgfetch" "github.com/gnolang/gno/gnovm/pkg/gnoimports" "github.com/gnolang/gno/gnovm/pkg/gnomod" - "github.com/gnolang/gno/gnovm/pkg/gnopkgfetch" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "go.uber.org/multierr" From 4e4b71e442bdbd5058573ba802456c9a9e10c828 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 22 Nov 2024 16:02:53 +0100 Subject: [PATCH 39/51] fix: examples path Signed-off-by: Norman Meier --- gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go index c40981a7d9d..4c04b903652 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go @@ -25,7 +25,7 @@ func InjectExamplesClient(t *testing.T) { if !ok { t.Fatalf("failed to get source path") } - examplesDir := filepath.Join(filepath.Dir(filename), "..", "..", "..", "examples") + examplesDir := filepath.Join(filepath.Dir(filename), "..", "..", "..", "..", "..", "examples") oldClient := fetchClient fetchClient = tm2client.NewRPCClient(&examplesMockClient{examplesRoot: examplesDir}) t.Cleanup(func() { From 52d8d965f0479a0f050db716b697b44fbfd3e919 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 22 Nov 2024 16:03:23 +0100 Subject: [PATCH 40/51] chore: move helper near call site Signed-off-by: Norman Meier --- gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go | 7 ++++++- gnovm/pkg/gnolang/helpers.go | 6 ------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go index 97782376619..9c0d3309474 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go @@ -28,7 +28,7 @@ func FetchPackageImportsRecursively(io commands.IO, pkgDir string, gnoMod *gnomo resolved := gnoMod.Resolve(module.Version{Path: pkgPath}) resolvedPkgPath := resolved.Path - if !gnolang.IsRemotePkgPath(resolvedPkgPath) { + if !isRemotePkgPath(resolvedPkgPath) { continue } @@ -128,3 +128,8 @@ func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { } var fetchClient tm2client.Client + +// isRemotePkgPath determines whether s is a remote pkg path, i.e.: not a filepath nor a standard library +func isRemotePkgPath(s string) bool { + return !strings.HasPrefix(s, ".") && !filepath.IsAbs(s) && !gnolang.IsStdlib(s) +} diff --git a/gnovm/pkg/gnolang/helpers.go b/gnovm/pkg/gnolang/helpers.go index 50678707e0e..c6f7e696ea4 100644 --- a/gnovm/pkg/gnolang/helpers.go +++ b/gnovm/pkg/gnolang/helpers.go @@ -2,7 +2,6 @@ package gnolang import ( "fmt" - "path/filepath" "regexp" "strconv" "strings" @@ -36,11 +35,6 @@ func IsStdlib(s string) bool { return !strings.HasPrefix(s, "gno.land/") } -// IsRemotePkgPath determines whether s is a remote pkg path, i.e.: not a filepath nor a standard library -func IsRemotePkgPath(s string) bool { - return !strings.HasPrefix(s, ".") && !filepath.IsAbs(s) && !IsStdlib(s) -} - // ---------------------------------------- // AST Construction (Expr) // These are copied over from go-amino-x, but produces Gno ASTs. From 9182eb3b079d9ee3c2dc7461312a36ade05ea847 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 22 Nov 2024 16:48:32 +0100 Subject: [PATCH 41/51] fix: deletefunc use Signed-off-by: Norman Meier --- gnovm/pkg/gnomod/pkg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index 36098074775..12f35410a28 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -119,7 +119,7 @@ func ListPkgs(root string) (PkgList, error) { _ = err // ignore error to get valid imports while ignoring bad/partial files // remove self and standard libraries from imports - _ = slices.DeleteFunc(imports, func(imp string) bool { + imports = slices.DeleteFunc(imports, func(imp string) bool { return imp == gnoMod.Module.Mod.Path || gnolang.IsStdlib(imp) }) From dce417e07d830c79454253f37cb0fc6ee29f80f0 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Sat, 23 Nov 2024 00:30:38 +0100 Subject: [PATCH 42/51] chore: refacto test client injection Signed-off-by: Norman Meier --- .../gno/internal/gnopkgfetch/gnopkgfetch.go | 82 +++++++++++++------ .../internal/gnopkgfetch/gnopkgfetch_test.go | 4 +- .../gnopkgfetch/gnopkgfetch_testing.go | 18 ---- gnovm/cmd/gno/main_test.go | 5 +- gnovm/cmd/gno/mod_test.go | 4 +- 5 files changed, 61 insertions(+), 52 deletions(-) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go index 9c0d3309474..21ad7a7cbf0 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go @@ -2,12 +2,13 @@ package gnopkgfetch import ( "fmt" - "net/url" "os" "path" "path/filepath" "strings" + "unicode" + "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnoimports" "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" @@ -54,49 +55,34 @@ func fetchPackage(io commands.IO, pkgPath string, dst string) error { // modfile exists in modcache, do nothing return nil } else if !os.IsNotExist(err) { - return fmt.Errorf("failed to stat downloaded module %q at %q: %w", pkgPath, dst, err) + return fmt.Errorf("stat downloaded module %q at %q: %w", pkgPath, dst, err) } io.ErrPrintfln("gno: downloading %s", pkgPath) - client := fetchClient - if client == nil { - // create client from pkgpath - parts := strings.Split(pkgPath, "/") - if len(parts) < 1 { - return fmt.Errorf("bad pkg path %q", pkgPath) - } - // XXX: retrieve host/port from r/sys/zones. - rpcURL := (&url.URL{ - Scheme: "https", - Host: "rpc." + parts[0] + ":443", - }).String() - tmClient, err := tm2client.NewHTTPClient(rpcURL) - if err != nil { - return fmt.Errorf("failed to instantiate tm2 client with remote %q: %w", rpcURL, err) - } - defer tmClient.Close() - client = tmClient + client, err := clientFromPkgPath(pkgPath) + if err != nil { + return fmt.Errorf("get client for pkg path %q: %w", pkgPath, err) } // fetch files data, err := qfile(client, pkgPath) if err != nil { - return fmt.Errorf("failed to query files list for pkg %q: %w", pkgPath, err) + return fmt.Errorf("query files list for pkg %q: %w", pkgPath, err) } if err := os.MkdirAll(dst, 0o744); err != nil { - return fmt.Errorf("failed to create cache dir for %q at %q: %w", pkgPath, dst, err) + return fmt.Errorf("create cache dir for %q at %q: %w", pkgPath, dst, err) } files := strings.Split(string(data), "\n") for _, file := range files { filePath := path.Join(pkgPath, file) data, err := qfile(client, filePath) if err != nil { - return fmt.Errorf("failed to query package file %q: %w", filePath, err) + return fmt.Errorf("query package file %q: %w", filePath, err) } dst := filepath.Join(dst, file) if err := os.WriteFile(dst, data, 0o644); err != nil { - return fmt.Errorf("failed to write file at %q: %w", dst, err) + return fmt.Errorf("write file at %q: %w", dst, err) } } @@ -105,12 +91,56 @@ func fetchPackage(io commands.IO, pkgPath string, dst string) error { // we need to know that gno.land/r/foo is not downloaded. // We do this by checking for the presence of gno.land/r/foo/gno.mod if err := os.WriteFile(modFilePath, []byte("module "+pkgPath+"\n"), 0o644); err != nil { - return fmt.Errorf("failed to write modfile at %q: %w", modFilePath, err) + return fmt.Errorf("write modfile at %q: %w", modFilePath, err) } return nil } +func clientFromPkgPath(pkgPath string) (tm2client.Client, error) { + parts := strings.Split(pkgPath, "/") + if len(parts) < 1 { + return nil, fmt.Errorf("bad pkg path %q", pkgPath) + } + domain := parts[0] + + rpcURL, ok := overrideURLFromEnv(domain) + if !ok { + // XXX: retrieve host/port from r/sys/zones. + rpcURL = fmt.Sprintf("https://rpc.%s:443", domain) + } + + if rpcURL == "gno-examples" { + examplesDir := filepath.Join(gnoenv.RootDir(), "examples") + return tm2client.NewRPCClient(&examplesMockClient{examplesRoot: examplesDir}), nil + } + + client, err := tm2client.NewHTTPClient(rpcURL) + if err != nil { + return nil, fmt.Errorf("failed to instantiate tm2 client with remote %q: %w", rpcURL, err) + } + return client, nil +} + +// overrideURLFromEnv looks for `domain=url` comma-separated pairs in the GNO_PKG_HOSTS env variable +// and return the `url` matching `domain` if found +func overrideURLFromEnv(pkgDomain string) (string, bool) { + hostsOverrides := os.Getenv("GNO_PKG_HOSTS") + overrides := strings.Split(hostsOverrides, ",") + for _, override := range overrides { + parts := strings.Split(override, "=") + if len(parts) != 2 { + continue + } + domain := strings.TrimFunc(parts[0], unicode.IsSpace) + if domain != pkgDomain { + continue + } + return strings.TrimFunc(parts[1], unicode.IsSpace), true + } + return pkgDomain, false +} + // not using gno client due to cyclic dep func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { path := "vm/qfile" @@ -127,8 +157,6 @@ func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { return qres.Response.Data, nil } -var fetchClient tm2client.Client - // isRemotePkgPath determines whether s is a remote pkg path, i.e.: not a filepath nor a standard library func isRemotePkgPath(s string) bool { return !strings.HasPrefix(s, ".") && !filepath.IsAbs(s) && !gnolang.IsStdlib(s) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_test.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_test.go index dfa939fff93..9d3d73892a2 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_test.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_test.go @@ -35,7 +35,7 @@ func TestFetchDeps(t *testing.T) { }, }, }, - errorShouldContain: "failed to query files list for pkg \"gno.land/p/demo/does_not_exists\": package \"gno.land/p/demo/does_not_exists\" is not available", + errorShouldContain: "query files list for pkg \"gno.land/p/demo/does_not_exists\": package \"gno.land/p/demo/does_not_exists\" is not available", }, { desc: "fetch_gno.land/p/demo/avl", pkgPath: "gno.land/p/demo/avl", @@ -105,7 +105,7 @@ func TestFetchDeps(t *testing.T) { io := commands.NewTestIO() io.SetErr(commands.WriteNopCloser(mockErr)) - InjectExamplesClient(t) + t.Setenv("GNO_PKG_HOSTS", "gno.land=gno-examples") // Create test dir dirPath, cleanUpFn := testutils.NewTestCaseDir(t) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go index 4c04b903652..b98ad870bcb 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go @@ -7,32 +7,14 @@ import ( "fmt" "os" "path/filepath" - "runtime" "strings" - "testing" "github.com/gnolang/gno/tm2/pkg/amino" - tm2client "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" "github.com/gnolang/gno/tm2/pkg/sdk" ) -func InjectExamplesClient(t *testing.T) { - t.Helper() - - _, filename, _, ok := runtime.Caller(0) - if !ok { - t.Fatalf("failed to get source path") - } - examplesDir := filepath.Join(filepath.Dir(filename), "..", "..", "..", "..", "..", "examples") - oldClient := fetchClient - fetchClient = tm2client.NewRPCClient(&examplesMockClient{examplesRoot: examplesDir}) - t.Cleanup(func() { - fetchClient = oldClient - }) -} - type examplesMockClient struct { examplesRoot string } diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 4864a4e91e0..150df753bb3 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -9,7 +9,6 @@ import ( "strings" "testing" - "github.com/gnolang/gno/gnovm/cmd/gno/internal/gnopkgfetch" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/stretchr/testify/require" ) @@ -43,8 +42,6 @@ type testMainCase struct { func testMainCaseRun(t *testing.T, tc []testMainCase) { t.Helper() - gnopkgfetch.InjectExamplesClient(t) - workingDir, err := os.Getwd() require.Nil(t, err) @@ -68,6 +65,8 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { t.Setenv("GNOHOME", tmpGnoHome) } + t.Setenv("GNO_PKG_HOSTS", "gno.land=gno-examples") + checkOutputs := func(t *testing.T) { t.Helper() diff --git a/gnovm/cmd/gno/mod_test.go b/gnovm/cmd/gno/mod_test.go index e06eba6decf..afce25597cd 100644 --- a/gnovm/cmd/gno/mod_test.go +++ b/gnovm/cmd/gno/mod_test.go @@ -46,7 +46,7 @@ func TestModApp(t *testing.T) { testDir: "../../tests/integ/require_invalid_module", simulateExternalRepo: true, stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", - errShouldContain: "failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", + errShouldContain: "query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", }, { args: []string{"mod", "download"}, @@ -69,7 +69,7 @@ func TestModApp(t *testing.T) { testDir: "../../tests/integ/replace_with_invalid_module", simulateExternalRepo: true, stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", - errShouldContain: "failed to query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", + errShouldContain: "query files list for pkg \"gno.land/p/demo/notexists\": package \"gno.land/p/demo/notexists\" is not available", }, // test `gno mod init` with no module name From b220ab8a1e780a61051feac85e1ae665603e247b Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Sat, 23 Nov 2024 00:38:01 +0100 Subject: [PATCH 43/51] fix: gracefully close client Signed-off-by: Norman Meier --- gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go index 21ad7a7cbf0..0a773c179f4 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go @@ -64,6 +64,7 @@ func fetchPackage(io commands.IO, pkgPath string, dst string) error { if err != nil { return fmt.Errorf("get client for pkg path %q: %w", pkgPath, err) } + defer client.Close() // fetch files data, err := qfile(client, pkgPath) @@ -97,7 +98,7 @@ func fetchPackage(io commands.IO, pkgPath string, dst string) error { return nil } -func clientFromPkgPath(pkgPath string) (tm2client.Client, error) { +func clientFromPkgPath(pkgPath string) (*tm2client.RPCClient, error) { parts := strings.Split(pkgPath, "/") if len(parts) < 1 { return nil, fmt.Errorf("bad pkg path %q", pkgPath) From a12d12aaaefc91e65635860daf012835411cdc8b Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Sat, 23 Nov 2024 00:42:57 +0100 Subject: [PATCH 44/51] chore: use constant for qfile path Signed-off-by: Norman Meier --- gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go | 4 ++-- gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go index 0a773c179f4..9fae83c4bee 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go @@ -8,6 +8,7 @@ import ( "strings" "unicode" + "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnoimports" "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -142,9 +143,8 @@ func overrideURLFromEnv(pkgDomain string) (string, bool) { return pkgDomain, false } -// not using gno client due to cyclic dep func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { - path := "vm/qfile" + path := "vm/" + vm.QueryFile data := []byte(pkgPath) qres, err := tmClient.ABCIQuery(path, data) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go index b98ad870bcb..3c5e00d258a 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" + "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/tm2/pkg/amino" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" @@ -28,7 +29,7 @@ func (m *examplesMockClient) SendRequest(ctx context.Context, request types.RPCR return nil, fmt.Errorf("failed to unmarshal params: %w", err) } path := params.Path - if path != "vm/qfile" { + if path != "vm/"+vm.QueryFile { return nil, fmt.Errorf("unexpected call to %q", path) } data := string(params.Data) From 48ae91d7917936b397160fec1b81057ac29b7d1d Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Sat, 23 Nov 2024 02:57:38 +0100 Subject: [PATCH 45/51] chore: rename test to align with function rename Signed-off-by: Norman Meier --- gnovm/pkg/gnoimports/imports_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnoimports/imports_test.go b/gnovm/pkg/gnoimports/imports_test.go index 81c639fcabf..1862955f438 100644 --- a/gnovm/pkg/gnoimports/imports_test.go +++ b/gnovm/pkg/gnoimports/imports_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestGetGnoImports(t *testing.T) { +func TestPackageImports(t *testing.T) { workingDir, err := os.Getwd() require.NoError(t, err) From 3d0533c0e2e072604f04088be861a571d38c7c2b Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Wed, 27 Nov 2024 15:36:26 +0100 Subject: [PATCH 46/51] remove requires --- examples/gno.land/p/n2p5/mgroup/gno.mod | 6 ------ examples/gno.land/r/moul/home/gno.mod | 5 ----- examples/gno.land/r/n2p5/config/gno.mod | 5 ----- examples/gno.land/r/n2p5/home/gno.mod | 6 ------ 4 files changed, 22 deletions(-) diff --git a/examples/gno.land/p/n2p5/mgroup/gno.mod b/examples/gno.land/p/n2p5/mgroup/gno.mod index 95fdbe2f195..132913d9c3d 100644 --- a/examples/gno.land/p/n2p5/mgroup/gno.mod +++ b/examples/gno.land/p/n2p5/mgroup/gno.mod @@ -1,7 +1 @@ module gno.land/p/n2p5/mgroup - -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/testutils v0.0.0-latest -) diff --git a/examples/gno.land/r/moul/home/gno.mod b/examples/gno.land/r/moul/home/gno.mod index f42a2c2ced8..91e02df3707 100644 --- a/examples/gno.land/r/moul/home/gno.mod +++ b/examples/gno.land/r/moul/home/gno.mod @@ -1,6 +1 @@ module gno.land/r/moul/home - -require ( - gno.land/r/leon/hof v0.0.0-latest - gno.land/r/moul/config v0.0.0-latest -) diff --git a/examples/gno.land/r/n2p5/config/gno.mod b/examples/gno.land/r/n2p5/config/gno.mod index 33f9276a409..29d5a74eb0a 100644 --- a/examples/gno.land/r/n2p5/config/gno.mod +++ b/examples/gno.land/r/n2p5/config/gno.mod @@ -1,6 +1 @@ module gno.land/r/n2p5/config - -require ( - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/n2p5/mgroup v0.0.0-latest -) diff --git a/examples/gno.land/r/n2p5/home/gno.mod b/examples/gno.land/r/n2p5/home/gno.mod index 779aa914989..3b6ddbf86bb 100644 --- a/examples/gno.land/r/n2p5/home/gno.mod +++ b/examples/gno.land/r/n2p5/home/gno.mod @@ -1,7 +1 @@ module gno.land/r/n2p5/home - -require ( - gno.land/p/n2p5/chonk v0.0.0-latest - gno.land/r/leon/hof v0.0.0-latest - gno.land/r/n2p5/config v0.0.0-latest -) From af0cf96c7af3958c187da590aee6e315f429d8a3 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 28 Nov 2024 03:57:54 +0100 Subject: [PATCH 47/51] chore: use Unquote instead of TrimX address: https://github.com/gnolang/gno/pull/3123?notification_referrer_id=NT_kwDOAHjOCLMxMzM1NjYwMzEyMjo3OTE3MDY0#discussion_r1860797880 Signed-off-by: Norman Meier --- gnovm/pkg/gnoimports/imports.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnoimports/imports.go b/gnovm/pkg/gnoimports/imports.go index 5170958bfc0..b3a404945e5 100644 --- a/gnovm/pkg/gnoimports/imports.go +++ b/gnovm/pkg/gnoimports/imports.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "sort" + "strconv" "strings" ) @@ -65,7 +66,10 @@ func FileImports(fname string) ([]string, error) { } res := make([]string, len(f.Imports)) for i, im := range f.Imports { - importPath := strings.TrimPrefix(strings.TrimSuffix(im.Path.Value, `"`), `"`) + importPath, err := strconv.Unquote(im.Path.Value) + if err != nil { + return nil, fmt.Errorf("unquote %q: %w", im.Path.Value, err) + } res[i] = importPath } return res, nil From e5fae2d6d8b94c78303fe65c72421458f51a15e8 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 28 Nov 2024 04:50:47 +0100 Subject: [PATCH 48/51] chore: simplify test env setup Signed-off-by: Norman Meier --- gnovm/pkg/doc/dirs_test.go | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/gnovm/pkg/doc/dirs_test.go b/gnovm/pkg/doc/dirs_test.go index 88c5f837f9a..3139298a7ae 100644 --- a/gnovm/pkg/doc/dirs_test.go +++ b/gnovm/pkg/doc/dirs_test.go @@ -65,23 +65,7 @@ func tNewDirs(t *testing.T) (string, *bfsDirs) { // modify GNOHOME to testdata/dirsdep -- this allows us to test // dependency lookup by dirs. - oldLegacy, exLegacy := os.LookupEnv("GNO_HOME") - old, ex := os.LookupEnv("GNOHOME") - os.Setenv("GNO_HOME", wdJoin(t, "testdata/dirsdep")) - os.Setenv("GNOHOME", wdJoin(t, "testdata/dirsdep")) - - t.Cleanup(func() { - if exLegacy { - os.Setenv("GNO_HOME", oldLegacy) - } else { - os.Unsetenv("GNO_HOME") - } - if ex { - os.Setenv("GNOHOME", old) - } else { - os.Unsetenv("GNOHOME") - } - }) + t.Setenv("GNOHOME", wdJoin(t, "testdata/dirsdep")) return wdJoin(t, "testdata"), newDirs([]string{wdJoin(t, "testdata/dirs")}, []string{wdJoin(t, "testdata/dirsmod")}) From 246bfbc818bc41438a556fd716e357eafe5e2bbd Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 28 Nov 2024 08:40:31 +0100 Subject: [PATCH 49/51] chore: refacto and use it in Signed-off-by: Norman Meier --- gnovm/cmd/gno/mod.go | 7 +++-- gnovm/pkg/gnoimports/imports.go | 55 +++++++++++++++++++++------------ gnovm/pkg/test/imports.go | 22 ++++++------- 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 1a59eccecb1..51536809736 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -333,13 +333,16 @@ func getImportToFilesMap(pkgPath string) (map[string][]string, error) { if strings.HasSuffix(filename, "_filetest.gno") { continue } - imports, err := gnoimports.FileImports(filepath.Join(pkgPath, filename)) + imports, _, err := gnoimports.FileImportsFromPath(filepath.Join(pkgPath, filename)) if err != nil { return nil, err } for _, imp := range imports { - m[imp] = append(m[imp], filename) + if imp.Error != nil { + return nil, err + } + m[imp.PkgPath] = append(m[imp.PkgPath], filename) } } return m, nil diff --git a/gnovm/pkg/gnoimports/imports.go b/gnovm/pkg/gnoimports/imports.go index b3a404945e5..d0959fdddf4 100644 --- a/gnovm/pkg/gnoimports/imports.go +++ b/gnovm/pkg/gnoimports/imports.go @@ -2,6 +2,7 @@ package gnoimports import ( "fmt" + "go/ast" "go/parser" "go/token" "os" @@ -33,16 +34,20 @@ func PackageImports(path string) ([]string, error) { if strings.HasSuffix(filename, "_filetest.gno") { continue } - imports, err := FileImports(filepath.Join(path, filename)) + filePath := filepath.Join(path, filename) + imports, _, err := FileImportsFromPath(filePath) if err != nil { return nil, err } for _, im := range imports { - if _, ok := seen[im]; ok { + if im.Error != nil { + return nil, err + } + if _, ok := seen[im.PkgPath]; ok { continue } - allImports = append(allImports, im) - seen[im] = struct{}{} + allImports = append(allImports, im.PkgPath) + seen[im.PkgPath] = struct{}{} } } sort.Strings(allImports) @@ -50,27 +55,39 @@ func PackageImports(path string) ([]string, error) { return allImports, nil } -// FileImports returns the list of gno imports in a given file. -func FileImports(fname string) ([]string, error) { - if !strings.HasSuffix(fname, ".gno") { - return nil, fmt.Errorf("not a gno file: %q", fname) - } - data, err := os.ReadFile(fname) - if err != nil { - return nil, err - } +type FileImport struct { + PkgPath string + Spec *ast.ImportSpec + Error error +} + +// FileImports returns the list of gno imports in the given file src. +// The given filename is only used when recording position information. +func FileImports(filename string, src []byte) ([]*FileImport, *token.FileSet, error) { fs := token.NewFileSet() - f, err := parser.ParseFile(fs, fname, data, parser.ImportsOnly) + f, err := parser.ParseFile(fs, filename, src, parser.ImportsOnly) if err != nil { - return nil, err + return nil, nil, err } - res := make([]string, len(f.Imports)) + res := make([]*FileImport, len(f.Imports)) for i, im := range f.Imports { + fi := FileImport{Spec: im} importPath, err := strconv.Unquote(im.Path.Value) if err != nil { - return nil, fmt.Errorf("unquote %q: %w", im.Path.Value, err) + fi.Error = fmt.Errorf("%v: unexpected invalid import path: %v", fs.Position(im.Pos()).String(), im.Path.Value) + } else { + fi.PkgPath = importPath } - res[i] = importPath + res[i] = &fi + } + return res, fs, nil +} + +// FileImportsFromPath reads the file at filePath and returns the list of gno imports in it. +func FileImportsFromPath(filePath string) ([]*FileImport, *token.FileSet, error) { + data, err := os.ReadFile(filePath) + if err != nil { + return nil, nil, err } - return res, nil + return FileImports(filePath, data) } diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index dabb5644cdd..66c03c8e599 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -4,17 +4,15 @@ import ( "encoding/json" "errors" "fmt" - "go/parser" - "go/token" "io" "math/big" "os" "path/filepath" "runtime/debug" - "strconv" "strings" "time" + "github.com/gnolang/gno/gnovm/pkg/gnoimports" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" teststdlibs "github.com/gnolang/gno/gnovm/tests/stdlibs" teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" @@ -241,24 +239,22 @@ func LoadImports(store gno.Store, filename string, content []byte) (err error) { } }() - fset := token.NewFileSet() - fl, err := parser.ParseFile(fset, filename, content, parser.ImportsOnly) + imports, fset, err := gnoimports.FileImports(filename, content) if err != nil { - return fmt.Errorf("parse failure: %w", err) + return err } - for _, imp := range fl.Imports { - impPath, err := strconv.Unquote(imp.Path.Value) - if err != nil { - return fmt.Errorf("%v: unexpected invalid import path: %v", fset.Position(imp.Pos()).String(), imp.Path.Value) + for _, imp := range imports { + if imp.Error != nil { + return imp.Error } - if gno.IsRealmPath(impPath) { + if gno.IsRealmPath(imp.PkgPath) { // Don't eagerly load realms. // Realms persist state and can change the state of other realms in initialization. continue } - pkg := store.GetPackage(impPath, true) + pkg := store.GetPackage(imp.PkgPath, true) if pkg == nil { - return fmt.Errorf("%v: unknown import path %v", fset.Position(imp.Pos()).String(), impPath) + return fmt.Errorf("%v: unknown import path %v", fset.Position(imp.Spec.Pos()).String(), imp.PkgPath) } } return nil From 35efc26e70cd524bf9736324284d23ff699bb37a Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 28 Nov 2024 08:48:01 +0100 Subject: [PATCH 50/51] chore: Revert "chore: use constant for qfile path" This reverts commit a12d12aaaefc91e65635860daf012835411cdc8b. --- gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go | 4 ++-- gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go index 9fae83c4bee..0a773c179f4 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch.go @@ -8,7 +8,6 @@ import ( "strings" "unicode" - "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnoimports" "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -143,8 +142,9 @@ func overrideURLFromEnv(pkgDomain string) (string, bool) { return pkgDomain, false } +// not using gno client due to cyclic dep func qfile(tmClient tm2client.Client, pkgPath string) ([]byte, error) { - path := "vm/" + vm.QueryFile + path := "vm/qfile" data := []byte(pkgPath) qres, err := tmClient.ABCIQuery(path, data) diff --git a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go index 3c5e00d258a..b98ad870bcb 100644 --- a/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go +++ b/gnovm/cmd/gno/internal/gnopkgfetch/gnopkgfetch_testing.go @@ -9,7 +9,6 @@ import ( "path/filepath" "strings" - "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/tm2/pkg/amino" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" @@ -29,7 +28,7 @@ func (m *examplesMockClient) SendRequest(ctx context.Context, request types.RPCR return nil, fmt.Errorf("failed to unmarshal params: %w", err) } path := params.Path - if path != "vm/"+vm.QueryFile { + if path != "vm/qfile" { return nil, fmt.Errorf("unexpected call to %q", path) } data := string(params.Data) From d90f89a0f77d55328228b999593530e22251d0bb Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Thu, 28 Nov 2024 08:55:30 +0100 Subject: [PATCH 51/51] chore: add doc.go for gnoimports Signed-off-by: Norman Meier --- gnovm/pkg/gnoimports/doc.go | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 gnovm/pkg/gnoimports/doc.go diff --git a/gnovm/pkg/gnoimports/doc.go b/gnovm/pkg/gnoimports/doc.go new file mode 100644 index 00000000000..9495c0629cc --- /dev/null +++ b/gnovm/pkg/gnoimports/doc.go @@ -0,0 +1,2 @@ +// Package gnoimports provides utility functions to get the list of imports from a gno file or package +package gnoimports