Handle Google Project Hosting redirects

If the owner of a project on Google Project Hosting configured a
redirect to another service, then redirect the corresponding pages on
godoc.org.

Examples of redirected packags are:

    code.google.com/p/gocc -> github.com/goccmack/gocc
    code.google.com/p/vitess/go/bson -> github.com/youtube/vitess/go/bson
diff --git a/gosrc/client.go b/gosrc/client.go
index be19e0f..09d54e3 100644
--- a/gosrc/client.go
+++ b/gosrc/client.go
@@ -30,6 +30,7 @@
 	return &RemoteError{resp.Request.URL.Host, fmt.Errorf("%d: (%s)", resp.StatusCode, resp.Request.URL.String())}
 }
 
+// get issues a GET to the specified URL.
 func (c *httpClient) get(url string) (*http.Response, error) {
 	req, err := http.NewRequest("GET", url, nil)
 	if err != nil {
@@ -45,6 +46,26 @@
 	return resp, err
 }
 
+// getNoFollow issues a GET to the specified URL without following redirects.
+func (c *httpClient) getNoFollow(url string) (*http.Response, error) {
+	req, err := http.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	for k, vs := range c.header {
+		req.Header[k] = vs
+	}
+	t := c.client.Transport
+	if t == nil {
+		t = http.DefaultTransport
+	}
+	resp, err := t.RoundTrip(req)
+	if err != nil {
+		return nil, &RemoteError{req.URL.Host, err}
+	}
+	return resp, err
+}
+
 func (c *httpClient) getBytes(url string) ([]byte, error) {
 	resp, err := c.get(url)
 	if err != nil {
diff --git a/gosrc/google.go b/gosrc/google.go
index c36c223..1a47b59 100644
--- a/gosrc/google.go
+++ b/gosrc/google.go
@@ -30,10 +30,32 @@
 	googleFileRe     = regexp.MustCompile(`<li><a href="([^"]+)"`)
 )
 
+func checkGoogleRedir(c *httpClient, match map[string]string) error {
+	resp, err := c.getNoFollow(expand("https://code.google.com/{pr}/{repo}/", match))
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode == http.StatusOK {
+		return nil
+	}
+	if resp.StatusCode == http.StatusMovedPermanently {
+		if u, err := url.Parse(resp.Header.Get("Location")); err == nil {
+			p := u.Host + u.Path + match["dir"]
+			return NotFoundError{Message: "Project moved", Redirect: p}
+		}
+	}
+	return c.err(resp)
+}
+
 func getGoogleDir(client *http.Client, match map[string]string, savedEtag string) (*Directory, error) {
+	setupGoogleMatch(match)
 	c := &httpClient{client: client}
 
-	setupGoogleMatch(match)
+	if err := checkGoogleRedir(c, match); err != nil {
+		return nil, err
+	}
+
 	if m := googleEtagRe.FindStringSubmatch(savedEtag); m != nil {
 		match["vcs"] = m[1]
 	} else if err := getGoogleVCS(c, match); err != nil {
diff --git a/gosrc/print.go b/gosrc/print.go
index 46de29c..f833bc3 100644
--- a/gosrc/print.go
+++ b/gosrc/print.go
@@ -44,8 +44,10 @@
 		gosrc.SetLocalDevMode(*local)
 	}
 	dir, err := gosrc.Get(http.DefaultClient, path, *etag)
-	if err != nil {
-		log.Fatal(err)
+	if e, ok := err.(gosrc.NotFoundError); ok && e.Redirect != "" {
+		log.Fatalf("redirect to %s", e.Redirect)
+	} else if err != nil {
+		log.Fatalf("%+v", err)
 	}
 
 	fmt.Println("ImportPath    ", dir.ImportPath)