diff --git a/api.go b/api.go index 171f14e..4198981 100644 --- a/api.go +++ b/api.go @@ -2,9 +2,10 @@ package main import ( "fmt" + "os" + "git.icechen.cn/pkg/wujian_develop_tool/config" "git.icechen.cn/pkg/wujian_develop_tool/util" - "os" "git.icechen.cn/pkg/wujian_develop_tool/template/api/deploy" @@ -23,7 +24,7 @@ func ActionListApi(c *cli.Context) error { } color.Green("API应用列表:") for _, api := range config.Config.HasApi { - color.Green("\t%s", api.Name) + color.Green("\t%s.%s", api.Name, api.NameSpace) color.Green("\t\t路径:\t%s", api.Root) color.Green("\t\t类型:\t%s", api.Type) color.Green("\t\t端口:\t%s", api.Port) @@ -59,11 +60,21 @@ func ActionNewApi(c *cli.Context) error { appList = append(appList, appName) } for _, newApp := range appList { + namespace := "" + for { + namespace = util.ReadLineWithMessage(fmt.Sprintf("请输入%s所属的项目(namespace): ", newApp)) + if namespace != "" { + break + } else { + color.Red("项目名称不能为空!") + } + } color.Green("正在创建[%s]API应用...", newApp) - app := config.Config.Api.GetApp(newApp) + app := config.Config.Api.GetApp(namespace, newApp) app = config.Api{ - Name: newApp, - Root: "app/api/" + newApp, + NameSpace: namespace, + Name: newApp, + Root: fmt.Sprintf("app/%s/api/%s", namespace, newApp), } if util.ExistDir(app.Root) && !util.ReadBoolWithMessage(app.Root+"目录已存在,是否要覆盖app文件目录(y/n): ") { @@ -96,12 +107,12 @@ func ActionNewApi(c *cli.Context) error { app.Host = util.ReadLineWithMessage("请输入API应用请求的域名(host,如:api.seamlesser.com,建议为空): ") app.Path = util.ReadLineWithMessage("请输入API应用请求的路由(path,如:/uwe/core/?(.*),建议为空): ") - err = deploy.GenDeploy(config.Config.Name, app) + err = deploy.GenDeploy(app) if err != nil { return err } - err = golang.GenDockerfile(newApp) + err = golang.GenDockerfile(app) if err != nil { return err } diff --git a/config/configFile.go b/config/configFile.go index eb8db83..7753498 100644 --- a/config/configFile.go +++ b/config/configFile.go @@ -1,9 +1,10 @@ package config import ( - "git.icechen.cn/pkg/wujian_develop_tool/util" "io/ioutil" + "git.icechen.cn/pkg/wujian_develop_tool/util" + "github.com/urfave/cli/v2" "gopkg.in/yaml.v3" @@ -42,6 +43,7 @@ type ConfigFile struct { type ( ApiList []Api Api struct { + NameSpace string `json:"name_space" yaml:"nameSpace"` Name string `json:"name" yaml:"name"` AliasName string `json:"alias_name" yaml:"aliasName"` Root string `json:"root" yaml:"root"` @@ -55,6 +57,7 @@ type ( type ( ServiceList []Service Service struct { + NameSpace string `json:"name_space" yaml:"nameSpace"` Name string `json:"name" yaml:"name"` AliasName string `json:"alias_name" yaml:"aliasName"` Root string `json:"root" yaml:"root"` @@ -80,7 +83,7 @@ func ReadConfig() error { func (c *ConfigFile) AppendAPI(api Api) error { has := false for i, a := range c.Api { - if a.Name == api.Name { + if a.Name == api.Name && a.NameSpace == api.NameSpace { c.Api[i] = api has = true break @@ -102,7 +105,7 @@ func (c *ConfigFile) AppendAPI(api Api) error { func (c *ConfigFile) AppendService(service Service) error { has := false for i, s := range c.Service { - if s.Name == service.Name { + if s.Name == service.Name && s.NameSpace == service.NameSpace { c.Service[i] = service has = true break @@ -140,9 +143,9 @@ al: return hasApp } -func (sl ApiList) GetApp(appName string) Api { +func (sl ApiList) GetApp(namespace, appName string) Api { for _, api := range sl { - if api.Name == appName { + if api.Name == appName && api.NameSpace == namespace { return api } } @@ -168,9 +171,9 @@ sl: return hasApp } -func (sl ServiceList) GetApp(appName string) Service { +func (sl ServiceList) GetApp(namespace, appName string) Service { for _, service := range sl { - if service.Name == appName { + if service.Name == appName && service.NameSpace == namespace { return service } } diff --git a/go.mod b/go.mod index 4c0bac0..749e5f2 100644 --- a/go.mod +++ b/go.mod @@ -5,22 +5,20 @@ go 1.17 require ( github.com/drone/drone-go v1.7.1 github.com/fatih/color v1.13.0 + github.com/sergi/go-diff v1.2.0 github.com/urfave/cli/v2 v2.3.0 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) require ( - github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sergi/go-diff v1.2.0 // indirect golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d // indirect golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) diff --git a/go.sum b/go.sum index 98108ef..9112480 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -46,6 +44,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/drone/drone-go v1.7.1 h1:ZX+3Rs8YHUSUQ5mkuMLmm1zr1ttiiE2YGNxF3AnyDKw= github.com/drone/drone-go v1.7.1/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg= @@ -125,6 +124,7 @@ github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -135,6 +135,7 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -397,6 +398,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/service.go b/service.go index 412fadd..0dbba73 100644 --- a/service.go +++ b/service.go @@ -2,9 +2,10 @@ package main import ( "fmt" + "os" + "git.icechen.cn/pkg/wujian_develop_tool/config" "git.icechen.cn/pkg/wujian_develop_tool/util" - "os" "git.icechen.cn/pkg/wujian_develop_tool/template/service/deploy" @@ -23,7 +24,7 @@ func ActionListService(c *cli.Context) error { } color.Green("Service应用列表:") for _, service := range config.Config.HasService { - color.Green("\t%s", service.Name) + color.Green("\t%s.%s", service.Name, service.NameSpace) color.Green("\t\t路径:\t%s", service.Root) color.Green("\t\t类型:\t%s", service.Type) color.Green("\t\t端口:\t%s", service.Port) @@ -59,11 +60,21 @@ func ActionNewService(c *cli.Context) error { appList = append(appList, appName) } for _, newApp := range appList { + namespace := "" + for { + namespace = util.ReadLineWithMessage(fmt.Sprintf("请输入%s所属的项目(namespace): ", newApp)) + if namespace != "" { + break + } else { + color.Red("项目名称不能为空!") + } + } color.Green("正在创建[%s]Service应用...", newApp) - app := config.Config.Service.GetApp(newApp) + app := config.Config.Service.GetApp(namespace, newApp) app = config.Service{ - Name: newApp, - Root: "app/service/" + newApp, + NameSpace: namespace, + Name: newApp, + Root: fmt.Sprintf("app/%s/service/%s", namespace, newApp), } if util.ExistDir(app.Root) && !util.ReadBoolWithMessage(app.Root+"目录已存在,是否要覆盖app文件目录(y/n): ") { @@ -94,12 +105,12 @@ func ActionNewService(c *cli.Context) error { } } - err = deploy.GenDeploy(config.Config.Name, app) + err = deploy.GenDeploy(app) if err != nil { return err } - err = golang.GenDockerfile(newApp) + err = golang.GenDockerfile(app) if err != nil { return err } diff --git a/template/api/deploy/deoloy.go b/template/api/deploy/deoloy.go index 7e5e719..925f1ab 100644 --- a/template/api/deploy/deoloy.go +++ b/template/api/deploy/deoloy.go @@ -4,10 +4,9 @@ import ( "embed" _ "embed" "fmt" - "git.icechen.cn/pkg/wujian_develop_tool/config" - "github.com/sergi/go-diff/diffmatchpatch" "os" + "git.icechen.cn/pkg/wujian_develop_tool/config" "github.com/fatih/color" "git.icechen.cn/pkg/wujian_develop_tool/util" @@ -16,7 +15,7 @@ import ( //go:embed "*" var deployDir embed.FS -func GenDeploy(namespace string, api config.Api) error { +func GenDeploy(api config.Api) error { color.Green("正在生成deploy...") // deploy 文件夹 @@ -33,16 +32,17 @@ func GenDeploy(namespace string, api config.Api) error { path := api.Path if path == "" { - path = fmt.Sprintf("/%s/%s/?(.*)", namespace, api.Name) + path = fmt.Sprintf("/%s/%s/?(.*)", api.NameSpace, api.Name) } data := map[string]string{ - "NameSpace": namespace, + "NameSpace": api.NameSpace, "AppName": api.Name, "AliasName": api.AliasName, "Port": api.Port, "Host": host, - "Path": path} + "Path": path, + } // value.yaml valuesTemplate, err := deployDir.ReadFile("values.tpl") @@ -121,24 +121,5 @@ func copyTo(fileName string, toPath string) error { if err != nil { return err } - - toFileContent, err := os.ReadFile(toPath) - if err == nil { - dmp := diffmatchpatch.New() - diffContent := dmp.DiffMain(string(fileContent), string(toFileContent), true) - diffString := dmp.DiffToDelta(diffContent) - if diffString == "" || util.ReadBoolWithMessage(diffString) { - color.Red("跳过文件: %s", fileName) - return nil - } - } - - toFile, err := os.OpenFile(toPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm) - if err != nil { - return err - } - defer toFile.Close() - - _, err = toFile.Write(fileContent) - return err + return util.WriteFile(toPath, fileContent) } diff --git a/template/api/docker/golang/Dockerfile.tpl b/template/api/docker/golang/Dockerfile.tpl index d69e511..a68d096 100644 --- a/template/api/docker/golang/Dockerfile.tpl +++ b/template/api/docker/golang/Dockerfile.tpl @@ -8,7 +8,7 @@ RUN go mod download -x WORKDIR /go/src ADD . . RUN go mod tidy -RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o api_{{ .Name }} ./app/api/{{ .Name }} +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o api_{{ .Name }} ./{{ .Root }} FROM reg.icechen.cn/alpine as {{ .Name }} WORKDIR /go/src diff --git a/template/api/docker/golang/golang.go b/template/api/docker/golang/golang.go index 41eca60..f4d6faf 100644 --- a/template/api/docker/golang/golang.go +++ b/template/api/docker/golang/golang.go @@ -3,6 +3,8 @@ package golang import ( _ "embed" + "git.icechen.cn/pkg/wujian_develop_tool/config" + "github.com/fatih/color" "git.icechen.cn/pkg/wujian_develop_tool/util" @@ -14,11 +16,11 @@ var dockerfileTemplate string //go:embed "main.tpl" var mainGoTemplate string -func GenDockerfile(name string) error { +func GenDockerfile(api config.Api) error { color.Green("正在生成dockerfile...") - err := util.TemplateToFile("app/api/"+name+"/Dockerfile", dockerfileTemplate, map[string]string{"Name": name}) + err := util.TemplateToFile(api.Root+"/Dockerfile", dockerfileTemplate, api) if err != nil { return err } - return util.TemplateToFile("app/api/"+name+"/main.go", mainGoTemplate, nil) + return util.TemplateToFile(api.Root+"/main.go", mainGoTemplate, nil) } diff --git a/template/service/deploy/deoloy.go b/template/service/deploy/deoloy.go index e937d13..34411ff 100644 --- a/template/service/deploy/deoloy.go +++ b/template/service/deploy/deoloy.go @@ -3,9 +3,10 @@ package deploy import ( "embed" _ "embed" - "git.icechen.cn/pkg/wujian_develop_tool/config" "os" + "git.icechen.cn/pkg/wujian_develop_tool/config" + "github.com/fatih/color" "git.icechen.cn/pkg/wujian_develop_tool/util" @@ -14,7 +15,7 @@ import ( //go:embed "*" var deployDir embed.FS -func GenDeploy(namespace string, service config.Service) error { +func GenDeploy(service config.Service) error { color.Green("正在生成deploy...") // deploy 文件夹 @@ -25,10 +26,11 @@ func GenDeploy(namespace string, service config.Service) error { } data := map[string]string{ - "NameSpace": namespace, + "NameSpace": service.NameSpace, "AppName": service.Name, "AliasName": service.AliasName, - "Port": service.Port} + "Port": service.Port, + } // value.yaml valuesTemplate, err := deployDir.ReadFile("values.tpl") @@ -101,13 +103,5 @@ func copyTo(fileName string, toPath string) error { if err != nil { return err } - - toFile, err := os.OpenFile(toPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm) - if err != nil { - return err - } - defer toFile.Close() - - _, err = toFile.Write(fileContent) - return err + return util.WriteFile(toPath, fileContent) } diff --git a/template/service/deploy/values.tpl b/template/service/deploy/values.tpl index e0800f2..6396038 100644 --- a/template/service/deploy/values.tpl +++ b/template/service/deploy/values.tpl @@ -1,5 +1,5 @@ nameSpace: {{ .NameSpace }} aliasName: {{ .AliasName }} -image: reg.icechen.cn/{{ .NameSpace }}/api-{{ .AppName }} +image: reg.icechen.cn/{{ .NameSpace }}/service-{{ .AppName }} imageTag: latest port: {{ .Port }} \ No newline at end of file diff --git a/template/service/docker/golang/Dockerfile.tpl b/template/service/docker/golang/Dockerfile.tpl index 21d7afb..4ec63e5 100644 --- a/template/service/docker/golang/Dockerfile.tpl +++ b/template/service/docker/golang/Dockerfile.tpl @@ -8,7 +8,7 @@ RUN go mod download -x WORKDIR /go/src ADD . . RUN go mod tidy -RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o service_{{ .Name }} ./app/service/{{ .Name }} +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o service_{{ .Name }} ./{{ .Root }} FROM reg.icechen.cn/alpine as {{ .Name }} WORKDIR /go/src diff --git a/template/service/docker/golang/golang.go b/template/service/docker/golang/golang.go index 262e0a2..1016ee5 100644 --- a/template/service/docker/golang/golang.go +++ b/template/service/docker/golang/golang.go @@ -3,6 +3,8 @@ package golang import ( _ "embed" + "git.icechen.cn/pkg/wujian_develop_tool/config" + "github.com/fatih/color" "git.icechen.cn/pkg/wujian_develop_tool/util" @@ -14,11 +16,11 @@ var dockerfileTemplate string //go:embed "main.tpl" var mainGoTemplate string -func GenDockerfile(name string) error { +func GenDockerfile(service config.Service) error { color.Green("正在生成dockerfile...") - err := util.TemplateToFile("app/service/"+name+"/Dockerfile", dockerfileTemplate, map[string]string{"Name": name}) + err := util.TemplateToFile(service.Root+"/Dockerfile", dockerfileTemplate, service) if err != nil { return err } - return util.TemplateToFile("app/service/"+name+"/main.go", mainGoTemplate, nil) + return util.TemplateToFile(service.Root+"/main.go", mainGoTemplate, nil) } diff --git a/util/common.go b/util/common.go index 3aa3c2e..9c356d3 100644 --- a/util/common.go +++ b/util/common.go @@ -3,9 +3,10 @@ package util import ( "bufio" "fmt" - "github.com/fatih/color" "os" "strings" + + "github.com/fatih/color" ) func ReadBool() bool { @@ -22,6 +23,7 @@ retry: case 'N': return false default: + NoNewLinePrint(color.HiRedString, "请输入(y,Y,n,N)其中之一: ") goto retry } } diff --git a/util/file.go b/util/file.go index 44e5ebd..f98d525 100644 --- a/util/file.go +++ b/util/file.go @@ -2,19 +2,18 @@ package util import ( "bytes" + "fmt" "os" + "strings" "text/template" + + "github.com/fatih/color" + "github.com/sergi/go-diff/diffmatchpatch" ) func TemplateToFile(desFile string, templateContent string, data interface{}) error { - file, err := os.OpenFile(desFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm) - if err != nil { - return err - } - defer file.Close() - tpl := template.New("template") - tpl, err = tpl.Parse(templateContent) + tpl, err := tpl.Parse(templateContent) if err != nil { return err } @@ -25,14 +24,66 @@ func TemplateToFile(desFile string, templateContent string, data interface{}) er return err } - _, err = file.Write(b.Bytes()) + err = WriteFile(desFile, b.Bytes()) if err != nil { return err } return nil } +var defaultPrintDiff = color.WhiteString + +func IsChange(diff []diffmatchpatch.Diff) bool { + for _, d := range diff { + if d.Type != diffmatchpatch.DiffEqual { + return true + } + } + return false +} + +// AddLine 增加行号 TODO: 颜色不完美 +func AddLine(s string) string { + lines := strings.Split(s, "\n") + for i, line := range lines { + // lines[i] = fmt.Sprintf("%s %s", defaultPrintDiff("%4d.", i+1), line) + lines[i] = fmt.Sprintf("%4d. %s", i+1, line) + } + return strings.Join(lines, "\n") +} + func WriteFile(filePath string, data []byte) error { + color.Green("写入[%s]文件...", filePath) + toFileContent, err := os.ReadFile(filePath) + if err == nil { + dmp := diffmatchpatch.New() + diffContent := dmp.DiffMain(string(toFileContent), string(data), true) + + if IsChange(diffContent) { + color.Red("文件[%s]已存在:", filePath) + b := bytes.Buffer{} + diffContent = dmp.DiffCleanupSemanticLossless(diffContent) + for _, diff := range diffContent { + switch diff.Type { + case diffmatchpatch.DiffDelete: + b.WriteString(color.RedString(diff.Text)) + case diffmatchpatch.DiffInsert: + b.WriteString(color.GreenString(diff.Text)) + case diffmatchpatch.DiffEqual: + b.WriteString(diff.Text) + } + } + fmt.Println(AddLine(b.String())) + if !ReadBoolWithMessage("是否确认此次修改(y修改/n跳过): ") { + color.Red("跳过文件: %s\n\n", filePath) + return nil + } + } else { + color.Red("文件已存在且无变动,跳过文件: %s\n\n", filePath) + return nil + } + } + file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm) if err != nil { return err @@ -40,6 +91,7 @@ func WriteFile(filePath string, data []byte) error { defer file.Close() _, err = file.Write(data) + color.Red("写入文件完成: %s\n\n", filePath) return err }