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