func runGoCrossCompileInit() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) GOROOT := kmgc.GOROOT if GOROOT == "" { //guess GOROOT out, err := exec.Command("go", "env", "GOROOT").CombinedOutput() kmgConsole.ExitOnErr(err) GOROOT = strings.TrimSpace(string(out)) if GOROOT == "" { kmgConsole.ExitOnErr(fmt.Errorf("you must set $GOROOT in environment to use GoCrossComplieInit")) } } var makeShellArgs []string var makeShellName string runCmdPath := filepath.Join(GOROOT, "src") if runtime.GOOS == "windows" { makeShellName = "cmd" makeShellArgs = []string{"/C", filepath.Join(GOROOT, "src", "make.bat"), "--no-clean"} } else { makeShellName = filepath.Join(GOROOT, "src", "make.bash") makeShellArgs = []string{"--no-clean"} } for _, target := range kmgc.CrossCompileTarget { err = kmgCmd.CmdSlice(append([]string{makeShellName}, makeShellArgs...)). MustSetEnv("GOOS", target.GetGOOS()). MustSetEnv("GOARCH", target.GetGOARCH()). SetDir(runCmdPath). Run() kmgConsole.ExitOnErr(err) } return }
func checkOneBasePathFoldDiff(path string) (isSameOrNotExist bool) { fileName := filepath.Base(path) dirPath := filepath.Dir(path) names, ok := folderFileCache[dirPath] if !ok { dirFile, err := os.Open(filepath.Dir(path)) defer dirFile.Close() if err != nil { if os.IsNotExist(err) { return true //dir not exist } kmgConsole.ExitOnErr(err) } names, err = dirFile.Readdirnames(-1) kmgConsole.ExitOnErr(err) folderFileCache[dirPath] = names } for _, n := range names { if n == fileName { return true //case same } if strings.EqualFold(n, fileName) { return false //case not same } } return true // base path not exist }
// run go command in current project // 1.go build -i github.com/xxx/xxx use to get fastest speed of build. // 2.try remove pkg directory if you found you change is ignore. func GoCommand() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) err = kmgCmd.CmdSlice(append([]string{"go"}, os.Args[1:]...)). MustSetEnv("GOPATH", kmgc.GOPATHToString()).StdioRun() kmgConsole.ExitOnErr(err) }
func gitFixNameCaseCmd() { //检查index里面的文件名大小写和当前的文件名大小写是否一致 var basePath string var err error flag.StringVar(&basePath, "p", "", "base path of git directory") flag.Parse() if basePath == "" { basePath, err = os.Getwd() kmgConsole.ExitOnErr(err) } err = GitFixNameCase(basePath) kmgConsole.ExitOnErr(err) }
func selfUpdate() { prefixB, err := kmgHttp.UrlGetContent("http://kmgtools.qiniudn.com/v1/kmgUrlPrefix.txt?v=" + kmgRand.MustCryptoRandToAlphaNum(16)) kmgConsole.ExitOnErr(err) exeContent, err := kmgHttp.UrlGetContent(string(prefixB) + "_windows_amd64.exe") kmgConsole.ExitOnErr(err) //cmd 这个东西有超级神力,直接os.Rename不行 但是360会报警 // 已经试过下列方案: // 1.os.Rename 后面的write会没有权限,原因不明 // 2.move windows上面没有这个命令 kmgCmd.ProxyRun(`cmd /c move C:\windows\system32\kmg.exe C:\windows\system32\kmg-old.exe`) kmgFile.MustWriteFile(`C:\windows\system32\kmg.exe`, exeContent) }
func AddCommandList() { kmgConsole.AddAction(kmgConsole.Command{ Name: "FileHttpServer", Runner: runFileHttpServer, }) kmgConsole.AddCommandWithName("HttpGet", func() { requestUrl := "" key := "" flag.StringVar(&requestUrl, "url", "", "") flag.StringVar(&key, "key", "", "crypto key use to decrypt respond") flag.Parse() if requestUrl == "" { kmgConsole.ExitOnErr(errors.New("Usage: kmg HttpGet -url http://xxx")) } b := MustUrlGetContent(requestUrl) var err error if key != "" { b, err = kmgCrypto.CompressAndEncryptBytesDecodeV2(kmgCrypto.Get32PskFromString(key), b) if err != nil { panic(err) } } fmt.Print(string(b)) }) }
//不回显命令 func runCmdSliceWithGoPath(gopath string, cmdSlice []string) { err := kmgCmd.CmdSlice(cmdSlice). MustSetEnv("GOPATH", gopath).StdioRun() if err != nil { err = fmt.Errorf("kmg gorun: %s", err) kmgConsole.ExitOnErr(err) } }
func RunGoHttpApiServerCmd() { command := &GoHttpApiServerCommand{} flag.StringVar(&command.http, "http", ":18080", "listen http port of the server") flag.StringVar(&command.https, "https", "", "listen https port of the server") flag.BoolVar(&command.randPort, "randPort", false, "if can not listen on default port ,will listen on random port") flag.Parse() if command.https != "" { command.isHttps = true command.tcpListenAddr = command.https } else { command.tcpListenAddr = command.http } jsonHttpHandler := &JsonHttpHandler{ ApiManager: DefaultApiManager, SessionStoreManager: &sessionStore.Manager{ Provider: sessionStore.NewMemoryProvider(), //Provider: memcacheProvider.New(kmgConfig.DefaultParameter().MemcacheHostList...), }, } http.Handle("/api", &HttpApiFilterManager{ Filters: []HttpApiFilter{ jsonHttpHandler.Filter, }, }) http.Handle("/api.deflate", &HttpApiFilterManager{ Filters: []HttpApiFilter{ HttpApiDeflateCompressFilter, jsonHttpHandler.Filter, }, }) for _, handlerConfig := range AdditionHttpHandler { http.Handle(handlerConfig.Path, handlerConfig.Handler) } l, err := command.listen() kmgConsole.ExitOnErr(err) fmt.Printf("Listen on %s\n", l.Addr().String()) if command.isHttps { tlsConfig, err := kmgCrypto.CreateTlsConfig() if err != nil { kmgConsole.ExitOnErr(fmt.Errorf("fail at kmgTls.CreateTlsConfig,error:%s", err.Error())) } l = tls.NewListener(l, tlsConfig) } err = http.Serve(l, nil) kmgConsole.ExitOnErr(err) }
/* 递归目录的go test 支持.kmg.yml目录结构提示文件(该文件必须存在) -v 更详细的描述 -m 一个模块名,从这个模块名开始递归目录测试 -d 一个目录名,从这个目录开始递归目录测试 -bench benchmarks参数,直接传递到go test -onePackage 不递归目录测试,仅测试一个package */ func runGoTest() { command := GoTest{} flag.BoolVar(&command.v, "v", false, "show output of test") flag.StringVar(&command.dir, "d", "", "dir path to test") flag.StringVar(&command.moduleName, "m", "", "module name to test") flag.StringVar(&command.bench, "bench", "", "bench parameter pass to go test") flag.BoolVar(&command.onePackage, "onePackage", false, "only test one package") flag.StringVar(&command.runArg, "run", "", "Run only those tests and examples matching the regular expression.") flag.BoolVar(&command.onlyBuild, "onlyBuild", false, "only build all package(not test)") flag.Parse() kmgc, err := kmgConfig.LoadEnvFromWd() if err == nil { command.gopath = kmgc.GOPATH[0] } else { if kmgConfig.IsNotFound(err) { command.gopath = os.Getenv("GOPATH") } else { kmgConsole.ExitOnErr(err) } } //find root path root, err := command.findRootPath() kmgConsole.ExitOnErr(err) command.buildContext = &build.Context{ GOPATH: command.gopath, Compiler: build.Default.Compiler, } if command.onePackage { err = command.handlePath(root) kmgConsole.ExitOnErr(err) } err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { return nil } if kmgFile.IsDotFile(path) { return filepath.SkipDir } return command.handlePath(path) }) kmgConsole.ExitOnErr(err) }
/* GoCrossComplie [gofile] the output file will put into $project_root/bin/name_GOOS_GOARCH[.exe] */ func runGoCrossCompile() { command := GoCrossCompile{} flag.StringVar(&command.outputPath, "o", "", "output file dir(file name come from source file name),default to $project_root/bin") flag.StringVar(&command.version, "v", "", "version string in output file name") flag.StringVar(&command.platform, "platform", "", "platform(default use .kmg.yml config)") flag.Parse() if len(os.Args) <= 1 { kmgConsole.ExitOnErr(fmt.Errorf("need gofile parameter")) return } targetFile := flag.Arg(0) kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) targetName := kmgFile.GetFileBaseWithoutExt(targetFile) if command.outputPath == "" { command.outputPath = filepath.Join(kmgc.ProjectPath, "bin") } targetList := []kmgConfig.CompileTarget{} if command.platform == "" { targetList = kmgc.CrossCompileTarget } else { targetList = []kmgConfig.CompileTarget{kmgConfig.CompileTarget(command.platform)} } for _, target := range targetList { fileName := "" if command.version == "" { fileName = targetName + "_" + target.GetGOOS() + "_" + target.GetGOARCH() } else { fileName = targetName + "_" + command.version + "_" + target.GetGOOS() + "_" + target.GetGOARCH() } if target.GetGOOS() == "windows" { fileName = fileName + ".exe" } outputFilePath := filepath.Join(command.outputPath, fileName) err := kmgCmd.CmdSlice([]string{"go", "build", "-i", "-o", outputFilePath, targetFile}). MustSetEnv("GOOS", target.GetGOOS()). MustSetEnv("GOARCH", target.GetGOARCH()). MustSetEnv("GOPATH", kmgc.GOPATHToString()). Run() kmgConsole.ExitOnErr(err) } return }
func selfUpdate() { baseFileContent, err := kmgHttp.UrlGetContent("http://kmgtools.qiniudn.com/v1/installKmg.bash?v=" + kmgRand.MustCryptoRandToAlphaNum(16)) kmgConsole.ExitOnErr(err) baseFilePath := "/tmp/installKmg.bash" kmgFile.MustDeleteFile(baseFilePath) kmgFile.MustAppendFile(baseFilePath, baseFileContent) kmgCmd.MustRunInBash(baseFilePath) }
func runCommand(kmgc *kmgConfig.Env, args []string) { os.Chdir(kmgc.ProjectPath) logDir := filepath.Join(kmgc.LogPath, "run") kmgFile.MustMkdirAll(logDir) thisLogFilePath := filepath.Join(logDir, time.Now().Format(kmgTime.FormatFileName)+".log") kmgFile.MustWriteFile(thisLogFilePath, []byte{}) if !kmgPlatform.GetCompiledPlatform().Compatible(kmgPlatform.WindowsAmd64) { lastLogPath := filepath.Join(logDir, "last.log") if kmgFile.MustFileExist(lastLogPath) { kmgFile.MustSymlink(kmgFile.MustReadSymbolLink(lastLogPath), filepath.Join(logDir, "last2.log")) } kmgFile.MustSymlink(filepath.Base(thisLogFilePath), lastLogPath) } //TODO 大部分命令是 kmg gorun xxx 在这个地方可以直接调用gorun解决问题,这样可以少开一个进程加快了一些速度 // 问题: 上述做法不靠谱,会导致last.log没有用处. //if len(args) >= 2 && args[0] == "kmg" && strings.EqualFold(args[1], "gorun") { // os.Args = append(args[1:], os.Args[1:]...) // goCmd.GoRunCmd() // return //} // 下面的做法不靠谱,会让signle无法传递 //err := kmgCmd.CmdSlice(append(args, os.Args[1:]...)). // SetDir(kmgc.ProjectPath). // RunAndTeeOutputToFile(thisLogFilePath) // TODO bash转义 bashCmd := strings.Join(append(args, os.Args[1:]...), " ") bashCmdStr := bashCmd + " 2>&1 | tee -i " + thisLogFilePath + " ; test ${PIPESTATUS[0]} -eq 0" if kmgPlatform.IsWindows() { err := kmgCmd.CmdString(bashCmdStr).SetDir(kmgc.ProjectPath).StdioRun() if err != nil { err = fmt.Errorf("kmg make: %s", err) kmgConsole.ExitOnErr(err) } return } else { err := kmgCmd.CmdBash(bashCmdStr).SetDir(kmgc.ProjectPath).StdioRun() if err != nil { err = fmt.Errorf("kmg make: %s", err) kmgConsole.ExitOnErr(err) } return } }
func newNameCmd(fn func(name string) error) func() { return func() { if len(os.Args) <= 1 { fmt.Println("require name args") return } name := os.Args[1] err := fn(name) kmgConsole.ExitOnErr(err) } }
//kmg service.process start {"Name":"xxx",} func processCmd() { if len(os.Args) < 3 { kmgConsole.ExitOnErr(fmt.Errorf(`example: kmg service.process start {"Name":"xxx",}`)) } cmd := os.Args[1] dataJson := os.Args[2] s := &Service{} err := json.Unmarshal([]byte(dataJson), s) kmgConsole.ExitOnErr(err) switch cmd { case "start": case "stop": case "restart": case "status": default: kmgConsole.ExitOnErr(fmt.Errorf(`not support command.`)) } }
func goRunPackageName(goPath string, pathOrPkg string) { //goRunInstall(goPath, pathOrPkg) goRunInstallSimple(goPath, pathOrPkg) //run outPath := filepath.Join(goPath, "bin", filepath.Base(pathOrPkg)) p := kmgPlatform.GetCompiledPlatform() if p.Compatible(kmgPlatform.WindowsAmd64) { outPath += ".exe" } if !kmgFile.MustFileExist(outPath) { kmgConsole.ExitOnErr(fmt.Errorf("please make sure you are kmg gorun a main package. (binary file not exist. %s)", outPath)) } runCmdSliceWithGoPath(goPath, append([]string{outPath}, os.Args[2:]...)) }
// go install bug func GoRunCmd() { runtime.GOMAXPROCS(runtime.NumCPU()) kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) goPath := kmgc.GOPATHToString() //假设第一个是文件或者package名称,后面是传给命令行的参数 if len(os.Args) < 2 { kmgConsole.ExitOnErr(fmt.Errorf("you need pass in running filename")) return } pathOrPkg := os.Args[1] _, err = os.Stat(pathOrPkg) switch { case os.IsNotExist(err): //package名称 goRunPackageName(goPath, pathOrPkg) return case err != nil: //其他错误 kmgConsole.ExitOnErr(err) return default: //文件或目录 wd, err := os.Getwd() kmgConsole.ExitOnErr(err) if wd == filepath.Join(goPath, "src") { //用户在src下 goRunPackageName(goPath, pathOrPkg) return } // 找出指向的这个文件的所有import的包,全部install一遍,再go run //靠谱实现这个东西的复杂度太高,目前已有的方案不能达到目标,暂时先使用go run // 如果有需要使用请把这个文件放到package里面,或者运行前删除pkg目录. // TODO 速度比较慢. //已经证实不行的方案: // 1.在临时目录建一个package,并且使用GOPATH指向那个临时目录,缓存会出现问题,并且效果和 go build -i 没有区别 // 2.使用go build -i 效果和直接go run没有区别(缓存还是会出现问题) //找出这个文件所有的 import然后install 一遍 importPathList, err := kmgGoSource.GetImportPathListFromFile(pathOrPkg) kmgConsole.ExitOnErr(err) for _, pkgPath := range importPathList { runCmdSliceWithGoPath(goPath, []string{"go", "install", pkgPath}) } runCmdSliceWithGoPath(goPath, append([]string{"go", "run"}, os.Args[1:]...)) return } kmgConsole.ExitOnErr(fmt.Errorf("unexpected run path")) }
func makeCmd() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) if kmgc.Make == "" { kmgConsole.ExitOnStderr(errors.New("Please defined a Make command in .kmg.yml file to use kmg make")) return } if len(os.Args) >= 2 && kmgc.MakeSubCommandMap != nil { for cmdName, cmdString := range kmgc.MakeSubCommandMap { if strings.EqualFold(cmdName, os.Args[1]) { args := strings.Split(cmdString, " ") os.Args = os.Args[1:] runCommand(kmgc, args) return } } } args := strings.Split(kmgc.Make, " ") runCommand(kmgc, args) }
func installGolangWithUrlMap(urlMap map[string]string) { p := kmgPlatform.GetCompiledPlatform() if p.Compatible(kmgPlatform.WindowsAmd64) { contentB, err := kmgHttp.UrlGetContent(urlMap["windows_amd64"]) kmgConsole.ExitOnErr(err) kmgFile.MustDelete(`c:\go`) err = kmgCompress.ZipUncompressFromBytesToDir(contentB, `c:\go`, "go") kmgConsole.ExitOnErr(err) err = kmgFile.CopyFile(`c:\go\bin\go.exe`, `c:\windows\system32\go.exe`) kmgConsole.ExitOnErr(err) err = kmgFile.CopyFile(`c:\go\bin\godoc.exe`, `c:\windows\system32\godoc.exe`) kmgConsole.ExitOnErr(err) err = kmgFile.CopyFile(`c:\go\bin\gofmt.exe`, `c:\windows\system32\gofmt.exe`) kmgConsole.ExitOnErr(err) return } tmpPath := kmgFile.MustChangeToTmpPath() defer kmgFile.MustDelete(tmpPath) if !kmgSys.MustIsRoot() { fmt.Println("you need to be root to install golang") return } url, ok := urlMap[p.String()] if !ok { kmgConsole.ExitOnErr(fmt.Errorf("not support platform [%s]", p)) } packageName := path.Base(url) contentB := kmgHttp.MustUrlGetContentProcess(url) kmgFile.MustWriteFile(packageName, contentB) kmgCmd.ProxyRun("tar -xf " + packageName) if kmgFile.MustFileExist("/usr/local/go") { kmgCmd.ProxyRun("mv /usr/local/go /usr/local/go.bak." + time.Now().Format(kmgTime.FormatFileNameV2)) } kmgCmd.ProxyRun("cp -rf go /usr/local") kmgFile.MustDeleteFile("/bin/go") kmgCmd.ProxyRun("ln -s /usr/local/go/bin/go /bin/go") kmgFile.MustDeleteFile("/bin/godoc") kmgCmd.ProxyRun("ln -s /usr/local/go/bin/godoc /bin/godoc") kmgFile.MustDeleteFile("/bin/gofmt") kmgCmd.ProxyRun("ln -s /usr/local/go/bin/gofmt /bin/gofmt") kmgFile.MustEnsureBinPath("/bin/go") kmgFile.MustEnsureBinPath("/bin/godoc") kmgFile.MustEnsureBinPath("/bin/gofmt") }
// use `kmg goenv` to setup current work project GOPATH func GoEnvCmd() { kmgc, err := kmgConfig.LoadEnvFromWd() kmgConsole.ExitOnErr(err) fmt.Println("export", "GOPATH="+kmgc.GOPATHToString()) //TODO 解决转义问题? }