2019-03-06 15:04:18 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2019-08-03 16:18:48 +00:00
|
|
|
"encoding/json"
|
2019-08-04 04:35:44 +00:00
|
|
|
"fmt"
|
|
|
|
"github.com/shurcooL/httpfs/union"
|
|
|
|
"github.com/shurcooL/vfsgen"
|
2019-03-06 15:04:18 +00:00
|
|
|
"github.com/urfave/cli"
|
2019-08-04 04:35:44 +00:00
|
|
|
"io/ioutil"
|
2019-03-06 15:04:18 +00:00
|
|
|
"log"
|
2019-08-04 04:35:44 +00:00
|
|
|
"net/http"
|
2019-03-06 15:04:18 +00:00
|
|
|
"os"
|
2019-08-03 16:18:48 +00:00
|
|
|
"text/template"
|
2019-08-04 04:35:44 +00:00
|
|
|
"time"
|
2019-03-06 15:04:18 +00:00
|
|
|
)
|
|
|
|
|
2019-08-03 16:18:48 +00:00
|
|
|
type CliFlagInfo struct {
|
|
|
|
PackageName string
|
|
|
|
Flags []FlagType
|
|
|
|
}
|
|
|
|
|
|
|
|
type FlagType struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Type string `json:"type"`
|
|
|
|
Value bool `json:"value"`
|
|
|
|
Destination bool `json:"dest"`
|
|
|
|
Doctail string `json:"doctail"`
|
|
|
|
ContextDefault string `json:"context_default"`
|
|
|
|
ContextType string `json:"context_type"`
|
|
|
|
Parser string `json:"parser"`
|
|
|
|
ParserCast string `json:"parser_cast"`
|
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
// zeroModTimeFileSystem is an http.FileSystem wrapper.
|
|
|
|
// It exposes a filesystem exactly like Source, except
|
|
|
|
// all file modification times are changed to zero.
|
|
|
|
// See https://github.com/shurcooL/vfsgen/pull/40#issuecomment-355416103
|
|
|
|
type zeroModTimeFileSystem struct {
|
|
|
|
Source http.FileSystem
|
2019-08-03 16:18:48 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
func (fs zeroModTimeFileSystem) Open(name string) (http.File, error) {
|
|
|
|
f, err := fs.Source.Open(name)
|
|
|
|
return file{f}, err
|
2019-08-03 16:18:48 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
type file struct {
|
|
|
|
http.File
|
2019-08-03 16:18:48 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
func (f file) Stat() (os.FileInfo, error) {
|
|
|
|
fi, err := f.File.Stat()
|
|
|
|
return fileInfo{fi}, err
|
2019-08-03 16:18:48 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
type fileInfo struct {
|
|
|
|
os.FileInfo
|
2019-08-03 16:18:48 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
func (fi fileInfo) ModTime() time.Time { return time.Time{} }
|
2019-08-03 16:18:48 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
func main() {
|
|
|
|
app := cli.NewApp()
|
2019-08-03 16:44:58 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
app.Name = "fg"
|
|
|
|
app.Usage = "Generate flag type code!"
|
|
|
|
app.Version = "v0.1.0"
|
2019-08-03 16:44:58 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
app.Action = ActionFunc
|
2019-08-03 16:44:58 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
err := GenerateAssets()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-08-03 16:44:58 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
err = app.Run(os.Args)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-08-03 16:44:58 +00:00
|
|
|
}
|
2019-08-03 16:18:48 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
func GenerateAssets() error {
|
|
|
|
fs := zeroModTimeFileSystem{
|
|
|
|
Source: union.New(map[string]http.FileSystem{
|
|
|
|
"/templates": http.Dir("templates"),
|
|
|
|
"/source": http.Dir("source"),
|
|
|
|
}),
|
|
|
|
}
|
2019-08-03 16:18:48 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
return vfsgen.Generate(fs, vfsgen.Options{
|
|
|
|
PackageName: "main",
|
|
|
|
VariableName: "fs",
|
|
|
|
})
|
|
|
|
}
|
2019-03-06 15:04:18 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
func ActionFunc(_ *cli.Context) error {
|
|
|
|
var info CliFlagInfo
|
|
|
|
var tpl *template.Template
|
2019-03-06 15:04:18 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
inFile, err := fs.Open("/source/flag-types.json")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
2019-03-06 15:04:18 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
decoder := json.NewDecoder(inFile)
|
|
|
|
err = decoder.Decode(&info.Flags)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-08-03 16:44:58 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
err = inFile.Close()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, packageName := range []string{"cli", "altsrc"} {
|
2019-08-03 16:18:48 +00:00
|
|
|
info.PackageName = packageName
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
bytes, err := ReadTemplate(packageName)
|
2019-08-03 16:18:48 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
tpl = template.Must(template.New("").Parse(string(bytes)))
|
2019-08-03 16:18:48 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
var outFile *os.File
|
2019-08-03 16:18:48 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
if packageName == "cli" {
|
|
|
|
outFile, err = os.Create("flag_generated.go")
|
|
|
|
} else {
|
|
|
|
outFile, err = os.Create("altsrc/flag_generated.go")
|
|
|
|
}
|
2019-08-03 16:18:48 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
err = tpl.Execute(outFile, info)
|
2019-08-03 16:18:48 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
err = outFile.Close()
|
2019-08-03 16:18:48 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-08-04 04:35:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2019-08-03 16:18:48 +00:00
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
func ReadTemplate(packageName string) ([]byte, error) {
|
|
|
|
templateFile, err := fs.Open(fmt.Sprintf("/templates/%s_flags_generated.gotpl", packageName))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2019-08-03 16:18:48 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 04:35:44 +00:00
|
|
|
templateFileBytes, err := ioutil.ReadAll(templateFile)
|
2019-03-06 15:04:18 +00:00
|
|
|
if err != nil {
|
2019-08-04 04:35:44 +00:00
|
|
|
return nil, err
|
2019-03-06 15:04:18 +00:00
|
|
|
}
|
2019-08-04 04:35:44 +00:00
|
|
|
|
|
|
|
return templateFileBytes, nil
|
2019-03-06 15:04:18 +00:00
|
|
|
}
|