diff --git a/.gopmfile b/.gopmfile index a19877d1b..086c3463a 100644 --- a/.gopmfile +++ b/.gopmfile @@ -2,8 +2,8 @@ path=github.com/gpmgo/gopm [deps] -github.com/codegangsta/cli= -github.com/Unknwon/com= -github.com/Unknwon/goconfig= +github.com/codegangsta/cli= +github.com/Unknwon/com= +github.com/Unknwon/goconfig= github.com/aybabtme/color= diff --git a/README.md b/README.md index 2c9c2fce3..1cd774352 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ gopm - Go Package Manager Gopm(Go Package Manager) is a Go package manage tool for search, install, update and share packages in Go. -**[Documentation](https://github.com/gpmgo/docs)** +**News** The best IDE for Go development [LiteIDE](https://github.com/visualfc/liteide)(after X20) now has a simple integration of gopm! + +Please see **[Documentation](https://github.com/gpmgo/docs)** before you ever start. # Commands @@ -17,20 +19,21 @@ USAGE: gopm [global options] command [command options] [arguments...] VERSION: - 0.5.7.1202 + 0.6.0.1206 COMMANDS: - get fetch remote package(s) and dependencies to local repository - bin download and link dependencies and build executable binary - gen generate a gopmfile according current Go project - run link dependencies and go run - build link dependencies and go build - install link dependencies and go install - help, h Shows a list of commands or help for one command - + get fetch remote package(s) and dependencies to local repository + bin download and link dependencies and build executable binary + gen generate a gopmfile according current Go project + run link dependencies and go run + build link dependencies and go build + install link dependencies and go install + help, h Shows a list of commands or help for one command + GLOBAL OPTIONS: - --version print the version - --help, -h show help + --noterm disable color output + --version, -v print the version + --help, -h show help ``` diff --git a/cmd/bin.go b/cmd/bin.go index c79fd8772..9ee1007a4 100644 --- a/cmd/bin.go +++ b/cmd/bin.go @@ -81,13 +81,7 @@ func runBin(ctx *cli.Context) { var err error if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] - _, ver, err = validPath(info[i+1:]) - if err != nil { - log.Error("bin", "Cannot parse package version") - log.Error("", err.Error()+":") - log.Error("", "\t"+info[i+1:]) - log.Help("Try 'gopm help get' to get more information") - } + _, ver = validPath(info[i+1:]) } // Check package name. diff --git a/cmd/cmd.go b/cmd/cmd.go index 7bccbbb60..a7c2ac839 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -15,54 +15,65 @@ package cmd import ( - "fmt" "os" "strings" + + "github.com/codegangsta/cli" + + "github.com/gpmgo/gopm/doc" + "github.com/gpmgo/gopm/log" ) var ( - AppPath string + workDir string // The path of gopm was executed. ) -// A Command is an implementation of a go command -// like go build or go fix. -type Command struct { - // Run runs the command. - // The args are the arguments after the command name. - Run func(cmd *Command, args []string) - - // UsageLine is the one-line usage message. - // The first word in the line is taken to be the command name. - UsageLine string - - // Short is the short description shown in the 'go help' output. - Short string - - // Long is the long message shown in the 'go help ' output. - Long string +// setup initialize common environment for commands. +func setup(ctx *cli.Context) { + var err error + workDir, err = os.Getwd() + if err != nil { + log.Error("setup", "Fail to get work directory:") + log.Fatal("", "\t"+err.Error()) + } - // Flag is a set of flags specific to this command. - Flags map[string]bool + log.PureMode = ctx.GlobalBool("noterm") + log.Verbose = ctx.Bool("verbose") } -// Name returns the command's name: the first word in the usage line. -func (c *Command) Name() string { - name := c.UsageLine - i := strings.Index(name, " ") - if i >= 0 { - name = name[:i] +// parseTarget returns "." when target is empty string. +func parseTarget(target string) string { + if len(target) == 0 { + target = "." } - return name + return target } -func (c *Command) Usage() { - fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine) - fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long)) - os.Exit(2) +// validPath checks if the information of the package is valid. +func validPath(info string) (string, string) { + infos := strings.Split(info, ":") + + l := len(infos) + switch { + case l == 1: + return doc.BRANCH, "" + case l == 2: + switch infos[1] { + case doc.TRUNK, doc.MASTER, doc.DEFAULT: + infos[1] = "" + } + return infos[0], infos[1] + default: + log.Error("", "Cannot parse dependency version:") + log.Error("", "\t"+info) + log.Help("Try 'gopm help get' to get more information") + return "", "" + } } -// Runnable reports whether the command can be run; otherwise -// it is a documentation pseudo-command such as importpath. -func (c *Command) Runnable() bool { - return c.Run != nil +func versionSuffix(value string) string { + if len(value) > 0 { + return "." + value + } + return "" } diff --git a/cmd/gen.go b/cmd/gen.go index cedd2b81f..0b68f84c5 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -41,8 +41,7 @@ Make sure you run this command in the root path of a go project.`, // scan a directory and gen a gopm file func runGen(ctx *cli.Context) { - log.PureMode = ctx.GlobalBool("noterm") - log.Verbose = ctx.GlobalBool("verbose") + setup(ctx) if !com.IsExist(".gopmfile") { os.Create(".gopmfile") @@ -54,19 +53,9 @@ func runGen(ctx *cli.Context) { log.Fatal("", "\t"+err.Error()) } - curPath, err := os.Getwd() - if err != nil { - log.Error("gen", "Cannot get work directory:") - log.Fatal("", "\t"+err.Error()) - } - // Get dependencies. - importPath, err := gf.GetValue("target", "path") - if err != nil { - importPath = "." - } - imports := doc.GetAllImports([]string{curPath}, - importPath, ctx.Bool("example")) + imports := doc.GetAllImports([]string{workDir}, + parseTarget(gf.MustValue("target", "path")), ctx.Bool("example")) for _, p := range imports { if _, err := gf.GetValue("deps", doc.GetProjectPath(p)); err != nil { diff --git a/cmd/get.go b/cmd/get.go index 6828a8880..f96dae1b0 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -15,11 +15,9 @@ package cmd import ( - "errors" "fmt" "os" "path" - "path/filepath" "strings" "github.com/Unknwon/com" @@ -31,11 +29,13 @@ import ( ) var ( - installRepoPath string // The path of gopm local repository. - installGopath string // The first path in the GOPATH. - downloadCache map[string]bool // Saves packages that have been downloaded. - downloadCount int - failConut int + installRepoPath string // The path of gopm local repository. + installGopath string // The first path in the GOPATH. + isHasGopath bool // Indicates whether system has GOPATH. + + downloadCache map[string]bool // Saves packages that have been downloaded. + downloadCount int + failConut int ) var CmdGet = cli.Command{ @@ -50,16 +50,16 @@ gopm get @[:] Can specify one or more: gopm get beego@tag:v0.9.0 github.com/beego/bee -If no argument is supplied, then gopmfile must be present. If no version specified and package exists in GOPATH, it will be skipped unless user enabled '--remote, -r' option then all the packages go into gopm local repository.`, Action: runGet, Flags: []cli.Flag{ cli.BoolFlag{"gopath, g", "download all pakcages to GOPATH"}, - cli.BoolFlag{"force, f", "force to update pakcage(s) and dependencies"}, + cli.BoolFlag{"update, u", "update pakcage(s) and dependencies if any"}, cli.BoolFlag{"example, e", "download dependencies for example folder"}, cli.BoolFlag{"remote, r", "download all pakcages to gopm local repository"}, + cli.BoolFlag{"verbose, v", "show process details"}, }, } @@ -68,8 +68,7 @@ func init() { } func runGet(ctx *cli.Context) { - log.PureMode = ctx.GlobalBool("noterm") - log.Verbose = ctx.GlobalBool("verbose") + setup(ctx) // Check conflicts. if ctx.Bool("gopath") && ctx.Bool("remote") { @@ -82,85 +81,62 @@ func runGet(ctx *cli.Context) { if !ctx.Bool("remote") { // Get GOPATH. installGopath = com.GetGOPATHs()[0] - if !com.IsDir(installGopath) { - log.Error("get", "Invalid GOPATH path") - log.Error("", "GOPATH does not exist or is not a directory:") - log.Error("", "\t"+installGopath) - log.Help("Try 'go help gopath' to get more information") + if com.IsDir(installGopath) { + isHasGopath = true + log.Log("Indicated GOPATH: %s", installGopath) + installGopath += "/src" + } else { + if ctx.Bool("gopath") { + log.Error("get", "Invalid GOPATH path") + log.Error("", "GOPATH does not exist or is not a directory:") + log.Error("", "\t"+installGopath) + log.Help("Try 'go help gopath' to get more information") + } else { + // It's OK that no GOPATH setting + // when user does not specify to use. + log.Warn("No GOPATH setting available") + } } - log.Log("Indicated GOPATH: %s", installGopath) - installGopath += "/src" } // The gopm local repository. installRepoPath = doc.HomeDir + "/repos" log.Log("Local repository path: %s", installRepoPath) - // Check number of arguments. + // Check number of arguments to decide which function to call. switch len(ctx.Args()) { case 0: getByGopmfile(ctx) default: getByPath(ctx) } - } func getByGopmfile(ctx *cli.Context) { + // Check if gopmfile exists and generate one if not. if !com.IsFile(".gopmfile") { - log.Error("get", "Gopmfile not found") - log.Error("", "No argument is supplied and no gopmfile exists") - log.Help("\n%s\n%s\n%s", - "Work directory is supposed to have gopmfile when there is no argument supplied", - "Try 'gopm gen' to auto-generate gopmfile", - "Try 'gopm help gen' to get more information") + runGen(ctx) } - gf := doc.NewGopmfile(".") - absPath, err := filepath.Abs(".") - if err != nil { - log.Error("get", "Fail to get absolute path of work directory") - log.Fatal("", "\t"+err.Error()) - } - - log.Log("Work directory: %s", absPath) - // Get dependencies. - imports := doc.GetAllImports([]string{absPath}, - gf.MustValue("target", "path"), ctx.Bool("example")) - + imports := doc.GetAllImports([]string{workDir}, + parseTarget(gf.MustValue("target", "path")), ctx.Bool("example")) nodes := make([]*doc.Node, 0, len(imports)) for _, p := range imports { node := doc.NewNode(p, p, doc.BRANCH, "", true) // Check if user specified the version. if v, err := gf.GetValue("deps", p); err == nil && len(v) > 0 { - tp, ver, err := validPath(v) - if err != nil { - log.Error("get", "Cannot parse dependency version") - log.Error("", err.Error()+":") - log.Error("", "\t"+v) - log.Help("Try 'gopm help get' to get more information") - } - node.Type = tp - node.Value = ver + node.Type, node.Value = validPath(v) } nodes = append(nodes, node) } downloadPackages(ctx, nodes) + doc.SaveLocalNodes() - if doc.LocalNodes != nil { - if err := goconfig.SaveConfigFile(doc.LocalNodes, - doc.HomeDir+doc.LocalNodesFile); err != nil { - log.Error("get", "Fail to save localnodes.list:") - log.Error("", "\t"+err.Error()) - } - } - - log.Log("%d package(s) downloaded, %d failed", - downloadCount, failConut) + log.Log("%d package(s) downloaded, %d failed", downloadCount, failConut) } func getByPath(ctx *cli.Context) { @@ -171,13 +147,7 @@ func getByPath(ctx *cli.Context) { if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] - tp, ver, err := validPath(info[i+1:]) - if err != nil { - log.Error("get", "Cannot parse dependency version") - log.Error("", err.Error()+":") - log.Error("", "\t"+info[i+1:]) - log.Help("Try 'gopm help get' to get more information") - } + tp, ver := validPath(info[i+1:]) node = doc.NewNode(pkgPath, pkgPath, tp, ver, true) } @@ -190,17 +160,9 @@ func getByPath(ctx *cli.Context) { } downloadPackages(ctx, nodes) + doc.SaveLocalNodes() - if doc.LocalNodes != nil { - if err := goconfig.SaveConfigFile(doc.LocalNodes, - doc.HomeDir+doc.LocalNodesFile); err != nil { - log.Error("get", "Fail to save localnodes.list:") - log.Error("", "\t"+err.Error()) - } - } - - log.Log("%d package(s) downloaded, %d failed", - downloadCount, failConut) + log.Log("%d package(s) downloaded, %d failed", downloadCount, failConut) } func copyToGopath(srcPath, destPath string) { @@ -234,6 +196,7 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { if ctx.Bool("gopath") { copyToGopath(installPath, gopathDir) + log.Log("Package copied to GOPATH: %s", n.ImportPath) } continue } else { @@ -241,7 +204,7 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { } } - if !downloadCache[n.ImportPath] { + if !downloadCache[n.RootPath] { // Download package. nod, imports := downloadPackage(ctx, n) if len(imports) > 0 { @@ -249,7 +212,7 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { // Check if has gopmfile if com.IsFile(installPath + "/" + doc.GOPM_FILE_NAME) { - log.Log("Found gopmgile: %s@%s:%s", + log.Log("Found gopmfile: %s@%s:%s", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value)) gf = doc.NewGopmfile(installPath) @@ -268,15 +231,7 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { // Check if user specified the version. if v, err := gf.GetValue("deps", imports[i]); err == nil && len(v) > 0 { - tp, ver, err := validPath(v) - if err != nil { - log.Error("download", "Cannot parse dependency version") - log.Error("", err.Error()+":") - log.Error("", "\t"+v) - log.Help("Try 'gopm help get' to get more information") - } - nodes[i].Type = tp - nodes[i].Value = ver + nodes[i].Type, nodes[i].Value = validPath(v) } } downloadPackages(ctx, nodes) @@ -296,6 +251,7 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { if ctx.Bool("gopath") { copyToGopath(installPath, gopathDir) + log.Log("Package copied to GOPATH: %s", n.ImportPath) } } } else { @@ -318,7 +274,7 @@ func downloadPackage(ctx *cli.Context, nod *doc.Node) (*doc.Node, []string) { log.Message("Downloading", fmt.Sprintf("package: %s@%s:%s", nod.ImportPath, nod.Type, doc.CheckNodeValue(nod.Value))) // Mark as donwloaded. - downloadCache[nod.ImportPath] = true + downloadCache[nod.RootPath] = true nod.Revision = doc.LocalNodes.MustValue(nod.RootPath, "value") imports, err := doc.PureDownload(nod, installRepoPath, ctx) //CmdGet.Flags) @@ -332,29 +288,3 @@ func downloadPackage(ctx *cli.Context, nod *doc.Node) (*doc.Node, []string) { } return nod, imports } - -// validPath checks if the information of the package is valid. -func validPath(info string) (string, string, error) { - infos := strings.Split(info, ":") - - l := len(infos) - switch { - case l == 1: - return doc.BRANCH, "", nil - case l == 2: - switch infos[1] { - case doc.TRUNK, doc.MASTER, doc.DEFAULT: - infos[1] = "" - } - return infos[0], infos[1], nil - default: - return "", "", errors.New("Invalid version information") - } -} - -func versionSuffix(value string) string { - if len(value) > 0 { - return "." + value - } - return "" -} diff --git a/cmd/install.go b/cmd/install.go index d73e27d2a..9182c5e32 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -36,7 +36,6 @@ gopm install If no argument is supplied, then gopmfile must be present`, Action: runInstall, Flags: []cli.Flag{ - cli.BoolFlag{"verbose, v", "show process details"}, cli.BoolFlag{"pkg, p", "only install non-main packages"}, }, } diff --git a/cmd/search.go b/cmd/search.go index 17f8ad405..f3cb1b5cc 100644 --- a/cmd/search.go +++ b/cmd/search.go @@ -14,99 +14,99 @@ package cmd -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - - "github.com/Unknwon/com" -) - -var CmdSearch = &Command{ - UsageLine: "search [keyword]", - Short: "search for package", - Long: ` -search packages - -The search flags are: - - -e - search extactly, you should input an exactly package name as keyword -`, -} - -func init() { - CmdSearch.Run = runSearch - CmdSearch.Flags = map[string]bool{ - "-e": false, - } -} - -func printSearchPrompt(flag string) { - switch flag { - case "-e": - com.ColorLog("[INFO] You enabled exactly search.\n") - } -} - +// import ( +// "encoding/json" +// "fmt" +// "io/ioutil" +// "net/http" + +// "github.com/Unknwon/com" +// ) + +// var CmdSearch = &Command{ +// UsageLine: "search [keyword]", +// Short: "search for package", +// Long: ` // search packages -func runSearch(cmd *Command, args []string) { - - // Check length of arguments. - if len(args) < 1 { - com.ColorLog("[ERROR] Please input package's keyword.\n") - return - } - - var host, port string - host = "localhost" - port = "8991" - - if cmd.Flags["-e"] { - search(host, port, args[0], true) - } else { - search(host, port, args[0], false) - } -} - -type searchRes struct { - Pkg string - Desc string -} - -/* -request local or remote search service to find packages according to keyword inputed -*/ -func search(host, port, keyword string, isExactly bool) { - url := fmt.Sprintf("http://%v:%v/search?%v", host, port, keyword) - if isExactly { - url = fmt.Sprintf("http://%v:%v/searche?%v", host, port, keyword) - } - resp, err := http.Get(url) - if err != nil { - com.ColorLog(err.Error()) - return - } - defer resp.Body.Close() - - if resp.StatusCode == 200 { - contents, err := ioutil.ReadAll(resp.Body) - if err != nil { - com.ColorLog(err.Error()) - return - } - - pkgs := make([]searchRes, 0) - err = json.Unmarshal(contents, &pkgs) - if err != nil { - com.ColorLog(err.Error()) - return - } - for i, pkg := range pkgs { - fmt.Println(i+1, pkg.Pkg, "\t", pkg.Desc) - } - } else { - com.ColorLog(resp.Status) - } -} + +// The search flags are: + +// -e +// search extactly, you should input an exactly package name as keyword +// `, +// } + +// func init() { +// CmdSearch.Run = runSearch +// CmdSearch.Flags = map[string]bool{ +// "-e": false, +// } +// } + +// func printSearchPrompt(flag string) { +// switch flag { +// case "-e": +// com.ColorLog("[INFO] You enabled exactly search.\n") +// } +// } + +// // search packages +// func runSearch(cmd *Command, args []string) { + +// // Check length of arguments. +// if len(args) < 1 { +// com.ColorLog("[ERROR] Please input package's keyword.\n") +// return +// } + +// var host, port string +// host = "localhost" +// port = "8991" + +// if cmd.Flags["-e"] { +// search(host, port, args[0], true) +// } else { +// search(host, port, args[0], false) +// } +// } + +// type searchRes struct { +// Pkg string +// Desc string +// } + +// /* +// request local or remote search service to find packages according to keyword inputed +// */ +// func search(host, port, keyword string, isExactly bool) { +// url := fmt.Sprintf("http://%v:%v/search?%v", host, port, keyword) +// if isExactly { +// url = fmt.Sprintf("http://%v:%v/searche?%v", host, port, keyword) +// } +// resp, err := http.Get(url) +// if err != nil { +// com.ColorLog(err.Error()) +// return +// } +// defer resp.Body.Close() + +// if resp.StatusCode == 200 { +// contents, err := ioutil.ReadAll(resp.Body) +// if err != nil { +// com.ColorLog(err.Error()) +// return +// } + +// pkgs := make([]searchRes, 0) +// err = json.Unmarshal(contents, &pkgs) +// if err != nil { +// com.ColorLog(err.Error()) +// return +// } +// for i, pkg := range pkgs { +// fmt.Println(i+1, pkg.Pkg, "\t", pkg.Desc) +// } +// } else { +// com.ColorLog(resp.Status) +// } +// } diff --git a/cmd/update.go b/cmd/update.go index db592e65a..54d90c6dc 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -69,11 +69,7 @@ func runUpdate(ctx *cli.Context) { var err error if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] - _, ver, err = validPath(info[i+1:]) - if err != nil { - log.Error("Update", "Fail to parse version") - log.Fatal("", err.Error()) - } + _, ver = validPath(info[i+1:]) } // Check package name. diff --git a/doc/conf.go b/doc/conf.go index 64def7765..ca964bd96 100644 --- a/doc/conf.go +++ b/doc/conf.go @@ -93,7 +93,7 @@ func GetPkgFullPath(short string) string { name, ok := PackageNameList[short] if !ok { log.Error("", "Invalid package name") - log.Error("", "No match in the package name list:") + log.Error("", "It's not a invalid import path and no match in the package name list:") log.Fatal("", "\t"+short) } return name @@ -109,9 +109,17 @@ func LoadLocalNodes() { } var err error - LocalNodes, err = goconfig.LoadConfigFile(HomeDir + LocalNodesFile) + LocalNodes, err = goconfig.LoadConfigFile(path.Join(HomeDir + LocalNodesFile)) if err != nil { - log.Error("Load node", "Fail to load localnodes.list") + log.Error("load node", "Fail to load localnodes.list") log.Fatal("", err.Error()) } } + +func SaveLocalNodes() { + if err := goconfig.SaveConfigFile(LocalNodes, + path.Join(HomeDir+LocalNodesFile)); err != nil { + log.Error("", "Fail to save localnodes.list:") + log.Error("", "\t"+err.Error()) + } +} diff --git a/doc/vcs.go b/doc/vcs.go index 58635db3b..c3afc090c 100644 --- a/doc/vcs.go +++ b/doc/vcs.go @@ -26,6 +26,7 @@ import ( "github.com/Unknwon/com" "github.com/codegangsta/cli" + "github.com/gpmgo/gopm/log" ) var ( @@ -119,7 +120,7 @@ func PureDownload(nod *Node, installRepoPath string, ctx *cli.Context) ([]string return s.get(HttpClient, match, installRepoPath, nod, ctx) } - com.ColorLog("[TRAC] Cannot match any service, getting dynamic...\n") + log.Log("Cannot match any service, getting dynamic...") return getDynamic(HttpClient, nod, installRepoPath, ctx) } diff --git a/gopm.go b/gopm.go index 93ed8ea9b..49ac28adb 100644 --- a/gopm.go +++ b/gopm.go @@ -29,7 +29,7 @@ import ( // Test that go1.1 tag above is included in builds. main.go refers to this definition. const go11tag = true -const APP_VER = "0.5.7.1205" +const APP_VER = "0.6.0.1206" // //cmd.CmdSearch, // cmdClean, @@ -63,7 +63,6 @@ func main() { } app.Flags = append(app.Flags, []cli.Flag{ cli.BoolFlag{"noterm", "disable color output"}, - cli.BoolFlag{"verbose", "show process details"}, }...) app.Run(os.Args) }