mukan-ignite/ignite/cmd/cmd.go
Mukan Erkin Törük 26b204bd04
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
feat: fork Ignite CLI v29 as Mukan Ignite — remove cosmos-sdk restrictions
2026-05-11 03:31:37 +03:00

306 lines
8 KiB
Go

package ignitecmd
import (
"context"
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"time"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"github.com/ignite/cli/v29/ignite/config"
chainconfig "github.com/ignite/cli/v29/ignite/config/chain"
"github.com/ignite/cli/v29/ignite/internal/announcements"
"github.com/ignite/cli/v29/ignite/pkg/cache"
"github.com/ignite/cli/v29/ignite/pkg/cliui"
uilog "github.com/ignite/cli/v29/ignite/pkg/cliui/log"
"github.com/ignite/cli/v29/ignite/pkg/dircache"
"github.com/ignite/cli/v29/ignite/pkg/errors"
"github.com/ignite/cli/v29/ignite/pkg/goenv"
"github.com/ignite/cli/v29/ignite/pkg/gomodulepath"
"github.com/ignite/cli/v29/ignite/version"
)
type key int
const (
keyChainConfig key = iota
keyChainConfigPath key = iota
)
const (
flagPath = "path"
flagHome = "home"
flagYes = "yes"
flagClearCache = "clear-cache"
flagSkipProto = "skip-proto"
flagSkipBuild = "skip-build"
checkVersionTimeout = time.Millisecond * 600
cacheFileName = "ignite_cache.db"
statusGenerating = "Generating..."
statusImporting = "Importing..."
statusExporting = "Exporting..."
statusCreating = "Creating..."
statusDeleting = "Deleting..."
)
// List of CLI level one commands that should not load Ignite app instances.
var skipAppsLoadCommands = []string{"version", "help", "docs", "completion", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd}
// New creates a new root command for `Ignite CLI` with its sub commands.
// Returns the cobra.Command, a cleanup function and an error. The cleanup
// function must be invoked by the caller to clean eventual Ignite App instances.
func New(ctx context.Context) (*cobra.Command, func(), error) {
cobra.EnableCommandSorting = false
c := &cobra.Command{
Use: "ignite",
Short: "Ignite CLI offers everything you need to scaffold, test, build, and launch your blockchain",
Long: fmt.Sprintf(`Ignite CLI is a tool for creating sovereign blockchains built with Cosmos SDK, the world's
most popular modular blockchain framework. Ignite CLI offers everything you need to scaffold,
test, build, and launch your blockchain.
To get started, create a blockchain:
$ ignite scaffold chain example
%s`, announcements.Fetch()),
SilenceUsage: true,
SilenceErrors: true,
Args: cobra.MinimumNArgs(0), // note(@julienrbrt): without this, ignite __complete(noDesc) hidden commands are not working.
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
// Check for new versions only when shell completion scripts are not being
// generated to avoid invalid output to stdout when a new version is available
if cmd.Use != "completion" || !strings.HasPrefix(cmd.Use, cobra.ShellCompRequestCmd) {
checkNewVersion(cmd)
}
return goenv.ConfigurePath()
},
}
c.AddCommand(
NewScaffold(),
NewChain(),
NewGenerate(),
NewAccount(),
NewDocs(),
NewVersion(),
NewApp(),
NewDoctor(),
NewCompletionCmd(),
NewTestnet(),
)
c.AddCommand(deprecated()...)
c.SetContext(ctx)
// Don't load Ignite apps for level one commands that doesn't allow them
if len(os.Args) >= 2 && slices.Contains(skipAppsLoadCommands, os.Args[1]) {
return c, func() {}, nil
}
// Load plugins if any
session := cliui.New(cliui.WithStdout(os.Stdout))
if err := LoadPlugins(ctx, c, session); err != nil {
return nil, nil, errors.Errorf("error while loading apps: %w", err)
}
return c, func() {
UnloadPlugins()
session.End()
}, nil
}
func flagSetVerbose() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.BoolP(flagVerbose, "v", false, "verbose output")
return fs
}
func getVerbosity(cmd *cobra.Command) uilog.Verbosity {
if verbose, _ := cmd.Flags().GetBool(flagVerbose); verbose {
return uilog.VerbosityVerbose
}
return uilog.VerbosityDefault
}
func flagSetPath(cmd *cobra.Command) {
cmd.PersistentFlags().StringP(flagPath, "p", ".", "path of the app")
}
func flagGetPath(cmd *cobra.Command) (path string) {
path, _ = cmd.Flags().GetString(flagPath)
return
}
func goModulePath(cmd *cobra.Command) (string, error) {
path := flagGetPath(cmd)
path, err := filepath.Abs(path)
if err != nil {
return "", err
}
_, appPath, err := gomodulepath.Find(path)
if err != nil {
return "", err
}
return appPath, err
}
func flagSetHome() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.String(flagHome, "", "directory where the blockchain node is initialized")
return fs
}
func flagSetConfig() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.StringP(flagConfig, "c", "", "path to Ignite config file (default: ./config.yml)")
return fs
}
func getConfig(cmd *cobra.Command) (config string) {
config, _ = cmd.Flags().GetString(flagConfig)
return
}
func getChainConfig(cmd *cobra.Command) (*chainconfig.Config, string, error) {
cfg, ok := cmd.Context().Value(keyChainConfig).(*chainconfig.Config)
if ok {
configPath := cmd.Context().Value(keyChainConfigPath).(string)
return cfg, configPath, nil
}
configPath := getConfig(cmd)
path, err := goModulePath(cmd)
if err != nil {
return nil, "", err
}
if configPath == "" {
if configPath, err = chainconfig.LocateDefault(path); err != nil {
return nil, "", err
}
}
cfg, err = chainconfig.ParseFile(configPath)
if err != nil {
return nil, "", err
}
ctx := context.WithValue(cmd.Context(), keyChainConfig, cfg)
ctx = context.WithValue(ctx, keyChainConfigPath, configPath)
cmd.SetContext(ctx)
return cfg, configPath, err
}
func flagSetYes() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.BoolP(flagYes, "y", false, "answers interactive yes/no questions with yes")
return fs
}
func getYes(cmd *cobra.Command) (ok bool) {
ok, _ = cmd.Flags().GetBool(flagYes)
return
}
func flagSetSkipProto() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.Bool(flagSkipProto, false, "skip file generation from proto")
return fs
}
func flagGetSkipProto(cmd *cobra.Command) bool {
skip, _ := cmd.Flags().GetBool(flagSkipProto)
return skip
}
func flagSetSkipBuild() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.Bool(flagSkipBuild, false, "skip initial build of the app (uses local binary)")
return fs
}
func flagGetSkipBuild(cmd *cobra.Command) bool {
skip, _ := cmd.Flags().GetBool(flagSkipBuild)
return skip
}
func flagSetClearCache(cmd *cobra.Command) {
cmd.PersistentFlags().Bool(flagClearCache, false, "clear the build cache (advanced)")
}
func flagGetClearCache(cmd *cobra.Command) bool {
clearCache, _ := cmd.Flags().GetBool(flagClearCache)
return clearCache
}
func deprecated() []*cobra.Command {
return []*cobra.Command{
{
Use: "build",
Hidden: true,
Deprecated: "use `ignite chain build` instead.",
},
{
Use: "serve",
Hidden: true,
Deprecated: "use `ignite chain serve` instead.",
},
{
Use: "faucet",
Hidden: true,
Deprecated: "use `ignite chain faucet` instead.",
},
{
Use: "node",
Hidden: true,
Deprecated: "use ignite connect app instead (ignite app install -g github.com/ignite/apps/connect).",
},
}
}
func checkNewVersion(cmd *cobra.Command) {
ctx, cancel := context.WithTimeout(cmd.Context(), checkVersionTimeout)
defer cancel()
isAvailable, next, err := version.CheckNext(ctx)
if err != nil || !isAvailable {
return
}
cmd.Printf("⬆️ Ignite CLI %s is available! To upgrade: https://docs.ignite.com/welcome/install#upgrade (or use snap or homebrew)\n\n", next)
}
func newCache(cmd *cobra.Command) (cache.Storage, error) {
cacheRootDir, err := config.DirPath()
if err != nil {
return cache.Storage{}, err
}
storage, err := cache.NewStorage(
filepath.Join(cacheRootDir, cacheFileName),
cache.WithVersion(version.Version),
)
if err != nil {
return cache.Storage{}, err
}
if flagGetClearCache(cmd) {
if err := storage.Clear(); err != nil {
return cache.Storage{}, err
}
if err := dircache.ClearCache(); err != nil {
return cache.Storage{}, err
}
}
return storage, nil
}