dev: nft/ctl
This commit is contained in:
50
nft/nfctl/main.go
Normal file
50
nft/nfctl/main.go
Normal file
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-git/go-billy/v5/memfs"
|
||||
"github.com/go-git/go-git/v5"
|
||||
_ "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/go-git/go-git/v5/storage/memory"
|
||||
"github.com/loveuer/nf/nft/log"
|
||||
"io"
|
||||
)
|
||||
|
||||
func main() {
|
||||
memo := memory.NewStorage()
|
||||
fs := memfs.New()
|
||||
repo, err := git.Clone(memo, fs, &git.CloneOptions{
|
||||
URL: "http://10.220.10.35/dev/template/ultone.git",
|
||||
Auth: &http.BasicAuth{Username: "loveuer", Password: "uu_L6neSDseoWx55babJ"},
|
||||
Depth: 1,
|
||||
SingleBranch: true,
|
||||
InsecureSkipTLS: true,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
infos, err := fs.ReadDir(".")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, item := range infos {
|
||||
log.Info("[fs.info] %s", item.Name())
|
||||
if item.Name() == "main.go" {
|
||||
file, err := fs.Open(item.Name())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
bs, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Info("[fs.main]\n%s", string(bs))
|
||||
}
|
||||
}
|
||||
|
||||
_ = repo
|
||||
}
|
78
nft/nfctl/tp/cmd_parse.go
Normal file
78
nft/nfctl/tp/cmd_parse.go
Normal file
@ -0,0 +1,78 @@
|
||||
package tp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ParseCmd(pwd string, content []byte) ([]TpCmd, error) {
|
||||
var (
|
||||
err error
|
||||
cmds = make([]TpCmd, 0)
|
||||
start = false
|
||||
)
|
||||
|
||||
scanner := bufio.NewScanner(bytes.NewReader(content))
|
||||
scanner.Buffer(make([]byte, 1024), 1024*1024*10)
|
||||
|
||||
record := make([]string, 0)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "!") {
|
||||
if start {
|
||||
return nil, fmt.Errorf("invalid content: unEOF cmd block found")
|
||||
}
|
||||
|
||||
start = true
|
||||
record = append(record, line)
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "EOF") {
|
||||
start = false
|
||||
if len(record) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var cmd TpCmd
|
||||
if cmd, err = ParseBlock(pwd, record); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmds = append(cmds, cmd)
|
||||
record = record[:0]
|
||||
continue
|
||||
}
|
||||
|
||||
if start {
|
||||
record = append(record, line)
|
||||
}
|
||||
}
|
||||
|
||||
if err = scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cmds, err
|
||||
}
|
||||
|
||||
func ParseBlock(pwd string, lines []string) (TpCmd, error) {
|
||||
switch lines[0] {
|
||||
case "!replace":
|
||||
return newReplace(pwd, lines[1:])
|
||||
case "!generate":
|
||||
return newGenerate(pwd, lines[1:])
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid cmd block: unknown type: %s", lines[0])
|
||||
}
|
61
nft/nfctl/tp/parse_test.go
Normal file
61
nft/nfctl/tp/parse_test.go
Normal file
@ -0,0 +1,61 @@
|
||||
package tp
|
||||
|
||||
import (
|
||||
"github.com/loveuer/nf/nft/log"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseInitFile(t *testing.T) {
|
||||
const init_bs = `
|
||||
!replace
|
||||
content
|
||||
reg
|
||||
*.go
|
||||
ultone => {{.PROJECT_NAME}}
|
||||
EOF
|
||||
|
||||
!replace
|
||||
content
|
||||
exact
|
||||
go.mod
|
||||
module ultone => module {{.PROJECT_NAME}}
|
||||
EOF
|
||||
|
||||
!replace
|
||||
name
|
||||
main.go => loveuer.go
|
||||
EOF
|
||||
|
||||
!generate
|
||||
readme.md
|
||||
# {{.PROJECT_NAME}}
|
||||
|
||||
### run
|
||||
- ` + "`" + `go run . --help` + "`" + `
|
||||
- ` + "`" + `go run .` + "`" + `
|
||||
|
||||
### build
|
||||
- ` + "`" + `docker build -t {repo:tag} -f Dockerfile .` + "`" + `
|
||||
EOF
|
||||
`
|
||||
data := map[string]any{
|
||||
"PROJECT_NAME": "loveuer",
|
||||
}
|
||||
|
||||
result, err := RenderVar([]byte(init_bs), data)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
pwd, _ := os.Getwd()
|
||||
|
||||
cmds, err := ParseCmd(pwd, result)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
for _, item := range cmds {
|
||||
log.Info("one cmd => %s\n\n", item.String())
|
||||
}
|
||||
}
|
29
nft/nfctl/tp/template.go
Normal file
29
nft/nfctl/tp/template.go
Normal file
@ -0,0 +1,29 @@
|
||||
package tp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
_t *template.Template
|
||||
)
|
||||
|
||||
func init() {
|
||||
_t = template.New("tp")
|
||||
}
|
||||
|
||||
func RenderVar(t []byte, data map[string]any) ([]byte, error) {
|
||||
tr, err := _t.Parse(string(t))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
if err = tr.Execute(&buf, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
92
nft/nfctl/tp/tp.go
Normal file
92
nft/nfctl/tp/tp.go
Normal file
@ -0,0 +1,92 @@
|
||||
package tp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type TpCmd interface {
|
||||
String() string
|
||||
Execute() error
|
||||
}
|
||||
|
||||
var (
|
||||
_ TpCmd = (*TpGenerate)(nil)
|
||||
_ TpCmd = (*TpReplace)(nil)
|
||||
)
|
||||
|
||||
type TpGenerate struct {
|
||||
pwd string
|
||||
filename string
|
||||
content []string
|
||||
}
|
||||
|
||||
func (t *TpGenerate) String() string {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *TpGenerate) Execute() error {
|
||||
var (
|
||||
err error
|
||||
location = t.filename
|
||||
input *os.File
|
||||
)
|
||||
|
||||
if !path.IsAbs(t.filename) {
|
||||
location = path.Join(t.pwd, t.filename)
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(path.Dir(location), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(location, "/") {
|
||||
if input, err = os.OpenFile(location, os.O_CREATE|os.O_APPEND, 0744); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(t.content) > 0 {
|
||||
content := strings.Join(t.content, "\n")
|
||||
_, err = input.WriteString(content)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newGenerate(pwd string, lines []string) (*TpGenerate, error) {
|
||||
if len(lines) == 0 {
|
||||
return nil, fmt.Errorf("generate cmd require file/folder name")
|
||||
}
|
||||
|
||||
return &TpGenerate{
|
||||
pwd: pwd,
|
||||
filename: lines[0],
|
||||
content: lines[1:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
type TpReplace struct {
|
||||
pwd string
|
||||
}
|
||||
|
||||
func (t *TpReplace) String() string {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *TpReplace) Execute() error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func newReplace(pwd string, lines []string) (*TpReplace, error) {
|
||||
if len(lines) < 2 {
|
||||
return nil, fmt.Errorf("invalid replace cmd")
|
||||
}
|
||||
return &TpReplace{pwd: pwd}, nil
|
||||
}
|
Reference in New Issue
Block a user