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) + } +}