Browse Source

add command install flag -c: download pure code.

pull/103/head
Unknown 12 years ago
parent
commit
377a95c423
  1. 14
      README.md
  2. 12
      build.go
  3. 2
      conf/gpm.toml
  4. 7
      doc/bitbucket.go
  5. 54
      doc/github.go
  6. 9
      doc/google.go
  7. 45
      doc/launchpad.go
  8. 4
      i18n/en-US/prompt.txt
  9. 2
      i18n/en-US/usage_install.txt
  10. 4
      i18n/zh-CN/prompt.txt
  11. 2
      i18n/zh-CN/usage_install.txt
  12. 14
      install.go
  13. 51
      remove.go
  14. 24
      utils/utils.go
  15. 44
      utils/utils_test.go

14
README.md

@ -20,6 +20,7 @@ This application still in experiment, any change could happen, but it doesn't af
## Main commands
- `build` compiles and installs packages and dependencies: basically, it calls `go install` and moves executable to current path from `GOPATH` if any, the executable name is the folder name which is default by `go install`.
- `search` searchs packages in [Go Walker](http://gowalker.org) database by keyword.
- `install` downloads and installs packages and dependencies: you can download packages without version control tools like git, hg, svn, etc. It downloads and installs all packages including all dependencies automatically(except when you use bundle or snapshot). For now, this command supports `code.google.com`, `github.com`, `launchpad.net`, `bitbucket.org`.
- `remove` removes packages and dependencies: it removes all packages including all dependencies(except when you use bundle or snapshot).
@ -31,19 +32,15 @@ This application still in experiment, any change could happen, but it doesn't af
### v0.2.*
- Add gpm working principle design.
- Command `install` and `remove` Add bundle and snapshot parser code for downloading or removing by bundle or snapshot.
- Command `check` is for checking and downloading all missing dependencies.
- Command `update` is for checking updates.
- Command `remove` also need to remove files in `GPPATH/bin` and `GOPATH/pkg`.
- i18n support for Chinese.
- Add built-in application version in order to backup data when users update.
- Command `install` add flag `-pc` which only downloads source files(including LICENSE and README).
- Add template projects for testing commands.
- Add feature auto-catch if run under GOPATH/bin.
### Future
- Command `search` add flags `-n` and `-o` for number of list items and offset.
- Command `update` is for checking updates.
- Command `sync` is for sync packages in two computers, support client and server mode through ssh.
- Command `init` is for auto-configuring Go develop environment.
- Command `install` and `remove` and `update` backup data(up to 100 records) before executing.
@ -62,6 +59,11 @@ This application still in experiment, any change could happen, but it doesn't af
- Download package from code.google.com only support hg as version control system, probably support git and svn.
- Command `install` add support for downloading code from git.oschina.net, gitcafe.com, *.codeplex.com;
- Command `install` add support for downloading by tag and branch for packages in git.oschina.net, gitcafe.com.
- Command `install` and `remove` add bundle parse code for getting data from server.
- Command `install` and `remove` add snapshot parse code for downloading or removing snapshot.
- Add built-in application version in order to backup data when users update.
- Add gpm working principle design.
- Command `install -c` add arguments for add more exts.
## License

12
build.go

@ -7,9 +7,6 @@ package main
import (
"fmt"
"os"
"path"
"runtime"
"strings"
"github.com/GPMGo/gpm/utils"
)
@ -50,14 +47,9 @@ func runBuild(cmd *Command, args []string) {
executeCommand("go", cmdArgs)
wd, _ := os.Getwd()
wd = strings.Replace(wd, "\\", "/", -1)
proName := path.Base(wd)
if runtime.GOOS == "windows" {
proName += ".exe"
}
// Find executable in GOPATH and copy to current directory.
wd, _ := os.Getwd()
proName := utils.GetExecuteName(wd)
paths := utils.GetGOPATH()
for _, v := range paths {

2
conf/gpm.toml

@ -1,7 +1,7 @@
# This is a configuration file for gpm with toml format.
title = "gpm(Go Package Manager)"
version = "v0.1.7 Build 0523"
version = "v0.1.9 Build 0523"
user_language = "en-US"
#user_language = "zh-CN"

7
doc/bitbucket.go

@ -15,6 +15,8 @@ import (
"path"
"regexp"
"strings"
"github.com/GPMGo/gpm/utils"
)
var (
@ -103,6 +105,7 @@ func GetBitbucketDoc(client *http.Client, match map[string]string, installGOPATH
tr := tar.NewReader(gzr)
isCodeOnly := cmdFlags["-c"]
var autoPath string // Auto path is the root path that generated by bitbucket.org.
// Get source file data.
dirs := make([]string, 0, 5)
@ -134,6 +137,10 @@ func GetBitbucketDoc(client *http.Client, match map[string]string, installGOPATH
os.MkdirAll(dir+"/", os.ModePerm)
}
if isCodeOnly && !utils.IsDocFile(path.Base(absPath)) {
continue
}
// Get data from archive.
fbytes := make([]byte, h.Size)
if _, err := io.ReadFull(tr, fbytes); err != nil {

54
doc/github.go

@ -14,6 +14,8 @@ import (
"path"
"regexp"
"strings"
"github.com/GPMGo/gpm/utils"
)
var (
@ -116,47 +118,47 @@ func GetGithubDoc(client *http.Client, match map[string]string, installGOPATH st
return nil, err
}
isCodeOnly := cmdFlags["-c"]
dirs := make([]string, 0, 5)
// Need to add root path because we cannot get from tarball.
dirs = append(dirs, installPath+"/")
for _, f := range r.File {
absPath := strings.Replace(f.FileInfo().Name(), shaName, installPath, 1)
// Create diretory before create file.
os.MkdirAll(path.Dir(absPath)+"/", os.ModePerm)
// Check if it is a directory.
if strings.HasSuffix(absPath, "/") {
// Directory.
switch {
case strings.HasSuffix(absPath, "/"): // Directory.
// Check if current directory is example.
if !(!cmdFlags["-e"] && strings.Contains(absPath, "example")) {
dirs = append(dirs, absPath)
}
case isCodeOnly && !utils.IsDocFile(path.Base(absPath)):
continue
}
// Create diretory before create file.
os.MkdirAll(path.Dir(absPath)+"/", os.ModePerm)
default:
// Get file from archive.
rc, err := f.Open()
if err != nil {
return nil, err
}
// Get file from archive.
rc, err := f.Open()
if err != nil {
return nil, err
}
// Write data to file
fw, _ := os.Create(absPath)
if err != nil {
return nil, err
}
// Write data to file
fw, _ := os.Create(absPath)
if err != nil {
return nil, err
}
_, err = io.Copy(fw, rc)
// Close files.
rc.Close()
fw.Close()
if err != nil {
return nil, err
}
_, err = io.Copy(fw, rc)
// Close files.
rc.Close()
fw.Close()
if err != nil {
return nil, err
// Set modify time.
os.Chtimes(absPath, f.ModTime(), f.ModTime())
}
// Set modify time.
os.Chtimes(absPath, f.ModTime(), f.ModTime())
}
var imports []string

9
doc/google.go

@ -11,6 +11,8 @@ import (
"path"
"regexp"
"strings"
"github.com/GPMGo/gpm/utils"
)
var (
@ -90,10 +92,15 @@ func GetGoogleDoc(client *http.Client, match map[string]string, installGOPATH st
// Create destination directory.
os.MkdirAll(installPath+"/", os.ModePerm)
isCodeOnly := cmdFlags["-c"]
// Get source files in root path.
files := make([]*source, 0, 5)
for _, m := range googleFileRe.FindAllSubmatch(p, -1) {
fname := strings.Split(string(m[1]), "?")[0]
if isCodeOnly && !utils.IsDocFile(fname) {
continue
}
files = append(files, &source{
name: fname,
rawURL: expand("http://{subrepo}{dot}{repo}.googlecode.com/{vcs}{dir}/{0}", match, fname) + "?r=" + node.Value,
@ -182,7 +189,7 @@ func downloadFiles(client *http.Client, match map[string]string, rootPath, insta
// Get source files in current path.
files := make([]*source, 0, 5)
for _, m := range googleFileRe.FindAllSubmatch(p, -1) {
fname := string(m[1])
fname := strings.Split(string(m[1]), "?")[0]
files = append(files, &source{
name: fname,
rawURL: expand("http://{subrepo}{dot}{repo}.googlecode.com/{vcs}{dir}/", match) + d + fname + "?r=" + commit,

45
doc/launchpad.go

@ -14,6 +14,8 @@ import (
"path"
"regexp"
"strings"
"github.com/GPMGo/gpm/utils"
)
var LaunchpadPattern = regexp.MustCompile(`^launchpad\.net/(?P<repo>(?P<project>[a-z0-9A-Z_.\-]+)(?P<series>/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+)(?P<dir>/[a-z0-9A-Z_.\-/]+)*$`)
@ -72,6 +74,7 @@ func GetLaunchpadDoc(client *http.Client, match map[string]string, installGOPATH
tr := tar.NewReader(gzr)
isCodeOnly := cmdFlags["-c"]
var autoPath string // Auto path is the root path that generated by bitbucket.org.
// Get source file data.
dirs := make([]string, 0, 5)
@ -90,35 +93,35 @@ func GetLaunchpadDoc(client *http.Client, match map[string]string, installGOPATH
}
absPath := strings.Replace(fn, autoPath, installPath, 1)
// Check if it is a directory.
if h.FileInfo().IsDir() {
// Directory.
switch {
case h.FileInfo().IsDir(): // Directory.
// Check if current directory is example.
if !(!cmdFlags["-e"] && strings.Contains(absPath, "example")) {
dirs = append(dirs, absPath)
}
case isCodeOnly && !utils.IsDocFile(path.Base(absPath)):
continue
}
// Create diretory before create file.
os.MkdirAll(path.Dir(absPath)+"/", os.ModePerm)
default:
// Create diretory before create file.
os.MkdirAll(path.Dir(absPath)+"/", os.ModePerm)
// Get data from archive.
fbytes := make([]byte, h.Size)
if _, err := io.ReadFull(tr, fbytes); err != nil {
return nil, err
}
// Get data from archive.
fbytes := make([]byte, h.Size)
if _, err := io.ReadFull(tr, fbytes); err != nil {
return nil, err
}
// Write data to file
fw, err := os.Create(absPath)
if err != nil {
return nil, err
}
// Write data to file
fw, err := os.Create(absPath)
if err != nil {
return nil, err
}
_, err = fw.Write(fbytes)
fw.Close()
if err != nil {
return nil, err
_, err = fw.Write(fbytes)
fw.Close()
if err != nil {
return nil, err
}
}
}

4
i18n/en-US/prompt.txt

@ -14,6 +14,7 @@ PackageNotFound=Cannot find package: %s.
MovedFile=SUCCESS: Moved file from $GOPATH(%s) to current directory(%s).
PureDownload=You enabled pure download.
PureCode=You enabled pure code.
DownloadOnly=You enabled download without installing.
DownloadExDeps=You enabled download dependencies in example.
DownloadFromSrcs=You enabled download from sources.
@ -28,4 +29,5 @@ InstallByGoGet=Installing package(%s) through 'go get'.
NoVCSTool=No version control tool is available, pure download enabled!
DownloadStatus=Downloading package: %s.
RemovePackage=Removing package: %s.
NoKeyword=Cannot search without a keyword.
NoKeyword=Cannot search without a keyword.
ContinueRemove=Continue to remove?(Y/n).

2
i18n/en-US/usage_install.txt

@ -9,6 +9,8 @@ The install flags are:
-p
pure download packages without version control.
-c
download source code only.
-d
download without installing packages.
-u

4
i18n/zh-CN/prompt.txt

@ -14,6 +14,7 @@ PackageNotFound=无法找到包: %s.
MovedFile=SUCCESS: 成功将文件从 $GOPATH(%s) 移动至当前目录 (%s).
PureDownload=已激活纯净下载模式.
PureCode=已激活纯代码下载模式.
DownloadOnly=已激活无安装模式.
DownloadExDeps=已激活下载示例代码依赖.
DownloadFromSrcs=已激活从用户源下载.
@ -28,4 +29,5 @@ InstallByGoGet=正在通过 'go get' 安装包 (%s).
NoVCSTool=未找到合适的版本控制工具,已激活纯净下载模式!
DownloadStatus=正在下载包: %s.
RemovePackage=正在删除包: %s.
NoKeyword=没有关键字,无法搜索.
NoKeyword=没有关键字,无法搜索.
ContinueRemove=是否继续删除?(Y/n).

2
i18n/zh-CN/usage_install.txt

@ -9,6 +9,8 @@ The install flags are:
-p
pure download packages without version control.
-c
download source code only.
-d
download without installing packages.
-u

14
install.go

@ -33,6 +33,7 @@ func init() {
cmdInstall.Run = runInstall
cmdInstall.Flags = map[string]bool{
"-p": false,
"-c": false,
"-d": false,
"-u": false, // Flag for 'go get'.
"-e": false,
@ -46,6 +47,8 @@ func printInstallPrompt(flag string) {
switch flag {
case "-p":
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["PureDownload"]))
case "-c":
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["PureCode"]))
case "-d":
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["DownloadOnly"]))
case "-e":
@ -193,12 +196,13 @@ func downloadPackages(nodes []*doc.Node) {
for _, n := range nodes {
// Check if it is a bundle or snapshot.
switch {
case n.ImportPath[0] == 'B':
case strings.HasSuffix(n.ImportPath, ".b"):
l := len(n.ImportPath)
// Check local bundles.
bnodes := checkLocalBundles(n.ImportPath[1:])
bnodes := checkLocalBundles(n.ImportPath[:l-2])
if len(bnodes) > 0 {
// Check with users if continue.
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["BundleInfo"]), n.ImportPath[1:])
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["BundleInfo"]), n.ImportPath[:l-2])
for _, bn := range bnodes {
fmt.Printf("[%s] -> %s: %s.\n", bn.ImportPath, bn.Type, bn.Value)
}
@ -212,9 +216,9 @@ func downloadPackages(nodes []*doc.Node) {
} else {
// Check from server.
// TODO: api.GetBundleInfo()
fmt.Println("Unable to check with server right now.")
fmt.Println("Unable to find bundle, and we cannot check with server right now.")
}
case n.ImportPath[0] == 'S':
case strings.HasSuffix(n.ImportPath, ".s"):
// TODO: api.GetSnapshotInfo()
case utils.IsValidRemotePath(n.ImportPath):
if !downloadCache[n.ImportPath] {

51
remove.go

@ -8,6 +8,8 @@ import (
"encoding/json"
"fmt"
"os"
"runtime"
"strings"
"github.com/GPMGo/gpm/doc"
"github.com/GPMGo/gpm/utils"
@ -66,8 +68,29 @@ func removePackages(nodes []*doc.Node) {
for _, n := range nodes {
// Check if it is a bundle or snapshot.
switch {
case n.ImportPath[0] == 'B':
case n.ImportPath[0] == 'S':
case strings.HasSuffix(n.ImportPath, ".b"):
l := len(n.ImportPath)
// Check local bundles.
bnodes := checkLocalBundles(n.ImportPath[:l-2])
if len(bnodes) > 0 {
// Check with users if continue.
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["BundleInfo"]), n.ImportPath[:l-2])
for _, bn := range bnodes {
fmt.Printf("[%s] -> %s: %s.\n", bn.ImportPath, bn.Type, bn.Value)
}
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["ContinueRemove"]))
var option string
fmt.Fscan(os.Stdin, &option)
if strings.ToLower(option) != "y" {
os.Exit(0)
}
removePackages(bnodes)
} else {
// Check from server.
// TODO: api.GetBundleInfo()
fmt.Println("Unable to find bundle, and we cannot check with server right now.")
}
case strings.HasSuffix(n.ImportPath, ".s"):
case utils.IsValidRemotePath(n.ImportPath):
if !removeCache[n.ImportPath] {
// Remove package.
@ -109,6 +132,30 @@ func removePackage(node *doc.Node) (*doc.Node, []string) {
fmt.Printf(fmt.Sprintf("%s\n", promptMsg["RemovePackage"]), node.ImportPath)
// Remove files.
os.RemoveAll(absPath)
// Remove file in GOPATH/bin
proName := utils.GetExecuteName(node.ImportPath)
paths := utils.GetGOPATH()
var gopath string
for _, v := range paths {
if utils.IsExist(v + "/bin/" + proName) {
gopath = v // Don't need to find again.
os.Remove(v + "/bin/" + proName)
}
}
pkgPath := "/pkg/" + runtime.GOOS + "_" + runtime.GOARCH + "/" + node.ImportPath
// Remove file in GOPATH/pkg
if len(gopath) == 0 {
for _, v := range paths {
if utils.IsExist(v + pkgPath + "/") {
gopath = v
}
}
}
os.RemoveAll(gopath + pkgPath + "/")
os.Remove(gopath + pkgPath + ".a")
return node, nil
}
}

24
utils/utils.go

@ -568,3 +568,27 @@ func joinPath(importPath string, num int) string {
}
return importPath
}
// GetExecuteName returns work directory and possible execute name according work directory.
func GetExecuteName(wd string) string {
wd = strings.Replace(wd, "\\", "/", -1)
execName := path.Base(wd)
if runtime.GOOS == "windows" {
execName += ".exe"
}
return execName
}
var (
readmePat = regexp.MustCompile(`^[Rr][Ee][Aa][Dd][Mm][Ee](?:$|\.)`)
licensePat = regexp.MustCompile(`^[Ll][Ii][Cc][En][Nn][Ss][Ee]`)
)
func IsDocFile(n string) bool {
if (strings.HasSuffix(n, ".go") || strings.HasSuffix(n, ".h") || strings.HasSuffix(n, ".c")) &&
n[0] != '_' && n[0] != '.' {
return true
}
return readmePat.MatchString(n) || licensePat.MatchString(n)
}

44
utils/utils_test.go

@ -5,6 +5,7 @@
package utils
import (
"runtime"
"testing"
)
@ -15,13 +16,6 @@ var remotePaths = []string{
"bitbucket.org/gotamer/conv",
}
var importPaths = []string{
"github.com/coocood/qbs/test",
"code.google.com/p/draw2d/test",
"launchpad.net/goamz/test",
"bitbucket.org/gotamer/conv/test",
}
func TestIsValidRemotePath(t *testing.T) {
for _, p := range remotePaths {
if !IsValidRemotePath(p) {
@ -30,6 +24,13 @@ func TestIsValidRemotePath(t *testing.T) {
}
}
var importPaths = []string{
"github.com/coocood/qbs/test",
"code.google.com/p/draw2d/test",
"launchpad.net/goamz/test",
"bitbucket.org/gotamer/conv/test",
}
func TestGetProjectPath(t *testing.T) {
// Should return same path.
for _, p := range remotePaths {
@ -45,3 +46,32 @@ func TestGetProjectPath(t *testing.T) {
}
}
}
func TestGetExecuteName(t *testing.T) {
// Non-windows.
if runtime.GOOS != "windows" && GetExecuteName("gtihub.com/astaxie/beego") != "beego" {
t.Errorf("Fail to verify execute name in non-windows.")
}
// Windows.
if runtime.GOOS == "windows" && GetExecuteName("gtihub.com/astaxie/beego") != "beego.exe" {
t.Errorf("Fail to verify execute name in windows.")
}
}
var docFiles = []string{
"Readme",
"readme.md",
"README",
"README.MD",
"main.go",
"LICENse",
}
func TestIsDocFile(t *testing.T) {
for _, v := range docFiles {
if !IsDocFile(v) {
t.Errorf("Fail to verify doc file: %s", v)
}
}
}

Loading…
Cancel
Save