parent
2b3be86727
commit
5268a62166
@ -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) |
||||||
|
} |
@ -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