Merge pull request #487 from hori-ryota/feature/fix-unknown-packageroot
Fix NormalizeName for subpackage of unknown host
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a76e7d3..45e126d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,60 @@
+# Unreleased
+
+## Added
+- #533: Log VCS output with debug (`--debug` switch) when there was a VCS error (thanks @atombender)
+
+## Changed
+- #521: Sort subpackages for glide.yaml and glide.lock to avoid spurious diffs
+
+# Release 0.11.1 (2016-07-21)
+
+## Fixed
+- #505: Ignored dependency showing up in testImport
+
+# Release 0.11.0 (2016-07-05)
+
+## Added
+- #461: Resolve test imports
+- #458: Wizard and version detection are now on `glide get`
+- #444: New config wizard helps you find versions and set ranges. Can be run from
+ `glide init` or as separate command
+- #438: Added ability to read symlink basedirs (thanks @klnusbaum)
+- #436: Added .idea to .gitignore
+- #393 and #401: Added a PPA (https://github.com/Masterminds/glide-ppa) and instructions
+ on using it (thanks @franciscocpg)
+- #390: Added support for custom Go executable name. Needed for environments like
+ appengine. Environment variable GLIDE_GO_EXECUTABLE (thanks @dpmcnevin)
+- #382: `glide info` command takes a format string and returns info (thanks @franciscocpg)
+- #365: glide list: support json output format (thanks @chancez)
+
+## Changed
+- Tags are now in the form v[SemVer]. The change is the initial v on the tag.
+ This is to conform with other Go tools that require this.
+- #501: Updating the plugins documentation and adding listing
+- #500: Log an error if stripping version control data fails (thanks @alexbrand)
+- #496: Updated to github.com/Masterminds/semver 1.1.1
+- #495: Updated to github.com/Masterminds/vcs 1.8.0
+- #494: Glide install skips fetch when it is up to date
+- #489: Make shared funcs for lockfile usage (thanks @heewa)
+- #459: When a conflict occurs output the tag, if one exists, for the commit
+- #443: Updating message indentation to be uniform
+- #431: Updated the docs on subpackages
+- #433: The global shared cache was reworked in prep for future uses
+- #396: Don't update the lock file if nothing has changed
+
+## Fixed
+- #460: Sometimes ignored packages were written to lock file. Fixed.
+- #463: Fixed possible nil pointer issues
+- #453: Fix DeleteUnused flag which was not working (thanks @s-urbaniak)
+- #432: Fixed issue with new net/http/httptrace std lib package
+- #392: Correctly normalize Windows package paths (thanks @jrick)
+- #395: Creating the cache key did not handle SCP properly
+- #386: Fixed help text indentation
+- #383: Failed `glide get` had been updating files. No longer does this
+
+And thanks to @derelk, @franciscocpg, @shawnps, @kngu9, @tugberkugurlu, @rhcarvalho,
+@gyuho, and @7imon7ays for documentation updates.
+
# Release 0.10.2 (2016-04-06)
- Issue #362: Updated docs on how -update-vendored works to help avoid confusion.
diff --git a/README.md b/README.md
index 566bd30..39ef0e8 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
installed by a tool (e.g. glide), similar to `go get` or they can be vendored and
distributed with the package.
-[](https://travis-ci.org/Masterminds/glide) [](http://goreportcard.com/report/Masterminds/glide) [](https://godoc.org/github.com/Masterminds/glide) [](http://glide.readthedocs.org/en/stable/?badge=stable) [](http://glide.readthedocs.org/en/latest/?badge=latest) [](https://gitter.im/Masterminds/glide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[](https://travis-ci.org/Masterminds/glide) [](https://goreportcard.com/report/github.com/Masterminds/glide) [](https://godoc.org/github.com/Masterminds/glide) [](http://glide.readthedocs.org/en/stable/?badge=stable) [](http://glide.readthedocs.org/en/latest/?badge=latest) [](https://gitter.im/Masterminds/glide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
### Features
@@ -76,7 +76,13 @@
## Install
-On Mac OS X you can install the latest release via [Homebrew](https://github.com/Homebrew/homebrew):
+The easiest way to install the latest release on Mac or Linux is with the following script:
+
+```
+curl https://glide.sh/get | sh
+```
+
+On Mac OS X you can also install the latest release via [Homebrew](https://github.com/Homebrew/homebrew):
```
$ brew install glide
diff --git a/action/get.go b/action/get.go
index 5b0b72e..5c34d5e 100644
--- a/action/get.go
+++ b/action/get.go
@@ -95,7 +95,10 @@
if strip {
msg.Info("Removing version control data from vendor directory...")
- gpath.StripVcs()
+ err := gpath.StripVcs()
+ if err != nil {
+ msg.Err("Unable to strip version control data: %s", err)
+ }
}
if stripVendor {
diff --git a/action/install.go b/action/install.go
index 3deb9d2..ee91401 100644
--- a/action/install.go
+++ b/action/install.go
@@ -1,7 +1,6 @@
package action
import (
- "io/ioutil"
"path/filepath"
"github.com/Masterminds/glide/cache"
@@ -31,10 +30,17 @@
return
}
// Load lockfile
- lock, err := LoadLockfile(base, conf)
+ lock, err := cfg.ReadLockFile(filepath.Join(base, gpath.LockFile))
if err != nil {
msg.Die("Could not load lockfile.")
}
+ // Verify lockfile hasn't changed
+ hash, err := conf.Hash()
+ if err != nil {
+ msg.Die("Could not load lockfile.")
+ } else if hash != lock.Hash {
+ msg.Warn("Lock file may be out of date. Hash check of YAML failed. You may need to run 'update'")
+ }
// Delete unused packages
if installer.DeleteUnused {
@@ -66,7 +72,10 @@
if strip {
msg.Info("Removing version control data from vendor directory...")
- gpath.StripVcs()
+ err := gpath.StripVcs()
+ if err != nil {
+ msg.Err("Unable to strip version control data: %s", err)
+ }
}
if stripVendor {
@@ -77,28 +86,3 @@
}
}
}
-
-// LoadLockfile loads the contents of a glide.lock file.
-//
-// TODO: This should go in another package.
-func LoadLockfile(base string, conf *cfg.Config) (*cfg.Lockfile, error) {
- yml, err := ioutil.ReadFile(filepath.Join(base, gpath.LockFile))
- if err != nil {
- return nil, err
- }
- lock, err := cfg.LockfileFromYaml(yml)
- if err != nil {
- return nil, err
- }
-
- hash, err := conf.Hash()
- if err != nil {
- return nil, err
- }
-
- if hash != lock.Hash {
- msg.Warn("Lock file may be out of date. Hash check of YAML failed. You may need to run 'update'")
- }
-
- return lock, nil
-}
diff --git a/action/project_info.go b/action/project_info.go
index 5e0995e..379026e 100644
--- a/action/project_info.go
+++ b/action/project_info.go
@@ -6,13 +6,14 @@
"github.com/Masterminds/glide/msg"
)
+// Info prints information about a project based on a passed in format.
func Info(format string) {
conf := EnsureConfig()
var buffer bytes.Buffer
varInit := false
- for _, var_format := range format {
+ for _, varfmt := range format {
if varInit {
- switch var_format {
+ switch varfmt {
case 'n':
buffer.WriteString(conf.Name)
case 'd':
@@ -22,15 +23,15 @@
case 'l':
buffer.WriteString(conf.License)
default:
- msg.Die("Invalid format %s", string(var_format))
+ msg.Die("Invalid format %s", string(varfmt))
}
} else {
- switch var_format {
+ switch varfmt {
case '%':
varInit = true
continue
default:
- buffer.WriteString(string(var_format))
+ buffer.WriteString(string(varfmt))
}
}
varInit = false
diff --git a/action/rebuild.go b/action/rebuild.go
index f76d948..dffde39 100644
--- a/action/rebuild.go
+++ b/action/rebuild.go
@@ -98,4 +98,3 @@
}
return err
}
-
diff --git a/action/update.go b/action/update.go
index cb33e63..fdd90ad 100644
--- a/action/update.go
+++ b/action/update.go
@@ -117,7 +117,10 @@
if strip {
msg.Info("Removing version control data from vendor directory...")
- gpath.StripVcs()
+ err := gpath.StripVcs()
+ if err != nil {
+ msg.Err("Unable to strip version control data: %s", err)
+ }
}
if stripVendor {
diff --git a/cfg/config.go b/cfg/config.go
index cdfd943..115c76d 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -5,6 +5,7 @@
"fmt"
"io/ioutil"
"reflect"
+ "sort"
"strings"
"github.com/Masterminds/glide/util"
@@ -390,6 +391,19 @@
Os []string `yaml:"os,omitempty"`
}
+// DependencyFromLock converts a Lock to a Dependency
+func DependencyFromLock(lock *Lock) *Dependency {
+ return &Dependency{
+ Name: lock.Name,
+ Reference: lock.Version,
+ Repository: lock.Repository,
+ VcsType: lock.VcsType,
+ Subpackages: lock.Subpackages,
+ Arch: lock.Arch,
+ Os: lock.Os,
+ }
+}
+
// UnmarshalYAML is a hook for gopkg.in/yaml.v2 in the unmarshaling process
func (d *Dependency) UnmarshalYAML(unmarshal func(interface{}) error) error {
newDep := &dep{}
@@ -554,6 +568,7 @@
s = append(s, item)
}
}
+ sort.Strings(s)
return s
}
diff --git a/cfg/lock.go b/cfg/lock.go
index 2b2c4c8..8a26e24 100644
--- a/cfg/lock.go
+++ b/cfg/lock.go
@@ -34,6 +34,18 @@
return yml, nil
}
+// MarshalYAML is a hook for gopkg.in/yaml.v2.
+// It sorts import subpackages lexicographically for reproducibility.
+func (lf *Lockfile) MarshalYAML() (interface{}, error) {
+ for _, imp := range lf.Imports {
+ sort.Strings(imp.Subpackages)
+ }
+ for _, imp := range lf.DevImports {
+ sort.Strings(imp.Subpackages)
+ }
+ return lf, nil
+}
+
// WriteFile writes a Glide lock file.
//
// This is a convenience function that marshals the YAML and then writes it to
@@ -72,6 +84,19 @@
return sha256.Sum256(yml), nil
}
+// ReadLockFile loads the contents of a glide.lock file.
+func ReadLockFile(lockpath string) (*Lockfile, error) {
+ yml, err := ioutil.ReadFile(lockpath)
+ if err != nil {
+ return nil, err
+ }
+ lock, err := LockfileFromYaml(yml)
+ if err != nil {
+ return nil, err
+ }
+ return lock, nil
+}
+
// Locks is a slice of locked dependencies.
type Locks []*Lock
@@ -130,6 +155,19 @@
}
}
+// LockFromDependency converts a Dependency to a Lock
+func LockFromDependency(dep *Dependency) *Lock {
+ return &Lock{
+ Name: dep.Name,
+ Version: dep.Pin,
+ Repository: dep.Repository,
+ VcsType: dep.VcsType,
+ Subpackages: dep.Subpackages,
+ Arch: dep.Arch,
+ Os: dep.Os,
+ }
+}
+
// NewLockfile is used to create an instance of Lockfile.
func NewLockfile(ds, tds Dependencies, hash string) *Lockfile {
lf := &Lockfile{
@@ -140,29 +178,13 @@
}
for i := 0; i < len(ds); i++ {
- lf.Imports[i] = &Lock{
- Name: ds[i].Name,
- Version: ds[i].Pin,
- Repository: ds[i].Repository,
- VcsType: ds[i].VcsType,
- Subpackages: ds[i].Subpackages,
- Arch: ds[i].Arch,
- Os: ds[i].Os,
- }
+ lf.Imports[i] = LockFromDependency(ds[i])
}
sort.Sort(lf.Imports)
for i := 0; i < len(tds); i++ {
- lf.DevImports[i] = &Lock{
- Name: tds[i].Name,
- Version: tds[i].Pin,
- Repository: tds[i].Repository,
- VcsType: tds[i].VcsType,
- Subpackages: tds[i].Subpackages,
- Arch: tds[i].Arch,
- Os: tds[i].Os,
- }
+ lf.DevImports[i] = LockFromDependency(tds[i])
}
sort.Sort(lf.DevImports)
@@ -180,15 +202,8 @@
i := 0
for name, dep := range ds {
- lf.Imports[i] = &Lock{
- Name: name,
- Version: dep.Pin,
- Repository: dep.Repository,
- VcsType: dep.VcsType,
- Subpackages: dep.Subpackages,
- Arch: dep.Arch,
- Os: dep.Os,
- }
+ lf.Imports[i] = LockFromDependency(dep)
+ lf.Imports[i].Name = name
i++
}
diff --git a/cfg/lock_test.go b/cfg/lock_test.go
index 78dcee3..81edcd0 100644
--- a/cfg/lock_test.go
+++ b/cfg/lock_test.go
@@ -2,6 +2,7 @@
import (
"sort"
+ "strings"
"testing"
)
@@ -32,3 +33,80 @@
t.Error("Sorting of dependencies failed")
}
}
+
+const inputSubpkgYaml = `
+imports:
+- name: github.com/gogo/protobuf
+ version: 82d16f734d6d871204a3feb1a73cb220cc92574c
+ subpackages:
+ - plugin/equal
+ - sortkeys
+ - plugin/face
+ - plugin/gostring
+ - vanity
+ - plugin/grpc
+ - plugin/marshalto
+ - plugin/populate
+ - plugin/oneofcheck
+ - plugin/size
+ - plugin/stringer
+ - plugin/defaultcheck
+ - plugin/embedcheck
+ - plugin/description
+ - plugin/enumstringer
+ - gogoproto
+ - plugin/testgen
+ - plugin/union
+ - plugin/unmarshal
+ - protoc-gen-gogo/generator
+ - protoc-gen-gogo/plugin
+ - vanity/command
+ - protoc-gen-gogo/descriptor
+ - proto
+`
+const expectSubpkgYaml = `
+imports:
+- name: github.com/gogo/protobuf
+ version: 82d16f734d6d871204a3feb1a73cb220cc92574c
+ subpackages:
+ - gogoproto
+ - plugin/defaultcheck
+ - plugin/description
+ - plugin/embedcheck
+ - plugin/enumstringer
+ - plugin/equal
+ - plugin/face
+ - plugin/gostring
+ - plugin/grpc
+ - plugin/marshalto
+ - plugin/oneofcheck
+ - plugin/populate
+ - plugin/size
+ - plugin/stringer
+ - plugin/testgen
+ - plugin/union
+ - plugin/unmarshal
+ - proto
+ - protoc-gen-gogo/descriptor
+ - protoc-gen-gogo/generator
+ - protoc-gen-gogo/plugin
+ - sortkeys
+ - vanity
+ - vanity/command
+`
+
+func TestSortSubpackages(t *testing.T) {
+ lf, err := LockfileFromYaml([]byte(inputSubpkgYaml))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ out, err := lf.Marshal()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !strings.Contains(string(out), expectSubpkgYaml) {
+ t.Errorf("Expected %q\nto contain\n%q")
+ }
+}
diff --git a/docs/plugins.md b/docs/plugins.md
index 98f24ae..bc3b596 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -1,44 +1,47 @@
# Glide Plugins
-(Not to be confused with Glade Plugins. Pew.)
+Glide supports a simple plugin system similar to Git.
-Glide supports a simple plugin system similar to Git. When Glide
-encounters a subcommand that it does not know, it will try to delegate
-it to another executable according to the following rules.
+## Existing Plugins
+
+Some plugins exist today for Glide including:
+
+* [glide-vc](https://github.com/sgotti/glide-vc) - The vendor cleaner allows you to strip files files not needed for building your application from the `vendor/` directory.
+* [glide-brew](https://github.com/heewa/glide-brew) - Convert Go deps managed by glide to Homebrew resources to help you make brew formulas for you Go programs.
+* [glide-hash](https://github.com/mattfarina/glide-hash) - Generates a hash of the `glide.yaml` file compatible with Glides internal hash.
+
+_Note, to add plugins to this list please create a pull request._
+
+## How Plugins Work
+
+When Glide encounters a subcommand that it does not know, it will try to delegate it to another executable according to the following rules.
Example:
```
-$ glide in # We know this command, so we execute it
-$ glide foo # We don't know this command, so we look for a suitable
- # plugin.
+$ glide install # We know this command, so we execute it
+$ glide foo # We don't know this command, so we look for a suitable
+ # plugin.
```
-In the example above, when glide receives the command `foo`, which it
-does not know, it will do the following:
+In the example above, when glide receives the command `foo`, which it does not know, it will do the following:
1. Transform the name from `foo` to `glide-foo`
-2. Look on the system `$PATH` for `glide-foo`. If it finds a program by
- that name, execute it...
-3. Or else, look at the current project's root for `glide-foo`. (That
- is, look in the same directory as glide.yaml). If found, execute it.
+2. Look on the system `$PATH` for `glide-foo`. If it finds a program by that name, execute it...
+3. Or else, look at the current project's root for `glide-foo`. (That is, look in the same directory as `glide.yaml`). If found, execute it.
4. If no suitable command is found, exit with an error.
## Writing a Glide Plugin
-A Glide plugin can be written in any language you wish, provided that it
-can be executed from the command line as a subprocess of Glide. The
-example included with Glide is a simple Bash script. We could just as
-easily write Go, Python, Perl, or even Java code (with a wrapper) to
+A Glide plugin can be written in any language you wish, provided that it can be executed from the command line as a subprocess of Glide. The example included with Glide is a simple Bash script. We could just as easily write Go, Python, Perl, or even Java code (with a wrapper) to
execute.
A glide plugin must be in one of two locations:
-1. Somewhere on the PATH (including `$GLIDE_PATH/_vendor/bin`)
+1. Somewhere on the PATH
2. In the same directory as `glide.yaml`
-It is recommended that system-wide Glide plugins go in `/usr/local/bin`
-while project-specific plugins go in the same directory as `glide.yaml`.
+It is recommended that system-wide Glide plugins go in `/usr/local/bin` or `$GOPATH/bin` while project-specific plugins go in the same directory as `glide.yaml`.
### Arguments and Flags
@@ -48,32 +51,15 @@
$ glide foo -name=Matt myfile.txt
```
-Glide will interpret this as a request to execute `glide-foo` with the
-arguments `-name=Matt myfile.txt`. It will not attempt to interpret
-those arguments or modify them in any way.
+Glide will interpret this as a request to execute `glide-foo` with the arguments `-name=Matt myfile.txt`. It will not attempt to interpret those arguments or modify them in any way.
-Hypothetically, if Glide had a `-x` flag of its own, you could call
-this:
+Hypothetically, if Glide had a `-x` flag of its own, you could call this:
```
$ glide -x foo -name=Matt myfile.txt
```
-In this case, glide would interpret and swollow the -x and pass the rest
-on to glide-foo as in the example above.
-
-### Environment Variables
-
-When Glide executes a plugin, it passes through all of its environment
-variables, including...
-
-- GOPATH: Gopath
-- PATH: Executable paths
-- GLIDE_GOPATH: Gopath (in case GOPATH gets overridden by another
- script)
-- GLIDE_PROJECT: The path to the project
-- GLIDE_YAML: The path to the project's YAML
-- ALREADY_GLIDING: 1 if we are in a `glide in` session.
+In this case, glide would interpret and swollow the -x and pass the rest on to `glide-foo` as in the example above.
## Example Plugin
@@ -84,5 +70,3 @@
echo "Hello"
```
-
-Yup, that's it. Also see `glide-example-plugin` for a bigger example.
diff --git a/docs/versions.md b/docs/versions.md
index a323fb2..047a5ce 100644
--- a/docs/versions.md
+++ b/docs/versions.md
@@ -27,7 +27,7 @@
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `>= 1.2.x` is equivalent to `>= 1.2.0`
-* `<= 2.x` is equivalent to `<= 3`
+* `<= 2.x` is equivalent to `< 3`
* `*` is equivalent to `>= 0.0.0`
## Tilde Range Comparisons (Patch)
diff --git a/glide.lock b/glide.lock
index 572094a..c869e2f 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,12 +1,12 @@
-hash: ebc39e5b2036ba2235316f2897fb9f2e696c6a7d5389416812722cc8ed3dfa21
-updated: 2016-06-10T16:27:29.24243625-04:00
+hash: 0653c17bcbf6f1df79990f3d2211dbcbc920ca528c513b00f5cab0a508c984ab
+updated: 2016-06-30T10:51:49.633776379-04:00
imports:
- name: github.com/codegangsta/cli
version: 71f57d300dd6a780ac1856c005c4b518cfd498ec
- name: github.com/Masterminds/semver
- version: 808ed7761c233af2de3f9729a041d68c62527f3a
+ version: 8d0431362b544d1a3536cca26684828866a7de09
- name: github.com/Masterminds/vcs
- version: 7af28b64c5ec41b1558f5514fd938379822c237c
+ version: fbe9fb6ad5b5f35b3e82a7c21123cfc526cbf895
- name: gopkg.in/yaml.v2
version: a83829b6f1293c91addabc89d0571c246397bbf4
testImports: []
diff --git a/glide.yaml b/glide.yaml
index a8c5b4a..dfc97e9 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -11,8 +11,8 @@
import:
- package: gopkg.in/yaml.v2
- package: github.com/Masterminds/vcs
- version: ^1.7.0
+ version: ^1.8.0
- package: github.com/codegangsta/cli
version: ~1.14.0
- package: github.com/Masterminds/semver
- version: ^1.0.0
+ version: ^1.1.1
diff --git a/godep/strip/strip.go b/godep/strip/strip.go
index e70d607..39d54e1 100644
--- a/godep/strip/strip.go
+++ b/godep/strip/strip.go
@@ -82,11 +82,11 @@
func rewriteGodepfilesHandler(path string, info os.FileInfo, err error) error {
name := info.Name()
- if name == "testdata" || name == "vendor" {
- return filepath.SkipDir
- }
if info.IsDir() {
+ if name == "testdata" || name == "vendor" {
+ return filepath.SkipDir
+ }
return nil
}
diff --git a/gom/parser.go b/gom/parser.go
index bf54f61..3bcd9e0 100644
--- a/gom/parser.go
+++ b/gom/parser.go
@@ -16,10 +16,10 @@
var qx = `'[^']*'|"[^"]*"`
var kx = `:[a-z][a-z0-9_]*`
var ax = `(?:\s*` + kx + `\s*|,\s*` + kx + `\s*)`
-var re_group = regexp.MustCompile(`\s*group\s+((?:` + kx + `\s*|,\s*` + kx + `\s*)*)\s*do\s*$`)
-var re_end = regexp.MustCompile(`\s*end\s*$`)
-var re_gom = regexp.MustCompile(`^\s*gom\s+(` + qx + `)\s*((?:,\s*` + kx + `\s*=>\s*(?:` + qx + `|\s*\[\s*` + ax + `*\s*\]\s*))*)$`)
-var re_options = regexp.MustCompile(`(,\s*` + kx + `\s*=>\s*(?:` + qx + `|\s*\[\s*` + ax + `*\s*\]\s*)\s*)`)
+var reGroup = regexp.MustCompile(`\s*group\s+((?:` + kx + `\s*|,\s*` + kx + `\s*)*)\s*do\s*$`)
+var reEnd = regexp.MustCompile(`\s*end\s*$`)
+var reGom = regexp.MustCompile(`^\s*gom\s+(` + qx + `)\s*((?:,\s*` + kx + `\s*=>\s*(?:` + qx + `|\s*\[\s*` + ax + `*\s*\]\s*))*)$`)
+var reOptions = regexp.MustCompile(`(,\s*` + kx + `\s*=>\s*(?:` + qx + `|\s*\[\s*` + ax + `*\s*\]\s*)\s*)`)
func unquote(name string) string {
name = strings.TrimSpace(name)
@@ -32,13 +32,13 @@
}
func parseOptions(line string, options map[string]interface{}) {
- ss := re_options.FindAllStringSubmatch(line, -1)
- re_a := regexp.MustCompile(ax)
+ ss := reOptions.FindAllStringSubmatch(line, -1)
+ reA := regexp.MustCompile(ax)
for _, s := range ss {
kvs := strings.SplitN(strings.TrimSpace(s[0])[1:], "=>", 2)
kvs[0], kvs[1] = strings.TrimSpace(kvs[0]), strings.TrimSpace(kvs[1])
if kvs[1][0] == '[' {
- as := re_a.FindAllStringSubmatch(kvs[1][1:len(kvs[1])-1], -1)
+ as := reA.FindAllStringSubmatch(kvs[1][1:len(kvs[1])-1], -1)
a := []string{}
for i := range as {
it := strings.TrimSpace(as[i][0])
@@ -57,6 +57,7 @@
}
}
+// Gom represents configuration from Gom.
type Gom struct {
name string
options map[string]interface{}
@@ -95,14 +96,14 @@
name := ""
options := make(map[string]interface{})
var items []string
- if re_group.MatchString(line) {
- envs = strings.Split(re_group.FindStringSubmatch(line)[1], ",")
+ if reGroup.MatchString(line) {
+ envs = strings.Split(reGroup.FindStringSubmatch(line)[1], ",")
for i := range envs {
envs[i] = strings.TrimSpace(envs[i])[1:]
}
valid = true
continue
- } else if re_end.MatchString(line) {
+ } else if reEnd.MatchString(line) {
if !valid {
skip--
if skip < 0 {
@@ -114,8 +115,8 @@
continue
} else if skip > 0 {
continue
- } else if re_gom.MatchString(line) {
- items = re_gom.FindStringSubmatch(line)[1:]
+ } else if reGom.MatchString(line) {
+ items = reGom.FindStringSubmatch(line)[1:]
name = unquote(items[0])
parseOptions(items[1], options)
} else {
@@ -126,5 +127,4 @@
}
goms = append(goms, Gom{name, options})
}
- return goms, nil
-}
\ No newline at end of file
+}
diff --git a/mkdocs.yml b/mkdocs.yml
index 29109e0..6d6764b 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -8,5 +8,6 @@
- Commands: commands.md
- Resolving Imports: resolving-imports.md
- Vendor Directories: vendor.md
+- Plugins: plugins.md
- F.A.Q.: faq.md
theme: readthedocs
diff --git a/msg/msg.go b/msg/msg.go
index 34213fd..8b0f077 100644
--- a/msg/msg.go
+++ b/msg/msg.go
@@ -7,6 +7,8 @@
"os"
"strings"
"sync"
+
+ "github.com/Masterminds/vcs"
)
// Messenger provides the underlying implementation that displays output to
@@ -176,7 +178,6 @@
// locked to avoid displaying one message in the middle of another one.
m.Lock()
defer m.Unlock()
-
// Get rid of the annoying fact that messages need \n at the end, but do
// it in a backward compatible way.
if !strings.HasSuffix(msg, "\n") {
@@ -188,6 +189,21 @@
} else {
fmt.Fprintf(m.Stderr, msg, args...)
}
+
+ // If an arg is a vcs error print the output if in debug mode. This is
+ // capured here rather than calling Debug because concurrent operations
+ // could cause other messages to appear between the initial error and the
+ // debug output by unlocking and calling Debug.
+ if len(args) != 0 && !m.Quiet && m.IsDebugging {
+ if err, ok := args[len(args)-1].(error); ok {
+ switch t := err.(type) {
+ case *vcs.LocalError:
+ fmt.Fprintf(m.Stderr, "[DEBUG]\tOutput was: %s", strings.TrimSpace(t.Out()))
+ case *vcs.RemoteError:
+ fmt.Fprintf(m.Stderr, "[DEBUG]\tOutput was: %s", strings.TrimSpace(t.Out()))
+ }
+ }
+ }
}
// Msg prints a message with optional arguments, that can be printed, of
diff --git a/repo/installer.go b/repo/installer.go
index 6f4b2d0..13d3fb0 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -58,6 +58,7 @@
Updated *UpdateTracker
}
+// NewInstaller returns an Installer instance ready to use. This is the constructor.
func NewInstaller() *Installer {
i := &Installer{}
i.Updated = NewUpdateTracker()
@@ -93,28 +94,12 @@
newConf.Imports = make(cfg.Dependencies, len(lock.Imports))
for k, v := range lock.Imports {
- newConf.Imports[k] = &cfg.Dependency{
- Name: v.Name,
- Reference: v.Version,
- Repository: v.Repository,
- VcsType: v.VcsType,
- Subpackages: v.Subpackages,
- Arch: v.Arch,
- Os: v.Os,
- }
+ newConf.Imports[k] = cfg.DependencyFromLock(v)
}
newConf.DevImports = make(cfg.Dependencies, len(lock.DevImports))
for k, v := range lock.DevImports {
- newConf.DevImports[k] = &cfg.Dependency{
- Name: v.Name,
- Reference: v.Version,
- Repository: v.Repository,
- VcsType: v.VcsType,
- Subpackages: v.Subpackages,
- Arch: v.Arch,
- Os: v.Os,
- }
+ newConf.DevImports[k] = cfg.DependencyFromLock(v)
}
newConf.DeDupe()
@@ -126,8 +111,8 @@
msg.Info("Downloading dependencies. Please wait...")
- ConcurrentUpdate(newConf.Imports, cwd, i, newConf)
- ConcurrentUpdate(newConf.DevImports, cwd, i, newConf)
+ LazyConcurrentUpdate(newConf.Imports, cwd, i, newConf)
+ LazyConcurrentUpdate(newConf.DevImports, cwd, i, newConf)
return newConf, nil
}
@@ -207,6 +192,9 @@
var tdeps cfg.Dependencies
for _, v := range imps {
n := res.Stripv(v)
+ if conf.HasIgnore(n) {
+ continue
+ }
rt, sub := util.NormalizeName(n)
if sub == "" {
sub = "."
@@ -225,6 +213,9 @@
if i.ResolveTest {
for _, v := range timps {
n := res.Stripv(v)
+ if conf.HasIgnore(n) {
+ continue
+ }
rt, sub := util.NormalizeName(n)
if sub == "" {
sub = "."
@@ -317,6 +308,43 @@
return conf.Imports
}
+// LazyConcurrentUpdate updates only deps that are not already checkout out at the right version.
+//
+// This is only safe when updating from a lock file.
+func LazyConcurrentUpdate(deps []*cfg.Dependency, cwd string, i *Installer, c *cfg.Config) error {
+
+ newDeps := []*cfg.Dependency{}
+ for _, dep := range deps {
+ destPath := filepath.Join(i.VendorPath(), dep.Name)
+
+ // Get a VCS object for this directory
+ repo, err := dep.GetRepo(destPath)
+ if err != nil {
+ newDeps = append(newDeps, dep)
+ continue
+ }
+
+ ver, err := repo.Version()
+ if err != nil {
+ newDeps = append(newDeps, dep)
+ continue
+ }
+
+ if ver == dep.Reference {
+ msg.Info("--> Found desired version %s %s!", dep.Name, dep.Reference)
+ continue
+ }
+
+ msg.Debug("--> Queue %s for update (%s != %s).", dep.Name, ver, dep.Reference)
+ newDeps = append(newDeps, dep)
+ }
+ if len(newDeps) > 0 {
+ return ConcurrentUpdate(newDeps, cwd, i, c)
+ }
+
+ return nil
+}
+
// ConcurrentUpdate takes a list of dependencies and updates in parallel.
func ConcurrentUpdate(deps []*cfg.Dependency, cwd string, i *Installer, c *cfg.Config) error {
done := make(chan struct{}, concurrentWorkers)
diff --git a/repo/vcs.go b/repo/vcs.go
index 31bed50..3f5f80d 100644
--- a/repo/vcs.go
+++ b/repo/vcs.go
@@ -203,14 +203,14 @@
}
ver := dep.Reference
- // Referenes in Git can begin with a ^ which is similar to semver.
+ // References in Git can begin with a ^ which is similar to semver.
// If there is a ^ prefix we assume it's a semver constraint rather than
// part of the git/VCS commit id.
if repo.IsReference(ver) && !strings.HasPrefix(ver, "^") {
msg.Info("--> Setting version for %s to %s.\n", dep.Name, ver)
} else {
- // Create the constraing first to make sure it's valid before
+ // Create the constraint first to make sure it's valid before
// working on the repo.
constraint, err := semver.NewConstraint(ver)
diff --git a/vendor/github.com/Masterminds/semver/CHANGELOG.md b/vendor/github.com/Masterminds/semver/CHANGELOG.md
index 2382b75..c3808ea 100644
--- a/vendor/github.com/Masterminds/semver/CHANGELOG.md
+++ b/vendor/github.com/Masterminds/semver/CHANGELOG.md
@@ -1,4 +1,13 @@
-# Release 1.1.0 (2015-03-11)
+# Release 1.1.1 (2016-06-30)
+
+## Changed
+- Issue #9: Speed up version comparison performance (thanks @sdboyer)
+- Issue #8: Added benchmarks (thanks @sdboyer)
+- Updated Go Report Card URL to new location
+- Updated Readme to add code snippet formatting (thanks @mh-cbon)
+- Updating tagging to v[SemVer] structure for compatibility with other tools.
+
+# Release 1.1.0 (2016-03-11)
- Issue #2: Implemented validation to provide reasons a versions failed a
constraint.
diff --git a/vendor/github.com/Masterminds/semver/README.md b/vendor/github.com/Masterminds/semver/README.md
index aa133ea..1edec7a 100644
--- a/vendor/github.com/Masterminds/semver/README.md
+++ b/vendor/github.com/Masterminds/semver/README.md
@@ -7,13 +7,15 @@
* Check if a semantic version fits within a set of constraints
* Optionally work with a `v` prefix
-[](https://travis-ci.org/Masterminds/semver) [](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [](https://godoc.org/github.com/Masterminds/semver) [](http://goreportcard.com/report/Masterminds/semver)
+[](https://travis-ci.org/Masterminds/semver) [](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [](https://godoc.org/github.com/Masterminds/semver) [](https://goreportcard.com/report/github.com/Masterminds/semver)
## Parsing Semantic Versions
To parse a semantic version use the `NewVersion` function. For example,
+```go
v, err := semver.NewVersion("1.2.3-beta.1+build345")
+```
If there is an error the version wasn't parseable. The version object has methods
to get the parts of the version, compare it to other versions, convert the
@@ -25,6 +27,7 @@
A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/)
package from the standard library. For example,
+```go
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
@@ -37,12 +40,14 @@
}
sort.Sort(semver.Collection(vs))
+```
## Checking Version Constraints
Checking a version against version constraints is one of the most featureful
parts of the package.
+```go
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parseable.
@@ -54,6 +59,7 @@
}
// Check if the version meets the constraints. The a variable will be true.
a := c.Check(v)
+```
## Basic Comparisons
@@ -119,6 +125,7 @@
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
+```go
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// Handle constraint not being parseable.
@@ -139,6 +146,7 @@
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
+```
# Contribute
diff --git a/vendor/github.com/Masterminds/semver/benchmark_test.go b/vendor/github.com/Masterminds/semver/benchmark_test.go
new file mode 100644
index 0000000..58a5c28
--- /dev/null
+++ b/vendor/github.com/Masterminds/semver/benchmark_test.go
@@ -0,0 +1,157 @@
+package semver_test
+
+import (
+ "testing"
+
+ "github.com/Masterminds/semver"
+)
+
+/* Constraint creation benchmarks */
+
+func benchNewConstraint(c string, b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ semver.NewConstraint(c)
+ }
+}
+
+func BenchmarkNewConstraintUnary(b *testing.B) {
+ benchNewConstraint("=2.0", b)
+}
+
+func BenchmarkNewConstraintTilde(b *testing.B) {
+ benchNewConstraint("~2.0.0", b)
+}
+
+func BenchmarkNewConstraintCaret(b *testing.B) {
+ benchNewConstraint("^2.0.0", b)
+}
+
+func BenchmarkNewConstraintWildcard(b *testing.B) {
+ benchNewConstraint("1.x", b)
+}
+
+func BenchmarkNewConstraintRange(b *testing.B) {
+ benchNewConstraint(">=2.1.x, <3.1.0", b)
+}
+
+func BenchmarkNewConstraintUnion(b *testing.B) {
+ benchNewConstraint("~2.0.0 || =3.1.0", b)
+}
+
+/* Check benchmarks */
+
+func benchCheckVersion(c, v string, b *testing.B) {
+ version, _ := semver.NewVersion(v)
+ constraint, _ := semver.NewConstraint(c)
+
+ for i := 0; i < b.N; i++ {
+ constraint.Check(version)
+ }
+}
+
+func BenchmarkCheckVersionUnary(b *testing.B) {
+ benchCheckVersion("=2.0", "2.0.0", b)
+}
+
+func BenchmarkCheckVersionTilde(b *testing.B) {
+ benchCheckVersion("~2.0.0", "2.0.5", b)
+}
+
+func BenchmarkCheckVersionCaret(b *testing.B) {
+ benchCheckVersion("^2.0.0", "2.1.0", b)
+}
+
+func BenchmarkCheckVersionWildcard(b *testing.B) {
+ benchCheckVersion("1.x", "1.4.0", b)
+}
+
+func BenchmarkCheckVersionRange(b *testing.B) {
+ benchCheckVersion(">=2.1.x, <3.1.0", "2.4.5", b)
+}
+
+func BenchmarkCheckVersionUnion(b *testing.B) {
+ benchCheckVersion("~2.0.0 || =3.1.0", "3.1.0", b)
+}
+
+func benchValidateVersion(c, v string, b *testing.B) {
+ version, _ := semver.NewVersion(v)
+ constraint, _ := semver.NewConstraint(c)
+
+ for i := 0; i < b.N; i++ {
+ constraint.Validate(version)
+ }
+}
+
+/* Validate benchmarks, including fails */
+
+func BenchmarkValidateVersionUnary(b *testing.B) {
+ benchValidateVersion("=2.0", "2.0.0", b)
+}
+
+func BenchmarkValidateVersionUnaryFail(b *testing.B) {
+ benchValidateVersion("=2.0", "2.0.1", b)
+}
+
+func BenchmarkValidateVersionTilde(b *testing.B) {
+ benchValidateVersion("~2.0.0", "2.0.5", b)
+}
+
+func BenchmarkValidateVersionTildeFail(b *testing.B) {
+ benchValidateVersion("~2.0.0", "1.0.5", b)
+}
+
+func BenchmarkValidateVersionCaret(b *testing.B) {
+ benchValidateVersion("^2.0.0", "2.1.0", b)
+}
+
+func BenchmarkValidateVersionCaretFail(b *testing.B) {
+ benchValidateVersion("^2.0.0", "4.1.0", b)
+}
+
+func BenchmarkValidateVersionWildcard(b *testing.B) {
+ benchValidateVersion("1.x", "1.4.0", b)
+}
+
+func BenchmarkValidateVersionWildcardFail(b *testing.B) {
+ benchValidateVersion("1.x", "2.4.0", b)
+}
+
+func BenchmarkValidateVersionRange(b *testing.B) {
+ benchValidateVersion(">=2.1.x, <3.1.0", "2.4.5", b)
+}
+
+func BenchmarkValidateVersionRangeFail(b *testing.B) {
+ benchValidateVersion(">=2.1.x, <3.1.0", "1.4.5", b)
+}
+
+func BenchmarkValidateVersionUnion(b *testing.B) {
+ benchValidateVersion("~2.0.0 || =3.1.0", "3.1.0", b)
+}
+
+func BenchmarkValidateVersionUnionFail(b *testing.B) {
+ benchValidateVersion("~2.0.0 || =3.1.0", "3.1.1", b)
+}
+
+/* Version creation benchmarks */
+
+func benchNewVersion(v string, b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ semver.NewVersion(v)
+ }
+}
+
+func BenchmarkNewVersionSimple(b *testing.B) {
+ benchNewVersion("1.0.0", b)
+}
+
+func BenchmarkNewVersionPre(b *testing.B) {
+ benchNewVersion("1.0.0-alpha", b)
+}
+
+func BenchmarkNewVersionMeta(b *testing.B) {
+ benchNewVersion("1.0.0+metadata", b)
+}
+
+func BenchmarkNewVersionMetaDash(b *testing.B) {
+ benchNewVersion("1.0.0+metadata-dash", b)
+}
diff --git a/vendor/github.com/Masterminds/semver/constraints.go b/vendor/github.com/Masterminds/semver/constraints.go
index 9a5e9da..b63f5f6 100644
--- a/vendor/github.com/Masterminds/semver/constraints.go
+++ b/vendor/github.com/Masterminds/semver/constraints.go
@@ -312,8 +312,6 @@
return true
}
-type rwfunc func(i string) string
-
var constraintRangeRegex *regexp.Regexp
const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` +
@@ -321,8 +319,12 @@
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
func isX(x string) bool {
- l := strings.ToLower(x)
- return l == "x" || l == "*"
+ switch x {
+ case "x", "*", "X":
+ return true
+ default:
+ return false
+ }
}
func rewriteRange(i string) string {
diff --git a/vendor/github.com/Masterminds/semver/version.go b/vendor/github.com/Masterminds/semver/version.go
index 75dbbc0..dbb93f8 100644
--- a/vendor/github.com/Masterminds/semver/version.go
+++ b/vendor/github.com/Masterminds/semver/version.go
@@ -152,12 +152,6 @@
// Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is
// lower than the version without a prerelease.
func (v *Version) Compare(o *Version) int {
-
- // Fastpath if both versions are the same.
- if v.String() == o.String() {
- return 0
- }
-
// Compare the major, minor, and patch version for differences. If a
// difference is found return the comparison.
if d := compareSegment(v.Major(), o.Major()); d != 0 {
diff --git a/vendor/github.com/Masterminds/vcs/.travis.yml b/vendor/github.com/Masterminds/vcs/.travis.yml
index a8c32da..5c50c4a 100644
--- a/vendor/github.com/Masterminds/vcs/.travis.yml
+++ b/vendor/github.com/Masterminds/vcs/.travis.yml
@@ -18,4 +18,9 @@
sudo: false
notifications:
- irc: "irc.freenode.net#masterminds"
+ webhooks:
+ urls:
+ - https://webhooks.gitter.im/e/06e3328629952dabe3e0
+ on_success: change # options: [always|never|change] default: always
+ on_failure: always # options: [always|never|change] default: always
+ on_start: never # options: [always|never|change] default: always
diff --git a/vendor/github.com/Masterminds/vcs/CHANGELOG.md b/vendor/github.com/Masterminds/vcs/CHANGELOG.md
index d178685..6362674 100644
--- a/vendor/github.com/Masterminds/vcs/CHANGELOG.md
+++ b/vendor/github.com/Masterminds/vcs/CHANGELOG.md
@@ -1,4 +1,18 @@
-1.7.0 (2016-05-05)
+# 1.8.0 (2016-06-29)
+
+## Added
+- #43: Detect when tool (e.g., git, svn, etc) not installed
+- #49: Detect access denied and not found situations
+
+## Changed
+- #48: Updated Go Report Gard url to new format
+- Refactored SVN handling to detect when not in a top level directory
+- Updating tagging to v[SemVer] structure for compatibility with other tools.
+
+## Fixed
+- #45: Fixed hg's update method so that it pulls from remote before updates
+
+# 1.7.0 (2016-05-05)
- Adds a glide.yaml file with some limited information.
- Implements #37: Ability to export source as a directory.
diff --git a/vendor/github.com/Masterminds/vcs/README.md b/vendor/github.com/Masterminds/vcs/README.md
index 6025f2d..cdb981f 100644
--- a/vendor/github.com/Masterminds/vcs/README.md
+++ b/vendor/github.com/Masterminds/vcs/README.md
@@ -3,7 +3,7 @@
Manage repos in varying version control systems with ease through a common
interface.
-[](https://travis-ci.org/Masterminds/vcs) [](https://godoc.org/github.com/Masterminds/vcs) [](http://goreportcard.com/report/Masterminds/vcs)
+[](https://travis-ci.org/Masterminds/vcs) [](https://godoc.org/github.com/Masterminds/vcs) [](https://goreportcard.com/report/github.com/Masterminds/vcs)
## Quick Usage
diff --git a/vendor/github.com/Masterminds/vcs/bzr.go b/vendor/github.com/Masterminds/vcs/bzr.go
index a62451f..e8f55b6 100644
--- a/vendor/github.com/Masterminds/vcs/bzr.go
+++ b/vendor/github.com/Masterminds/vcs/bzr.go
@@ -16,6 +16,10 @@
// NewBzrRepo creates a new instance of BzrRepo. The remote and local directories
// need to be passed in.
func NewBzrRepo(remote, local string) (*BzrRepo, error) {
+ ins := depInstalled("bzr")
+ if !ins {
+ return nil, NewLocalError("bzr is not installed", nil, "")
+ }
ltype, err := DetectVcsFromFS(local)
// Found a VCS other than Bzr. Need to report an error.
diff --git a/vendor/github.com/Masterminds/vcs/git.go b/vendor/github.com/Masterminds/vcs/git.go
index 778b6af..eb4b86e 100644
--- a/vendor/github.com/Masterminds/vcs/git.go
+++ b/vendor/github.com/Masterminds/vcs/git.go
@@ -14,6 +14,10 @@
// NewGitRepo creates a new instance of GitRepo. The remote and local directories
// need to be passed in.
func NewGitRepo(remote, local string) (*GitRepo, error) {
+ ins := depInstalled("git")
+ if !ins {
+ return nil, NewLocalError("git is not installed", nil, "")
+ }
ltype, err := DetectVcsFromFS(local)
// Found a VCS other than Git. Need to report an error.
diff --git a/vendor/github.com/Masterminds/vcs/hg.go b/vendor/github.com/Masterminds/vcs/hg.go
index 0d7a994..df41cd6 100644
--- a/vendor/github.com/Masterminds/vcs/hg.go
+++ b/vendor/github.com/Masterminds/vcs/hg.go
@@ -14,6 +14,10 @@
// NewHgRepo creates a new instance of HgRepo. The remote and local directories
// need to be passed in.
func NewHgRepo(remote, local string) (*HgRepo, error) {
+ ins := depInstalled("hg")
+ if !ins {
+ return nil, NewLocalError("hg is not installed", nil, "")
+ }
ltype, err := DetectVcsFromFS(local)
// Found a VCS other than Hg. Need to report an error.
@@ -84,11 +88,7 @@
// Update performs a Mercurial pull to an existing checkout.
func (s *HgRepo) Update() error {
- out, err := s.RunFromDir("hg", "update")
- if err != nil {
- return NewRemoteError("Unable to update repository", err, string(out))
- }
- return nil
+ return s.UpdateVersion(``)
}
// UpdateVersion sets the version of a package currently checked out via Hg.
@@ -97,7 +97,11 @@
if err != nil {
return NewLocalError("Unable to update checked out version", err, string(out))
}
- out, err = s.RunFromDir("hg", "update", version)
+ if len(strings.TrimSpace(version)) > 0 {
+ out, err = s.RunFromDir("hg", "update", version)
+ } else {
+ out, err = s.RunFromDir("hg", "update")
+ }
if err != nil {
return NewLocalError("Unable to update checked out version", err, string(out))
}
diff --git a/vendor/github.com/Masterminds/vcs/repo.go b/vendor/github.com/Masterminds/vcs/repo.go
index 99bc2d2..1298a5f 100644
--- a/vendor/github.com/Masterminds/vcs/repo.go
+++ b/vendor/github.com/Masterminds/vcs/repo.go
@@ -257,3 +257,11 @@
}
return out
}
+
+func depInstalled(name string) bool {
+ if _, err := exec.LookPath(name); err != nil {
+ return false
+ }
+
+ return true
+}
diff --git a/vendor/github.com/Masterminds/vcs/repo_test.go b/vendor/github.com/Masterminds/vcs/repo_test.go
index 12f63f5..d61f6cb 100644
--- a/vendor/github.com/Masterminds/vcs/repo_test.go
+++ b/vendor/github.com/Masterminds/vcs/repo_test.go
@@ -60,3 +60,15 @@
t.Errorf("Not detecting repo switch from SVN to Git")
}
}
+
+func TestDepInstalled(t *testing.T) {
+ i := depInstalled("git")
+ if i != true {
+ t.Error("depInstalled not finding installed dep.")
+ }
+
+ i = depInstalled("thisreallyisntinstalled")
+ if i != false {
+ t.Error("depInstalled finding not installed dep.")
+ }
+}
diff --git a/vendor/github.com/Masterminds/vcs/svn.go b/vendor/github.com/Masterminds/vcs/svn.go
index 48d089b..888ae09 100644
--- a/vendor/github.com/Masterminds/vcs/svn.go
+++ b/vendor/github.com/Masterminds/vcs/svn.go
@@ -2,21 +2,23 @@
import (
"encoding/xml"
+ "fmt"
"os"
"os/exec"
"path/filepath"
- "regexp"
"strings"
"time"
)
-var svnDetectURL = regexp.MustCompile("URL: (?P<foo>.+)\n")
-
// NewSvnRepo creates a new instance of SvnRepo. The remote and local directories
// need to be passed in. The remote location should include the branch for SVN.
// For example, if the package is https://github.com/Masterminds/cookoo/ the remote
// should be https://github.com/Masterminds/cookoo/trunk for the trunk branch.
func NewSvnRepo(remote, local string) (*SvnRepo, error) {
+ ins := depInstalled("svn")
+ if !ins {
+ return nil, NewLocalError("svn is not installed", nil, "")
+ }
ltype, err := DetectVcsFromFS(local)
// Found a VCS other than Svn. Need to report an error.
@@ -39,15 +41,18 @@
return nil, NewLocalError("Unable to retrieve local repo information", err, string(out))
}
- m := svnDetectURL.FindStringSubmatch(string(out))
- if m[1] != "" && m[1] != remote {
+ detectedRemote, err := detectRemoteFromInfoCommand(string(out))
+ if err != nil {
+ return nil, NewLocalError("Unable to retrieve local repo information", err, string(out))
+ }
+ if detectedRemote != "" && remote != "" && detectedRemote != remote {
return nil, ErrWrongRemote
}
// If no remote was passed in but one is configured for the locally
// checked out Svn repo use that one.
- if remote == "" && m[1] != "" {
- r.setRemote(m[1])
+ if remote == "" && detectedRemote != "" {
+ r.setRemote(detectedRemote)
}
}
@@ -185,12 +190,15 @@
// CheckLocal verifies the local location is an SVN repo.
func (s *SvnRepo) CheckLocal() bool {
- if _, err := os.Stat(s.LocalPath() + "/.svn"); err == nil {
- return true
+ sep := fmt.Sprintf("%c", os.PathSeparator)
+ psplit := strings.Split(s.LocalPath(), sep)
+ for i := 0; i < len(psplit); i++ {
+ path := fmt.Sprintf("%s%s", sep, filepath.Join(psplit[0:(len(psplit)-(i))]...))
+ if _, err := os.Stat(filepath.Join(path, ".svn")); err == nil {
+ return true
+ }
}
-
return false
-
}
// Tags returns []string{} as there are no formal tags in SVN. Tags are a
@@ -344,3 +352,24 @@
return false
}
+
+// detectRemoteFromInfoCommand finds the remote url from the `svn info`
+// command's output without using a regex. We avoid regex because URLs
+// are notoriously complex to accurately match with a regex and
+// splitting strings is less complex and often faster
+func detectRemoteFromInfoCommand(infoOut string) (string, error) {
+ sBytes := []byte(infoOut)
+ urlIndex := strings.Index(infoOut, "URL: ")
+ if urlIndex == -1 {
+ return "", fmt.Errorf("Remote not specified in svn info")
+ }
+ urlEndIndex := strings.Index(string(sBytes[urlIndex:]), "\n")
+ if urlEndIndex == -1 {
+ urlEndIndex = strings.Index(string(sBytes[urlIndex:]), "\r")
+ if urlEndIndex == -1 {
+ return "", fmt.Errorf("Unable to parse remote URL for svn info")
+ }
+ }
+
+ return string(sBytes[(urlIndex + 5):(urlIndex + urlEndIndex)]), nil
+}
diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go
index 85fac7f..0567af8 100644
--- a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go
+++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go
@@ -88,6 +88,8 @@
t, e := detectVcsFromURL(vcsURL)
if e == nil {
return t, vcsURL, nil
+ } else if e != ErrCannotDetectVCS {
+ return NoVCS, "", e
}
// Pages like https://golang.org/x/net provide an html document with
@@ -114,6 +116,11 @@
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
+ if resp.StatusCode == 404 {
+ return NoVCS, "", NewRemoteError(fmt.Sprintf("%s Not Found", vcsURL), nil, "")
+ } else if resp.StatusCode == 401 || resp.StatusCode == 403 {
+ return NoVCS, "", NewRemoteError(fmt.Sprintf("%s Access Denied", vcsURL), nil, "")
+ }
return NoVCS, "", ErrCannotDetectVCS
}
@@ -202,6 +209,10 @@
}
t, err := v.addCheck(info, u)
if err != nil {
+ switch err.(type) {
+ case *RemoteError:
+ return "", err
+ }
return "", ErrCannotDetectVCS
}
@@ -299,7 +310,11 @@
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
- // TODO(mattfarina): log the failed status
+ if resp.StatusCode == 404 {
+ return nil, NewRemoteError("Not Found", err, resp.Status)
+ } else if resp.StatusCode == 401 || resp.StatusCode == 403 {
+ return nil, NewRemoteError("Access Denied", err, resp.Status)
+ }
return nil, fmt.Errorf("%s: %s", url, resp.Status)
}
b, err := ioutil.ReadAll(resp.Body)
diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go
index fd7663e..e97bba8 100644
--- a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go
+++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go
@@ -1,6 +1,7 @@
package vcs
import (
+ "strings"
"testing"
)
@@ -58,7 +59,11 @@
t.Errorf("Error detecting VCS from URL(%s): %s", u, err)
}
- if err != nil && err != ErrCannotDetectVCS && c.work == false {
+ if err != nil &&
+ err != ErrCannotDetectVCS &&
+ !strings.HasSuffix(err.Error(), "Not Found") &&
+ !strings.HasSuffix(err.Error(), "Access Denied") &&
+ c.work == false {
t.Errorf("Unexpected error returned (%s): %s", u, err)
}
@@ -67,3 +72,27 @@
}
}
}
+
+func TestNotFound(t *testing.T) {
+ _, _, err := detectVcsFromRemote("https://mattfarina.com/notfound")
+ if err == nil || !strings.HasSuffix(err.Error(), " Not Found") {
+ t.Errorf("Failed to find not found repo")
+ }
+
+ _, err = NewRepo("https://mattfarina.com/notfound", "")
+ if err == nil || !strings.HasSuffix(err.Error(), " Not Found") {
+ t.Errorf("Failed to find not found repo")
+ }
+}
+
+func TestAccessDenied(t *testing.T) {
+ _, _, err := detectVcsFromRemote("https://bitbucket.org/mattfarina/private-repo-for-vcs-testing")
+ if err == nil || err.Error() != "Access Denied" {
+ t.Errorf("Failed to detect access denied")
+ }
+
+ _, err = NewRepo("https://bitbucket.org/mattfarina/private-repo-for-vcs-testing", "")
+ if err == nil || err.Error() != "Access Denied" {
+ t.Errorf("Failed to detect access denied")
+ }
+}