Some checks are pending
Docs Deploy / build_and_deploy (push) Waiting to run
Generate Docs / cli (push) Waiting to run
Generate Config Doc / cli (push) Waiting to run
Go formatting / go-formatting (push) Waiting to run
Check links / markdown-link-check (push) Waiting to run
Integration / pre-test (push) Waiting to run
Integration / test on (push) Blocked by required conditions
Integration / status (push) Blocked by required conditions
Lint / Lint Go code (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
165 lines
4.1 KiB
Go
165 lines
4.1 KiB
Go
package ignitecmd
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/ignite/cli/v29/ignite/pkg/cliui"
|
|
"github.com/ignite/cli/v29/ignite/pkg/cosmosanalysis/app"
|
|
"github.com/ignite/cli/v29/ignite/pkg/gomodule"
|
|
"github.com/ignite/cli/v29/ignite/services/chain"
|
|
)
|
|
|
|
func NewChainModulesList() *cobra.Command {
|
|
c := &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all Cosmos SDK modules in the app",
|
|
Long: "The list command lists all modules in the app.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
session := cliui.New(cliui.StartSpinner())
|
|
defer session.End()
|
|
|
|
chainOption := []chain.Option{
|
|
chain.WithOutputer(session),
|
|
chain.CollectEvents(session.EventBus()),
|
|
}
|
|
|
|
c, err := chain.NewWithHomeFlags(cmd, chainOption...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
modules, err := app.FindRegisteredModules(c.AppPath())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(modules) == 0 {
|
|
session.Println("no modules found")
|
|
return nil
|
|
}
|
|
|
|
modFile, err := gomodule.ParseAt(c.AppPath())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
deps, err := gomodule.ResolveDependencies(modFile, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
depMap := make(map[string]string)
|
|
for _, dep := range deps {
|
|
depMap[dep.Path] = dep.Version
|
|
}
|
|
|
|
// create a map of replaced modules for easy lookup
|
|
// check the original required modules, not the resolved ones
|
|
replacedMap := make(map[string]bool)
|
|
for _, replace := range modFile.Replace {
|
|
replacedMap[replace.Old.Path] = true
|
|
}
|
|
|
|
// get the app's module path to identify app modules
|
|
appModulePath := modFile.Module.Mod.Path
|
|
|
|
var entries [][]string
|
|
for _, m := range modules {
|
|
ver := depMap[m]
|
|
modName := m
|
|
|
|
switch {
|
|
case strings.HasPrefix(m, appModulePath+"/"):
|
|
ver = "main"
|
|
case strings.HasPrefix(m, cosmosSDKModulePrefix+"/"):
|
|
ver = depMap[cosmosSDKModulePrefix]
|
|
modName = strings.TrimPrefix(m, cosmosSDKModulePrefix+"/")
|
|
case strings.Contains(m, ibcModulePrefix+"/v"):
|
|
modName, ver = getIBCVersion(m, depMap)
|
|
case isModuleReplaced(m, replacedMap):
|
|
ver = "locally replaced"
|
|
}
|
|
|
|
if ver == "" {
|
|
ver = findBestMatchingVersion(m, depMap)
|
|
if ver == "" {
|
|
ver = "-"
|
|
}
|
|
}
|
|
|
|
entries = append(entries, []string{modName, ver})
|
|
}
|
|
|
|
session.StopSpinner()
|
|
|
|
// Sort entries by module name
|
|
sort.SliceStable(entries, func(i, j int) bool {
|
|
return entries[i][0] < entries[j][0]
|
|
})
|
|
|
|
header := []string{"module", "version"}
|
|
return session.PrintTable(header, entries...)
|
|
},
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
const (
|
|
cosmosSDKModulePrefix = "github.com/cosmos/cosmos-sdk"
|
|
ibcModulePrefix = "github.com/cosmos/ibc-go"
|
|
)
|
|
|
|
// isModuleReplaced checks if a module path (or its parent paths) is in the replaced map.
|
|
func isModuleReplaced(modulePath string, replacedMap map[string]bool) bool {
|
|
checkPath := modulePath
|
|
for checkPath != "" && checkPath != "." {
|
|
if replacedMap[checkPath] {
|
|
return true
|
|
}
|
|
// check parent path
|
|
if idx := strings.LastIndex(checkPath, "/"); idx > 0 {
|
|
checkPath = checkPath[:idx]
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// for a given module path by checking progressively shorter paths.
|
|
func findBestMatchingVersion(modulePath string, depMap map[string]string) string {
|
|
checkPath := modulePath
|
|
for checkPath != "" && checkPath != "." {
|
|
if version, exists := depMap[checkPath]; exists {
|
|
return version
|
|
}
|
|
// check parent path
|
|
if idx := strings.LastIndex(checkPath, "/"); idx > 0 {
|
|
checkPath = checkPath[:idx]
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// getIBCVersion tries to extract the ibc-go version from the module path or dependencies.
|
|
func getIBCVersion(modulePath string, depMap map[string]string) (string, string) {
|
|
// find the root ibc-go module path (with major version)
|
|
parts := strings.Split(modulePath, "/")
|
|
for i := range parts {
|
|
if parts[i] == "ibc-go" && i+1 < len(parts) && strings.HasPrefix(parts[i+1], "v") {
|
|
root := strings.Join(parts[:i+2], "/")
|
|
ver := depMap[root]
|
|
// clean module name after root
|
|
mod := strings.TrimPrefix(modulePath, root+"/")
|
|
return mod, ver
|
|
}
|
|
}
|
|
return modulePath, ""
|
|
}
|