Import upstream changes up to constabulary/gb@218104db
diff --git a/fetch.go b/fetch.go
index 831d620..dd953a8 100644
--- a/fetch.go
+++ b/fetch.go
@@ -91,14 +91,7 @@
return fmt.Errorf("%s is already vendored", path)
}
- var wc vendor.WorkingCopy
-
- // if we are not recursing, then always fetch the HEAD of the master
- if recurse {
- wc, err = repo.Checkout(branch, tag, revision)
- } else {
- wc, err = repo.Checkout("", "", "")
- }
+ wc, err := repo.Checkout(branch, tag, revision)
if err != nil {
return err
@@ -145,6 +138,12 @@
return nil
}
+ // if we are recursing, overwrite branch, tag and revision
+ // values so recursive fetching checks out from HEAD.
+ branch = ""
+ tag = ""
+ revision = ""
+
for done := false; !done; {
paths := []struct {
diff --git a/gbvendor/copy.go b/gbvendor/copy.go
index 1d2f599..52d4c98 100644
--- a/gbvendor/copy.go
+++ b/gbvendor/copy.go
@@ -61,6 +61,7 @@
if err != nil {
return fmt.Errorf("copyfile: create(%q): %v", dst, err)
}
+ defer w.Close()
if debugCopyfile {
fmt.Printf("copyfile(dst: %v, src: %v)\n", dst, src)
}
diff --git a/gbvendor/imports.go b/gbvendor/imports.go
index d3c34b2..80174af 100644
--- a/gbvendor/imports.go
+++ b/gbvendor/imports.go
@@ -5,7 +5,6 @@
"go/parser"
"go/token"
"io"
- "log"
"net/http"
"os"
"path/filepath"
@@ -48,36 +47,36 @@
}
// FetchMetadata fetchs the remote metadata for path.
-func FetchMetadata(path string, insecure bool) (io.ReadCloser, error) {
- schemes := []string{"https", "http"}
- for _, s := range schemes {
- if r, err := fetchMetadata(s, path, insecure); err == nil {
- return r, nil
+func FetchMetadata(path string, insecure bool) (rc io.ReadCloser, err error) {
+ defer func() {
+ if err != nil {
+ err = fmt.Errorf("unable to determine remote metadata protocol: %s", err)
}
+ }()
+ // try https first
+ rc, err = fetchMetadata("https", path)
+ if err == nil {
+ return
}
- return nil, fmt.Errorf("unable to determine remote metadata protocol")
+ // try http if supported
+ if insecure {
+ rc, err = fetchMetadata("http", path)
+ }
+ return
}
-func fetchMetadata(scheme, path string, insecure bool) (io.ReadCloser, error) {
+func fetchMetadata(scheme, path string) (io.ReadCloser, error) {
url := fmt.Sprintf("%s://%s?go-get=1", scheme, path)
switch scheme {
- case "https":
+ case "https", "http":
resp, err := http.Get(url)
- if err == nil {
- return resp.Body, nil
+ if err != nil {
+ return nil, fmt.Errorf("failed to access url %q", url)
}
- case "http":
- if !insecure {
- log.Printf("skipping insecure protocol: %v", url)
- } else {
- resp, err := http.Get(url)
- if err == nil {
- return resp.Body, nil
- }
- }
+ return resp.Body, nil
+ default:
+ return nil, fmt.Errorf("unknown remote protocol scheme: %q", scheme)
}
-
- return nil, fmt.Errorf("unknown remote protocol scheme: %q", scheme)
}
// ParseMetadata fetchs and decodes remote metadata for path.
diff --git a/gbvendor/imports_test.go b/gbvendor/imports_test.go
index 2794292..37d029d 100644
--- a/gbvendor/imports_test.go
+++ b/gbvendor/imports_test.go
@@ -2,7 +2,6 @@
import (
"bytes"
- "fmt"
"io"
"os"
"path/filepath"
@@ -28,11 +27,12 @@
if testing.Short() {
t.Skipf("skipping network tests in -short mode")
}
- tests := []struct {
+ type testParams struct {
path string
want string
insecure bool
- }{{
+ }
+ tests := []testParams{{
path: "golang.org/x/tools/cmd/godoc",
want: `<!DOCTYPE html>
<html>
@@ -80,6 +80,32 @@
t.Errorf("FetchMetadata(%q): want %q, got %q", tt.path, tt.want, got)
}
}
+
+ // Test for error catch.
+ errTests := []testParams{{
+ path: "any.inaccessible.server/the.project",
+ want: `unable to determine remote metadata protocol: failed to access url "http://any.inaccessible.server/the.project?go-get=1"`,
+ insecure: true,
+ }, {
+ path: "any.inaccessible.server/the.project",
+ want: `unable to determine remote metadata protocol: failed to access url "https://any.inaccessible.server/the.project?go-get=1"`,
+ insecure: false,
+ }}
+
+ for _, ett := range errTests {
+ r, err := FetchMetadata(ett.path, ett.insecure)
+ if err == nil {
+ t.Errorf("Access to url %q without any error, but the error should be happen.", ett.path)
+ if r != nil {
+ r.Close()
+ }
+ continue
+ }
+ got := err.Error()
+ if got != ett.want {
+ t.Errorf("FetchMetadata(%q): want %q, got %q", ett.path, ett.want, got)
+ }
+ }
}
func TestParseMetadata(t *testing.T) {
@@ -108,9 +134,10 @@
importpath: "gopkg.in/mgo.v2",
vcs: "git",
reporoot: "https://gopkg.in/mgo.v2",
- }, {
- path: "speter.net/go/exp",
- err: fmt.Errorf("go-import metadata not found"),
+ // disabled: certificate has expired
+ // }, {
+ // path: "speter.net/go/exp",
+ // err: fmt.Errorf("go-import metadata not found"),
}}
for _, tt := range tests {
diff --git a/gbvendor/remove.go b/gbvendor/path.go
similarity index 70%
rename from gbvendor/remove.go
rename to gbvendor/path.go
index fdc155b..bb8334d 100644
--- a/gbvendor/remove.go
+++ b/gbvendor/path.go
@@ -10,8 +10,17 @@
// deletes read only files on Windows.
func RemoveAll(path string) error {
if runtime.GOOS == "windows" {
+ // Simple case: if Remove works, we're done.
+ err := os.Remove(path)
+ if err == nil || os.IsNotExist(err) {
+ return nil
+ }
// make sure all files are writable so we can delete them
filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ // walk gave us some error, give it back.
+ return err
+ }
mode := info.Mode()
if mode|0200 == mode {
return nil
diff --git a/gbvendor/path_test.go b/gbvendor/path_test.go
new file mode 100644
index 0000000..2bba91b
--- /dev/null
+++ b/gbvendor/path_test.go
@@ -0,0 +1,106 @@
+// Copyright 2009 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 vendor
+
+import (
+ "os"
+ "runtime"
+ "testing"
+)
+
+var isReadonlyError = func(error) bool { return false }
+
+func TestRemoveAll(t *testing.T) {
+ tmpDir := os.TempDir()
+ // Work directory.
+ path := tmpDir + "/_TestRemoveAll_"
+ fpath := path + "/file"
+ dpath := path + "/dir"
+
+ // Make directory with 1 file and remove.
+ if err := os.MkdirAll(path, 0777); err != nil {
+ t.Fatalf("MkdirAll %q: %s", path, err)
+ }
+ fd, err := os.Create(fpath)
+ if err != nil {
+ t.Fatalf("create %q: %s", fpath, err)
+ }
+ fd.Close()
+ if err = RemoveAll(path); err != nil {
+ t.Fatalf("RemoveAll %q (first): %s", path, err)
+ }
+ if _, err = os.Lstat(path); err == nil {
+ t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path)
+ }
+
+ // Make directory with file and subdirectory and remove.
+ if err = os.MkdirAll(dpath, 0777); err != nil {
+ t.Fatalf("MkdirAll %q: %s", dpath, err)
+ }
+ fd, err = os.Create(fpath)
+ if err != nil {
+ t.Fatalf("create %q: %s", fpath, err)
+ }
+ fd.Close()
+ fd, err = os.Create(dpath + "/file")
+ if err != nil {
+ t.Fatalf("create %q: %s", fpath, err)
+ }
+ fd.Close()
+ if err = RemoveAll(path); err != nil {
+ t.Fatalf("RemoveAll %q (second): %s", path, err)
+ }
+ if _, err := os.Lstat(path); err == nil {
+ t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path)
+ }
+
+ // Determine if we should run the following test.
+ testit := true
+ if runtime.GOOS == "windows" {
+ // Chmod is not supported under windows.
+ testit = false
+ } else {
+ // Test fails as root.
+ testit = os.Getuid() != 0
+ }
+ if testit {
+ // Make directory with file and subdirectory and trigger error.
+ if err = os.MkdirAll(dpath, 0777); err != nil {
+ t.Fatalf("MkdirAll %q: %s", dpath, err)
+ }
+
+ for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
+ fd, err = os.Create(s)
+ if err != nil {
+ t.Fatalf("create %q: %s", s, err)
+ }
+ fd.Close()
+ }
+ if err = os.Chmod(dpath, 0); err != nil {
+ t.Fatalf("Chmod %q 0: %s", dpath, err)
+ }
+
+ // No error checking here: either RemoveAll
+ // will or won't be able to remove dpath;
+ // either way we want to see if it removes fpath
+ // and path/zzz. Reasons why RemoveAll might
+ // succeed in removing dpath as well include:
+ // * running as root
+ // * running on a file system without permissions (FAT)
+ RemoveAll(path)
+ os.Chmod(dpath, 0777)
+
+ for _, s := range []string{fpath, path + "/zzz"} {
+ if _, err = os.Lstat(s); err == nil {
+ t.Fatalf("Lstat %q succeeded after partial RemoveAll", s)
+ }
+ }
+ }
+ if err = RemoveAll(path); err != nil {
+ t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err)
+ }
+ if _, err = os.Lstat(path); err == nil {
+ t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path)
+ }
+}