From 53cee96236e93e647bc11fedd44729a5618344db Mon Sep 17 00:00:00 2001 From: n0izn0iz Date: Sat, 7 Dec 2024 21:44:26 +0100 Subject: [PATCH] feat(gnomod)!: forbid require and find dependencies without it (#3123) A step towards the importer package (#2932) and future of `gno.mod` (#2904) - BREAKING CHANGE: remove `require` statement support from `gno.mod` - BREAKING CHANGE: remove `-v` (verbose) and `--remote` flags in `gno mod download` - Don't require version specification in `gno.mod`'s `replace` statements - Use `.gno` files `import` statements to find dependencies - Extract and refacto imports gathering utils in `gnovm/pkg/packages` - Add `gnovm/cmd/gno/internal/pkgdownload.PackageFetcher` interface - Implement `PackageFetcher` using `vm/qfile` queries in `gnovm/cmd/gno/internal/pkgdownload/rpcpackagefetcher` - Rewrite single package download routine in `gnovm/cmd/gno/internal/pkgdownload` - Move and refacto dependencies download routine in `gnovm/cmd/gno/download_deps.go` - Add a `--remote-overrides` flag for `gno mod download` that takes `chain-domain=rpc-url` comma-separated pairs to override endpoints used to fetch packages - Add and use a testing implementation of `PackageFetcher` called `examplesPackageFetcher` that serves package from the `examples` directory for testing purposes (download tests before this PR use the portal loop public endpoint) - Make `ReadMemPackage` and it's dependencies error-out instead of panicking - Create panicking `MemPackage` utils that wrap the erroring ones and use them at existing callsites I decided to do this first to avoid having multiple ways to resolve dependencies lying around in the codebase and causing confusion in subsequent steps
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests
--------- Signed-off-by: Norman Meier Co-authored-by: Morgan Bazalgette --- contribs/gnodev/pkg/dev/packages.go | 2 +- contribs/gnogenesis/go.mod | 1 - contribs/gnogenesis/go.sum | 2 - contribs/gnomigrate/go.mod | 1 - contribs/gnomigrate/go.sum | 2 - examples/gno.land/p/demo/acl/gno.mod | 7 - examples/gno.land/p/demo/avl/pager/gno.mod | 7 - examples/gno.land/p/demo/avlhelpers/gno.mod | 2 - examples/gno.land/p/demo/blog/gno.mod | 6 - examples/gno.land/p/demo/dao/gno.mod | 2 - examples/gno.land/p/demo/dom/gno.mod | 2 - examples/gno.land/p/demo/fqname/gno.mod | 2 - .../gno.land/p/demo/gnorkle/agent/gno.mod | 5 - .../p/demo/gnorkle/feeds/static/gno.mod | 12 -- .../gno.land/p/demo/gnorkle/gnorkle/gno.mod | 8 - .../p/demo/gnorkle/ingesters/single/gno.mod | 7 - .../gno.land/p/demo/gnorkle/message/gno.mod | 2 - .../p/demo/gnorkle/storage/simple/gno.mod | 8 - examples/gno.land/p/demo/grc/grc1155/gno.mod | 6 - examples/gno.land/p/demo/grc/grc20/gno.mod | 9 - examples/gno.land/p/demo/grc/grc721/gno.mod | 7 - examples/gno.land/p/demo/grc/grc777/gno.mod | 2 - examples/gno.land/p/demo/groups/gno.mod | 2 - examples/gno.land/p/demo/int256/gno.mod | 2 - examples/gno.land/p/demo/json/gno.mod | 2 - .../gno.land/p/demo/math_eval/int32/gno.mod | 2 - examples/gno.land/p/demo/membstore/gno.mod | 8 - examples/gno.land/p/demo/memeland/gno.mod | 9 - examples/gno.land/p/demo/microblog/gno.mod | 5 - .../p/demo/ownable/exts/authorizable/gno.mod | 8 - examples/gno.land/p/demo/ownable/gno.mod | 5 - examples/gno.land/p/demo/pausable/gno.mod | 5 - examples/gno.land/p/demo/seqid/gno.mod | 2 - examples/gno.land/p/demo/simpledao/gno.mod | 11 -- .../p/demo/subscription/lifetime/gno.mod | 7 - .../p/demo/subscription/recurring/gno.mod | 7 - examples/gno.land/p/demo/svg/gno.mod | 2 - examples/gno.land/p/demo/tamagotchi/gno.mod | 2 - examples/gno.land/p/demo/tests/gno.mod | 5 - examples/gno.land/p/demo/todolist/gno.mod | 5 - examples/gno.land/p/demo/uassert/gno.mod | 2 - examples/gno.land/p/demo/urequire/gno.mod | 2 - examples/gno.land/p/demo/watchdog/gno.mod | 2 - examples/gno.land/p/gov/executor/gno.mod | 6 - examples/gno.land/p/moul/helplink/gno.mod | 5 - examples/gno.land/p/moul/mdtable/gno.mod | 2 - .../gno.land/p/moul/printfdebugging/gno.mod | 2 - examples/gno.land/p/moul/realmpath/gno.mod | 5 - examples/gno.land/p/moul/txlink/gno.mod | 2 - examples/gno.land/p/n2p5/haystack/gno.mod | 5 - examples/gno.land/p/n2p5/mgroup/gno.mod | 6 - examples/gno.land/p/nt/poa/gno.mod | 9 - .../gno.land/p/wyhaines/rand/isaac/gno.mod | 6 - .../gno.land/p/wyhaines/rand/isaac64/gno.mod | 6 - .../p/wyhaines/rand/xorshift64star/gno.mod | 5 - .../p/wyhaines/rand/xorshiftr128plus/gno.mod | 5 - examples/gno.land/r/demo/art/gnoface/gno.mod | 6 - .../gno.land/r/demo/art/millipede/gno.mod | 5 - examples/gno.land/r/demo/bar20/gno.mod | 8 - examples/gno.land/r/demo/boards/gno.mod | 6 - examples/gno.land/r/demo/daoweb/gno.mod | 6 - examples/gno.land/r/demo/disperse/gno.mod | 2 - examples/gno.land/r/demo/echo/gno.mod | 2 - examples/gno.land/r/demo/foo1155/gno.mod | 7 - examples/gno.land/r/demo/foo20/gno.mod | 11 -- examples/gno.land/r/demo/foo721/gno.mod | 7 - .../gno.land/r/demo/games/dice_roller/gno.mod | 10 -- .../gno.land/r/demo/games/shifumi/gno.mod | 6 - examples/gno.land/r/demo/grc20factory/gno.mod | 10 -- examples/gno.land/r/demo/grc20reg/gno.mod | 8 - examples/gno.land/r/demo/groups/gno.mod | 5 - examples/gno.land/r/demo/keystore/gno.mod | 7 - examples/gno.land/r/demo/math_eval/gno.mod | 5 - examples/gno.land/r/demo/memeland/gno.mod | 2 - examples/gno.land/r/demo/microblog/gno.mod | 8 - examples/gno.land/r/demo/mirror/gno.mod | 2 - examples/gno.land/r/demo/nft/gno.mod | 5 - examples/gno.land/r/demo/profile/gno.mod | 8 - .../gno.land/r/demo/releases_example/gno.mod | 2 - examples/gno.land/r/demo/tamagotchi/gno.mod | 5 - .../gno.land/r/demo/tests/crossrealm/gno.mod | 5 - .../r/demo/tests/crossrealm_b/gno.mod | 2 - examples/gno.land/r/demo/tests/gno.mod | 5 - examples/gno.land/r/demo/tests_foo/gno.mod | 2 - examples/gno.land/r/demo/todolist/gno.mod | 8 - examples/gno.land/r/demo/types/gno.mod | 2 - examples/gno.land/r/demo/ui/gno.mod | 5 - examples/gno.land/r/demo/userbook/gno.mod | 7 - examples/gno.land/r/demo/users/gno.mod | 8 - examples/gno.land/r/demo/wugnot/gno.mod | 8 - examples/gno.land/r/docs/adder/gno.mod | 2 - examples/gno.land/r/docs/avl_pager/gno.mod | 5 - examples/gno.land/r/gnoland/blog/gno.mod | 7 - examples/gno.land/r/gnoland/events/gno.mod | 8 - examples/gno.land/r/gnoland/faucet/gno.mod | 6 - examples/gno.land/r/gnoland/ghverify/gno.mod | 8 - examples/gno.land/r/gnoland/home/gno.mod | 9 - examples/gno.land/r/gnoland/monit/gno.mod | 7 - examples/gno.land/r/gnoland/pages/gno.mod | 5 - .../gno.land/r/gnoland/valopers/v2/gno.mod | 11 -- examples/gno.land/r/gov/dao/bridge/gno.mod | 10 -- examples/gno.land/r/gov/dao/v2/gno.mod | 11 -- examples/gno.land/r/leon/hof/gno.mod | 14 -- examples/gno.land/r/leon/home/gno.mod | 9 - examples/gno.land/r/morgan/guestbook/gno.mod | 6 - examples/gno.land/r/morgan/home/gno.mod | 2 - examples/gno.land/r/moul/home/gno.mod | 5 - examples/gno.land/r/moul/present/gno.mod | 5 - examples/gno.land/r/n2p5/config/gno.mod | 5 - examples/gno.land/r/n2p5/haystack/gno.mod | 7 - examples/gno.land/r/n2p5/home/gno.mod | 6 - examples/gno.land/r/stefann/home/gno.mod | 8 - examples/gno.land/r/stefann/registry/gno.mod | 2 - examples/gno.land/r/sys/params/gno.mod | 5 - examples/gno.land/r/sys/users/gno.mod | 5 - examples/gno.land/r/sys/validators/v2/gno.mod | 12 -- examples/gno.land/r/x/manfred_outfmt/gno.mod | 2 - gno.land/pkg/gnoland/genesis.go | 2 +- .../pkg/integration/testing_integration.go | 20 ++- gno.land/pkg/keyscli/addpkg.go | 2 +- gno.land/pkg/keyscli/run.go | 2 +- gno.land/pkg/sdk/vm/keeper.go | 2 +- gno.land/pkg/sdk/vm/msgs.go | 4 +- gnovm/cmd/gno/download_deps.go | 86 +++++++++ gnovm/cmd/gno/download_deps_test.go | 152 ++++++++++++++++ .../examplespkgfetcher/examplespkgfetcher.go | 52 ++++++ .../gno/internal/pkgdownload/pkgdownload.go | 30 ++++ .../gno/internal/pkgdownload/pkgfetcher.go | 7 + .../rpcpkgfetcher/rpcpkgfetcher.go | 89 ++++++++++ .../rpcpkgfetcher/rpcpkgfetcher_test.go | 53 ++++++ gnovm/cmd/gno/lint.go | 2 +- gnovm/cmd/gno/main_test.go | 11 +- gnovm/cmd/gno/mod.go | 164 +++++------------ gnovm/cmd/gno/mod_test.go | 158 +---------------- gnovm/cmd/gno/test.go | 2 +- gnovm/pkg/doc/dirs.go | 58 +++++- gnovm/pkg/doc/dirs_test.go | 13 +- gnovm/pkg/doc/testdata/dirsmod/a.gno | 9 + gnovm/pkg/doc/testdata/dirsmod/gno.mod | 6 +- gnovm/pkg/gnolang/files_test.go | 2 +- gnovm/pkg/gnolang/nodes.go | 59 +++++-- gnovm/pkg/gnomod/fetch.go | 30 ---- gnovm/pkg/gnomod/file.go | 129 +------------- gnovm/pkg/gnomod/file_test.go | 142 --------------- gnovm/pkg/gnomod/gnomod.go | 138 +-------------- gnovm/pkg/gnomod/parse.go | 22 +-- gnovm/pkg/gnomod/parse_test.go | 21 ++- gnovm/pkg/gnomod/pkg.go | 52 ++++-- gnovm/pkg/gnomod/pkg_test.go | 142 ++------------- gnovm/pkg/gnomod/preprocess.go | 37 +--- gnovm/pkg/gnomod/preprocess_test.go | 127 ------------- gnovm/pkg/gnomod/read.go | 60 ------- gnovm/pkg/gnomod/read_test.go | 167 ------------------ gnovm/pkg/packages/doc.go | 2 + gnovm/pkg/packages/imports.go | 72 ++++++++ gnovm/pkg/packages/imports_test.go | 127 +++++++++++++ gnovm/pkg/test/imports.go | 28 ++- .../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 - misc/loop/go.mod | 1 - 171 files changed, 988 insertions(+), 1999 deletions(-) create mode 100644 gnovm/cmd/gno/download_deps.go create mode 100644 gnovm/cmd/gno/download_deps_test.go create mode 100644 gnovm/cmd/gno/internal/pkgdownload/examplespkgfetcher/examplespkgfetcher.go create mode 100644 gnovm/cmd/gno/internal/pkgdownload/pkgdownload.go create mode 100644 gnovm/cmd/gno/internal/pkgdownload/pkgfetcher.go create mode 100644 gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher.go create mode 100644 gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher_test.go create mode 100644 gnovm/pkg/doc/testdata/dirsmod/a.gno delete mode 100644 gnovm/pkg/gnomod/fetch.go delete mode 100644 gnovm/pkg/gnomod/file_test.go create mode 100644 gnovm/pkg/packages/doc.go create mode 100644 gnovm/pkg/packages/imports.go create mode 100644 gnovm/pkg/packages/imports_test.go 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/contribs/gnodev/pkg/dev/packages.go b/contribs/gnodev/pkg/dev/packages.go index cccbf316525..62c1907b8c9 100644 --- a/contribs/gnodev/pkg/dev/packages.go +++ b/contribs/gnodev/pkg/dev/packages.go @@ -138,7 +138,7 @@ func (pm PackagesMap) Load(fee std.Fee, start time.Time) ([]gnoland.TxWithMetada } // Open files in directory as MemPackage. - memPkg := gno.ReadMemPackage(modPkg.Dir, modPkg.Name) + memPkg := gno.MustReadMemPackage(modPkg.Dir, modPkg.Name) if err := memPkg.Validate(); err != nil { return nil, fmt.Errorf("invalid package: %w", err) } 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/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= diff --git a/examples/gno.land/p/demo/acl/gno.mod b/examples/gno.land/p/demo/acl/gno.mod index 15d9f078048..04fbf9043c4 100644 --- a/examples/gno.land/p/demo/acl/gno.mod +++ b/examples/gno.land/p/demo/acl/gno.mod @@ -1,8 +1 @@ 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..020b809b208 100644 --- a/examples/gno.land/p/demo/avl/pager/gno.mod +++ b/examples/gno.land/p/demo/avl/pager/gno.mod @@ -1,8 +1 @@ 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..5adffd13a43 100644 --- a/examples/gno.land/p/demo/avlhelpers/gno.mod +++ b/examples/gno.land/p/demo/avlhelpers/gno.mod @@ -1,3 +1 @@ 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..e4e3def299b 100644 --- a/examples/gno.land/p/demo/blog/gno.mod +++ b/examples/gno.land/p/demo/blog/gno.mod @@ -1,7 +1 @@ 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..fbb23299116 100644 --- a/examples/gno.land/p/demo/dao/gno.mod +++ b/examples/gno.land/p/demo/dao/gno.mod @@ -1,3 +1 @@ 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..bd8bba14d06 100644 --- a/examples/gno.land/p/demo/dom/gno.mod +++ b/examples/gno.land/p/demo/dom/gno.mod @@ -1,3 +1 @@ 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..afee55e0b7b 100644 --- a/examples/gno.land/p/demo/fqname/gno.mod +++ b/examples/gno.land/p/demo/fqname/gno.mod @@ -1,3 +1 @@ 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..e784354c35e 100644 --- a/examples/gno.land/p/demo/gnorkle/agent/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/agent/gno.mod @@ -1,6 +1 @@ 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..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,13 +1 @@ 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..ce2c2c3706d 100644 --- a/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/gnorkle/gno.mod @@ -1,9 +1 @@ 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..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,8 +1 @@ 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..5544d0eb873 100644 --- a/examples/gno.land/p/demo/gnorkle/message/gno.mod +++ b/examples/gno.land/p/demo/gnorkle/message/gno.mod @@ -1,3 +1 @@ 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..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,9 +1 @@ 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..1c3ec6360eb 100644 --- a/examples/gno.land/p/demo/grc/grc1155/gno.mod +++ b/examples/gno.land/p/demo/grc/grc1155/gno.mod @@ -1,7 +1 @@ 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 91b430d3d2f..37377b32e73 100644 --- a/examples/gno.land/p/demo/grc/grc20/gno.mod +++ b/examples/gno.land/p/demo/grc/grc20/gno.mod @@ -1,10 +1 @@ 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/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/grc721/gno.mod b/examples/gno.land/p/demo/grc/grc721/gno.mod index 9e1d6f56ffc..f27caee5282 100644 --- a/examples/gno.land/p/demo/grc/grc721/gno.mod +++ b/examples/gno.land/p/demo/grc/grc721/gno.mod @@ -1,8 +1 @@ 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..da5c762b2ec 100644 --- a/examples/gno.land/p/demo/grc/grc777/gno.mod +++ b/examples/gno.land/p/demo/grc/grc777/gno.mod @@ -1,3 +1 @@ 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 cf33d0ce74b..d33df3866fa 100644 --- a/examples/gno.land/p/demo/groups/gno.mod +++ b/examples/gno.land/p/demo/groups/gno.mod @@ -1,3 +1 @@ module gno.land/p/demo/groups - -require gno.land/p/demo/rat 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..33fb0bc4e72 100644 --- a/examples/gno.land/p/demo/int256/gno.mod +++ b/examples/gno.land/p/demo/int256/gno.mod @@ -1,3 +1 @@ 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..831fa56c0f9 100644 --- a/examples/gno.land/p/demo/json/gno.mod +++ b/examples/gno.land/p/demo/json/gno.mod @@ -1,3 +1 @@ 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..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,3 +1 @@ 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..007e7a5d883 100644 --- a/examples/gno.land/p/demo/membstore/gno.mod +++ b/examples/gno.land/p/demo/membstore/gno.mod @@ -1,9 +1 @@ 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..06cc8fbf487 100644 --- a/examples/gno.land/p/demo/memeland/gno.mod +++ b/examples/gno.land/p/demo/memeland/gno.mod @@ -1,10 +1 @@ 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..a285ef5f903 100644 --- a/examples/gno.land/p/demo/microblog/gno.mod +++ b/examples/gno.land/p/demo/microblog/gno.mod @@ -1,6 +1 @@ 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..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,9 +1 @@ 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..9a9abb1e661 100644 --- a/examples/gno.land/p/demo/ownable/gno.mod +++ b/examples/gno.land/p/demo/ownable/gno.mod @@ -1,6 +1 @@ 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..a741342eb84 100644 --- a/examples/gno.land/p/demo/pausable/gno.mod +++ b/examples/gno.land/p/demo/pausable/gno.mod @@ -1,6 +1 @@ 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..63e6a1fb551 100644 --- a/examples/gno.land/p/demo/seqid/gno.mod +++ b/examples/gno.land/p/demo/seqid/gno.mod @@ -1,3 +1 @@ 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..51de621cbec 100644 --- a/examples/gno.land/p/demo/simpledao/gno.mod +++ b/examples/gno.land/p/demo/simpledao/gno.mod @@ -1,12 +1 @@ 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..59b6c1cf001 100644 --- a/examples/gno.land/p/demo/subscription/lifetime/gno.mod +++ b/examples/gno.land/p/demo/subscription/lifetime/gno.mod @@ -1,8 +1 @@ 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..356402978b5 100644 --- a/examples/gno.land/p/demo/subscription/recurring/gno.mod +++ b/examples/gno.land/p/demo/subscription/recurring/gno.mod @@ -1,8 +1 @@ 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..b9dd7f47434 100644 --- a/examples/gno.land/p/demo/svg/gno.mod +++ b/examples/gno.land/p/demo/svg/gno.mod @@ -1,3 +1 @@ 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..a9c6026629e 100644 --- a/examples/gno.land/p/demo/tamagotchi/gno.mod +++ b/examples/gno.land/p/demo/tamagotchi/gno.mod @@ -1,3 +1 @@ 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 8a19acdbb18..a342a726f61 100644 --- a/examples/gno.land/p/demo/tests/gno.mod +++ b/examples/gno.land/p/demo/tests/gno.mod @@ -1,6 +1 @@ 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 -) diff --git a/examples/gno.land/p/demo/todolist/gno.mod b/examples/gno.land/p/demo/todolist/gno.mod index bbccf357e3b..46d21bf0bc0 100644 --- a/examples/gno.land/p/demo/todolist/gno.mod +++ b/examples/gno.land/p/demo/todolist/gno.mod @@ -1,6 +1 @@ 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..a70e7db825d 100644 --- a/examples/gno.land/p/demo/uassert/gno.mod +++ b/examples/gno.land/p/demo/uassert/gno.mod @@ -1,3 +1 @@ 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..e5336b2c80d 100644 --- a/examples/gno.land/p/demo/urequire/gno.mod +++ b/examples/gno.land/p/demo/urequire/gno.mod @@ -1,3 +1 @@ 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..96fba14451b 100644 --- a/examples/gno.land/p/demo/watchdog/gno.mod +++ b/examples/gno.land/p/demo/watchdog/gno.mod @@ -1,3 +1 @@ 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..5dbb6f7f85e 100644 --- a/examples/gno.land/p/gov/executor/gno.mod +++ b/examples/gno.land/p/gov/executor/gno.mod @@ -1,7 +1 @@ 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..cb070b79d6a 100644 --- a/examples/gno.land/p/moul/helplink/gno.mod +++ b/examples/gno.land/p/moul/helplink/gno.mod @@ -1,6 +1 @@ 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/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 diff --git a/examples/gno.land/p/moul/printfdebugging/gno.mod b/examples/gno.land/p/moul/printfdebugging/gno.mod index 2cf6aa09e61..4b8d0f3256c 100644 --- a/examples/gno.land/p/moul/printfdebugging/gno.mod +++ b/examples/gno.land/p/moul/printfdebugging/gno.mod @@ -1,3 +1 @@ module gno.land/p/demo/printfdebugging - -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/moul/realmpath/gno.mod b/examples/gno.land/p/moul/realmpath/gno.mod index e391b76390f..0c012a0c3ae 100644 --- a/examples/gno.land/p/moul/realmpath/gno.mod +++ b/examples/gno.land/p/moul/realmpath/gno.mod @@ -1,6 +1 @@ module gno.land/p/moul/realmpath - -require ( - 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/txlink/gno.mod b/examples/gno.land/p/moul/txlink/gno.mod index 6110464316f..ed16b8b74fd 100644 --- a/examples/gno.land/p/moul/txlink/gno.mod +++ b/examples/gno.land/p/moul/txlink/gno.mod @@ -1,3 +1 @@ module gno.land/p/moul/txlink - -require gno.land/p/demo/urequire v0.0.0-latest diff --git a/examples/gno.land/p/n2p5/haystack/gno.mod b/examples/gno.land/p/n2p5/haystack/gno.mod index ebd0d07a987..987d62d4565 100644 --- a/examples/gno.land/p/n2p5/haystack/gno.mod +++ b/examples/gno.land/p/n2p5/haystack/gno.mod @@ -1,6 +1 @@ module gno.land/p/n2p5/haystack - -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/n2p5/haystack/needle v0.0.0-latest -) 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/p/nt/poa/gno.mod b/examples/gno.land/p/nt/poa/gno.mod index 5c1b75eb05a..965eeb56aed 100644 --- a/examples/gno.land/p/nt/poa/gno.mod +++ b/examples/gno.land/p/nt/poa/gno.mod @@ -1,10 +1 @@ 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/p/wyhaines/rand/isaac/gno.mod b/examples/gno.land/p/wyhaines/rand/isaac/gno.mod index 0cca6aa5174..538f52e6e7e 100644 --- a/examples/gno.land/p/wyhaines/rand/isaac/gno.mod +++ b/examples/gno.land/p/wyhaines/rand/isaac/gno.mod @@ -1,7 +1 @@ module gno.land/p/wyhaines/rand/isaac - -require ( - gno.land/p/demo/entropy v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/wyhaines/rand/xorshiftr128plus v0.0.0-latest -) diff --git a/examples/gno.land/p/wyhaines/rand/isaac64/gno.mod b/examples/gno.land/p/wyhaines/rand/isaac64/gno.mod index dbc8713094e..79772dfe8d8 100644 --- a/examples/gno.land/p/wyhaines/rand/isaac64/gno.mod +++ b/examples/gno.land/p/wyhaines/rand/isaac64/gno.mod @@ -1,7 +1 @@ module gno.land/p/wyhaines/rand/isaac64 - -require ( - gno.land/p/demo/entropy v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/wyhaines/rand/xorshiftr128plus v0.0.0-latest -) diff --git a/examples/gno.land/p/wyhaines/rand/xorshift64star/gno.mod b/examples/gno.land/p/wyhaines/rand/xorshift64star/gno.mod index bc40b1bc71b..7918a7e7d2d 100644 --- a/examples/gno.land/p/wyhaines/rand/xorshift64star/gno.mod +++ b/examples/gno.land/p/wyhaines/rand/xorshift64star/gno.mod @@ -1,6 +1 @@ module gno.land/p/wyhaines/rand/xorshift64star - -require ( - gno.land/p/demo/entropy v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) diff --git a/examples/gno.land/p/wyhaines/rand/xorshiftr128plus/gno.mod b/examples/gno.land/p/wyhaines/rand/xorshiftr128plus/gno.mod index c778fc72550..9f3be9ea8df 100644 --- a/examples/gno.land/p/wyhaines/rand/xorshiftr128plus/gno.mod +++ b/examples/gno.land/p/wyhaines/rand/xorshiftr128plus/gno.mod @@ -1,6 +1 @@ module gno.land/p/wyhaines/rand/xorshiftr128plus - -require ( - gno.land/p/demo/entropy v0.0.0-latest - gno.land/p/demo/ufmt 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..9465af6216a 100644 --- a/examples/gno.land/r/demo/art/gnoface/gno.mod +++ b/examples/gno.land/r/demo/art/gnoface/gno.mod @@ -1,7 +1 @@ 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..3e5177efdcd 100644 --- a/examples/gno.land/r/demo/art/millipede/gno.mod +++ b/examples/gno.land/r/demo/art/millipede/gno.mod @@ -1,6 +1 @@ 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 9fb0f083e1b..e8ede1ea44f 100644 --- a/examples/gno.land/r/demo/bar20/gno.mod +++ b/examples/gno.land/r/demo/bar20/gno.mod @@ -1,9 +1 @@ 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 - gno.land/r/demo/grc20reg 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..dffb96740fc 100644 --- a/examples/gno.land/r/demo/boards/gno.mod +++ b/examples/gno.land/r/demo/boards/gno.mod @@ -1,7 +1 @@ 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..74ae149cdb6 100644 --- a/examples/gno.land/r/demo/daoweb/gno.mod +++ b/examples/gno.land/r/demo/daoweb/gno.mod @@ -1,7 +1 @@ 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..06e81884dfa 100644 --- a/examples/gno.land/r/demo/disperse/gno.mod +++ b/examples/gno.land/r/demo/disperse/gno.mod @@ -1,3 +1 @@ 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..f07d78943d1 100644 --- a/examples/gno.land/r/demo/echo/gno.mod +++ b/examples/gno.land/r/demo/echo/gno.mod @@ -1,3 +1 @@ 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..eae12bcd1e3 100644 --- a/examples/gno.land/r/demo/foo1155/gno.mod +++ b/examples/gno.land/r/demo/foo1155/gno.mod @@ -1,8 +1 @@ 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 64b8f90a27d..79dea556e78 100644 --- a/examples/gno.land/r/demo/foo20/gno.mod +++ b/examples/gno.land/r/demo/foo20/gno.mod @@ -1,12 +1 @@ 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/grc20reg 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..4779f2fc467 100644 --- a/examples/gno.land/r/demo/foo721/gno.mod +++ b/examples/gno.land/r/demo/foo721/gno.mod @@ -1,8 +1 @@ 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..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,11 +1 @@ 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..e6a428090a9 100644 --- a/examples/gno.land/r/demo/games/shifumi/gno.mod +++ b/examples/gno.land/r/demo/games/shifumi/gno.mod @@ -1,7 +1 @@ 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 a2d2a55fdf0..f89ee5872a5 100644 --- a/examples/gno.land/r/demo/grc20factory/gno.mod +++ b/examples/gno.land/r/demo/grc20factory/gno.mod @@ -1,11 +1 @@ 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/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/r/demo/grc20reg v0.0.0-latest -) diff --git a/examples/gno.land/r/demo/grc20reg/gno.mod b/examples/gno.land/r/demo/grc20reg/gno.mod index f02ee09c35a..c5065c60064 100644 --- a/examples/gno.land/r/demo/grc20reg/gno.mod +++ b/examples/gno.land/r/demo/grc20reg/gno.mod @@ -1,9 +1 @@ module gno.land/r/demo/grc20reg - -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/fqname v0.0.0-latest - gno.land/p/demo/grc/grc20 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/groups/gno.mod b/examples/gno.land/r/demo/groups/gno.mod index fc6756e13e2..6f715471ced 100644 --- a/examples/gno.land/r/demo/groups/gno.mod +++ b/examples/gno.land/r/demo/groups/gno.mod @@ -1,6 +1 @@ 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..cd07d24adf6 100644 --- a/examples/gno.land/r/demo/keystore/gno.mod +++ b/examples/gno.land/r/demo/keystore/gno.mod @@ -1,8 +1 @@ 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..c797becfa7d 100644 --- a/examples/gno.land/r/demo/math_eval/gno.mod +++ b/examples/gno.land/r/demo/math_eval/gno.mod @@ -1,6 +1 @@ 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..0ccb353659f 100644 --- a/examples/gno.land/r/demo/memeland/gno.mod +++ b/examples/gno.land/r/demo/memeland/gno.mod @@ -1,3 +1 @@ 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..a622200b76d 100644 --- a/examples/gno.land/r/demo/microblog/gno.mod +++ b/examples/gno.land/r/demo/microblog/gno.mod @@ -1,9 +1 @@ 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/mirror/gno.mod b/examples/gno.land/r/demo/mirror/gno.mod index 2bf27fd6916..cb53585644a 100644 --- a/examples/gno.land/r/demo/mirror/gno.mod +++ b/examples/gno.land/r/demo/mirror/gno.mod @@ -1,3 +1 @@ module gno.land/r/demo/mirror - -require gno.land/p/demo/avl 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..ad760d186ab 100644 --- a/examples/gno.land/r/demo/nft/gno.mod +++ b/examples/gno.land/r/demo/nft/gno.mod @@ -1,6 +1 @@ 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..3e875672a99 100644 --- a/examples/gno.land/r/demo/profile/gno.mod +++ b/examples/gno.land/r/demo/profile/gno.mod @@ -1,9 +1 @@ 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..0dc5d6561dc 100644 --- a/examples/gno.land/r/demo/releases_example/gno.mod +++ b/examples/gno.land/r/demo/releases_example/gno.mod @@ -1,3 +1 @@ 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..bccf4841666 100644 --- a/examples/gno.land/r/demo/tamagotchi/gno.mod +++ b/examples/gno.land/r/demo/tamagotchi/gno.mod @@ -1,6 +1 @@ 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..2f7f217d288 100644 --- a/examples/gno.land/r/demo/tests/crossrealm/gno.mod +++ b/examples/gno.land/r/demo/tests/crossrealm/gno.mod @@ -1,6 +1 @@ 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/crossrealm_b/gno.mod b/examples/gno.land/r/demo/tests/crossrealm_b/gno.mod index 74548712caa..236010c21b3 100644 --- a/examples/gno.land/r/demo/tests/crossrealm_b/gno.mod +++ b/examples/gno.land/r/demo/tests/crossrealm_b/gno.mod @@ -1,3 +1 @@ module gno.land/r/demo/tests/crossrealm_b - -require gno.land/r/demo/tests/crossrealm 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..f04aa5cf7bd 100644 --- a/examples/gno.land/r/demo/tests/gno.mod +++ b/examples/gno.land/r/demo/tests/gno.mod @@ -1,6 +1 @@ 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..e5a00113181 100644 --- a/examples/gno.land/r/demo/tests_foo/gno.mod +++ b/examples/gno.land/r/demo/tests_foo/gno.mod @@ -1,3 +1 @@ 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..acd336f1724 100644 --- a/examples/gno.land/r/demo/todolist/gno.mod +++ b/examples/gno.land/r/demo/todolist/gno.mod @@ -1,9 +1 @@ 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..c24f7ddbc93 100644 --- a/examples/gno.land/r/demo/types/gno.mod +++ b/examples/gno.land/r/demo/types/gno.mod @@ -1,3 +1 @@ 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..591b0b93190 100644 --- a/examples/gno.land/r/demo/ui/gno.mod +++ b/examples/gno.land/r/demo/ui/gno.mod @@ -1,6 +1 @@ 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..bb709a39ed7 100644 --- a/examples/gno.land/r/demo/userbook/gno.mod +++ b/examples/gno.land/r/demo/userbook/gno.mod @@ -1,8 +1 @@ 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..4d7fd15d1cd 100644 --- a/examples/gno.land/r/demo/users/gno.mod +++ b/examples/gno.land/r/demo/users/gno.mod @@ -1,9 +1 @@ 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 c7081ce6963..12b6baa7ae2 100644 --- a/examples/gno.land/r/demo/wugnot/gno.mod +++ b/examples/gno.land/r/demo/wugnot/gno.mod @@ -1,9 +1 @@ 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/grc20reg v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest -) diff --git a/examples/gno.land/r/docs/adder/gno.mod b/examples/gno.land/r/docs/adder/gno.mod index f8bbf9d6fe8..f4958c6494d 100644 --- a/examples/gno.land/r/docs/adder/gno.mod +++ b/examples/gno.land/r/docs/adder/gno.mod @@ -1,3 +1 @@ module gno.land/r/docs/adder - -require gno.land/p/moul/txlink v0.0.0-latest diff --git a/examples/gno.land/r/docs/avl_pager/gno.mod b/examples/gno.land/r/docs/avl_pager/gno.mod index 0d05b24bcd0..bc7214f7bc1 100644 --- a/examples/gno.land/r/docs/avl_pager/gno.mod +++ b/examples/gno.land/r/docs/avl_pager/gno.mod @@ -1,6 +1 @@ module gno.land/r/docs/avl_pager - -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/avl/pager 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..b510867c485 100644 --- a/examples/gno.land/r/gnoland/blog/gno.mod +++ b/examples/gno.land/r/gnoland/blog/gno.mod @@ -1,8 +1 @@ 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..50aa3d8fc27 100644 --- a/examples/gno.land/r/gnoland/events/gno.mod +++ b/examples/gno.land/r/gnoland/events/gno.mod @@ -1,9 +1 @@ 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..6193d111e4f 100644 --- a/examples/gno.land/r/gnoland/faucet/gno.mod +++ b/examples/gno.land/r/gnoland/faucet/gno.mod @@ -1,7 +1 @@ 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..8ffdec663f7 100644 --- a/examples/gno.land/r/gnoland/ghverify/gno.mod +++ b/examples/gno.land/r/gnoland/ghverify/gno.mod @@ -1,9 +1 @@ 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 52d01c6d38c..09eb0eb19e1 100644 --- a/examples/gno.land/r/gnoland/home/gno.mod +++ b/examples/gno.land/r/gnoland/home/gno.mod @@ -1,10 +1 @@ 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 - gno.land/r/leon/hof 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..6086a3fa21f 100644 --- a/examples/gno.land/r/gnoland/monit/gno.mod +++ b/examples/gno.land/r/gnoland/monit/gno.mod @@ -1,8 +1 @@ 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..e041fd948bc 100644 --- a/examples/gno.land/r/gnoland/pages/gno.mod +++ b/examples/gno.land/r/gnoland/pages/gno.mod @@ -1,6 +1 @@ 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..064fe6d811e 100644 --- a/examples/gno.land/r/gnoland/valopers/v2/gno.mod +++ b/examples/gno.land/r/gnoland/valopers/v2/gno.mod @@ -1,12 +1 @@ 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..9f472eaa464 100644 --- a/examples/gno.land/r/gov/dao/bridge/gno.mod +++ b/examples/gno.land/r/gov/dao/bridge/gno.mod @@ -1,11 +1 @@ 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 4da6e0a2484..4daf8c600a1 100644 --- a/examples/gno.land/r/gov/dao/v2/gno.mod +++ b/examples/gno.land/r/gov/dao/v2/gno.mod @@ -1,12 +1 @@ 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 - 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/leon/hof/gno.mod b/examples/gno.land/r/leon/hof/gno.mod index feb31992513..f4720eb2b5a 100644 --- a/examples/gno.land/r/leon/hof/gno.mod +++ b/examples/gno.land/r/leon/hof/gno.mod @@ -1,15 +1 @@ module gno.land/r/leon/hof - -require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/p/demo/avl/pager v0.0.0-latest - gno.land/p/demo/fqname v0.0.0-latest - gno.land/p/demo/ownable v0.0.0-latest - gno.land/p/demo/pausable 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 - gno.land/p/moul/txlink 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 e7ffc49a37f..56fea265e29 100644 --- a/examples/gno.land/r/leon/home/gno.mod +++ b/examples/gno.land/r/leon/home/gno.mod @@ -1,10 +1 @@ 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/demo/mirror v0.0.0-latest - gno.land/r/leon/config v0.0.0-latest - gno.land/r/leon/hof 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..ac63a4cf8cd 100644 --- a/examples/gno.land/r/morgan/guestbook/gno.mod +++ b/examples/gno.land/r/morgan/guestbook/gno.mod @@ -1,7 +1 @@ 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/morgan/home/gno.mod b/examples/gno.land/r/morgan/home/gno.mod index 412666e4171..573a7e139e7 100644 --- a/examples/gno.land/r/morgan/home/gno.mod +++ b/examples/gno.land/r/morgan/home/gno.mod @@ -1,3 +1 @@ module gno.land/r/morgan/home - -require gno.land/r/leon/hof 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/moul/present/gno.mod b/examples/gno.land/r/moul/present/gno.mod index 3ae0bf2e64d..a0a7777d0ed 100644 --- a/examples/gno.land/r/moul/present/gno.mod +++ b/examples/gno.land/r/moul/present/gno.mod @@ -1,6 +1 @@ module gno.land/r/moul/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/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/haystack/gno.mod b/examples/gno.land/r/n2p5/haystack/gno.mod index 9203eb2d3b1..17c131b8370 100644 --- a/examples/gno.land/r/n2p5/haystack/gno.mod +++ b/examples/gno.land/r/n2p5/haystack/gno.mod @@ -1,8 +1 @@ module gno.land/r/n2p5/haystack - -require ( - gno.land/p/demo/testutils v0.0.0-latest - gno.land/p/demo/urequire v0.0.0-latest - gno.land/p/n2p5/haystack v0.0.0-latest - gno.land/p/n2p5/haystack/needle 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 -) diff --git a/examples/gno.land/r/stefann/home/gno.mod b/examples/gno.land/r/stefann/home/gno.mod index dd556e7f817..89071aa70fb 100644 --- a/examples/gno.land/r/stefann/home/gno.mod +++ b/examples/gno.land/r/stefann/home/gno.mod @@ -1,9 +1 @@ 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..7ef0c32030f 100644 --- a/examples/gno.land/r/stefann/registry/gno.mod +++ b/examples/gno.land/r/stefann/registry/gno.mod @@ -1,3 +1 @@ module gno.land/r/stefann/registry - -require gno.land/p/demo/ownable v0.0.0-latest diff --git a/examples/gno.land/r/sys/params/gno.mod b/examples/gno.land/r/sys/params/gno.mod index 4b4c2bf790f..c633412ced7 100644 --- a/examples/gno.land/r/sys/params/gno.mod +++ b/examples/gno.land/r/sys/params/gno.mod @@ -1,6 +1 @@ module gno.land/r/sys/params - -require ( - 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/sys/users/gno.mod b/examples/gno.land/r/sys/users/gno.mod index 774a364a272..e5e84a49faf 100644 --- a/examples/gno.land/r/sys/users/gno.mod +++ b/examples/gno.land/r/sys/users/gno.mod @@ -1,6 +1 @@ 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..beae6e95d34 100644 --- a/examples/gno.land/r/sys/validators/v2/gno.mod +++ b/examples/gno.land/r/sys/validators/v2/gno.mod @@ -1,13 +1 @@ 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..e8165d847c9 100644 --- a/examples/gno.land/r/x/manfred_outfmt/gno.mod +++ b/examples/gno.land/r/x/manfred_outfmt/gno.mod @@ -1,5 +1,3 @@ // Draft module gno.land/r/x/manfred_outfmt - -require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index ea692bcaf0d..778121d59ed 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -168,7 +168,7 @@ func LoadPackage(pkg gnomod.Pkg, creator bft.Address, fee std.Fee, deposit std.C var tx std.Tx // Open files in directory as MemPackage. - memPkg := gno.ReadMemPackage(pkg.Dir, pkg.Name) + memPkg := gno.MustReadMemPackage(pkg.Dir, pkg.Name) err := memPkg.Validate() if err != nil { return tx, fmt.Errorf("invalid package: %w", err) diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 235b9581ae0..2a0a4cf1106 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" + "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/packages" "github.com/gnolang/gno/tm2/pkg/bft/node" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" @@ -743,8 +745,20 @@ 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) + + pkg, err := gnolang.ReadMemPackage(currentPkg.Dir, currentPkg.Name) + if err != nil { + return fmt.Errorf("unable to read package at %q: %w", currentPkg.Dir, err) + } + imports, err := packages.Imports(pkg) + if err != nil { + return fmt.Errorf("unable to load package imports in %q: %w", currentPkg.Dir, err) + } + for _, imp := range imports { + if imp == currentPkg.Name || gnolang.IsStdlib(imp) { + continue + } + currentPkg.Imports = append(currentPkg.Imports, imp) } } @@ -758,7 +772,7 @@ func (pl *pkgsLoader) LoadPackage(modroot string, path, name string) error { pl.add(currentPkg) // Add requirements to the queue - for _, pkgPath := range currentPkg.Requires { + for _, pkgPath := range currentPkg.Imports { fullPath := filepath.Join(modroot, pkgPath) queue = append(queue, gnomod.Pkg{Dir: fullPath}) } diff --git a/gno.land/pkg/keyscli/addpkg.go b/gno.land/pkg/keyscli/addpkg.go index 37463d13b5c..eb6e727fedd 100644 --- a/gno.land/pkg/keyscli/addpkg.go +++ b/gno.land/pkg/keyscli/addpkg.go @@ -96,7 +96,7 @@ func execMakeAddPkg(cfg *MakeAddPkgCfg, args []string, io commands.IO) error { } // open files in directory as MemPackage. - memPkg := gno.ReadMemPackage(cfg.PkgDir, cfg.PkgPath) + memPkg := gno.MustReadMemPackage(cfg.PkgDir, cfg.PkgPath) if memPkg.IsEmpty() { panic(fmt.Sprintf("found an empty package %q", cfg.PkgPath)) } diff --git a/gno.land/pkg/keyscli/run.go b/gno.land/pkg/keyscli/run.go index b0e05fe5a84..00b2be585c6 100644 --- a/gno.land/pkg/keyscli/run.go +++ b/gno.land/pkg/keyscli/run.go @@ -92,7 +92,7 @@ func execMakeRun(cfg *MakeRunCfg, args []string, cmdio commands.IO) error { return fmt.Errorf("could not read source path: %q, %w", sourcePath, err) } if info.IsDir() { - memPkg = gno.ReadMemPackage(sourcePath, "") + memPkg = gno.MustReadMemPackage(sourcePath, "") } else { // is file b, err := os.ReadFile(sourcePath) if err != nil { diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index e4f7a8543a7..00a0544cad6 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -186,7 +186,7 @@ func loadStdlibPackage(pkgPath, stdlibDir string, store gno.Store) { // does not exist. panic(fmt.Sprintf("failed loading stdlib %q: does not exist", pkgPath)) } - memPkg := gno.ReadMemPackage(stdlibPath, pkgPath) + memPkg := gno.MustReadMemPackage(stdlibPath, pkgPath) if memPkg.IsEmpty() { // no gno files are present panic(fmt.Sprintf("failed loading stdlib %q: not a valid MemPackage", pkgPath)) diff --git a/gno.land/pkg/sdk/vm/msgs.go b/gno.land/pkg/sdk/vm/msgs.go index 1ce648acb19..38f35ab7110 100644 --- a/gno.land/pkg/sdk/vm/msgs.go +++ b/gno.land/pkg/sdk/vm/msgs.go @@ -29,7 +29,7 @@ func NewMsgAddPackage(creator crypto.Address, pkgPath string, files []*gnovm.Mem var pkgName string for _, file := range files { if strings.HasSuffix(file.Name, ".gno") { - pkgName = string(gno.PackageNameFromFileBody(file.Name, file.Body)) + pkgName = string(gno.MustPackageNameFromFileBody(file.Name, file.Body)) break } } @@ -156,7 +156,7 @@ var _ std.Msg = MsgRun{} func NewMsgRun(caller crypto.Address, send std.Coins, files []*gnovm.MemFile) MsgRun { for _, file := range files { if strings.HasSuffix(file.Name, ".gno") { - pkgName := string(gno.PackageNameFromFileBody(file.Name, file.Body)) + pkgName := string(gno.MustPackageNameFromFileBody(file.Name, file.Body)) if pkgName != "main" { panic("package name should be 'main'") } diff --git a/gnovm/cmd/gno/download_deps.go b/gnovm/cmd/gno/download_deps.go new file mode 100644 index 00000000000..d19de9dd338 --- /dev/null +++ b/gnovm/cmd/gno/download_deps.go @@ -0,0 +1,86 @@ +package main + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload" + "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/packages" + "github.com/gnolang/gno/tm2/pkg/commands" + "golang.org/x/mod/module" +) + +// downloadDeps recursively fetches the imports of a local package while following a given gno.mod replace directives +func downloadDeps(io commands.IO, pkgDir string, gnoMod *gnomod.File, fetcher pkgdownload.PackageFetcher) error { + if fetcher == nil { + return errors.New("fetcher is nil") + } + + pkg, err := gnolang.ReadMemPackage(pkgDir, gnoMod.Module.Mod.Path) + if err != nil { + return fmt.Errorf("read package at %q: %w", pkgDir, err) + } + imports, err := packages.Imports(pkg) + 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 !isRemotePkgPath(resolvedPkgPath) { + continue + } + + depDir := gnomod.PackageDir("", module.Version{Path: resolvedPkgPath}) + + if err := downloadPackage(io, resolvedPkgPath, depDir, fetcher); err != nil { + return fmt.Errorf("download import %q of %q: %w", resolvedPkgPath, pkgDir, err) + } + + if err := downloadDeps(io, depDir, gnoMod, fetcher); err != nil { + return err + } + } + + return nil +} + +// downloadPackage downloads a remote gno package by pkg path and store it at dst +func downloadPackage(io commands.IO, pkgPath string, dst string, fetcher pkgdownload.PackageFetcher) 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("stat downloaded module %q at %q: %w", pkgPath, dst, err) + } + + io.ErrPrintfln("gno: downloading %s", pkgPath) + + if err := pkgdownload.Download(pkgPath, dst, fetcher); err != nil { + return err + } + + // 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 yet. + // 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("write modfile at %q: %w", modFilePath, err) + } + + return nil +} + +// 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/download_deps_test.go b/gnovm/cmd/gno/download_deps_test.go new file mode 100644 index 00000000000..3ccfdb0055e --- /dev/null +++ b/gnovm/cmd/gno/download_deps_test.go @@ -0,0 +1,152 @@ +package main + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload/examplespkgfetcher" + "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/mod/modfile" + "golang.org/x/mod/module" +) + +func TestDownloadDeps(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: "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", + }, + }, { + 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", + }, + }, { + 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) { + mockErr := bytes.NewBufferString("") + io := commands.NewTestIO() + io.SetErr(commands.WriteNopCloser(mockErr)) + + dirPath := t.TempDir() + + err := os.WriteFile(filepath.Join(dirPath, "main.gno"), []byte(fmt.Sprintf("package main\n\n import %q\n", tc.pkgPath)), 0o644) + require.NoError(t, err) + + tmpGnoHome := t.TempDir() + t.Setenv("GNOHOME", tmpGnoHome) + + fetcher := examplespkgfetcher.New() + + // gno: downloading dependencies + err = downloadDeps(io, dirPath, &tc.modFile, fetcher) + 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")) + if !os.IsNotExist(err) { + 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 fetching again. Should be cached + downloadDeps(io, dirPath, &tc.modFile, fetcher) + for _, c := range tc.ioErrContains { + assert.NotContains(t, mockErr.String(), c) + } + } + }) + } +} diff --git a/gnovm/cmd/gno/internal/pkgdownload/examplespkgfetcher/examplespkgfetcher.go b/gnovm/cmd/gno/internal/pkgdownload/examplespkgfetcher/examplespkgfetcher.go new file mode 100644 index 00000000000..1642c62d21e --- /dev/null +++ b/gnovm/cmd/gno/internal/pkgdownload/examplespkgfetcher/examplespkgfetcher.go @@ -0,0 +1,52 @@ +// Package examplespkgfetcher provides an implementation of [pkgdownload.PackageFetcher] +// to fetch packages from the examples folder at GNOROOT +package examplespkgfetcher + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/gnolang/gno/gnovm" + "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload" + "github.com/gnolang/gno/gnovm/pkg/gnoenv" +) + +type ExamplesPackageFetcher struct{} + +var _ pkgdownload.PackageFetcher = (*ExamplesPackageFetcher)(nil) + +func New() pkgdownload.PackageFetcher { + return &ExamplesPackageFetcher{} +} + +// FetchPackage implements [pkgdownload.PackageFetcher]. +func (e *ExamplesPackageFetcher) FetchPackage(pkgPath string) ([]*gnovm.MemFile, error) { + pkgDir := filepath.Join(gnoenv.RootDir(), "examples", filepath.FromSlash(pkgPath)) + + entries, err := os.ReadDir(pkgDir) + if os.IsNotExist(err) { + return nil, fmt.Errorf("query files list for pkg %q: package %q is not available", pkgPath, pkgPath) + } else if err != nil { + return nil, err + } + + res := []*gnovm.MemFile{} + for _, entry := range entries { + if entry.IsDir() { + continue + } + + name := entry.Name() + filePath := filepath.Join(pkgDir, name) + + body, err := os.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("read file at %q: %w", filePath, err) + } + + res = append(res, &gnovm.MemFile{Name: name, Body: string(body)}) + } + + return res, nil +} diff --git a/gnovm/cmd/gno/internal/pkgdownload/pkgdownload.go b/gnovm/cmd/gno/internal/pkgdownload/pkgdownload.go new file mode 100644 index 00000000000..722cab01555 --- /dev/null +++ b/gnovm/cmd/gno/internal/pkgdownload/pkgdownload.go @@ -0,0 +1,30 @@ +// Package pkgdownload provides interfaces and utility functions to download gno packages files. +package pkgdownload + +import ( + "fmt" + "os" + "path/filepath" +) + +// Download downloads the package identified by `pkgPath` in the directory at `dst` using the provided [PackageFetcher]. +// The directory at `dst` is created if it does not exists. +func Download(pkgPath string, dst string, fetcher PackageFetcher) error { + files, err := fetcher.FetchPackage(pkgPath) + if err != nil { + return err + } + + if err := os.MkdirAll(dst, 0o744); err != nil { + return err + } + + for _, file := range files { + fileDst := filepath.Join(dst, file.Name) + if err := os.WriteFile(fileDst, []byte(file.Body), 0o644); err != nil { + return fmt.Errorf("write file at %q: %w", fileDst, err) + } + } + + return nil +} diff --git a/gnovm/cmd/gno/internal/pkgdownload/pkgfetcher.go b/gnovm/cmd/gno/internal/pkgdownload/pkgfetcher.go new file mode 100644 index 00000000000..79a7a6a54e2 --- /dev/null +++ b/gnovm/cmd/gno/internal/pkgdownload/pkgfetcher.go @@ -0,0 +1,7 @@ +package pkgdownload + +import "github.com/gnolang/gno/gnovm" + +type PackageFetcher interface { + FetchPackage(pkgPath string) ([]*gnovm.MemFile, error) +} diff --git a/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher.go b/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher.go new file mode 100644 index 00000000000..a71c1d43719 --- /dev/null +++ b/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher.go @@ -0,0 +1,89 @@ +// Package rpcpkgfetcher provides an implementation of [pkgdownload.PackageFetcher] +// to fetch packages from gno.land rpc endpoints +package rpcpkgfetcher + +import ( + "fmt" + "path" + "strings" + + "github.com/gnolang/gno/gnovm" + "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload" + "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" +) + +type gnoPackageFetcher struct { + remoteOverrides map[string]string +} + +var _ pkgdownload.PackageFetcher = (*gnoPackageFetcher)(nil) + +func New(remoteOverrides map[string]string) pkgdownload.PackageFetcher { + return &gnoPackageFetcher{ + remoteOverrides: remoteOverrides, + } +} + +// FetchPackage implements [pkgdownload.PackageFetcher]. +func (gpf *gnoPackageFetcher) FetchPackage(pkgPath string) ([]*gnovm.MemFile, error) { + rpcURL, err := rpcURLFromPkgPath(pkgPath, gpf.remoteOverrides) + if err != nil { + return nil, fmt.Errorf("get rpc url for pkg path %q: %w", pkgPath, err) + } + + client, err := client.NewHTTPClient(rpcURL) + if err != nil { + return nil, fmt.Errorf("failed to instantiate tm2 client with remote %q: %w", rpcURL, err) + } + defer client.Close() + + data, err := qfile(client, pkgPath) + if err != nil { + return nil, fmt.Errorf("query files list for pkg %q: %w", pkgPath, err) + } + + files := strings.Split(string(data), "\n") + res := make([]*gnovm.MemFile, len(files)) + for i, file := range files { + filePath := path.Join(pkgPath, file) + data, err := qfile(client, filePath) + if err != nil { + return nil, fmt.Errorf("query package file %q: %w", filePath, err) + } + + res[i] = &gnovm.MemFile{Name: file, Body: string(data)} + } + return res, nil +} + +func rpcURLFromPkgPath(pkgPath string, remoteOverrides map[string]string) (string, error) { + parts := strings.Split(pkgPath, "/") + if len(parts) < 2 { + return "", fmt.Errorf("bad pkg path %q", pkgPath) + } + domain := parts[0] + + if override, ok := remoteOverrides[domain]; ok { + return override, nil + } + + // XXX: retrieve host/port from r/sys/zones. + rpcURL := fmt.Sprintf("https://rpc.%s:443", domain) + + return rpcURL, nil +} + +func qfile(c client.Client, pkgPath string) ([]byte, error) { + path := "vm/qfile" + data := []byte(pkgPath) + + qres, err := c.ABCIQuery(path, data) + if err != nil { + return nil, fmt.Errorf("query qfile: %w", err) + } + if qres.Response.Error != nil { + return nil, fmt.Errorf("qfile failed: %w\n%s", qres.Response.Error, qres.Response.Log) + } + + return qres.Response.Data, nil +} diff --git a/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher_test.go b/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher_test.go new file mode 100644 index 00000000000..56db5b796de --- /dev/null +++ b/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher/rpcpkgfetcher_test.go @@ -0,0 +1,53 @@ +package rpcpkgfetcher + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestRpcURLFromPkgPath(t *testing.T) { + cases := []struct { + name string + pkgPath string + overrides map[string]string + result string + errorContains string + }{ + { + name: "happy path simple", + pkgPath: "gno.land/p/demo/avl", + result: "https://rpc.gno.land:443", + }, + { + name: "happy path override", + pkgPath: "gno.land/p/demo/avl", + overrides: map[string]string{"gno.land": "https://example.com/rpc:42"}, + result: "https://example.com/rpc:42", + }, + { + name: "happy path override no effect", + pkgPath: "gno.land/p/demo/avl", + overrides: map[string]string{"some.chain": "https://example.com/rpc:42"}, + result: "https://rpc.gno.land:443", + }, + { + name: "error bad pkg path", + pkgPath: "std", + result: "", + errorContains: `bad pkg path "std"`, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + res, err := rpcURLFromPkgPath(c.pkgPath, c.overrides) + if len(c.errorContains) == 0 { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, c.errorContains) + } + require.Equal(t, c.result, res) + }) + } +} diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index ef35cf9af83..6d5399ca932 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -102,7 +102,7 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error { targetPath = filepath.Dir(pkgPath) } - memPkg := gno.ReadMemPackage(targetPath, targetPath) + memPkg := gno.MustReadMemPackage(targetPath, targetPath) tm := test.Machine(testStore, stdout, memPkg.Path) defer tm.Release() diff --git a/gnovm/cmd/gno/main_test.go b/gnovm/cmd/gno/main_test.go index 76c67f6807b..2ea3e31f977 100644 --- a/gnovm/cmd/gno/main_test.go +++ b/gnovm/cmd/gno/main_test.go @@ -9,9 +9,9 @@ import ( "strings" "testing" - "github.com/stretchr/testify/require" - + "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload/examplespkgfetcher" "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/stretchr/testify/require" ) func TestMain_Gno(t *testing.T) { @@ -60,10 +60,7 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { mockErr := bytes.NewBufferString("") if !test.noTmpGnohome { - tmpGnoHome, err := os.MkdirTemp(os.TempDir(), "gnotesthome_") - require.NoError(t, err) - t.Cleanup(func() { os.RemoveAll(tmpGnoHome) }) - t.Setenv("GNOHOME", tmpGnoHome) + t.Setenv("GNOHOME", t.TempDir()) } checkOutputs := func(t *testing.T) { @@ -131,6 +128,8 @@ func testMainCaseRun(t *testing.T, tc []testMainCase) { io.SetOut(commands.WriteNopCloser(mockOut)) io.SetErr(commands.WriteNopCloser(mockErr)) + testPackageFetcher = examplespkgfetcher.New() + err := newGnocliCmd(io).ParseAndRun(context.Background(), test.args) if errShouldBeEmpty { diff --git a/gnovm/cmd/gno/mod.go b/gnovm/cmd/gno/mod.go index 67af5631c71..f762b070fe4 100644 --- a/gnovm/cmd/gno/mod.go +++ b/gnovm/cmd/gno/mod.go @@ -4,19 +4,22 @@ import ( "context" "flag" "fmt" - "go/parser" - "go/token" "os" "path/filepath" - "sort" "strings" + "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload" + "github.com/gnolang/gno/gnovm/cmd/gno/internal/pkgdownload/rpcpkgfetcher" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/packages" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "go.uber.org/multierr" ) +// testPackageFetcher allows to override the package fetcher during tests. +var testPackageFetcher pkgdownload.PackageFetcher + func newModCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ @@ -123,23 +126,17 @@ For example: } type modDownloadCfg struct { - remote string - verbose bool + remoteOverrides string } +const remoteOverridesArgName = "remote-overrides" + func (c *modDownloadCfg) RegisterFlags(fs *flag.FlagSet) { fs.StringVar( - &c.remote, - "remote", - "gno.land:26657", - "remote for fetching gno modules", - ) - - fs.BoolVar( - &c.verbose, - "v", - false, - "verbose output when running", + &c.remoteOverrides, + remoteOverridesArgName, + "", + "chain-domain=rpc-url comma-separated list", ) } @@ -148,6 +145,17 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { return flag.ErrHelp } + fetcher := testPackageFetcher + if fetcher == nil { + remoteOverrides, err := parseRemoteOverrides(cfg.remoteOverrides) + if err != nil { + return fmt.Errorf("invalid %s flag: %w", remoteOverridesArgName, err) + } + fetcher = rpcpkgfetcher.New(remoteOverrides) + } else if len(cfg.remoteOverrides) != 0 { + return fmt.Errorf("can't use %s flag with a custom package fetcher", remoteOverridesArgName) + } + path, err := os.Getwd() if err != nil { return err @@ -176,23 +184,26 @@ func execModDownload(cfg *modDownloadCfg, args []string, io commands.IO) error { return fmt.Errorf("validate: %w", err) } - // fetch dependencies - if err := gnoMod.FetchDeps(gnomod.ModCachePath(), cfg.remote, cfg.verbose); err != nil { - return fmt.Errorf("fetch: %w", err) + if err := downloadDeps(io, path, gnoMod, fetcher); err != nil { + return err } - gomod, err := gnomod.GnoToGoMod(*gnoMod) - if err != nil { - return fmt.Errorf("sanitize: %w", err) - } + return nil +} - // write go.mod file - err = gomod.Write(filepath.Join(path, "go.mod")) - if err != nil { - return fmt.Errorf("write go.mod file: %w", err) +func parseRemoteOverrides(arg string) (map[string]string, error) { + pairs := strings.Split(arg, ",") + res := make(map[string]string, len(pairs)) + for _, pair := range pairs { + parts := strings.Split(pair, "=") + if len(parts) != 2 { + return nil, fmt.Errorf("expected 2 parts in chain-domain=rpc-url pair %q", arg) + } + domain := strings.TrimSpace(parts[0]) + rpcURL := strings.TrimSpace(parts[1]) + res[domain] = rpcURL } - - return nil + return res, nil } func execModInit(args []string) error { @@ -276,26 +287,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 } @@ -366,79 +357,22 @@ func getImportToFilesMap(pkgPath string) (map[string][]string, error) { if strings.HasSuffix(filename, "_filetest.gno") { continue } - imports, err := getGnoFileImports(filepath.Join(pkgPath, filename)) + + data, err := os.ReadFile(filepath.Join(pkgPath, filename)) if err != nil { return nil, err } - - for _, imp := range imports { - m[imp] = append(m[imp], filename) - } - } - 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)) + imports, _, err := packages.FileImports(filename, string(data)) if err != nil { return nil, err } - for _, im := range imports { - if !strings.HasPrefix(im, "gno.land/") { - continue - } - if _, ok := seen[im]; ok { - continue + + for _, imp := range imports { + if imp.Error != nil { + return nil, err } - allImports = append(allImports, im) - seen[im] = struct{}{} + m[imp.PkgPath] = append(m[imp.PkgPath], filename) } } - 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 + return m, nil } diff --git a/gnovm/cmd/gno/mod_test.go b/gnovm/cmd/gno/mod_test.go index d35ab311b6c..afce25597cd 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) { @@ -44,24 +39,19 @@ func TestModApp(t *testing.T) { args: []string{"mod", "download"}, testDir: "../../tests/integ/require_remote_module", simulateExternalRepo: 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", + stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", + errShouldContain: "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", }, { args: []string{"mod", "download"}, @@ -72,12 +62,14 @@ func TestModApp(t *testing.T) { args: []string{"mod", "download"}, testDir: "../../tests/integ/replace_with_module", simulateExternalRepo: 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", + stderrShouldContain: "gno: downloading gno.land/p/demo/notexists", + 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 @@ -158,12 +150,6 @@ func TestModApp(t *testing.T) { simulateExternalRepo: 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", @@ -179,12 +165,6 @@ func TestModApp(t *testing.T) { testDir: "../../tests/integ/valid2", simulateExternalRepo: true, }, - { - args: []string{"mod", "tidy"}, - testDir: "../../tests/integ/invalid_gno_file", - simulateExternalRepo: true, - errShouldContain: "expected 'package', found packag", - }, // test `gno mod why` { @@ -199,12 +179,6 @@ func TestModApp(t *testing.T) { simulateExternalRepo: 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", @@ -239,122 +213,6 @@ 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]) - } + testMainCaseRun(t, tc) } diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 511a704dd7d..fec0de7c221 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -209,7 +209,7 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { } } - memPkg := gno.ReadMemPackage(pkg.Dir, gnoPkgPath) + memPkg := gno.MustReadMemPackage(pkg.Dir, gnoPkgPath) startedAt := time.Now() hasError := catchRuntimeError(gnoPkgPath, io.Err(), func() { diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index 19d312f6826..eadbec7d464 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -9,10 +9,15 @@ import ( "os" "path" "path/filepath" + "slices" "sort" "strings" + "github.com/gnolang/gno/gnovm" + "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" + "github.com/gnolang/gno/gnovm/pkg/packages" + "golang.org/x/mod/module" ) // A bfsDir describes a directory holding code by specifying @@ -60,25 +65,27 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { dir: mdir, importPath: gm.Module.Mod.Path, }) - roots = append(roots, getGnoModDirs(gm)...) + roots = append(roots, getGnoModDirs(gm, mdir)...) } go d.walk(roots) return d } -func getGnoModDirs(gm *gnomod.File) []bfsDir { +func getGnoModDirs(gm *gnomod.File, root string) []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) + imports := packageImportsRecursive(root, gm.Module.Mod.Path) + + 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 { // 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) + log.Println("open source directories from import:", err) } continue } @@ -91,6 +98,45 @@ func getGnoModDirs(gm *gnomod.File) []bfsDir { return dirs } +func packageImportsRecursive(root string, pkgPath string) []string { + pkg, err := gnolang.ReadMemPackage(root, pkgPath) + if err != nil { + // ignore invalid packages + pkg = &gnovm.MemPackage{} + } + + res, err := packages.Imports(pkg) + if err != nil { + // ignore packages with invalid imports + res = nil + } + + entries, err := os.ReadDir(root) + if err != nil { + // ignore unreadable dirs + entries = nil + } + + for _, entry := range entries { + if !entry.IsDir() { + continue + } + + dirName := entry.Name() + sub := packageImportsRecursive(filepath.Join(root, dirName), path.Join(pkgPath, dirName)) + + 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/doc/dirs_test.go b/gnovm/pkg/doc/dirs_test.go index 8659f3cbfcb..3139298a7ae 100644 --- a/gnovm/pkg/doc/dirs_test.go +++ b/gnovm/pkg/doc/dirs_test.go @@ -63,18 +63,9 @@ 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") - os.Setenv("GNO_HOME", wdJoin(t, "testdata/dirsdep")) - - t.Cleanup(func() { - if ex { - os.Setenv("GNO_HOME", old) - } else { - os.Unsetenv("GNO_HOME") - } - }) + t.Setenv("GNOHOME", wdJoin(t, "testdata/dirsdep")) return wdJoin(t, "testdata"), newDirs([]string{wdJoin(t, "testdata/dirs")}, []string{wdJoin(t, "testdata/dirsmod")}) 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/gnolang/files_test.go b/gnovm/pkg/gnolang/files_test.go index 09be600b198..2c82f6d8f29 100644 --- a/gnovm/pkg/gnolang/files_test.go +++ b/gnovm/pkg/gnolang/files_test.go @@ -138,7 +138,7 @@ func TestStdlibs(t *testing.T) { } fp := filepath.Join(dir, path) - memPkg := gnolang.ReadMemPackage(fp, path) + memPkg := gnolang.MustReadMemPackage(fp, path) t.Run(strings.ReplaceAll(memPkg.Path, "/", "-"), func(t *testing.T) { capture, opts := sharedCapture, sharedOpts switch memPkg.Path { diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 3368c7c7bde..8d3d6d8a2cc 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1132,14 +1132,23 @@ type FileSet struct { // PackageNameFromFileBody extracts the package name from the given Gno code body. // The 'name' parameter is used for better error traces, and 'body' contains the Gno code. -func PackageNameFromFileBody(name, body string) Name { +func PackageNameFromFileBody(name, body string) (Name, error) { fset := token.NewFileSet() astFile, err := parser.ParseFile(fset, name, body, parser.PackageClauseOnly) if err != nil { - panic(err) + return "", err } - return Name(astFile.Name.Name) + return Name(astFile.Name.Name), nil +} + +// MustPackageNameFromFileBody is a wrapper around [PackageNameFromFileBody] that panics on error. +func MustPackageNameFromFileBody(name, body string) Name { + pkgName, err := PackageNameFromFileBody(name, body) + if err != nil { + panic(err) + } + return pkgName } // ReadMemPackage initializes a new MemPackage by reading the OS directory @@ -1152,10 +1161,10 @@ func PackageNameFromFileBody(name, body string) Name { // // NOTE: panics if package name is invalid (characters must be alphanumeric or _, // lowercase, and must start with a letter). -func ReadMemPackage(dir string, pkgPath string) *gnovm.MemPackage { +func ReadMemPackage(dir string, pkgPath string) (*gnovm.MemPackage, error) { files, err := os.ReadDir(dir) if err != nil { - panic(err) + return nil, err } allowedFiles := []string{ // make case insensitive? "LICENSE", @@ -1186,24 +1195,36 @@ func ReadMemPackage(dir string, pkgPath string) *gnovm.MemPackage { return ReadMemPackageFromList(list, pkgPath) } +// MustReadMemPackage is a wrapper around [ReadMemPackage] that panics on error. +func MustReadMemPackage(dir string, pkgPath string) *gnovm.MemPackage { + pkg, err := ReadMemPackage(dir, pkgPath) + if err != nil { + panic(err) + } + return pkg +} + // ReadMemPackageFromList creates a new [gnovm.MemPackage] with the specified pkgPath, // containing the contents of all the files provided in the list slice. // No parsing or validation is done on the filenames. // -// NOTE: panics if package name is invalid (characters must be alphanumeric or _, +// NOTE: errors out if package name is invalid (characters must be alphanumeric or _, // lowercase, and must start with a letter). -func ReadMemPackageFromList(list []string, pkgPath string) *gnovm.MemPackage { +func ReadMemPackageFromList(list []string, pkgPath string) (*gnovm.MemPackage, error) { memPkg := &gnovm.MemPackage{Path: pkgPath} var pkgName Name for _, fpath := range list { fname := filepath.Base(fpath) bz, err := os.ReadFile(fpath) if err != nil { - panic(err) + return nil, err } // XXX: should check that all pkg names are the same (else package is invalid) if pkgName == "" && strings.HasSuffix(fname, ".gno") { - pkgName = PackageNameFromFileBody(fname, string(bz)) + pkgName, err = PackageNameFromFileBody(fname, string(bz)) + if err != nil { + return nil, err + } if strings.HasSuffix(string(pkgName), "_test") { pkgName = pkgName[:len(pkgName)-len("_test")] } @@ -1217,11 +1238,22 @@ func ReadMemPackageFromList(list []string, pkgPath string) *gnovm.MemPackage { // If no .gno files are present, package simply does not exist. if !memPkg.IsEmpty() { - validatePkgName(string(pkgName)) + if err := validatePkgName(string(pkgName)); err != nil { + return nil, err + } memPkg.Name = string(pkgName) } - return memPkg + return memPkg, nil +} + +// MustReadMemPackageFromList is a wrapper around [ReadMemPackageFromList] that panics on error. +func MustReadMemPackageFromList(list []string, pkgPath string) *gnovm.MemPackage { + pkg, err := ReadMemPackageFromList(list, pkgPath) + if err != nil { + panic(err) + } + return pkg } // ParseMemPackage executes [ParseFile] on each file of the memPkg, excluding @@ -2140,10 +2172,11 @@ var rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]+$`) // TODO: consider length restrictions. // If this function is changed, ReadMemPackage's documentation should be updated accordingly. -func validatePkgName(name string) { +func validatePkgName(name string) error { if !rePkgName.MatchString(name) { - panic(fmt.Sprintf("cannot create package with invalid name %q", name)) + return fmt.Errorf("cannot create package with invalid name %q", name) } + return nil } const hiddenResultVariable = ".res_" 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/file.go b/gnovm/pkg/gnomod/file.go index b6ee95acac8..a1c77b51e45 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 { @@ -136,76 +82,17 @@ 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 { + if f == nil { + return m + } + mod, replaced := isReplaced(m, f.Replace) if replaced { return mod } - 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 + return m } // writes file to the given absolute file path @@ -220,5 +107,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 9384c41c293..a34caa2e48d 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -3,22 +3,16 @@ 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" - "github.com/gnolang/gno/gnovm/pkg/transpiler" "golang.org/x/mod/modfile" "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") @@ -27,127 +21,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) -} - -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 -} - -// 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 := ModCachePath() - - 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 - } - } - 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 + return filepath.Join(root, filepath.FromSlash(v.Path)) } func CreateGnoModFile(rootDir, modPath string) error { @@ -180,7 +57,7 @@ func CreateGnoModFile(rootDir, modPath string) error { return fmt.Errorf("read file %q: %w", fpath, err) } - pn := gnolang.PackageNameFromFileBody(file.Name(), string(bz)) + pn := gnolang.MustPackageNameFromFileBody(file.Name(), string(bz)) if strings.HasSuffix(string(pkgName), "_test") { pkgName = pkgName[:len(pkgName)-len("_test")] } @@ -217,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/parse.go b/gnovm/pkg/gnomod/parse.go index a6314d5729f..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,26 +180,6 @@ 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, - }) - 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 61aaa83482b..ec54c6424fc 100644 --- a/gnovm/pkg/gnomod/parse_test.go +++ b/gnovm/pkg/gnomod/parse_test.go @@ -194,16 +194,29 @@ 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: "error validating gno.mod file at", + errShouldContain: "unknown directive: require", }, } { t.Run(tc.desc, func(t *testing.T) { diff --git a/gnovm/pkg/gnomod/pkg.go b/gnovm/pkg/gnomod/pkg.go index f6fe7f60301..35f52e3dded 100644 --- a/gnovm/pkg/gnomod/pkg.go +++ b/gnovm/pkg/gnomod/pkg.go @@ -5,14 +5,19 @@ import ( "io/fs" "os" "path/filepath" + "slices" "strings" + + "github.com/gnolang/gno/gnovm" + "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/packages" ) 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 // direct imports of this pkg + Draft bool // whether the package is a draft } type SubPkg struct { @@ -60,10 +65,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 +78,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) } } @@ -111,17 +116,28 @@ func ListPkgs(root string) (PkgList, error) { return fmt.Errorf("validate: %w", err) } + pkg, err := gnolang.ReadMemPackage(path, gnoMod.Module.Mod.Path) + if err != nil { + // ignore package files on error + pkg = &gnovm.MemPackage{} + } + + imports, err := packages.Imports(pkg) + if err != nil { + // ignore imports on error + imports = []string{} + } + + // remove self and standard libraries from imports + imports = slices.DeleteFunc(imports, func(imp string) bool { + return imp == gnoMod.Module.Mod.Path || gnolang.IsStdlib(imp) + }) + pkgs = append(pkgs, Pkg{ - 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) - } - return reqs - }(), + Dir: path, + Name: gnoMod.Module.Mod.Path, + Draft: gnoMod.Draft, + Imports: imports, }) return nil }) @@ -144,7 +160,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..df6910f769b 100644 --- a/gnovm/pkg/gnomod/preprocess.go +++ b/gnovm/pkg/gnomod/preprocess.go @@ -3,50 +3,15 @@ package gnomod import ( "golang.org/x/mod/modfile" "golang.org/x/mod/module" - "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) } } -// 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..bb03ddf6efd 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)") } @@ -862,60 +856,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 -// 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 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) { diff --git a/gnovm/pkg/packages/doc.go b/gnovm/pkg/packages/doc.go new file mode 100644 index 00000000000..fb63ae3838e --- /dev/null +++ b/gnovm/pkg/packages/doc.go @@ -0,0 +1,2 @@ +// Package packages provides utility functions to statically analyze Gno MemPackages +package packages diff --git a/gnovm/pkg/packages/imports.go b/gnovm/pkg/packages/imports.go new file mode 100644 index 00000000000..e72f37276db --- /dev/null +++ b/gnovm/pkg/packages/imports.go @@ -0,0 +1,72 @@ +package packages + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "sort" + "strconv" + "strings" + + "github.com/gnolang/gno/gnovm" +) + +// Imports returns the list of gno imports from a [gnovm.MemPackage]. +func Imports(pkg *gnovm.MemPackage) ([]string, error) { + allImports := make([]string, 0) + seen := make(map[string]struct{}) + for _, file := range pkg.Files { + if !strings.HasSuffix(file.Name, ".gno") { + continue + } + if strings.HasSuffix(file.Name, "_filetest.gno") { + continue + } + imports, _, err := FileImports(file.Name, file.Body) + if err != nil { + return nil, err + } + for _, im := range imports { + if im.Error != nil { + return nil, err + } + if _, ok := seen[im.PkgPath]; ok { + continue + } + allImports = append(allImports, im.PkgPath) + seen[im.PkgPath] = struct{}{} + } + } + sort.Strings(allImports) + + return allImports, nil +} + +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 string) ([]*FileImport, *token.FileSet, error) { + fs := token.NewFileSet() + f, err := parser.ParseFile(fs, filename, src, parser.ImportsOnly) + if err != nil { + return nil, nil, err + } + 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 { + fi.Error = fmt.Errorf("%v: unexpected invalid import path: %v", fs.Position(im.Pos()).String(), im.Path.Value) + } else { + fi.PkgPath = importPath + } + res[i] = &fi + } + return res, fs, nil +} diff --git a/gnovm/pkg/packages/imports_test.go b/gnovm/pkg/packages/imports_test.go new file mode 100644 index 00000000000..14808dcbd6f --- /dev/null +++ b/gnovm/pkg/packages/imports_test.go @@ -0,0 +1,127 @@ +package packages + +import ( + "os" + "path/filepath" + "testing" + + "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/stretchr/testify/require" +) + +func TestImports(t *testing.T) { + workingDir, err := os.Getwd() + require.NoError(t, err) + + // create external dir + tmpDir := t.TempDir() + + // 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", + "std", + "testing", + } + + // 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) + } + + pkg, err := gnolang.ReadMemPackage(tmpDir, "test") + require.NoError(t, err) + imports, err := Imports(pkg) + require.NoError(t, err) + + require.Equal(t, expected, imports) +} diff --git a/gnovm/pkg/test/imports.go b/gnovm/pkg/test/imports.go index b57fc6388b1..731bf9756dd 100644 --- a/gnovm/pkg/test/imports.go +++ b/gnovm/pkg/test/imports.go @@ -4,18 +4,16 @@ import ( "encoding/json" "errors" "fmt" - "go/parser" - "go/token" "io" "math/big" "os" "path/filepath" "runtime/debug" - "strconv" "strings" "time" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" + "github.com/gnolang/gno/gnovm/pkg/packages" teststdlibs "github.com/gnolang/gno/gnovm/tests/stdlibs" teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" "github.com/gnolang/gno/tm2/pkg/db/memdb" @@ -45,7 +43,7 @@ func Store( const testPath = "github.com/gnolang/gno/_test/" if strings.HasPrefix(pkgPath, testPath) { baseDir := filepath.Join(rootDir, "gnovm", "tests", "files", "extern", pkgPath[len(testPath):]) - memPkg := gno.ReadMemPackage(baseDir, pkgPath) + memPkg := gno.MustReadMemPackage(baseDir, pkgPath) send := std.Coins{} ctx := Context(pkgPath, send) m2 := gno.NewMachineWithOptions(gno.MachineOptions{ @@ -137,7 +135,7 @@ func Store( // if examples package... examplePath := filepath.Join(rootDir, "examples", pkgPath) if osm.DirExists(examplePath) { - memPkg := gno.ReadMemPackage(examplePath, pkgPath) + memPkg := gno.MustReadMemPackage(examplePath, pkgPath) if memPkg.IsEmpty() { panic(fmt.Sprintf("found an empty package %q", pkgPath)) } @@ -193,7 +191,7 @@ func loadStdlib(rootDir, pkgPath string, store gno.Store, stdout io.Writer) (*gn return nil, nil } - memPkg := gno.ReadMemPackageFromList(files, pkgPath) + memPkg := gno.MustReadMemPackageFromList(files, pkgPath) m2 := gno.NewMachineWithOptions(gno.MachineOptions{ // NOTE: see also pkgs/sdk/vm/builtins.go // Needs PkgPath != its name because TestStore.getPackage is the package @@ -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 := packages.FileImports(filename, string(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 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 diff --git a/misc/loop/go.mod b/misc/loop/go.mod index f1c09cd9f82..a6bbdad3c82 100644 --- a/misc/loop/go.mod +++ b/misc/loop/go.mod @@ -73,7 +73,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