--- /dev/null
+// Copyright 2011 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.
+
+package main
+
+import (
+ "go/ast"
+ "regexp"
+)
+
+func init() {
+ register(googlecodeFix)
+}
+
+var googlecodeFix = fix{
+ "googlecode",
+ "2011-11-21",
+ googlecode,
+ `Rewrite Google Code imports from the deprecated form
+"foo.googlecode.com/vcs/path" to "code.google.com/p/foo/path".
+`,
+}
+
+var googlecodeRe = regexp.MustCompile(`^([a-z0-9\-]+)\.googlecode\.com/(svn|git|hg)(/[a-z0-9A-Z_.\-/]+)?$`)
+
+func googlecode(f *ast.File) bool {
+ fixed := false
+
+ for _, s := range f.Imports {
+ old := importPath(s)
+ if m := googlecodeRe.FindStringSubmatch(old); m != nil {
+ new := "code.google.com/p/" + m[1] + m[3]
+ if rewriteImport(f, old, new) {
+ fixed = true
+ }
+ }
+ }
+
+ return fixed
+}
var knownHosts = []host{
{
- regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|git|hg))(/[a-z0-9A-Z_.\-/]+)?$`),
+ regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+(\.[a-z0-9\-]+)?)(/[a-z0-9A-Z_.\-/]+)?$`),
matchGoogleRepo,
},
- {
- regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+\.[a-z0-9\-]+)(/[a-z0-9A-Z_.\-/]+)?$`),
- matchGoogleSubrepo,
- },
{
regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]+)?$`),
matchGithubRepo,
return isDir(filepath.Join(pkgPath, r.vcs.metadir))
}
-// matchGoogleRepo handles matches of the form "repo.googlecode.com/vcs/path".
-func matchGoogleRepo(root string) (RemoteRepo, error) {
- p := strings.SplitN(root, "/", 2)
- if vcs := vcsMap[p[1]]; vcs != nil {
- return &baseRepo{"https://" + root, root, vcs}, nil
- }
- return nil, errors.New("unsupported googlecode vcs: " + p[1])
-}
-
// matchGithubRepo handles matches for github.com repositories.
func matchGithubRepo(root string) (RemoteRepo, error) {
if strings.HasSuffix(root, ".git") {
return &baseRepo{"https://" + root, root, vcsMap["bzr"]}, nil
}
-// matchGoogleSubrepo matches repos like "code.google.com/p/repo.subrepo/path".
-// Note that it doesn't match primary Google Code repositories,
-// which should use the "foo.googlecode.com" form only. (for now)
-func matchGoogleSubrepo(id string) (RemoteRepo, error) {
+// matchGoogleRepo matches repos like "code.google.com/p/repo.subrepo/path".
+func matchGoogleRepo(id string) (RemoteRepo, error) {
root := "code.google.com/p/" + id
- return &googleSubrepo{baseRepo{"https://" + root, root, nil}}, nil
+ return &googleRepo{baseRepo{"https://" + root, root, nil}}, nil
}
-// googleSubrepo implements a RemoteRepo that discovers a Google Code
+// googleRepo implements a RemoteRepo that discovers a Google Code
// repository's VCS type by scraping the code.google.com source checkout page.
-type googleSubrepo struct{ baseRepo }
+type googleRepo struct{ baseRepo }
-var googleSubrepoRe = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
+var googleRepoRe = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
-func (r *googleSubrepo) Repo(client *http.Client) (url, root string, vcs *vcs, err error) {
+func (r *googleRepo) Repo(client *http.Client) (url, root string, vcs *vcs, err error) {
if r.vcs != nil {
return r.url, r.root, r.vcs, nil
}
// Use the code.google.com source checkout page to find the VCS type.
const prefix = "code.google.com/p/"
p := strings.SplitN(r.root[len(prefix):], ".", 2)
- u := fmt.Sprintf("https://%s%s/source/checkout?repo=%s", prefix, p[0], p[1])
+ u := fmt.Sprintf("https://%s%s/source/checkout", prefix, p[0])
+ if len(p) == 2 {
+ u += fmt.Sprintf("?repo=%s", p[1])
+ }
resp, err := client.Get(u)
if err != nil {
return "", "", nil, err
}
// Scrape result for vcs details.
- m := googleSubrepoRe.FindSubmatch(b)
+ m := googleRepoRe.FindSubmatch(b)
if len(m) == 2 {
if v := vcsMap[string(m[1])]; v != nil {
r.vcs = v
return "", nil
}
+var oldGoogleRepo = regexp.MustCompile(`^([a-z0-9\-]+)\.googlecode\.com/(svn|git|hg)(/[a-z0-9A-Z_.\-/]+)?$`)
+
// download checks out or updates the specified package from the remote server.
func download(importPath, srcDir string) (public bool, err error) {
if strings.Contains(importPath, "..") {
return
}
+ if m := oldGoogleRepo.FindStringSubmatch(importPath); m != nil {
+ fixedPath := "code.google.com/p/" + m[1] + m[3]
+ err = fmt.Errorf(
+ "unsupported import path; should be %q\n"+
+ "Run goinstall with -fix to gofix the code.",
+ fixedPath,
+ )
+ return
+ }
+
repo, err := findPublicRepo(importPath)
if err != nil {
return false, err
transport *testTransport
}{
{
- "repo.googlecode.com/hg/path/foo",
+ "code.google.com/p/repo/path/foo",
"hg",
- "repo.googlecode.com/hg",
- "https://repo.googlecode.com/hg",
- nil,
+ "code.google.com/p/repo",
+ "https://code.google.com/p/repo",
+ &testTransport{
+ "https://code.google.com/p/repo/source/checkout",
+ `<tt id="checkoutcmd">hg clone https://...`,
+ },
},
{
- "repo.googlecode.com/svn/path",
+ "code.google.com/p/repo/path/foo",
"svn",
- "repo.googlecode.com/svn",
- "https://repo.googlecode.com/svn",
- nil,
+ "code.google.com/p/repo",
+ "https://code.google.com/p/repo",
+ &testTransport{
+ "https://code.google.com/p/repo/source/checkout",
+ `<tt id="checkoutcmd">svn checkout https://...`,
+ },
},
{
- "repo.googlecode.com/git",
+ "code.google.com/p/repo/path/foo",
"git",
- "repo.googlecode.com/git",
- "https://repo.googlecode.com/git",
- nil,
+ "code.google.com/p/repo",
+ "https://code.google.com/p/repo",
+ &testTransport{
+ "https://code.google.com/p/repo/source/checkout",
+ `<tt id="checkoutcmd">git clone https://...`,
+ },
},
{
"code.google.com/p/repo.sub/path",