Skip to content

Commit

Permalink
Merge branch 'main' into feat/config-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Pantani authored May 13, 2024
2 parents 90604ef + 8682f3e commit 9c00e42
Show file tree
Hide file tree
Showing 31 changed files with 414 additions and 407 deletions.
5 changes: 4 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Features

- [#3707](https://github.com/ignite/cli/pull/3707) Add collections support.
- [#3707](https://github.com/ignite/cli/pull/3707) and [#4094](https://github.com/ignite/cli/pull/4094) Add collections support.
- [#3977](https://github.com/ignite/cli/pull/3977) Add `chain lint` command to lint the chain's codebase using `golangci-lint`
- [#3770](https://github.com/ignite/cli/pull/3770) Add `scaffold configs` and `scaffold params` commands
- [#4001](https://github.com/ignite/cli/pull/4001) Improve `xgenny` dry run
Expand All @@ -18,9 +18,11 @@
- [#4110](https://github.com/ignite/cli/pull/4110) Scaffold a consumer chain with `interchain-security` v5.0.0-rc0.
- [#4111](https://github.com/ignite/cli/pull/4111) Remove vuex generation
- [#4113](https://github.com/ignite/cli/pull/4113) Generate chain config documentation automatically #4113
- [#4117](https://github.com/ignite/cli/pull/4117), [#4125](https://github.com/ignite/cli/pull/4125) Support relative path when installing local plugins

### Changes

- [#4094](https://github.com/ignite/cli/pull/4094) Scaffolding a multi-index map using `ignite s map foo bar baz --index foobar,foobaz` is no longer supported. Use one index instead of use `collections.IndexedMap`.
- [#4058](https://github.com/ignite/cli/pull/4058) Simplify scaffolded modules by including `ValidateBasic()` logic in message handler.
- [#4058](https://github.com/ignite/cli/pull/4058) Use `address.Codec` instead of `AccAddressFromBech32`.
- [#3993](https://github.com/ignite/cli/pull/3993) Oracle scaffolding was deprecated and has been removed
Expand All @@ -39,6 +41,7 @@
- [#4086](https://github.com/ignite/cli/pull/4086) Retry to get the IBC balance if it fails the first time
- [#4091](https://github.com/ignite/cli/pull/4091) Fix race conditions in the plugin logic
- [#4096](https://github.com/ignite/cli/pull/4096) Add new reserved names module and remove duplicated genesis order
- [#4128](https://github.com/ignite/cli/pull/4128) Check for duplicate proto fields in config

## [`v28.3.0`](https://github.com/ignite/cli/releases/tag/v28.3.0)

Expand Down
19 changes: 5 additions & 14 deletions ignite/cmd/scaffold_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import (
"github.com/ignite/cli/v29/ignite/services/scaffolder"
)

const (
FlagIndexes = "index"
)
const FlagIndexName = "index"

// NewScaffoldMap returns a new command to scaffold a map.
func NewScaffoldMap() *cobra.Command {
Expand Down Expand Up @@ -42,14 +40,7 @@ for the "hello" key.
blogd q blog show-post hello
To customize the index, use the "--index" flag. Multiple indices can be
provided, which simplifies querying values. For example:
ignite scaffold map product price desc --index category,guid
With this command, you would get a "Product" value indexed by both a category
and a GUID (globally unique ID). This will let you programmatically fetch
product values that have the same category but are using different GUIDs.
By default, the index is called "index", to customize the index, use the "--index" flag.
Since the behavior of "list" and "map" scaffolding is very similar, you can use
the "--no-message", "--module", "--signer" flags as well as the colon syntax for
Expand All @@ -67,12 +58,12 @@ For detailed type information use ignite scaffold type --help

c.Flags().AddFlagSet(flagSetYes())
c.Flags().AddFlagSet(flagSetScaffoldType())
c.Flags().StringSlice(FlagIndexes, []string{"index"}, "fields that index the value")
c.Flags().String(FlagIndexName, "index", "field that index the value")

return c
}

func scaffoldMapHandler(cmd *cobra.Command, args []string) error {
indexes, _ := cmd.Flags().GetStringSlice(FlagIndexes)
return scaffoldType(cmd, args, scaffolder.MapType(indexes...))
index, _ := cmd.Flags().GetString(FlagIndexName)
return scaffoldType(cmd, args, scaffolder.MapType(index))
}
9 changes: 7 additions & 2 deletions ignite/config/plugins/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package plugins

import (
"os"
"slices"
"strings"

"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"

"github.com/ignite/cli/v29/ignite/pkg/errors"
Expand Down Expand Up @@ -76,14 +76,19 @@ func RemoveDuplicates(plugins []Plugin) (unique []Plugin) {
return unique
}

// IsLocalPath returns true if the path is a local directory.
func IsLocalPath(path string) bool {
return strings.HasPrefix(path, "/") || strings.HasPrefix(path, ".") || strings.HasPrefix(path, "~")
}

// IsGlobal returns whether the plugin is installed globally or locally for a chain.
func (p Plugin) IsGlobal() bool {
return p.Global
}

// IsLocalPath returns true if the plugin path is a local directory.
func (p Plugin) IsLocalPath() bool {
return strings.HasPrefix(p.Path, "/")
return IsLocalPath(p.Path)
}

// HasPath verifies if a plugin has the given path regardless of version.
Expand Down
2 changes: 2 additions & 0 deletions ignite/config/plugins/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func TestPluginIsLocalPath(t *testing.T) {
assert.False(t, pluginsconfig.Plugin{}.IsLocalPath())
assert.False(t, pluginsconfig.Plugin{Path: "github.com/ignite/example"}.IsLocalPath())
assert.True(t, pluginsconfig.Plugin{Path: "/home/bob/example"}.IsLocalPath())
assert.True(t, pluginsconfig.Plugin{Path: "./example"}.IsLocalPath())
assert.True(t, pluginsconfig.Plugin{Path: "../example"}.IsLocalPath())
}

func TestPluginHasPath(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions ignite/pkg/cosmosver/cosmosver.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var (
StargateFortyFourVersion,
StargateFortyFiveThreeVersion,
StargateFortySevenTwoVersion,
StargateFiftyVersion,
}

// Latest is the latest known version of the Cosmos-SDK.
Expand Down
90 changes: 77 additions & 13 deletions ignite/pkg/protoanalysis/protoutil/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func AddAfterPackage(f *proto.Proto, v proto.Visitee) error {
if inserted {
return nil
}
return errors.New("could not find package statement")
return errors.New("could not find proto package statement")
}

// Fallback logic, try and use import after a package and if that fails
Expand Down Expand Up @@ -118,7 +118,7 @@ func AddImports(f *proto.Proto, fallback bool, imports ...*proto.Import) (err er
// recurse with the rest. (might be empty)
return AddImports(f, false, imports[1:]...)
}
return errors.New("unable to add import, no import statements found")
return errors.New("unable to add proto import, no import statements found")
}

// NextUniqueID goes through the fields of the given Message and returns
Expand Down Expand Up @@ -180,10 +180,11 @@ func GetMessageByName(f *proto.Proto, name string) (node *proto.Message, err err
},
// return immediately iff found.
func(*Cursor) bool { return !found })

if found {
return
}
return nil, errors.Errorf("message %s not found", name)
return nil, errors.Errorf("proto message %s not found", name)
}

// GetServiceByName returns the service with the given name or nil if not found.
Expand All @@ -192,8 +193,12 @@ func GetMessageByName(f *proto.Proto, name string) (node *proto.Message, err err
// f, _ := ParseProtoPath("foo.proto")
// s := GetServiceByName(f, "FooSrv")
// s.Name // "FooSrv"
func GetServiceByName(f *proto.Proto, name string) (node *proto.Service, err error) {
node, err = nil, nil
func GetServiceByName(f *proto.Proto, name string) (*proto.Service, error) {
var (
node *proto.Service
err error
)

found := false
Apply(f,
func(c *Cursor) bool {
Expand All @@ -209,12 +214,15 @@ func GetServiceByName(f *proto.Proto, name string) (node *proto.Service, err err
_, ok := c.Node().(*proto.Proto)
return ok
},

// return immediately iff found.
func(*Cursor) bool { return !found })
func(*Cursor) bool { return !found },
)
if found {
return
return node, err
}
return nil, errors.Errorf("service %s not found", name)

return nil, errors.Errorf("proto service %s not found", name)
}

// GetImportByPath returns the import with the given path or nil if not found.
Expand All @@ -223,9 +231,13 @@ func GetServiceByName(f *proto.Proto, name string) (node *proto.Service, err err
// f, _ := ParseProtoPath("foo.proto")
// s := GetImportByPath(f, "other.proto")
// s.FileName // "other.proto"
func GetImportByPath(f *proto.Proto, path string) (node *proto.Import, err error) {
func GetImportByPath(f *proto.Proto, path string) (*proto.Import, error) {
var (
node *proto.Import
err error
)

found := false
node, err = nil, nil
Apply(f,
func(c *Cursor) bool {
if i, ok := c.Node().(*proto.Import); ok {
Expand All @@ -240,12 +252,54 @@ func GetImportByPath(f *proto.Proto, path string) (node *proto.Import, err error
_, ok := c.Node().(*proto.Proto)
return ok
},

// return immediately iff found.
func(*Cursor) bool { return !found })
func(*Cursor) bool { return !found },
)
if found {
return
return node, err
}
return nil, errors.Errorf("import %s not found", path)

return nil, errors.Errorf("proto import %s not found", path)
}

// GetFieldByName returns the field with the given name or nil if not found within a message.
// Only traverses in proto.Message since they are the only nodes that contain fields:
//
// f, _ := ParseProtoPath("foo.proto")
// m := GetMessageByName(f, "Foo")
// f := GetFieldByName(m, "Bar")
// f.Name // "Bar"
func GetFieldByName(f *proto.Message, name string) (*proto.NormalField, error) {
var (
node *proto.NormalField
err error
)

found := false
Apply(f,
func(c *Cursor) bool {
if m, ok := c.Node().(*proto.NormalField); ok {
if m.Name == name {
found = true
node = m
return false
}
// keep looking if we're in a Message
return true
}
// keep looking while we're in a proto.Message.
_, ok := c.Node().(*proto.Message)
return ok
},
// return immediately iff found.
func(*Cursor) bool { return !found },
)
if found {
return node, err
}

return nil, errors.Errorf("proto field %s not found", name)
}

// HasMessage returns true if the given message is found in the given file.
Expand Down Expand Up @@ -277,3 +331,13 @@ func HasImport(f *proto.Proto, path string) bool {
_, err := GetImportByPath(f, path)
return err == nil
}

func HasField(f *proto.Proto, messageName, field string) bool {
msg, err := GetMessageByName(f, messageName)
if err != nil {
return false
}

_, err = GetFieldByName(msg, field)
return err == nil
}
2 changes: 1 addition & 1 deletion ignite/pkg/xstrings/xstrings.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package xstrings

import (
"slices"
"strings"
"unicode"

"golang.org/x/exp/slices" // TODO: replace with slices.Contains when it will be available in stdlib (1.21)
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
Expand Down
16 changes: 14 additions & 2 deletions ignite/services/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,19 @@ func newPlugin(pluginsDir string, cp pluginsconfig.Plugin, options ...Option) *P
apply(p)
}

if strings.HasPrefix(pluginPath, "/") {
// This is a local plugin, check if the file exists
// This is a local plugin, check if the file exists
if pluginsconfig.IsLocalPath(pluginPath) {
// if directory is relative, make it absolute
if !filepath.IsAbs(pluginPath) {
pluginPathAbs, err := filepath.Abs(pluginPath)
if err != nil {
p.Error = errors.Errorf("failed to get absolute path of %s: %w", pluginPath, err)
return p
}

pluginPath = pluginPathAbs
}

st, err := os.Stat(pluginPath)
if err != nil {
p.Error = errors.Wrapf(err, "local app path %q not found", pluginPath)
Expand All @@ -157,6 +168,7 @@ func newPlugin(pluginsDir string, cp pluginsconfig.Plugin, options ...Option) *P
p.name = path.Base(pluginPath)
return p
}

// This is a remote plugin, parse the URL
if i := strings.LastIndex(pluginPath, "@"); i != -1 {
// path contains a reference
Expand Down
10 changes: 10 additions & 0 deletions ignite/services/plugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ func TestNewPlugin(t *testing.T) {
stderr: os.Stderr,
},
},
{
name: "ok: relative local plugin",
pluginCfg: pluginsconfig.Plugin{Path: "./testdata"},
expectedPlugin: Plugin{
srcPath: path.Join(wd, "testdata"),
name: "testdata",
stdout: os.Stdout,
stderr: os.Stderr,
},
},
{
name: "fail: remote plugin with only domain",
pluginCfg: pluginsconfig.Plugin{Path: "github.com"},
Expand Down
Loading

0 comments on commit 9c00e42

Please sign in to comment.