Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vgo #817

Merged
merged 28 commits into from
Jun 7, 2019
Merged

Vgo #817

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b3e76f8
vgo-support - re-working code generator
jharshman Jan 29, 2019
d9b54e8
add .idea/* to gitignore
jharshman Jan 29, 2019
2ab82d1
vgo - fixing up the root template
jharshman Jan 29, 2019
f3ea814
fixing up templates more
jharshman Jan 29, 2019
cdf9a77
vgo - create directory
jharshman Jan 30, 2019
5a88abf
vgo - add Create method to Project struct
jharshman Jan 30, 2019
e5b5fab
vgo - generate license
jharshman Jan 30, 2019
7da993a
remove commented code
jharshman Jan 30, 2019
3b1a457
fix calling to createLicenseFile
jharshman Jan 30, 2019
6080b96
vgo - fix format
jharshman Jan 30, 2019
5771947
vgo - remove unused methods
jharshman Jan 30, 2019
0c27591
simplify test
jharshman Jan 30, 2019
feb8de7
vgo - add todo
jharshman Jan 30, 2019
2706a1c
vgo - take named directory or current wd
jharshman Jan 30, 2019
df9dd74
vgo - compare generated files against golden files
jharshman Jan 30, 2019
1ccdc39
vgo - update golden templates
jharshman Jan 30, 2019
8ca19e8
add CommandTemplate
jharshman Jan 30, 2019
6403965
vgo - fixing up the add op to work with vgo
jharshman Jan 30, 2019
a18c744
vgo - trim some uneeded data from struct
jharshman Jan 30, 2019
6d31298
reorder some operations
jharshman Jan 30, 2019
0edf725
depricate package name flag
jharshman Jan 30, 2019
b5119a8
fix duplicated dir
jharshman Jan 30, 2019
061ac40
vgo - add command working
jharshman Jan 30, 2019
9c84eaa
remove commented field in struct
jharshman Jan 30, 2019
019a891
vgo - strip out unused methods
jharshman Jan 30, 2019
13d61eb
test add
jharshman Jan 31, 2019
2d154be
clean up testproject files after test executes
jharshman Jan 31, 2019
35a3584
remove unused struct fields
jharshman May 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ tags
*.exe

cobra.test

.idea/*
122 changes: 36 additions & 86 deletions cobra/cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,20 @@ package cmd
import (
"fmt"
"os"
"path/filepath"
"unicode"

"github.com/spf13/cobra"
)

func init() {
addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command")
}

var packageName, parentName string
var (
packageName string
parentName string

var addCmd = &cobra.Command{
Use: "add [command name]",
Aliases: []string{"command"},
Short: "Add a command to a Cobra Application",
Long: `Add (cobra add) will create a new command, with a license and
addCmd = &cobra.Command{
Use: "add [command name]",
Aliases: []string{"command"},
Short: "Add a command to a Cobra Application",
Long: `Add (cobra add) will create a new command, with a license and
the appropriate structure for a Cobra-based CLI application,
and register it to its parent (default rootCmd).

Expand All @@ -42,28 +38,41 @@ with an initial uppercase letter.

Example: cobra add server -> resulting in a new cmd/server.go`,

Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
er("add needs a name for the command")
}
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
er("add needs a name for the command")
}

var project *Project
if packageName != "" {
project = NewProject(packageName)
} else {
wd, err := os.Getwd()
if err != nil {
er(err)
}
project = NewProjectFromPath(wd)
}

cmdName := validateCmdName(args[0])
cmdPath := filepath.Join(project.CmdPath(), cmdName+".go")
createCmdFile(project.License(), cmdPath, cmdName)
commandName := validateCmdName(args[0])
command := &Command{
CmdName: commandName,
CmdParent: parentName,
Project: &Project{
AbsolutePath: wd,
Legal: getLicense(),
Copyright: copyrightLine(),
},
}

fmt.Fprintln(cmd.OutOrStdout(), cmdName, "created at", cmdPath)
},
err = command.Create()
if err != nil {
er(err)
}

fmt.Printf("%s created at %s", command.CmdName, command.AbsolutePath)
},
}
)

func init() {
addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command")
addCmd.Flags().MarkDeprecated("package", "this operation has been removed.")
}

// validateCmdName returns source without any dashes and underscore.
Expand Down Expand Up @@ -118,62 +127,3 @@ func validateCmdName(source string) string {
}
return output
}

func createCmdFile(license License, path, cmdName string) {
template := `{{comment .copyright}}
{{if .license}}{{comment .license}}{{end}}

package {{.cmdPackage}}

import (
"fmt"

"github.com/spf13/cobra"
)

// {{.cmdName}}Cmd represents the {{.cmdName}} command
var {{.cmdName}}Cmd = &cobra.Command{
Use: "{{.cmdName}}",
Short: "A brief description of your command",
Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.` + "`" + `,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("{{.cmdName}} called")
},
}

func init() {
{{.parentName}}.AddCommand({{.cmdName}}Cmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// {{.cmdName}}Cmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// {{.cmdName}}Cmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
`

data := make(map[string]interface{})
data["copyright"] = copyrightLine()
data["license"] = license.Header
data["cmdPackage"] = filepath.Base(filepath.Dir(path)) // last dir of path
data["parentName"] = parentName
data["cmdName"] = cmdName

cmdScript, err := executeTemplate(template, data)
if err != nil {
er(err)
}
err = writeStringToFile(path, cmdScript)
if err != nil {
er(err)
}
}
92 changes: 26 additions & 66 deletions cobra/cmd/add_test.go
Original file line number Diff line number Diff line change
@@ -1,85 +1,45 @@
package cmd

import (
"errors"
"io/ioutil"
"fmt"
"os"
"path/filepath"
"testing"

"github.com/spf13/viper"
)

// TestGoldenAddCmd initializes the project "github.com/spf13/testproject"
// in GOPATH, adds "test" command
// and compares the content of all files in cmd directory of testproject
// with appropriate golden files.
// Use -update to update existing golden files.
func TestGoldenAddCmd(t *testing.T) {
projectName := "github.com/spf13/testproject"
project := NewProject(projectName)
defer os.RemoveAll(project.AbsPath())

viper.Set("author", "NAME HERE <EMAIL ADDRESS>")
viper.Set("license", "apache")
viper.Set("year", 2017)
defer viper.Set("author", nil)
defer viper.Set("license", nil)
defer viper.Set("year", nil)

// Initialize the project first.
initializeProject(project)

// Then add the "test" command.
cmdName := "test"
cmdPath := filepath.Join(project.CmdPath(), cmdName+".go")
createCmdFile(project.License(), cmdPath, cmdName)
wd, _ := os.Getwd()
command := &Command{
CmdName: "test",
CmdParent: parentName,
Project: &Project{
AbsolutePath: fmt.Sprintf("%s/testproject", wd),
Legal: getLicense(),
Copyright: copyrightLine(),

expectedFiles := []string{".", "root.go", "test.go"}
gotFiles := []string{}

// Check project file hierarchy and compare the content of every single file
// with appropriate golden file.
err := filepath.Walk(project.CmdPath(), func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// required to init
AppName: "testproject",
PkgName: "github.com/spf13/testproject",
Viper: true,
},
}

// Make path relative to project.CmdPath().
// E.g. path = "/home/user/go/src/github.com/spf13/testproject/cmd/root.go"
// then it returns just "root.go".
relPath, err := filepath.Rel(project.CmdPath(), path)
if err != nil {
return err
// init project first
command.Project.Create()
defer func() {
if _, err := os.Stat(command.AbsolutePath); err == nil {
os.RemoveAll(command.AbsolutePath)
}
relPath = filepath.ToSlash(relPath)
gotFiles = append(gotFiles, relPath)
goldenPath := filepath.Join("testdata", filepath.Base(path)+".golden")
}()

switch relPath {
// Known directories.
case ".":
return nil
// Known files.
case "root.go", "test.go":
if *update {
got, err := ioutil.ReadFile(path)
if err != nil {
return err
}
ioutil.WriteFile(goldenPath, got, 0644)
}
return compareFiles(path, goldenPath)
}
// Unknown file.
return errors.New("unknown file: " + path)
})
if err != nil {
if err := command.Create(); err != nil {
t.Fatal(err)
}

// Check if some files lack.
if err := checkLackFiles(expectedFiles, gotFiles); err != nil {
generatedFile := fmt.Sprintf("%s/cmd/%s.go", command.AbsolutePath, command.CmdName)
goldenFile := fmt.Sprintf("testdata/%s.go.golden", command.CmdName)
err := compareFiles(generatedFile, goldenFile)
if err != nil {
t.Fatal(err)
}
}
Expand Down
Loading