github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/cmd/vpm/init.go (about) 1 /* 2 * Copyright (c) 2024-present unTill Pro, Ltd. 3 * @author Alisher Nurmanov 4 */ 5 6 package main 7 8 import ( 9 "fmt" 10 "go/format" 11 "io" 12 "os" 13 "path/filepath" 14 "runtime" 15 "strings" 16 17 "github.com/spf13/cobra" 18 "github.com/voedger/voedger/pkg/goutils/exec" 19 "github.com/voedger/voedger/pkg/goutils/logger" 20 "github.com/voedger/voedger/pkg/sys" 21 "golang.org/x/mod/semver" 22 23 "github.com/voedger/voedger/pkg/compile" 24 coreutils "github.com/voedger/voedger/pkg/utils" 25 ) 26 27 var minimalRequiredGoVersionValue = minimalRequiredGoVersion 28 29 func newInitCmd(params *vpmParams) *cobra.Command { 30 cmd := &cobra.Command{ 31 Use: "init module-path", 32 Short: "initialize a new package", 33 Args: exactArgs(1), 34 RunE: func(cmd *cobra.Command, args []string) (err error) { 35 return initPackage(params.Dir, params.PackagePath) 36 }, 37 } 38 return cmd 39 40 } 41 42 func initPackage(dir, packagePath string) error { 43 if packagePath == "" { 44 return fmt.Errorf(packagePathIsNotDeterminedErrFormat, dir) 45 } 46 if err := createGoMod(dir, packagePath); err != nil { 47 return err 48 } 49 if err := createPackagesGen(nil, dir, packagePath, false); err != nil { 50 return err 51 } 52 if err := createWasmDir(dir); err != nil { 53 return err 54 } 55 return execGoModTidy(dir) 56 } 57 58 func execGoModTidy(dir string) error { 59 var stdout io.Writer 60 if logger.IsVerbose() { 61 stdout = os.Stdout 62 } 63 return new(exec.PipedExec).Command("go", "mod", "tidy").WorkingDir(dir).Run(stdout, os.Stderr) 64 } 65 66 func createWasmDir(dir string) error { 67 exists, err := coreutils.Exists(filepath.Join(dir, wasmDirName)) 68 if err != nil { 69 return err 70 } 71 if !exists { 72 if err := os.Mkdir(filepath.Join(dir, wasmDirName), coreutils.FileMode_rwxrwxrwx); err != nil { 73 return err 74 } 75 } 76 return nil 77 } 78 79 func createGoMod(dir, packagePath string) error { 80 filePath := filepath.Join(dir, goModFileName) 81 82 exists, err := coreutils.Exists(filePath) 83 if err != nil { 84 // notest 85 return err 86 } 87 if exists { 88 return fmt.Errorf("%s already exists", filePath) 89 } 90 goVersion := runtime.Version() 91 goVersionNumber := strings.TrimSpace(strings.TrimPrefix(goVersion, "go")) 92 if !checkGoVersion(goVersionNumber) { 93 return fmt.Errorf(unsupportedGoVersionErrFormat, goVersionNumber) 94 } 95 96 goModContent := fmt.Sprintf(goModContentTemplate, packagePath, goVersionNumber) 97 if err := os.WriteFile(filePath, []byte(goModContent), coreutils.FileMode_rw_rw_rw_); err != nil { 98 return err 99 } 100 if err := execGoGet(dir, compile.VoedgerPath); err != nil { 101 return err 102 } 103 return nil 104 } 105 106 func checkGoVersion(goVersionNumber string) bool { 107 return semver.Compare("v"+goVersionNumber, "v"+minimalRequiredGoVersionValue) >= 0 108 } 109 110 func checkPackageGenFileExists(dir string) (bool, error) { 111 packagesGenFilePath := filepath.Join(dir, packagesGenFileName) 112 return coreutils.Exists(packagesGenFilePath) 113 } 114 115 func createPackagesGen(imports []string, dir, packagePath string, recreate bool) error { 116 // pkg subfolder for packages 117 packagesGenFilePath := filepath.Join(dir, packagesGenFileName) 118 if !recreate { 119 exists, err := checkPackageGenFileExists(dir) 120 if err != nil { 121 // notest 122 return err 123 } 124 if exists { 125 return fmt.Errorf("%s already exists", packagesGenFilePath) 126 } 127 } 128 129 strBuffer := &strings.Builder{} 130 for _, imp := range imports { 131 if imp == sys.PackagePath { 132 continue 133 } 134 strBuffer.WriteString(fmt.Sprintf("_ %q\n", imp)) 135 } 136 137 packagesGenContent := fmt.Sprintf(packagesGenContentTemplate, filepath.Base(packagePath), strBuffer.String()) 138 packagesGenContentFormatted, err := format.Source([]byte(packagesGenContent)) 139 if err != nil { 140 return err 141 } 142 143 if err := os.WriteFile(packagesGenFilePath, packagesGenContentFormatted, coreutils.FileMode_rw_rw_rw_); err != nil { 144 return err 145 } 146 return nil 147 } 148 149 func execGoGet(goModDir, dependencyToGet string) error { 150 var stdout io.Writer 151 if logger.IsVerbose() { 152 stdout = os.Stdout 153 } 154 return new(exec.PipedExec).Command("go", "get", dependencyToGet+"@latest").WorkingDir(goModDir).Run(stdout, os.Stderr) 155 }