github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/cmd/fns/initialization/command.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package initialization 19 20 import ( 21 "fmt" 22 "github.com/aacfactory/errors" 23 "github.com/aacfactory/fns/cmd/fns/initialization/base" 24 "github.com/urfave/cli/v2" 25 "golang.org/x/mod/modfile" 26 "path/filepath" 27 "runtime" 28 "strconv" 29 "strings" 30 ) 31 32 var Command = &cli.Command{ 33 Name: "init", 34 Aliases: nil, 35 Usage: "fns init --mod={mod} --img={docker image name} --work={true} --version={go version} {project dir}", 36 Description: "init fns project", 37 ArgsUsage: "", 38 Category: "", 39 Flags: []cli.Flag{ 40 &cli.StringFlag{ 41 Name: "mod", 42 Aliases: []string{"m"}, 43 Required: true, 44 Usage: "project go mod path", 45 }, 46 &cli.BoolFlag{ 47 Name: "work", 48 Aliases: []string{"w"}, 49 Required: false, 50 Usage: "use go work", 51 }, 52 &cli.StringFlag{ 53 Name: "img", 54 Aliases: []string{"i"}, 55 Required: false, 56 Usage: "project docker image name", 57 }, 58 &cli.StringFlag{ 59 Name: "version", 60 Required: false, 61 Usage: "go version, e.g.: 1.21.0", 62 }, 63 }, 64 Action: func(ctx *cli.Context) (err error) { 65 projectDir := strings.TrimSpace(ctx.Args().First()) 66 if projectDir == "" { 67 projectDir = "." 68 } 69 if !filepath.IsAbs(projectDir) { 70 projectDir, err = filepath.Abs(projectDir) 71 if err != nil { 72 err = errors.Warning("fns: init fns project failed").WithCause(err).WithMeta("dir", projectDir) 73 return 74 } 75 } 76 projectDir = filepath.ToSlash(projectDir) 77 projectPath := strings.TrimSpace(ctx.String("mod")) 78 img := strings.TrimSpace(ctx.String("img")) 79 work := ctx.Bool("work") 80 goVersion := ctx.String("version") 81 if goVersion == "" { 82 goVersion = runtime.Version()[2:] 83 } 84 if !ValidGoVersion(goVersion) { 85 err = errors.Warning("fns: init fns project failed").WithCause(fmt.Errorf("go version must be gte %s", runtime.Version())).WithMeta("dir", projectDir).WithMeta("path", projectPath) 86 return 87 } 88 writeErr := base.Write(ctx.Context, goVersion, projectPath, img, work, projectDir) 89 if writeErr != nil { 90 err = errors.Warning("fns: init fns project failed").WithCause(writeErr).WithMeta("dir", projectDir).WithMeta("path", projectPath) 91 return 92 } 93 if work { 94 fmt.Println("fns: project has been initialized, please run `go work sync` and `go mod tidy` to fetch requires and run `go generate` to generate source files!") 95 } else { 96 fmt.Println("fns: project has been initialized, please run `go mod tidy` to fetch requires and run `go generate` to generate source files!") 97 } 98 return 99 }, 100 } 101 102 func ParseGoVersion(s string) (v Version) { 103 ss := strings.Split(s, ".") 104 if len(ss) > 0 { 105 v.Major, _ = strconv.Atoi(ss[0]) 106 } 107 if len(ss) > 1 { 108 v.Miner, _ = strconv.Atoi(ss[1]) 109 } 110 if len(ss) > 2 { 111 v.Miner, _ = strconv.Atoi(ss[2]) 112 } 113 return 114 } 115 116 type Version struct { 117 Major int 118 Miner int 119 Patch int 120 } 121 122 func ValidGoVersion(target string) (ok bool) { 123 if !modfile.GoVersionRE.MatchString(target) { 124 return 125 } 126 tv := ParseGoVersion(target) 127 rv := ParseGoVersion(runtime.Version()[2:]) 128 if tv.Major >= rv.Major { 129 if tv.Miner >= rv.Miner { 130 if tv.Patch >= rv.Patch { 131 ok = true 132 } 133 } 134 } 135 return 136 }