diff options
Diffstat (limited to 'src/cmd/goinstall/download.go')
-rw-r--r-- | src/cmd/goinstall/download.go | 306 |
1 files changed, 0 insertions, 306 deletions
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go deleted file mode 100644 index da892a69d..000000000 --- a/src/cmd/goinstall/download.go +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Download remote packages. - -package main - -import ( - "exec" - "fmt" - "http" - "os" - "path/filepath" - "regexp" - "strings" -) - -const dashboardURL = "http://godashboard.appspot.com/package" - -// maybeReportToDashboard reports path to dashboard unless -// -dashboard=false is on command line. It ignores errors. -func maybeReportToDashboard(path string) { - // if -dashboard=false was on command line, do nothing - if !*reportToDashboard { - return - } - - // otherwise lob url to dashboard - r, _ := http.Post(dashboardURL, "application/x-www-form-urlencoded", strings.NewReader("path="+path)) - if r != nil && r.Body != nil { - r.Body.Close() - } -} - -// a vcs represents a version control system -// like Mercurial, Git, or Subversion. -type vcs struct { - name string - cmd string - metadir string - checkout string - clone string - update string - updateReleaseFlag string - pull string - pullForceFlag string - log string - logLimitFlag string - logReleaseFlag string - check string - protocols []string - suffix string - defaultHosts []host -} - -type host struct { - pattern *regexp.Regexp - protocol string - suffix string -} - -var hg = vcs{ - name: "Mercurial", - cmd: "hg", - metadir: ".hg", - checkout: "checkout", - clone: "clone", - update: "update", - updateReleaseFlag: "release", - pull: "pull", - log: "log", - logLimitFlag: "-l1", - logReleaseFlag: "-rrelease", - check: "identify", - protocols: []string{"https", "http"}, - suffix: ".hg", - defaultHosts: []host{ - {regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/hg)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""}, - {regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ""}, - }, -} - -var git = vcs{ - name: "Git", - cmd: "git", - metadir: ".git", - checkout: "checkout", - clone: "clone", - update: "pull", - updateReleaseFlag: "release", - pull: "fetch", - log: "show-ref", - logLimitFlag: "", - logReleaseFlag: "release", - check: "ls-remote", - protocols: []string{"git", "https", "http"}, - suffix: ".git", - defaultHosts: []host{ - {regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ".git"}, - }, -} - -var svn = vcs{ - name: "Subversion", - cmd: "svn", - metadir: ".svn", - checkout: "checkout", - clone: "checkout", - update: "update", - updateReleaseFlag: "release", - log: "log", - logLimitFlag: "-l1", - logReleaseFlag: "release", - check: "info", - protocols: []string{"https", "http", "svn"}, - suffix: ".svn", - defaultHosts: []host{ - {regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/svn)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""}, - }, -} - -var bzr = vcs{ - name: "Bazaar", - cmd: "bzr", - metadir: ".bzr", - checkout: "update", - clone: "branch", - update: "update", - updateReleaseFlag: "-rrelease", - pull: "pull", - pullForceFlag: "--overwrite", - log: "log", - logLimitFlag: "-l1", - logReleaseFlag: "-rrelease", - check: "info", - protocols: []string{"https", "http", "bzr"}, - suffix: ".bzr", - defaultHosts: []host{ - {regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`), "https", ""}, - }, -} - -var vcsList = []*vcs{&git, &hg, &bzr, &svn} - -type vcsMatch struct { - *vcs - prefix, repo string -} - -// findHostedRepo checks whether pkg is located at one of -// the supported code hosting sites and, if so, returns a match. -func findHostedRepo(pkg string) (*vcsMatch, os.Error) { - for _, v := range vcsList { - for _, host := range v.defaultHosts { - if hm := host.pattern.FindStringSubmatch(pkg); hm != nil { - if host.suffix != "" && strings.HasSuffix(hm[1], host.suffix) { - return nil, os.NewError("repository " + pkg + " should not have " + v.suffix + " suffix") - } - repo := host.protocol + "://" + hm[1] + host.suffix - return &vcsMatch{v, hm[1], repo}, nil - } - } - } - return nil, nil -} - -// findAnyRepo looks for a vcs suffix in pkg (.git, etc) and returns a match. -func findAnyRepo(pkg string) (*vcsMatch, os.Error) { - for _, v := range vcsList { - i := strings.Index(pkg+"/", v.suffix+"/") - if i < 0 { - continue - } - if !strings.Contains(pkg[:i], "/") { - continue // don't match vcs suffix in the host name - } - if m := v.find(pkg[:i]); m != nil { - return m, nil - } - return nil, fmt.Errorf("couldn't find %s repository", v.name) - } - return nil, nil -} - -func (v *vcs) find(pkg string) *vcsMatch { - for _, proto := range v.protocols { - for _, suffix := range []string{"", v.suffix} { - repo := proto + "://" + pkg + suffix - out, err := exec.Command(v.cmd, v.check, repo).CombinedOutput() - if err == nil { - printf("find %s: found %s\n", pkg, repo) - return &vcsMatch{v, pkg + v.suffix, repo} - } - printf("find %s: %s %s %s: %v\n%s\n", pkg, v.cmd, v.check, repo, err, out) - } - } - return nil -} - -// isRemote returns true if the first part of the package name looks like a -// hostname - i.e. contains at least one '.' and the last part is at least 2 -// characters. -func isRemote(pkg string) bool { - parts := strings.SplitN(pkg, "/", 2) - if len(parts) != 2 { - return false - } - parts = strings.Split(parts[0], ".") - if len(parts) < 2 || len(parts[len(parts)-1]) < 2 { - return false - } - return true -} - -// download checks out or updates pkg from the remote server. -func download(pkg, srcDir string) (dashReport bool, err os.Error) { - if strings.Contains(pkg, "..") { - err = os.NewError("invalid path (contains ..)") - return - } - m, err := findHostedRepo(pkg) - if err != nil { - return - } - if m != nil { - dashReport = true // only report public code hosting sites - } else { - m, err = findAnyRepo(pkg) - if err != nil { - return - } - } - if m == nil { - err = os.NewError("cannot download: " + pkg) - return - } - installed, err := m.checkoutRepo(srcDir, m.prefix, m.repo) - if err != nil { - return - } - if !installed { - dashReport = false - } - return -} - -// Try to detect if a "release" tag exists. If it does, update -// to the tagged version, otherwise just update the current branch. -// NOTE(_nil): svn will always fail because it is trying to get -// the revision history of a file named "release" instead of -// looking for a commit with a release tag -func (v *vcs) updateRepo(dst string) os.Error { - if err := quietRun(dst, nil, v.cmd, v.log, v.logLimitFlag, v.logReleaseFlag); err == nil { - if err := run(dst, nil, v.cmd, v.checkout, v.updateReleaseFlag); err != nil { - return err - } - } else if err := run(dst, nil, v.cmd, v.update); err != nil { - return err - } - return nil -} - -// checkoutRepo checks out repo into dst using vcs. -// It tries to check out (or update, if the dst already -// exists and -u was specified on the command line) -// the repository at tag/branch "release". If there is no -// such tag or branch, it falls back to the repository tip. -func (vcs *vcs) checkoutRepo(srcDir, pkgprefix, repo string) (installed bool, err os.Error) { - dst := filepath.Join(srcDir, filepath.FromSlash(pkgprefix)) - dir, err := os.Stat(filepath.Join(dst, vcs.metadir)) - if err == nil && !dir.IsDirectory() { - err = os.NewError("not a directory: " + dst) - return - } - if err != nil { - parent, _ := filepath.Split(dst) - if err = os.MkdirAll(parent, 0777); err != nil { - return - } - if err = run(string(filepath.Separator), nil, vcs.cmd, vcs.clone, repo, dst); err != nil { - return - } - if err = vcs.updateRepo(dst); err != nil { - return - } - installed = true - } else if *update { - // Retrieve new revisions from the remote branch, if the VCS - // supports this operation independently (e.g. svn doesn't) - if vcs.pull != "" { - if vcs.pullForceFlag != "" { - if err = run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil { - return - } - } else if err = run(dst, nil, vcs.cmd, vcs.pull); err != nil { - return - } - } - // Update to release or latest revision - if err = vcs.updateRepo(dst); err != nil { - return - } - } - return -} |