From a3c123b9291561ebbb20d9c3a16229371177d564 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 12 Oct 2013 16:53:17 -0400 Subject: [PATCH 1/4] Fixed bugs in gopm get --- README.md | 105 +++++++++++++++++++++--- beewatch.json | 9 --- doc/bitbucket.go | 23 ++---- doc/github.go | 41 ++-------- doc/google.go | 203 ++++++++++++++++++++++++++++++++++++++++++----- doc/launchpad.go | 19 ++--- doc/oschina.go | 11 +-- doc/utils.go | 3 +- doc/vcs.go | 119 +-------------------------- gopm.go | 2 +- 10 files changed, 308 insertions(+), 227 deletions(-) delete mode 100644 beewatch.json diff --git a/README.md b/README.md index c1b8e7b40..4bb5b4163 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,103 @@ -gopm - Go Package Manager -========================= +validation +============== -![GPMGo_Logo](https://raw.github.com/gpmgo/gopmweb/master/static/img/gpmgo.png?raw=true) +validation is a form validation for a data validation and error collecting using Go. -gopm(Go Package Manager) is a Go package manage tool for search, install, update and share packages in Go. +## Installation and tests -**Attention** This application still in experiment, we'are working on new break version, you may use [old version](https://github.com/gpmgo/gopm/tree/v0.1.0) for now. +Install: -## Credits + go get github.com/astaxie/beego/validation -- [Go Walker](https://github.com/Unknwon/gowalker) +Test: -## License + go test github.com/astaxie/beego/validation -[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). \ No newline at end of file +## Example + +Direct Use: + + import ( + "github.com/astaxie/beego/validation" + "log" + ) + + type User struct { + Name string + Age int + } + + func main() { + u := User{"man", 40} + valid := validation.Validation{} + valid.Required(u.Name, "name") + valid.MaxSize(u.Name, 15, "nameMax") + valid.Range(u.Age, 0, 140, "age") + if valid.HasErrors { + // validation does not pass + // print invalid message + for _, err := range valid.Errors { + log.Println(err.Key, err.Message) + } + } + // or use like this + if v := valid.Max(u.Age, 140); !v.Ok { + log.Println(v.Error.Key, v.Error.Message) + } + } + +Struct Tag Use: + + import ( + "github.com/astaxie/beego/validation" + ) + + // validation function follow with "valid" tag + // functions divide with ";" + // parameters in parentheses "()" and divide with "," + // Match function's pattern string must in "//" + type user struct { + Id int + Name string `valid:"Required;Match(/^(test)?\\w*@;com$/)"` + Age int `valid:"Required;Range(1, 140)"` + } + + func main() { + valid := Validation{} + u := user{Name: "test", Age: 40} + b, err := valid.Valid(u) + if err != nil { + // handle error + } + if !b { + // validation does not pass + // blabla... + } + } + +Struct Tag Functions: + + Required + Min(min int) + Max(max int) + Range(min, max int) + MinSize(min int) + MaxSize(max int) + Length(length int) + Alpha + Numeric + AlphaNumeric + Match(pattern string) + AlphaDash + Email + IP + Base64 + Mobile + Tel + Phone + ZipCode + + +## LICENSE + +BSD License http://creativecommons.org/licenses/BSD/ diff --git a/beewatch.json b/beewatch.json deleted file mode 100644 index b0d5a08aa..000000000 --- a/beewatch.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "app_name": "Go Package Manager", - "http_port": 23456, - "watch_enabled": true, - "cmd_mode": true, - "skip_suspend": false, - "print_stack": true, - "print_source": true -} diff --git a/doc/bitbucket.go b/doc/bitbucket.go index 342f6ce6d..0b192a9ba 100644 --- a/doc/bitbucket.go +++ b/doc/bitbucket.go @@ -43,7 +43,7 @@ func getBitbucketDoc(client *http.Client, match map[string]string, installRepoPa var repo struct { Scm string } - if err := com.HttpGetJSON(client, expand("https://api.bitbucket.org/1.0/repositories/{owner}/{repo}", match), &repo); err != nil { + if err := com.HttpGetJSON(client, com.Expand("https://api.bitbucket.org/1.0/repositories/{owner}/{repo}", match), &repo); err != nil { return nil, err } match["vcs"] = repo.Scm @@ -64,7 +64,7 @@ func getBitbucketDoc(client *http.Client, match map[string]string, installRepoPa var nodes map[string]struct { Node string } - if err := com.HttpGetJSON(client, expand("https://api.bitbucket.org/1.0/repositories/{owner}/{repo}/{0}", match, nodeType), &nodes); err != nil { + if err := com.HttpGetJSON(client, com.Expand("https://api.bitbucket.org/1.0/repositories/{owner}/{repo}/{0}", match, nodeType), &nodes); err != nil { return nil, err } for t, n := range nodes { @@ -96,7 +96,7 @@ func getBitbucketDoc(client *http.Client, match map[string]string, installRepoPa // tarball : https://bitbucket.org/{owner}/{repo}/get/{commit}.tar.gz // Downlaod archive. - p, err := com.HttpGetBytes(client, expand("https://bitbucket.org/{owner}/{repo}/get/{commit}.tar.gz", match), nil) + p, err := com.HttpGetBytes(client, com.Expand("https://bitbucket.org/{owner}/{repo}/get/{commit}.tar.gz", match), nil) if err != nil { return nil, err } @@ -107,7 +107,7 @@ func getBitbucketDoc(client *http.Client, match map[string]string, installRepoPa if len(suf) == 1 { suf = "" } - projectPath := expand("bitbucket.org/{owner}/{repo}", match) + projectPath := com.Expand("bitbucket.org/{owner}/{repo}", match) installPath = installRepoPath + "/" + projectPath + suf nod.ImportPath = projectPath } else { @@ -137,7 +137,7 @@ func getBitbucketDoc(client *http.Client, match map[string]string, installRepoPa return nil, err } - fn := h.FileInfo().Name() + fn := h.Name // In case that we find directory, usually we should not. if strings.HasSuffix(fn, "/") { @@ -157,24 +157,13 @@ func getBitbucketDoc(client *http.Client, match map[string]string, installRepoPa os.MkdirAll(dir+"/", os.ModePerm) } - if strings.HasPrefix(fn, ".") { - continue - } - // 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 - } - - _, err = fw.Write(fbytes) - fw.Close() + _, err = com.SaveFile(absPath, fbytes) if err != nil { return nil, err } diff --git a/doc/github.go b/doc/github.go index 6254f9de5..686234040 100644 --- a/doc/github.go +++ b/doc/github.go @@ -29,25 +29,11 @@ import ( ) var ( - githubRawHeader = http.Header{"Accept": {"application/vnd.github-blob.raw"}} - githubPattern = regexp.MustCompile(`^github\.com/(?P[a-z0-9A-Z_.\-]+)/(?P[a-z0-9A-Z_.\-]+)(?P/[a-z0-9A-Z_.\-/]*)?$`) - githubCred string + githubPattern = regexp.MustCompile(`^github\.com/(?P[a-z0-9A-Z_.\-]+)/(?P[a-z0-9A-Z_.\-]+)(?P/[a-z0-9A-Z_.\-/]*)?$`) ) -/*func SetGithubCredentials(id, secret string) { - //githubCred = "client_id=" + id + "&client_secret=" + secret -}*/ - -func SetGithubCredentials(token string) { - if len(token) > 0 { - githubCred = "access_token=" + token - } -} - // getGithubDoc downloads tarball from github.com. func getGithubDoc(client *http.Client, match map[string]string, installRepoPath string, nod *Node, cmdFlags map[string]bool) ([]string, error) { - match["cred"] = githubCred - // Check downlaod type. switch nod.Type { case BRANCH: @@ -67,12 +53,12 @@ func getGithubDoc(client *http.Client, match map[string]string, installRepoPath // tarball: https://github.com/{owner}/{repo}/tarball/{sha} // Downlaod archive. - p, err := com.HttpGetBytes(client, expand("https://github.com/{owner}/{repo}/archive/{sha}.zip", match), nil) + p, err := com.HttpGetBytes(client, com.Expand("https://github.com/{owner}/{repo}/archive/{sha}.zip", match), nil) if err != nil { return nil, errors.New("Fail to donwload Github repo -> " + err.Error()) } - shaName := expand("{repo}-{sha}", match) + shaName := com.Expand("{repo}-{sha}", match) if nod.Type == "tag" { shaName = strings.Replace(shaName, "-v", "-", 1) } @@ -83,7 +69,7 @@ func getGithubDoc(client *http.Client, match map[string]string, installRepoPath if len(suf) == 1 { suf = "" } - projectPath := expand("github.com/{owner}/{repo}", match) + projectPath := com.Expand("github.com/{owner}/{repo}", match) installPath = installRepoPath + "/" + projectPath + suf nod.ImportPath = projectPath } else { @@ -96,14 +82,14 @@ func getGithubDoc(client *http.Client, match map[string]string, installRepoPath r, err := zip.NewReader(bytes.NewReader(p), int64(len(p))) if err != nil { - return nil, err + return nil, errors.New(nod.ImportPath + " -> new zip: " + err.Error()) } 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) + absPath := strings.Replace(f.Name, shaName, installPath, 1) // Create diretory before create file. os.MkdirAll(path.Dir(absPath)+"/", os.ModePerm) @@ -119,7 +105,7 @@ func getGithubDoc(client *http.Client, match map[string]string, installRepoPath } dirs = append(dirs, absPath) } - case !strings.HasPrefix(f.FileInfo().Name(), "."): + default: // Get file from archive. rc, err := f.Open() if err != nil { @@ -157,18 +143,5 @@ func getGithubDoc(client *http.Client, match map[string]string, installRepoPath imports = append(imports, importPkgs...) } } - - /*fpath := appPath + "repo/tarballs/" + node.ImportPath + "-" + node.Value + ".zip" - // Save tarball. - if autoBackup && !utils.IsExist(fpath) { - os.MkdirAll(path.Dir(fpath)+"/", os.ModePerm) - f, err := os.Create(fpath) - if err != nil { - return nil, err - } - defer f.Close() - _, err = f.Write(p) - }*/ - return imports, err } diff --git a/doc/google.go b/doc/google.go index f363a3b23..fae9d9b82 100644 --- a/doc/google.go +++ b/doc/google.go @@ -15,28 +15,47 @@ package doc import ( + "archive/zip" + "bytes" "errors" + "io" "net/http" "os" "path" "regexp" + "strings" "github.com/Unknwon/com" - "github.com/Unknwon/ctw/packer" ) var ( + googleRepoRe = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`) + googleFileRe = regexp.MustCompile(`
  • [a-z0-9\-]+)(:?\.(?P[a-z0-9\-]+))?(?P/[a-z0-9A-Z_.\-/]+)?$`) ) // getGoogleDoc downloads raw files from code.google.com. func getGoogleDoc(client *http.Client, match map[string]string, installRepoPath string, nod *Node, cmdFlags map[string]bool) ([]string, error) { - packer.SetupGoogleMatch(match) + setupGoogleMatch(match) // Check version control. - if err := packer.GetGoogleVCS(client, match); err != nil { + if err := getGoogleVCS(client, match); err != nil { return nil, err } + switch nod.Type { + case BRANCH: + if len(nod.Value) == 0 { + match["tag"] = defaultTags[match["vcs"]] + } else { + match["tag"] = nod.Value + } + case TAG, COMMIT: + match["tag"] = nod.Value + default: + return nil, errors.New("Unknown node type: " + nod.Type) + } + var installPath string projectPath := GetProjectPath(nod.ImportPath) if nod.ImportPath == nod.DownloadURL { @@ -51,35 +70,67 @@ func getGoogleDoc(client *http.Client, match map[string]string, installRepoPath // Remove old files. os.RemoveAll(installPath + "/") - match["tag"] = nod.Value + os.MkdirAll(installPath+"/", os.ModePerm) - ext := ".zip" if match["vcs"] == "svn" { - ext = ".tar.gz" com.ColorLog("[WARN] SVN detected, may take very long time.\n") + + rootPath := com.Expand("http://{subrepo}{dot}{repo}.googlecode.com/{vcs}", match) + d, f := path.Split(rootPath) + err := downloadFiles(client, match, d, installPath+"/", match["tag"], + []string{f + "/"}) + if err != nil { + return nil, errors.New("Fail to download " + nod.ImportPath + " : " + err.Error()) + } } - err := packer.PackToFile(match["importPath"], installPath+ext, match) + p, err := com.HttpGetBytes(client, com.Expand("http://{subrepo}{dot}{repo}.googlecode.com/archive/{tag}.zip", match), nil) if err != nil { - return nil, err + return nil, errors.New("Fail to download " + nod.ImportPath + " : " + err.Error()) } - var dirs []string - if match["vcs"] != "svn" { - dirs, err = com.Unzip(installPath+ext, path.Dir(installPath)) - } else { - dirs, err = com.UnTarGz(installPath+ext, path.Dir(installPath)) + r, err := zip.NewReader(bytes.NewReader(p), int64(len(p))) + if err != nil { + return nil, errors.New(nod.ImportPath + " -> new zip: " + err.Error()) } - if len(dirs) == 0 { - return nil, errors.New("No file in repository") + nameLen := strings.Index(r.File[0].Name, "/") + dirPrefix := match["dir"] + if len(dirPrefix) != 0 { + dirPrefix = dirPrefix[1:] + "/" } - if err != nil { - return nil, err + dirs := make([]string, 0, 5) + for _, f := range r.File { + absPath := strings.Replace(f.Name, f.Name[:nameLen], installPath, 1) + + // Create diretory before create file. + dir := path.Dir(absPath) + if !checkDir(dir, dirs) && !(!cmdFlags["-e"] && strings.Contains(absPath, "example")) { + dirs = append(dirs, dir) + os.MkdirAll(dir+"/", os.ModePerm) + } + + // 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 + } + + _, err = io.Copy(fw, rc) + // Close files. + rc.Close() + fw.Close() + if err != nil { + return nil, err + } } - os.Remove(installPath + ext) - os.Rename(path.Dir(installPath)+"/"+dirs[0], installPath) // Check if need to check imports. if nod.IsGetDeps { @@ -89,3 +140,117 @@ func getGoogleDoc(client *http.Client, match map[string]string, installRepoPath return nil, err } + +type rawFile struct { + name string + rawURL string + data []byte +} + +func (rf *rawFile) Name() string { + return rf.name +} + +func (rf *rawFile) RawUrl() string { + return rf.rawURL +} + +func (rf *rawFile) Data() []byte { + return rf.data +} + +func (rf *rawFile) SetData(p []byte) { + rf.data = p +} + +func downloadFiles(client *http.Client, match map[string]string, rootPath, installPath, commit string, dirs []string) error { + suf := "?r=" + commit + if len(commit) == 0 { + suf = "" + } + + for _, d := range dirs { + p, err := com.HttpGetBytes(client, rootPath+d+suf, nil) + if err != nil { + return err + } + + // Create destination directory. + os.MkdirAll(installPath+d, os.ModePerm) + + // Get source files in current path. + files := make([]com.RawFile, 0, 5) + for _, m := range googleFileRe.FindAllSubmatch(p, -1) { + fname := strings.Split(string(m[1]), "?")[0] + files = append(files, &rawFile{ + name: fname, + rawURL: rootPath + d + fname + suf, + }) + } + + // Fetch files from VCS. + if err := com.FetchFilesCurl(files); err != nil { + return err + } + + // Save files. + for _, f := range files { + absPath := installPath + d + + // Create diretory before create file. + os.MkdirAll(path.Dir(absPath), os.ModePerm) + + // Write data to file + fw, err := os.Create(absPath + f.Name()) + if err != nil { + return err + } + + _, err = fw.Write(f.Data()) + fw.Close() + if err != nil { + return err + } + } + files = nil + + subdirs := make([]string, 0, 3) + // Get subdirectories. + for _, m := range googleDirRe.FindAllSubmatch(p, -1) { + dirName := strings.Split(string(m[1]), "?")[0] + if strings.HasSuffix(dirName, "/") { + subdirs = append(subdirs, d+dirName) + } + } + + err = downloadFiles(client, match, rootPath, installPath, commit, subdirs) + if err != nil { + return err + } + } + return nil +} + +func setupGoogleMatch(match map[string]string) { + if s := match["subrepo"]; s != "" { + match["dot"] = "." + match["query"] = "?repo=" + s + } else { + match["dot"] = "" + match["query"] = "" + } +} + +func getGoogleVCS(client *http.Client, match map[string]string) error { + // Scrape the HTML project page to find the VCS. + p, err := com.HttpGetBytes(client, com.Expand("http://code.google.com/p/{repo}/source/checkout", match), nil) + if err != nil { + return errors.New("doc.getGoogleVCS(" + match["importPath"] + ") -> " + err.Error()) + } + m := googleRepoRe.FindSubmatch(p) + if m == nil { + return com.NotFoundError{"Could not VCS on Google Code project page."} + } + match["vcs"] = string(m[1]) + return nil +} diff --git a/doc/launchpad.go b/doc/launchpad.go index a3bc7cb68..24b291d54 100644 --- a/doc/launchpad.go +++ b/doc/launchpad.go @@ -33,7 +33,7 @@ var launchpadPattern = regexp.MustCompile(`^launchpad\.net/(?P(?P func getLaunchpadDoc(client *http.Client, match map[string]string, installRepoPath string, nod *Node, cmdFlags map[string]bool) ([]string, error) { if match["project"] != "" && match["series"] != "" { - rc, err := com.HttpGet(client, expand("https://code.launchpad.net/{project}{series}/.bzr/branch-format", match), nil) + rc, err := com.HttpGet(client, com.Expand("https://code.launchpad.net/{project}{series}/.bzr/branch-format", match), nil) _, isNotFound := err.(com.NotFoundError) switch { case err == nil: @@ -42,7 +42,7 @@ func getLaunchpadDoc(client *http.Client, match map[string]string, installRepoPa case isNotFound: // The structure of the import path is is launchpad.net/{project}/{dir}. match["repo"] = match["project"] - match["dir"] = expand("{series}{dir}", match) + match["dir"] = com.Expand("{series}{dir}", match) default: return nil, err } @@ -51,9 +51,9 @@ func getLaunchpadDoc(client *http.Client, match map[string]string, installRepoPa var downloadPath string // Check if download with specific revision. if len(nod.Value) == 0 { - downloadPath = expand("https://bazaar.launchpad.net/+branch/{repo}/tarball", match) + downloadPath = com.Expand("https://bazaar.launchpad.net/+branch/{repo}/tarball", match) } else { - downloadPath = expand("https://bazaar.launchpad.net/+branch/{repo}/tarball/"+nod.Value, match) + downloadPath = com.Expand("https://bazaar.launchpad.net/+branch/{repo}/tarball/"+nod.Value, match) } // Scrape the repo browser to find the project revision and individual Go files. @@ -87,7 +87,7 @@ func getLaunchpadDoc(client *http.Client, match map[string]string, installRepoPa return nil, err } - fn := h.FileInfo().Name() + fn := h.Name // Check root path. if len(autoPath) == 0 { autoPath = fn[:strings.Index(fn, match["repo"])+len(match["repo"])] @@ -109,14 +109,7 @@ func getLaunchpadDoc(client *http.Client, match map[string]string, installRepoPa return nil, err } - // Write data to file - fw, err := os.Create(absPath) - if err != nil { - return nil, err - } - - _, err = fw.Write(fbytes) - fw.Close() + _, err = com.SaveFile(absPath, fbytes) if err != nil { return nil, err } diff --git a/doc/oschina.go b/doc/oschina.go index 940d4c535..651651adb 100644 --- a/doc/oschina.go +++ b/doc/oschina.go @@ -51,7 +51,7 @@ func getOSCDoc(client *http.Client, match map[string]string, installRepoPath str // zip: http://{projectRoot}/repository/archive?ref={sha} // Downlaod archive. - p, err := com.HttpGetBytes(client, expand("http://git.oschina.net/{owner}/{repo}/repository/archive?ref={sha}", match), nil) + p, err := com.HttpGetBytes(client, com.Expand("http://git.oschina.net/{owner}/{repo}/repository/archive?ref={sha}", match), nil) if err != nil { return nil, errors.New("Fail to donwload OSChina repo -> " + err.Error()) } @@ -62,7 +62,7 @@ func getOSCDoc(client *http.Client, match map[string]string, installRepoPath str if len(suf) == 1 { suf = "" } - projectPath := expand("git.oschina.net/{owner}/{repo}", match) + projectPath := com.Expand("git.oschina.net/{owner}/{repo}", match) installPath = installRepoPath + "/" + projectPath + suf nod.ImportPath = projectPath } else { @@ -83,7 +83,7 @@ func getOSCDoc(client *http.Client, match map[string]string, installRepoPath str // Need to add root path because we cannot get from tarball. dirs = append(dirs, installPath+"/") for _, f := range r.File { - fileName := f.FileInfo().Name()[nameLen+1:] + fileName := f.Name[nameLen+1:] absPath := installPath + "/" + fileName if strings.HasSuffix(absPath, "/") { @@ -91,11 +91,6 @@ func getOSCDoc(client *http.Client, match map[string]string, installRepoPath str os.MkdirAll(absPath, os.ModePerm) continue } - // d, _ := path.Split(absPath) - // if !checkDir(d, dirs) { - // dirs = append(dirs, d) - // os.MkdirAll(d, os.ModePerm) - // } // Get file from archive. rc, err := f.Open() diff --git a/doc/utils.go b/doc/utils.go index ebcbf5d72..b21cd54a9 100644 --- a/doc/utils.go +++ b/doc/utils.go @@ -97,7 +97,8 @@ func GetProjectPath(importPath string) (projectPath string) { // Check project hosting. switch { - case strings.HasPrefix(importPath, "github.com"): + case strings.HasPrefix(importPath, "github.com") || + strings.HasPrefix(importPath, "git.oschina.net"): projectPath = joinPath(importPath, 3) case strings.HasPrefix(importPath, "code.google.com"): projectPath = joinPath(importPath, 3) diff --git a/doc/vcs.go b/doc/vcs.go index e8a920621..51885bb52 100644 --- a/doc/vcs.go +++ b/doc/vcs.go @@ -15,18 +15,13 @@ package doc import ( - "bytes" "encoding/xml" "errors" "io" - "io/ioutil" - "log" "net/http" "os" - "os/exec" "path" "regexp" - "strconv" "strings" "github.com/Unknwon/com" @@ -90,117 +85,17 @@ type vcsCmd struct { download func([]string, string, string) (string, string, error) } -var vcsCmds = map[string]*vcsCmd{ - "git": &vcsCmd{ - schemes: []string{"http", "https", "git"}, - download: downloadGit, - }, -} - var lsremoteRe = regexp.MustCompile(`(?m)^([0-9a-f]{40})\s+refs/(?:tags|heads)/(.+)$`) -func downloadGit(schemes []string, repo, savedEtag string) (string, string, error) { - var p []byte - var scheme string - for i := range schemes { - cmd := exec.Command("git", "ls-remote", "--heads", "--tags", schemes[i]+"://"+repo+".git") - log.Println(strings.Join(cmd.Args, " ")) - var err error - p, err = cmd.Output() - if err == nil { - scheme = schemes[i] - break - } - } - - if scheme == "" { - return "", "", com.NotFoundError{"VCS not found"} - } - - tags := make(map[string]string) - for _, m := range lsremoteRe.FindAllSubmatch(p, -1) { - tags[string(m[2])] = string(m[1]) - } - - tag, commit, err := bestTag(tags, "master") - if err != nil { - return "", "", err - } - - etag := scheme + "-" + commit - - if etag == savedEtag { - return "", "", errNotModified - } - - dir := path.Join(repoRoot, repo+".git") - p, err = ioutil.ReadFile(path.Join(dir, ".git/HEAD")) - switch { - case err != nil: - if err := os.MkdirAll(dir, 0777); err != nil { - return "", "", err - } - cmd := exec.Command("git", "clone", scheme+"://"+repo, dir) - log.Println(strings.Join(cmd.Args, " ")) - if err := cmd.Run(); err != nil { - return "", "", err - } - case string(bytes.TrimRight(p, "\n")) == commit: - return tag, etag, nil - default: - cmd := exec.Command("git", "fetch") - log.Println(strings.Join(cmd.Args, " ")) - cmd.Dir = dir - if err := cmd.Run(); err != nil { - return "", "", err - } - } - - cmd := exec.Command("git", "checkout", "--detach", "--force", commit) - cmd.Dir = dir - if err := cmd.Run(); err != nil { - return "", "", err - } - - return tag, etag, nil -} - var defaultTags = map[string]string{"git": "master", "hg": "default"} func bestTag(tags map[string]string, defaultTag string) (string, string, error) { - if commit, ok := tags["go1"]; ok { - return "go1", commit, nil - } if commit, ok := tags[defaultTag]; ok { return defaultTag, commit, nil } return "", "", com.NotFoundError{"Tag or branch not found."} } -// expand replaces {k} in template with match[k] or subs[atoi(k)] if k is not in match. -func expand(template string, match map[string]string, subs ...string) string { - var p []byte - var i int - for { - i = strings.Index(template, "{") - if i < 0 { - break - } - p = append(p, template[:i]...) - template = template[i+1:] - i = strings.Index(template, "}") - if s, ok := match[template[:i]]; ok { - p = append(p, s...) - } else { - j, _ := strconv.Atoi(template[:i]) - p = append(p, subs[j]...) - } - template = template[i+1:] - } - p = append(p, template...) - return string(p) -} - // PureDownload downloads package without version control. func PureDownload(nod *Node, installRepoPath string, flags map[string]bool) ([]string, error) { for _, s := range services { @@ -243,7 +138,7 @@ func getDynamic(client *http.Client, nod *Node, installRepoPath string, flags ma } } - nod.DownloadURL = expand("{repo}{dir}", match) + nod.DownloadURL = com.Expand("{repo}{dir}", match) return PureDownload(nod, installRepoPath, flags) } @@ -384,22 +279,14 @@ func CheckImports(absPath, importPath string, nod *Node) (importPkgs []string, e for _, fi := range fis { // Only handle files. if strings.HasSuffix(fi.Name(), ".go") { - f, err := os.Open(absPath + fi.Name()) - if err != nil { - return nil, err - } - - fbytes := make([]byte, fi.Size()) - _, err = f.Read(fbytes) - f.Close() - + data, err := com.ReadFile(absPath + fi.Name()) if err != nil { return nil, err } files = append(files, &source{ name: fi.Name(), - data: fbytes, + data: data, }) } } diff --git a/gopm.go b/gopm.go index 13a91f1c0..40b8fe012 100644 --- a/gopm.go +++ b/gopm.go @@ -33,7 +33,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.2.5.0827" +const APP_VER = "0.4.0.1012" var ( config map[string]interface{} From 3f5900adee5a60dc6875f8fc90c09fa9de60f1b5 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 12 Oct 2013 16:56:28 -0400 Subject: [PATCH 2/4] Fixed license and readme --- LICENSE | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 105 ++---------------------------- 2 files changed, 196 insertions(+), 100 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..8405e89a0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/README.md b/README.md index 4bb5b4163..062b639e0 100644 --- a/README.md +++ b/README.md @@ -1,103 +1,8 @@ -validation -============== +gopm - Go Package Manager +========================= -validation is a form validation for a data validation and error collecting using Go. +![GPMGo_Logo](https://raw.github.com/gpmgo/gopmweb/master/static/img/gpmgo.png?raw=true) -## Installation and tests +gopm(Go Package Manager) is a Go package manage tool for search, install, update and share packages in Go. -Install: - - go get github.com/astaxie/beego/validation - -Test: - - go test github.com/astaxie/beego/validation - -## Example - -Direct Use: - - import ( - "github.com/astaxie/beego/validation" - "log" - ) - - type User struct { - Name string - Age int - } - - func main() { - u := User{"man", 40} - valid := validation.Validation{} - valid.Required(u.Name, "name") - valid.MaxSize(u.Name, 15, "nameMax") - valid.Range(u.Age, 0, 140, "age") - if valid.HasErrors { - // validation does not pass - // print invalid message - for _, err := range valid.Errors { - log.Println(err.Key, err.Message) - } - } - // or use like this - if v := valid.Max(u.Age, 140); !v.Ok { - log.Println(v.Error.Key, v.Error.Message) - } - } - -Struct Tag Use: - - import ( - "github.com/astaxie/beego/validation" - ) - - // validation function follow with "valid" tag - // functions divide with ";" - // parameters in parentheses "()" and divide with "," - // Match function's pattern string must in "//" - type user struct { - Id int - Name string `valid:"Required;Match(/^(test)?\\w*@;com$/)"` - Age int `valid:"Required;Range(1, 140)"` - } - - func main() { - valid := Validation{} - u := user{Name: "test", Age: 40} - b, err := valid.Valid(u) - if err != nil { - // handle error - } - if !b { - // validation does not pass - // blabla... - } - } - -Struct Tag Functions: - - Required - Min(min int) - Max(max int) - Range(min, max int) - MinSize(min int) - MaxSize(max int) - Length(length int) - Alpha - Numeric - AlphaNumeric - Match(pattern string) - AlphaDash - Email - IP - Base64 - Mobile - Tel - Phone - ZipCode - - -## LICENSE - -BSD License http://creativecommons.org/licenses/BSD/ +**Attention** This application still in experiment, we'are working on new break version, you may use [old version](https://github.com/gpmgo/gopm/tree/v0.1.0) for now. \ No newline at end of file From b08babcfec97ec980caf1dc8f73b2051850447e5 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 12 Oct 2013 17:30:09 -0400 Subject: [PATCH 3/4] Bug fixed --- cmd/get.go | 4 +++- doc/github.go | 11 ++++------- doc/google.go | 26 +++++++++++++++----------- doc/oschina.go | 11 ++++------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index 6ae456e8c..684ceea03 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -17,6 +17,7 @@ package cmd import ( "errors" "fmt" + //"os" "strings" "github.com/Unknwon/com" @@ -226,8 +227,9 @@ func downloadPackage(nod *doc.Node) (*doc.Node, []string) { imports, err := doc.PureDownload(nod, installRepoPath, CmdGet.Flags) if err != nil { - com.ColorLog("[ERRO] Download falied[ %s ]\n", err) + com.ColorLog("[ERRO] Download falied( %s )[ %s ]\n", nod.ImportPath, err) failConut++ + //os.RemoveAll(installRepoPath + "/" + doc.GetProjectPath(nod.ImportPath) + "/") return nil, nil } return nod, imports diff --git a/doc/github.go b/doc/github.go index 686234040..a47c39a94 100644 --- a/doc/github.go +++ b/doc/github.go @@ -107,21 +107,18 @@ func getGithubDoc(client *http.Client, match map[string]string, installRepoPath } default: // Get file from archive. - rc, err := f.Open() + r, err := f.Open() if err != nil { return nil, err } - // Write data to file - fw, _ := os.Create(absPath) + fbytes := make([]byte, f.FileInfo().Size()) + _, err = io.ReadFull(r, fbytes) if err != nil { return nil, err } - _, err = io.Copy(fw, rc) - // Close files. - rc.Close() - fw.Close() + _, err = com.SaveFile(absPath, fbytes) if err != nil { return nil, err } diff --git a/doc/google.go b/doc/google.go index fae9d9b82..18ab3e4f2 100644 --- a/doc/google.go +++ b/doc/google.go @@ -40,7 +40,7 @@ func getGoogleDoc(client *http.Client, match map[string]string, installRepoPath setupGoogleMatch(match) // Check version control. if err := getGoogleVCS(client, match); err != nil { - return nil, err + return nil, errors.New("fail to get vcs " + nod.ImportPath + " : " + err.Error()) } switch nod.Type { @@ -112,33 +112,37 @@ func getGoogleDoc(client *http.Client, match map[string]string, installRepoPath } // Get file from archive. - rc, err := f.Open() + r, err := f.Open() if err != nil { return nil, err } - // Write data to file - fw, _ := os.Create(absPath) + fbytes := make([]byte, f.FileInfo().Size()) + _, err = io.ReadFull(r, fbytes) if err != nil { return nil, err } - _, err = io.Copy(fw, rc) - // Close files. - rc.Close() - fw.Close() + _, err = com.SaveFile(absPath, fbytes) if err != nil { return nil, err } } + var imports []string + // Check if need to check imports. if nod.IsGetDeps { - imports := getImports(installPath+"/", match, cmdFlags, nod) - return imports, err + for _, d := range dirs { + importPkgs, err := CheckImports(d, match["importPath"], nod) + if err != nil { + return nil, err + } + imports = append(imports, importPkgs...) + } } - return nil, err + return imports, err } type rawFile struct { diff --git a/doc/oschina.go b/doc/oschina.go index 651651adb..ab3777c3a 100644 --- a/doc/oschina.go +++ b/doc/oschina.go @@ -93,21 +93,18 @@ func getOSCDoc(client *http.Client, match map[string]string, installRepoPath str } // Get file from archive. - rc, err := f.Open() + r, err := f.Open() if err != nil { return nil, errors.New("Fail to open OSChina repo -> " + err.Error()) } - // Write data to file - fw, _ := os.Create(absPath) + fbytes := make([]byte, f.FileInfo().Size()) + _, err = io.ReadFull(r, fbytes) if err != nil { return nil, err } - _, err = io.Copy(fw, rc) - // Close files. - rc.Close() - fw.Close() + _, err = com.SaveFile(absPath, fbytes) if err != nil { return nil, err } From 56ea7cd472c1bca12d1a2cd6f02594868dafdeb3 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 12 Oct 2013 17:46:31 -0400 Subject: [PATCH 4/4] DOne get --- cmd/get.go | 6 ++++-- doc/google.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index 684ceea03..517390e69 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -17,7 +17,7 @@ package cmd import ( "errors" "fmt" - //"os" + "os" "strings" "github.com/Unknwon/com" @@ -208,6 +208,8 @@ func downloadPackages(nodes []*doc.Node) { com.ColorLog("[WARN] Skipped downloaded package( %s => %s:%s )\n", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value)) } + } else if n.ImportPath == "C" { + continue } else { // Invalid import path. com.ColorLog("[WARN] Skipped invalid package path( %s => %s:%s )\n", @@ -229,7 +231,7 @@ func downloadPackage(nod *doc.Node) (*doc.Node, []string) { if err != nil { com.ColorLog("[ERRO] Download falied( %s )[ %s ]\n", nod.ImportPath, err) failConut++ - //os.RemoveAll(installRepoPath + "/" + doc.GetProjectPath(nod.ImportPath) + "/") + os.RemoveAll(installRepoPath + "/" + doc.GetProjectPath(nod.ImportPath) + "/") return nil, nil } return nod, imports diff --git a/doc/google.go b/doc/google.go index 18ab3e4f2..ee2b60e39 100644 --- a/doc/google.go +++ b/doc/google.go @@ -107,7 +107,7 @@ func getGoogleDoc(client *http.Client, match map[string]string, installRepoPath // Create diretory before create file. dir := path.Dir(absPath) if !checkDir(dir, dirs) && !(!cmdFlags["-e"] && strings.Contains(absPath, "example")) { - dirs = append(dirs, dir) + dirs = append(dirs, dir+"/") os.MkdirAll(dir+"/", os.ModePerm) }