mirror of https://github.com/minio/minio.git
Merge pull request #136 from harshavardhana/pr_out_add_minio_cli_stub_generator
This commit is contained in:
commit
a0b57edabe
1
Makefile
1
Makefile
|
@ -48,6 +48,7 @@ cover: build-erasure build-signify build-split build-crc32c build-cpu build-sha1
|
||||||
|
|
||||||
install: build-erasure
|
install: build-erasure
|
||||||
@godep go install github.com/minio-io/minio/cmd/minio && echo "Installed minio into ${GOPATH}/bin"
|
@godep go install github.com/minio-io/minio/cmd/minio && echo "Installed minio into ${GOPATH}/bin"
|
||||||
|
@godep go install github.com/minio-io/minio/cmd/minio-cli && echo "Install minio-cli into ${GOPATH}/bin"
|
||||||
|
|
||||||
save: restore
|
save: restore
|
||||||
@godep save ./...
|
@godep save ./...
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
templates.go
|
||||||
|
minio-cli
|
|
@ -0,0 +1,32 @@
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
`minio-cli` is option stub builder for ``minio`` project using [codegangsta/cli](https://github.com/codegangsta/cli),
|
||||||
|
|
||||||
|
The idea is to be able to do rapid prototyping and facilitate new contributors to the project
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You just need to set its application name and options:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ minio-cli -options option1,option2,option3 [application]
|
||||||
|
```
|
||||||
|
|
||||||
|
Generates three files namely [application].go, [application]-options.go, [application].md
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
If you want to start to building `bucket` application which has subcommands `get`, `put`, `list`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ minio-cli -options get,put,list foo
|
||||||
|
$ ls foo/
|
||||||
|
foo-options.go foo.go foo.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ go get github.com/minio-io/minio
|
||||||
|
$ make install
|
||||||
|
```
|
|
@ -0,0 +1,89 @@
|
||||||
|
// this code is from gofmt, modified for our internal usage - http://golang.org/src/cmd/gofmt/gofmt.go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/printer"
|
||||||
|
"go/token"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error {
|
||||||
|
if in == nil {
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
in = f
|
||||||
|
}
|
||||||
|
|
||||||
|
src, err := ioutil.ReadAll(in)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fileSet := token.NewFileSet()
|
||||||
|
file, err := parser.ParseFile(fileSet, filename, src, parser.ParseComments)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ast.SortImports(fileSet, file)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
tabWidth := 8
|
||||||
|
printerMode := printer.UseSpaces | printer.TabIndent
|
||||||
|
err = (&printer.Config{Mode: printerMode, Tabwidth: tabWidth}).Fprint(&buf, fileSet, file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res := buf.Bytes()
|
||||||
|
if !bytes.Equal(src, res) {
|
||||||
|
err = ioutil.WriteFile(filename, res, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isGofile(f os.FileInfo) bool {
|
||||||
|
name := f.Name()
|
||||||
|
return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
||||||
|
}
|
||||||
|
|
||||||
|
func visitFile(pathName string, f os.FileInfo, err error) error {
|
||||||
|
|
||||||
|
if err == nil && isGofile(f) {
|
||||||
|
err = processFile(pathName, nil, os.Stdout, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkDir(pathName string) {
|
||||||
|
filepath.Walk(pathName, visitFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GoFormat(pathName string) error {
|
||||||
|
dir, err := os.Stat(pathName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dir.IsDir() {
|
||||||
|
walkDir(pathName)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/minio-io/minio/pkgs/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type source struct {
|
||||||
|
Name string
|
||||||
|
TempLate template.Template
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Relative path from GOPATH default
|
||||||
|
TEMPLATEREPO = "/src/github.com/minio-io/minio/templates/"
|
||||||
|
)
|
||||||
|
|
||||||
|
type option struct {
|
||||||
|
Name string
|
||||||
|
Definename string
|
||||||
|
Functionname string
|
||||||
|
}
|
||||||
|
|
||||||
|
type application struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
Month string
|
||||||
|
Year int
|
||||||
|
Options []option
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f source) generate(appName string, def application) error {
|
||||||
|
wr, err := os.Create(path.Join(appName, f.Name))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer wr.Close()
|
||||||
|
return f.TempLate.Execute(wr, def)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initApplication(appname, usage string, inputOptions []string) application {
|
||||||
|
year, month, _ := time.Now().Date()
|
||||||
|
return application{
|
||||||
|
Name: appname,
|
||||||
|
Usage: usage,
|
||||||
|
Month: month.String(),
|
||||||
|
Year: year,
|
||||||
|
Options: initOptions(inputOptions),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initOptions(inputOptions []string) []option {
|
||||||
|
var options []option
|
||||||
|
|
||||||
|
if inputOptions[0] == "" {
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range inputOptions {
|
||||||
|
option := option{
|
||||||
|
Name: name,
|
||||||
|
Definename: utils.FirstUpper(name),
|
||||||
|
Functionname: "do" + utils.FirstUpper(name),
|
||||||
|
}
|
||||||
|
options = append(options, option)
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var flOptions, flUsage, flTemplatePath string
|
||||||
|
|
||||||
|
flag.StringVar(&flOptions, "options", "", "Comma-separated list of options to build")
|
||||||
|
flag.StringVar(&flUsage, "usage", "", "A one liner explains the purpose of the cli being built")
|
||||||
|
flag.StringVar(&flTemplatePath, "templatepath", "", "Non standard templates path")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
inputOptions := strings.Split(flOptions, ",")
|
||||||
|
|
||||||
|
appname := flag.Arg(0)
|
||||||
|
|
||||||
|
if appname == "" {
|
||||||
|
log.Fatal("app name must not be blank\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
if inputOptions[0] == "" {
|
||||||
|
log.Fatal("-options option1 should be specified with appname")
|
||||||
|
}
|
||||||
|
|
||||||
|
gopath := os.Getenv("GOPATH")
|
||||||
|
|
||||||
|
var mainTemplatePath, optionsTemplatePath, readmeTemplatePath string
|
||||||
|
if flTemplatePath == "" {
|
||||||
|
mainTemplatePath = path.Join(gopath, TEMPLATEREPO, "main.tmpl")
|
||||||
|
optionsTemplatePath = path.Join(gopath, TEMPLATEREPO, "options.tmpl")
|
||||||
|
readmeTemplatePath = path.Join(gopath, TEMPLATEREPO, "README.tmpl")
|
||||||
|
} else {
|
||||||
|
mainTemplatePath = path.Join(flTemplatePath, "main.tmpl")
|
||||||
|
optionsTemplatePath = path.Join(flTemplatePath, "options.tmpl")
|
||||||
|
readmeTemplatePath = path.Join(flTemplatePath, "README.tmpl")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(mainTemplatePath); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(optionsTemplatePath); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(readmeTemplatePath); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mainTemplate = template.Must(template.ParseFiles(mainTemplatePath))
|
||||||
|
var optionsTemplate = template.Must(template.ParseFiles(optionsTemplatePath))
|
||||||
|
var readmeTemplate = template.Must(template.ParseFiles(readmeTemplatePath))
|
||||||
|
|
||||||
|
if _, err := os.Stat(appname); err == nil {
|
||||||
|
// if exists, we overwrite by default
|
||||||
|
err = os.RemoveAll(appname)
|
||||||
|
utils.Assert(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := os.Mkdir(appname, 0755)
|
||||||
|
utils.Assert(err)
|
||||||
|
|
||||||
|
application := initApplication(appname, flUsage, inputOptions)
|
||||||
|
|
||||||
|
optionsGo := source{
|
||||||
|
Name: appname + "-options.go",
|
||||||
|
TempLate: *optionsTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
readmeMd := source{
|
||||||
|
Name: appname + ".md",
|
||||||
|
TempLate: *readmeTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
mainGo := source{
|
||||||
|
Name: appname + ".go",
|
||||||
|
TempLate: *mainTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = readmeMd.generate(appname, application)
|
||||||
|
utils.Assert(err)
|
||||||
|
|
||||||
|
mainGo.generate(appname, application)
|
||||||
|
utils.Assert(err)
|
||||||
|
|
||||||
|
optionsGo.generate(appname, application)
|
||||||
|
|
||||||
|
err = GoFormat(appname)
|
||||||
|
utils.Assert(err)
|
||||||
|
}
|
|
@ -16,8 +16,22 @@
|
||||||
|
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import "io/ioutil"
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func MakeTempTestDir() (string, error) {
|
func MakeTempTestDir() (string, error) {
|
||||||
return ioutil.TempDir("/tmp", "minio-test-")
|
return ioutil.TempDir("/tmp", "minio-test-")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Assert(err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FirstUpper(str string) string {
|
||||||
|
return strings.ToUpper(str[0:1]) + str[1:]
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
% MINIO(1) Minio Manual
|
||||||
|
% Minio community
|
||||||
|
% {{.Month}} {{.Year}}
|
||||||
|
# NAME
|
||||||
|
{{.Name}} - {{.Usage}}
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
# AUTHORS
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Mini Object Storage, (C) 2014 Minio, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Name = "{{.Name}}"
|
||||||
|
app.Usage = "{{.Usage}}"
|
||||||
|
app.Commands = Options
|
||||||
|
app.Run(os.Args)
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Mini Object Storage, (C) 2014 Minio, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Options = []cli.Command{
|
||||||
|
{{range .Options}}{{.Definename}},
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{range .Options}}
|
||||||
|
var {{.Definename}} = cli.Command{
|
||||||
|
Name: "{{.Name}}",
|
||||||
|
Usage: "",
|
||||||
|
Description: `
|
||||||
|
`,
|
||||||
|
Action: {{.Functionname}},
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{range .Options}}
|
||||||
|
func {{.Functionname}}(c *cli.Context) {
|
||||||
|
}
|
||||||
|
{{end}}
|
Loading…
Reference in New Issue