From c0af3a86ce2d0cd25a1207d96e96ec5babe1a408 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 17 May 2013 07:45:57 -0400 Subject: [PATCH] add command: build --- build.go | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ gpm.go | 25 ++++---- i18n/gpm.toml | 2 +- utils/utils.go | 15 +++++ 4 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 build.go create mode 100644 utils/utils.go diff --git a/build.go b/build.go new file mode 100644 index 000000000..acd692511 --- /dev/null +++ b/build.go @@ -0,0 +1,161 @@ +// Copyright (c) 2013 GPMGo Members. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "io" + "os" + "os/exec" + "path" + "runtime" + "strings" + + "github.com/GPMGo/gpm/utils" +) + +var cmdBuild = &Command{ + UsageLine: "build [-o output] [build flags] [packages]", + Short: "compile and install packages and dependencies", + Long: ` +Build compiles the packages named by the import paths, +along with their dependencies, but it does not install the results. + +If the arguments are a list of .go files, build treats them as a list +of source files specifying a single package. + +When the command line specifies a single main package, +build writes the resulting executable to output. +Otherwise build compiles the packages but discards the results, +serving only as a check that the packages can be built. + +The -o flag specifies the output file name. If not specified, the +output file name depends on the arguments and derives from the name +of the package, such as p.a for package p, unless p is 'main'. If +the package is main and file names are provided, the file name +derives from the first file name mentioned, such as f1 for 'go build +f1.go f2.go'; with no files provided ('go build'), the output file7 +name is the base name of the containing directory. + +The build flags are shared by the build, install, run, and test commands: + + -a + force rebuilding of packages that are already up-to-date. + -n + print the commands but do not run them. + -p n + the number of builds that can be run in parallel. + The default is the number of CPUs available. + -race + enable data race detection. + Supported only on linux/amd64, darwin/amd64 and windows/amd64. + -v + print the names of packages as they are compiled. + -work + print the name of the temporary work directory and + do not delete it when exiting. + -x + print the commands. + + -ccflags 'arg list' + arguments to pass on each 5c, 6c, or 8c compiler invocation. + -compiler name + name of compiler to use, as in runtime.Compiler (gccgo or gc). + -gccgoflags 'arg list' + arguments to pass on each gccgo compiler/linker invocation. + -gcflags 'arg list' + arguments to pass on each 5g, 6g, or 8g compiler invocation. + -installsuffix suffix + a suffix to use in the name of the package installation directory, + in order to keep output separate from default builds. + If using the -race flag, the install suffix is automatically set to race + or, if set explicitly, has _race appended to it. + -ldflags 'flag list' + arguments to pass on each 5l, 6l, or 8l linker invocation. + -tags 'tag list' + a list of build tags to consider satisfied during the build. + See the documentation for the go/build package for + more information about build tags. + +The list flags accept a space-separated list of strings. To embed spaces +in an element in the list, surround it with either single or double quotes. + +For more about specifying packages, see 'go help packages'. +For more about where packages and binaries are installed, +see 'go help gopath'. + +See also: go install, go get, go clean. + `, +} + +func init() { + // break init cycle + cmdBuild.Run = runBuild + //cmdInstall.Run = runInstall + + addBuildFlags(cmdBuild) + //addBuildFlags(cmdInstall) +} + +// Flags set by multiple commands. +var buildV bool // -v flag. + +// addBuildFlags adds the flags common to the build and install commands. +func addBuildFlags(cmd *Command) { + // NOTE: If you add flags here, also add them to testflag.go. + cmd.Flag.BoolVar(&buildV, "v", false, "") +} + +func runBuild(cmd *Command, args []string) { + var cmdArgs []string + cmdArgs = append(cmdArgs, "install") + cmdArgs = append(cmdArgs, args...) + + wd, _ := os.Getwd() + wd = strings.Replace(wd, "\\", "/", -1) + proName := path.Base(wd) + if runtime.GOOS == "windows" { + proName += ".exe" + } + + cmdExec := exec.Command("go", cmdArgs...) + stdout, err := cmdExec.StdoutPipe() + if err != nil { + fmt.Println(err) + } + stderr, err := cmdExec.StderrPipe() + if err != nil { + fmt.Println(err) + } + err = cmdExec.Start() + if err != nil { + fmt.Println(err) + } + go io.Copy(os.Stdout, stdout) + go io.Copy(os.Stderr, stderr) + cmdExec.Wait() + + // Find executable in GOPATH and copy to current directory. + gopath := strings.Replace(os.Getenv("GOPATH"), ";", ":", -1) + gopath = strings.Replace(gopath, "\\", "/", -1) + paths := strings.Split(gopath, ":") + for _, v := range paths { + if utils.IsExist(v + "/bin/" + proName) { + err = os.Remove(wd + "/" + proName) + if err != nil { + fmt.Println("Fail to remove file in current directory :", err) + return + } + err = os.Rename(v+"/bin/"+proName, wd+"/"+proName) + if err == nil { + fmt.Println("Moved file from $GOPATH to current directory.") + return + } else { + fmt.Println("Fail to move file from $GOPATH to current directory :", err) + } + break + } + } +} diff --git a/gpm.go b/gpm.go index 066795dda..ea1db2921 100644 --- a/gpm.go +++ b/gpm.go @@ -7,13 +7,13 @@ package main import ( - "bytes" "flag" "fmt" "go/build" "io" "log" "os" + "os/exec" "path/filepath" "runtime" "strings" @@ -26,7 +26,8 @@ import ( ) var ( - config tomlConfig + config tomlConfig + appPath string // Application path. ) type tomlConfig struct { @@ -83,7 +84,9 @@ func (c *Command) Runnable() bool { // Commands lists the available commands and help topics. // The order here is the order in which they are printed by 'go help'. -var commands = []*Command{} +var commands = []*Command{ + cmdBuild, +} var exitStatus = 0 var exitMu sync.Mutex @@ -97,14 +100,18 @@ func setExitStatus(n int) { } func main() { + // Get application path. + appPath, _ := exec.LookPath("gpm") + appPath = strings.Replace(filepath.Dir(appPath), "\\", "/", -1) + "/" + // Load configuration. - if _, err := toml.DecodeFile("i18n/gpm.toml", &config); err != nil { + if _, err := toml.DecodeFile(appPath+"i18n/gpm.toml", &config); err != nil { fmt.Println(err) return } // Load usage template by language. - f, err := os.Open("i18n/usage_" + config.Lang + ".tpl") + f, err := os.Open(appPath + "i18n/usage_" + config.Lang + ".tpl") if err != nil { fmt.Println(err) return @@ -155,13 +162,7 @@ func main() { for _, cmd := range commands { if cmd.Name() == args[0] && cmd.Run != nil { cmd.Flag.Usage = func() { cmd.Usage() } - if cmd.CustomFlags { - args = args[1:] - } else { - cmd.Flag.Parse(args[1:]) - args = cmd.Flag.Args() - } - cmd.Run(cmd, args) + cmd.Run(cmd, args[1:]) exit() return } diff --git a/i18n/gpm.toml b/i18n/gpm.toml index d4e9ea066..bd0cee6f2 100644 --- a/i18n/gpm.toml +++ b/i18n/gpm.toml @@ -1,5 +1,5 @@ # This is a configuration file for gpm with toml format. title = "gpm(Go Package Manager)" -version = "v0.0.0 Build 0516" +version = "v0.0.1 Build 0517" user_language = "en-US" \ No newline at end of file diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 000000000..560cc2516 --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,15 @@ +// Copyright (c) 2013 GPMGo Members. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package utils + +import ( + "os" +) + +// IsExist returns if a file or directory exists +func IsExist(path string) bool { + _, err := os.Stat(path) + return err == nil || os.IsExist(err) +}