Skip to content

Commit

Permalink
cmd: app command should support dashes in app name (#26)
Browse files Browse the repository at this point in the history
* cmd: app command should support dashes in app name

also we now have a strict validation check for user given app name both
against go.mod module name rules and go package name rules for generated x/ pkg.

* Remove dashes from appName in startServe

* cmd/app: keep binary name same as the user give one

also refactor the parts related to handling user given app path/name.

* templates/app/templates/Makefile: rm dashes from conf dirs

Co-authored-by: Denis Fadeev <[email protected]>

Co-authored-by: Denis Fadeev <[email protected]>
  • Loading branch information
ilgooz and fadeev authored Jul 16, 2020
1 parent 36a43ae commit 02ccba7
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 30 deletions.
24 changes: 13 additions & 11 deletions cmd/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,33 @@ import (
"context"
"fmt"
"os"
"strings"

"github.com/gobuffalo/genny"
"github.com/spf13/cobra"
"github.com/tendermint/starport/pkg/gomodulepath"
"github.com/tendermint/starport/templates/app"
)

var appCmd = &cobra.Command{
Use: "app [github.com/org/repo]",
Short: "Generates an empty application",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
denom, _ := cmd.Flags().GetString("denom")
var appName string
if t := strings.Split(args[0], "/"); len(t) > 0 {
appName = t[len(t)-1]
RunE: func(cmd *cobra.Command, args []string) error {
path, err := gomodulepath.Parse(args[0])
if err != nil {
return err
}
denom, _ := cmd.Flags().GetString("denom")
g, _ := app.New(&app.Options{
ModulePath: args[0],
AppName: appName,
Denom: denom,
ModulePath: path.RawPath,
AppName: path.Package,
BinaryNamePrefix: path.Root,
Denom: denom,
})
run := genny.WetRunner(context.Background())
run.With(g)
pwd, _ := os.Getwd()
run.Root = pwd + "/" + appName
run.Root = pwd + "/" + path.Root
run.Run()
message := `
⭐️ Successfully created a Cosmos app '%[1]v'.
Expand All @@ -40,6 +41,7 @@ var appCmd = &cobra.Command{
NOTE: add -v flag for advanced use.
`
fmt.Printf(message, appName)
fmt.Printf(message, path.Root)
return nil
},
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ require (
github.com/gobuffalo/plushgen v0.1.2
github.com/gorilla/mux v1.7.4
github.com/karrick/godirwalk v1.15.6 // indirect
github.com/pkg/errors v0.8.1
github.com/radovskyb/watcher v1.0.7
github.com/rogpeppe/go-internal v1.6.0 // indirect
github.com/sirupsen/logrus v1.6.0 // indirect
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.5.1
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 // indirect
golang.org/x/mod v0.3.0
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,10 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
70 changes: 70 additions & 0 deletions pkg/gomodulepath/gomodulepath.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package gomodulepath

import (
"fmt"
"go/parser"
"go/token"
"strings"

"github.com/pkg/errors"
"golang.org/x/mod/module"
)

// Path represents a Go module's path.
type Path struct {
// Path is Go module's full path.
// e.g.: github.com/tendermint/starport.
RawPath string

// Root is the root directory name of Go module.
// e.g.: starport for github.com/tendermint/starport.
Root string

// Package is the default package name for the Go module that can be used
// to host main functionality of the module.
// e.g.: starport for github.com/tendermint/starport.
Package string
}

// Parse parses rawpath into a module Path.
func Parse(rawpath string) (Path, error) {
if err := validateModulePath(rawpath); err != nil {
return Path{}, err
}
rootName := root(rawpath)
// package name cannot contain "-" so gracefully remove them
// if they present.
packageName := strings.ReplaceAll(rootName, "-", "")
if err := validatePackageName(packageName); err != nil {
return Path{}, err
}
p := Path{
RawPath: rawpath,
Root: rootName,
Package: packageName,
}
return p, nil
}

func validateModulePath(path string) error {
if err := module.CheckPath(path); err != nil {
return fmt.Errorf("app name is an invalid go module name: %w", err)
}
return nil
}

func validatePackageName(name string) error {
fset := token.NewFileSet()
src := fmt.Sprintf("package %s", name)
if _, err := parser.ParseFile(fset, "", src, parser.PackageClauseOnly); err != nil {
// parser error is very low level here so let's hide it from the user
// completely.
return errors.New("app name is an invalid go package name")
}
return nil
}

func root(path string) string {
sp := strings.Split(path, "/")
return sp[len(sp)-1]
}
42 changes: 42 additions & 0 deletions pkg/gomodulepath/gomodulepath_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package gomodulepath

import (
"errors"
"fmt"
"testing"

"github.com/stretchr/testify/require"
)

func TestParse(t *testing.T) {
cases := []struct {
name string
rawpath string
path Path
err error
}{
{"standard",
"github.com/a/b", Path{"github.com/a/b", "b", "b"}, nil,
},
{"with dash",
"github.com/a/b-c", Path{"github.com/a/b-c", "b-c", "bc"}, nil,
},
{"long",
"github.com/a/b/c", Path{"github.com/a/b/c", "c", "c"}, nil,
},
{"invalid as go.mod module name",
"github.com/a/b/c@", Path{}, fmt.Errorf("app name is an invalid go module name: %w",
errors.New(`malformed module path "github.com/a/b/c@": invalid char '@'`)),
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
path, err := Parse(tt.rawpath)
require.Equal(t, tt.err, err)
if err != nil {
return
}
require.Equal(t, tt.path, path)
})
}
}
2 changes: 2 additions & 0 deletions templates/app/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ func New(opts *Options) (*genny.Generator, error) {
ctx := plush.NewContext()
ctx.Set("ModulePath", opts.ModulePath)
ctx.Set("AppName", opts.AppName)
ctx.Set("BinaryNamePrefix", opts.BinaryNamePrefix)
ctx.Set("Denom", opts.Denom)
ctx.Set("title", strings.Title)

g.Transformer(plushgen.Transformer(ctx))
g.Transformer(genny.Replace("{{appName}}", opts.AppName))
g.Transformer(genny.Replace("{{binaryNamePrefix}}", opts.BinaryNamePrefix))
return g, nil
}
7 changes: 4 additions & 3 deletions templates/app/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package app

// Options ...
type Options struct {
AppName string
ModulePath string
Denom string
AppName string
BinaryNamePrefix string
ModulePath string
Denom string
}

// Validate that options are usuable
Expand Down
32 changes: 16 additions & 16 deletions templates/app/templates/Makefile.plush
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ VERSION := $(shell echo $(shell git describe --tags) | sed 's/^v//')
COMMIT := $(shell git log -1 --format='%H')

ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=NewApp \
-X github.com/cosmos/cosmos-sdk/version.ServerName=<%= AppName %>d \
-X github.com/cosmos/cosmos-sdk/version.ClientName=<%= AppName %>cli \
-X github.com/cosmos/cosmos-sdk/version.ServerName=<%= BinaryNamePrefix %>d \
-X github.com/cosmos/cosmos-sdk/version.ClientName=<%= BinaryNamePrefix %>cli \
-X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \
-X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT)

Expand All @@ -14,8 +14,8 @@ BUILD_FLAGS := -ldflags '$(ldflags)'
all: install

install: go.sum
go install -mod=readonly $(BUILD_FLAGS) ./cmd/<%= AppName %>d
go install -mod=readonly $(BUILD_FLAGS) ./cmd/<%= AppName %>cli
go install -mod=readonly $(BUILD_FLAGS) ./cmd/<%= BinaryNamePrefix %>d
go install -mod=readonly $(BUILD_FLAGS) ./cmd/<%= BinaryNamePrefix %>cli

go.sum: go.mod
@echo "--> Ensure dependencies have not been modified"
Expand All @@ -24,21 +24,21 @@ go.sum: go.mod
init-pre:
rm -rf ~/.<%= AppName %>cli
rm -rf ~/.<%= AppName %>d
<%= AppName %>d init mynode --chain-id <%= AppName %>
<%= AppName %>cli config keyring-backend test
<%= BinaryNamePrefix %>d init mynode --chain-id <%= AppName %>
<%= BinaryNamePrefix %>cli config keyring-backend test

init-user1:
<%= AppName %>cli keys add user1 --output json 2>&1
<%= BinaryNamePrefix %>cli keys add user1 --output json 2>&1

init-user2:
<%= AppName %>cli keys add user2 --output json 2>&1
<%= BinaryNamePrefix %>cli keys add user2 --output json 2>&1

init-post:
<%= AppName %>d add-genesis-account $$(<%= AppName %>cli keys show user1 -a) 1000token,100000000stake
<%= AppName %>d add-genesis-account $$(<%= AppName %>cli keys show user2 -a) 500token
<%= AppName %>cli config chain-id <%= AppName %>
<%= AppName %>cli config output json
<%= AppName %>cli config indent true
<%= AppName %>cli config trust-node true
<%= AppName %>d gentx --name user1 --keyring-backend test
<%= AppName %>d collect-gentxs
<%= BinaryNamePrefix %>d add-genesis-account $$(<%= BinaryNamePrefix %>cli keys show user1 -a) 1000token,100000000stake
<%= BinaryNamePrefix %>d add-genesis-account $$(<%= BinaryNamePrefix %>cli keys show user2 -a) 500token
<%= BinaryNamePrefix %>cli config chain-id <%= AppName %>
<%= BinaryNamePrefix %>cli config output json
<%= BinaryNamePrefix %>cli config indent true
<%= BinaryNamePrefix %>cli config trust-node true
<%= BinaryNamePrefix %>d gentx --name user1 --keyring-backend test
<%= BinaryNamePrefix %>d collect-gentxs

0 comments on commit 02ccba7

Please sign in to comment.