From 1c63ab09796426d04b37f64d2423e1b4b258c044 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 9 Nov 2013 16:47:39 -0500 Subject: [PATCH] Done get and gen --- .gopmfile | 7 +++- README.md | 53 +++++++----------------- cmd/cmd.go | 3 +- cmd/gen.go | 104 +++++++++++++++++------------------------------- cmd/get.go | 63 ++++++++++++++++++++++++----- doc/conf.go | 93 +++++++++++++++++++++++++++++++++++++++++++ doc/gopmfile.go | 40 ------------------- doc/utils.go | 38 +++++++----------- gopm.go | 5 +-- 9 files changed, 221 insertions(+), 185 deletions(-) create mode 100644 doc/conf.go delete mode 100644 doc/gopmfile.go diff --git a/.gopmfile b/.gopmfile index 2cedaa233..086c3463a 100644 --- a/.gopmfile +++ b/.gopmfile @@ -1,4 +1,9 @@ [target] -path = github.com/gpmgo/gopm +path=github.com/gpmgo/gopm [deps] +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 307eac08b..9abcafd48 100644 --- a/README.md +++ b/README.md @@ -30,51 +30,26 @@ The executable will be produced under `$GOPATH/bin` in your file system; for glo - When build program with `gopm build` or `gopm install`, everything just happen in its own GOPATH and do not bother anything you've done. * Put your Go project on anywhere you want. -# Quick start +# Commands -1. Show the command help - -``` -gopm help ``` +NAME: + gopm - Go Package Manager -2. Show gopm version - -``` -gopm version -``` +USAGE: + gopm [global options] command [command options] [arguments...] -3. Get a package +VERSION: + 0.5.2.1109 -``` -gopm get github.com/gpmgo/gopm -``` - -4. Search a package - -``` -gopm search gopm -``` +COMMANDS: + get fetch remote package(s) and dependencies to local repository + gen generate a gopmfile according current go project + help, h Shows a list of commands or help for one command -5. Build a project, the build's arguments are the same as go build. But it will check all the dependencies and dowload them. - -``` - -gopm build -``` - -6. Run a go file - -``` - -gopm run main.go -``` - -7. Install - -``` - -gopm install +GLOBAL OPTIONS: + --version print the version + --help, -h show help ``` diff --git a/cmd/cmd.go b/cmd/cmd.go index 19c96bb59..7bccbbb60 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -21,8 +21,7 @@ import ( ) var ( - AppPath string - reposDir string = "~/.gopm/repos" + AppPath string ) // A Command is an implementation of a go command diff --git a/cmd/gen.go b/cmd/gen.go index c7673a1c0..7d727f094 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -15,93 +15,63 @@ package cmd import ( - "github.com/Unknwon/com" - "go/build" "os" - "path" - "runtime" - "strings" -) - -var CmdGen = &Command{ - UsageLine: "gen [.gopmfile]", - Short: "generate a gopmfile according current go project", - Long: ` -generate a gopmfile according current go project -`, -} -func init() { - CmdGen.Run = runGen - CmdGen.Flags = map[string]bool{} -} + "github.com/Unknwon/com" + "github.com/Unknwon/goconfig" + "github.com/codegangsta/cli" -func printGenPrompt(flag string) { -} + "github.com/gpmgo/gopm/doc" + "github.com/gpmgo/gopm/log" +) -func isStdPkg(pkgName string) bool { - return com.IsExist(path.Join(path.Join(runtime.GOROOT(), "src/pkg"), pkgName)) -} +var CmdGen = cli.Command{ + Name: "gen", + Usage: "generate a gopmfile according current go project", + Description: `Command gen gets dependencies and generates a gopmfile -func getPkgs(path string, inludeSys bool) ([]string, error) { - pkg, err := build.ImportDir(path, build.AllowBinary) - if err != nil { - return []string{}, err - } +gopm gen - if inludeSys { - return pkg.Imports, nil - } else { - pkgs := make([]string, 0) - for _, name := range pkg.Imports { - if !isStdPkg(name) { - pkgs = append(pkgs, name) - } - } - return pkgs, nil - } +Make sure you run this command in the root path of a go project.`, + Action: runGen, + Flags: []cli.Flag{ + cli.BoolFlag{"example", "download dependencies for example(s)"}, + }, } // scan a directory and gen a gopm file -func runGen(cmd *Command, args []string) { +func runGen(ctx *cli.Context) { + if !com.IsExist(".gopmfile") { + os.Create(".gopmfile") + } - var gopmFile string = ".gopmfile" - if len(args) > 0 { - gopmFile = args[0] + gf, err := goconfig.LoadConfigFile(".gopmfile") + if err != nil { + log.Error("Gen", "Fail to load gopmfile") + log.Fatal("", err.Error()) } curPath, err := os.Getwd() if err != nil { - com.ColorLog("[ERRO] %v.\n", err) - return + log.Error("Gen", "Fail to get work directory") + log.Fatal("", err.Error()) } - gopmPath := path.Join(curPath, gopmFile) - - if com.IsExist(gopmPath) { - com.ColorLog("[WARN] %v already existed.\n", gopmFile) - return - } + // Get dependencies. + imports := doc.GetAllImports([]string{curPath}, + gf.MustValue("target", "path"), ctx.Bool("example")) - // search the project and gen gopmfile - pkgs, err := getPkgs(curPath, false) - if err != nil { - com.ColorLog("[ERRO] %v.\n", err) - return + for _, p := range imports { + if _, err := gf.GetValue("deps", doc.GetProjectPath(p)); err != nil { + gf.SetValue("deps", doc.GetProjectPath(p), " ") + } } - f, err := os.OpenFile(gopmPath, os.O_RDWR|os.O_CREATE, 0700) + err = goconfig.SaveConfigFile(gf, ".gopmfile") if err != nil { - com.ColorLog("[ERRO] %v.\n", err) - return + log.Error("Gen", "Fail to save gopmfile") + log.Fatal("", err.Error()) } - defer f.Close() - contents := "[build]\n" + strings.Join(pkgs, "\n") - _, err = f.WriteString(contents) - if err != nil { - com.ColorLog("[ERRO] %v.\n", err) - return - } - com.ColorLog("[INFO] %v generated successfully.\n", gopmFile) + log.Success("SUCC", "Gen", "Generate gopmfile successful!") } diff --git a/cmd/get.go b/cmd/get.go index 4912b3594..8436c7cab 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -22,6 +22,7 @@ import ( "strings" "github.com/Unknwon/com" + "github.com/Unknwon/goconfig" "github.com/codegangsta/cli" "github.com/gpmgo/gopm/doc" @@ -66,7 +67,10 @@ func runGet(ctx *cli.Context) { log.Fatal("", err.Error()) } - installRepoPath = strings.Replace(reposDir, "~", hd, -1) + doc.HomeDir = strings.Replace(doc.HomeDir, "~", hd, -1) + doc.LoadPkgNameList(doc.HomeDir + "/data/pkgname.list") + + installRepoPath = doc.HomeDir + "/repos" log.Log("Local repository path: %s", installRepoPath) // Check number of arguments. @@ -102,7 +106,7 @@ func getByGopmfile(ctx *cli.Context) { node := doc.NewNode(p, p, doc.BRANCH, "", true) // Check if user specified the version. - if v, err := gf.GetValue("deps", p); err == nil { + if v, err := gf.GetValue("deps", p); err == nil && len(v) > 0 { tp, ver, err := validPath(v) if err != nil { log.Error("", "Fail to parse version") @@ -116,6 +120,13 @@ func getByGopmfile(ctx *cli.Context) { downloadPackages(ctx, nodes) + 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.Log("%d package(s) downloaded, %d failed", downloadCount, failConut) } @@ -151,6 +162,13 @@ func getByPath(ctx *cli.Context) { downloadPackages(ctx, nodes) + 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.Log("%d package(s) downloaded, %d failed", downloadCount, failConut) } @@ -163,12 +181,13 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { for _, n := range nodes { // Check if it is a valid remote path. if doc.IsValidRemotePath(n.ImportPath) { + installPath := installRepoPath + "/" + doc.GetProjectPath(n.ImportPath) + if len(n.Value) > 0 { + installPath += "." + n.Value + } + if !ctx.Bool("force") { // Check if package has been downloaded. - installPath := installRepoPath + "/" + doc.GetProjectPath(n.ImportPath) - if len(n.Value) > 0 { - installPath += "." + n.Value - } if com.IsExist(installPath) { log.Trace("Skipped installed package: %s@%s:%s", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value)) @@ -180,13 +199,37 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { // Download package. nod, imports := downloadPackage(n) if len(imports) > 0 { - // TODO: 检查是否有 gopmfile + var gf *goconfig.ConfigFile + + // Check if has gopmfile + if com.IsFile(installPath + "/.gopmfile") { + log.Log("Found gopmgile: %s@%s:%s", + n.ImportPath, n.Type, doc.CheckNodeValue(n.Value)) + + gf = doc.NewGopmfile(installPath + "/.gopmfile") + } // Need to download dependencies. // Generate temporary nodes. nodes := make([]*doc.Node, len(imports)) for i := range nodes { nodes[i] = doc.NewNode(imports[i], imports[i], doc.BRANCH, "", true) + + if gf == nil { + continue + } + + // 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", "Fail to parse version") + log.Fatal("", err.Error()) + } + nodes[i].Type = tp + nodes[i].Value = ver + } } downloadPackages(ctx, nodes) } @@ -198,8 +241,10 @@ func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { n.ImportPath, n.Type, doc.CheckNodeValue(n.Value))) downloadCount++ - // TODO: 保存包信息 - //saveNode(nod) + // Only save non-commit node. + if len(nod.Value) == 0 { + doc.SaveNode(nod) + } } } else { log.Trace("Skipped downloaded package: %s@%s:%s", diff --git a/doc/conf.go b/doc/conf.go new file mode 100644 index 000000000..bed33cdf0 --- /dev/null +++ b/doc/conf.go @@ -0,0 +1,93 @@ +// Copyright 2013 gopm authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package doc + +import ( + "os" + "strings" + + "github.com/Unknwon/com" + "github.com/Unknwon/goconfig" + + "github.com/gpmgo/gopm/log" +) + +const ( + GopmFileName = ".gopmfile" +) + +var ( + HomeDir = "~/.gopm" + LocalNodesFile = "/data/localnodes.list" + LocalNodes *goconfig.ConfigFile +) + +func NewGopmfile(dirPath string) *goconfig.ConfigFile { + gf, err := goconfig.LoadConfigFile(dirPath + "/" + GopmFileName) + if err != nil { + log.Error("", "Fail to load gopmfile") + log.Fatal("", err.Error()) + } + return gf +} + +var PackageNameList map[string]string + +func LoadPkgNameList(filePath string) { + PackageNameList = make(map[string]string) + + // If file does not exist, simply ignore. + if !com.IsFile(filePath) { + return + } + + data, err := com.ReadFile(filePath) + if err != nil { + log.Error("Package name list", "Fail to read file") + log.Fatal("", err.Error()) + } + + pkgs := strings.Split(string(data), "\n") + for _, line := range pkgs { + infos := strings.Split(line, "=") + if len(infos) != 2 { + log.Error("", "Fail to parse package name: "+line) + log.Fatal("", "Invalid package name information") + } + PackageNameList[strings.TrimSpace(infos[0])] = + strings.TrimSpace(infos[1]) + } +} + +func SaveNode(nod *Node) { + if LocalNodes == nil { + if !com.IsDir(HomeDir + "/data") { + os.Mkdir(HomeDir+"/data", os.ModePerm) + } + + if !com.IsFile(HomeDir + LocalNodesFile) { + os.Create(HomeDir + LocalNodesFile) + } + + var err error + LocalNodes, err = goconfig.LoadConfigFile(HomeDir + LocalNodesFile) + if err != nil { + log.Error("Save node", "Fail to load localnodes.list") + log.Fatal("", err.Error()) + } + } + + LocalNodes.SetValue(nod.ImportPath, "value", nod.Value) +} diff --git a/doc/gopmfile.go b/doc/gopmfile.go deleted file mode 100644 index d947796c0..000000000 --- a/doc/gopmfile.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2013 gopm authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package doc - -import ( - "github.com/Unknwon/goconfig" - - "github.com/gpmgo/gopm/log" -) - -const ( - GopmFileName = ".gopmfile" -) - -func NewGopmfile(dirPath string) *goconfig.ConfigFile { - gf, err := goconfig.LoadConfigFile(dirPath + "/" + GopmFileName) - if err != nil { - log.Error("", "Fail to load gopmfile") - log.Fatal("", err.Error()) - } - return gf -} - -var PackageNameList map[string]string - -func init() { - PackageNameList = make(map[string]string) -} diff --git a/doc/utils.go b/doc/utils.go index 9af8cfcbb..b0daae599 100644 --- a/doc/utils.go +++ b/doc/utils.go @@ -15,6 +15,7 @@ package doc import ( + "go/build" "os" "path" "regexp" @@ -44,42 +45,31 @@ func GetDirsInfo(rootPath string) []os.FileInfo { } // GetImports returns package denpendencies. -func GetImports(absPath, importPath string, example bool) (imports []string) { +func GetImports(absPath, importPath string, example bool) []string { + pkg, err := build.ImportDir(absPath, build.AllowBinary) + if err != nil { + if _, ok := err.(*build.NoGoError); !ok { + log.Error("", "Fail to get imports") + log.Fatal("", err.Error()) + } + } + fis := GetDirsInfo(absPath) absPath += "/" dirs := make([]string, 0) - files := make([]*source, 0, 10) for _, fi := range fis { if fi.IsDir() { dirs = append(dirs, absPath+fi.Name()) - continue - } - - if strings.HasSuffix(fi.Name(), ".go") { - data, err := com.ReadFile(absPath + fi.Name()) - if err != nil { - log.Error("", "Fail to read file") - log.Fatal("", err.Error()) - } - - files = append(files, &source{ - name: fi.Name(), - data: data, - }) } } - var err error - if len(files) > 0 { - w := &walker{ImportPath: importPath} - imports, err = w.build(files, nil) - if err != nil { - log.Error("", "Fail to get imports") - log.Fatal("", err.Error()) + imports := make([]string, 0, len(pkg.Imports)) + for _, p := range pkg.Imports { + if !IsGoRepoPath(p) && !strings.HasPrefix(p, importPath) { + imports = append(imports, p) } } - if len(dirs) > 0 { imports = append(imports, GetAllImports(dirs, importPath, example)...) } diff --git a/gopm.go b/gopm.go index b6165ca6f..e9de6bddb 100644 --- a/gopm.go +++ b/gopm.go @@ -19,7 +19,6 @@ import ( "os" "runtime" - //"github.com/Unknwon/com" "github.com/codegangsta/cli" "github.com/gpmgo/gopm/cmd" @@ -30,10 +29,9 @@ 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.1.1108" +const APP_VER = "0.5.3.1109" // //cmd.CmdSearch, -// cmd.CmdGen, // cmd.CmdRun, // cmd.CmdBuild, // cmd.CmdInstall, @@ -59,6 +57,7 @@ func main() { app.Version = APP_VER app.Commands = []cli.Command{ cmd.CmdGet, + cmd.CmdGen, } app.Run(os.Args) }