Catch gps back up with master
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a76e7d3..9c1187a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,47 @@
+# 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.
 
-[![Build Status](https://travis-ci.org/Masterminds/glide.svg)](https://travis-ci.org/Masterminds/glide) [![Go Report Card](http://goreportcard.com/badge/Masterminds/glide)](http://goreportcard.com/report/Masterminds/glide) [![GoDoc](https://godoc.org/github.com/Masterminds/glide?status.svg)](https://godoc.org/github.com/Masterminds/glide) [![Documentation Status](https://readthedocs.org/projects/glide/badge/?version=stable)](http://glide.readthedocs.org/en/stable/?badge=stable) [![Documentation Status](https://readthedocs.org/projects/glide/badge/?version=latest)](http://glide.readthedocs.org/en/latest/?badge=latest) [![Join the chat at https://gitter.im/Masterminds/glide](https://badges.gitter.im/Masterminds/glide.svg)](https://gitter.im/Masterminds/glide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Build Status](https://travis-ci.org/Masterminds/glide.svg)](https://travis-ci.org/Masterminds/glide) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/glide)](https://goreportcard.com/report/github.com/Masterminds/glide) [![GoDoc](https://godoc.org/github.com/Masterminds/glide?status.svg)](https://godoc.org/github.com/Masterminds/glide) [![Documentation Status](https://readthedocs.org/projects/glide/badge/?version=stable)](http://glide.readthedocs.org/en/stable/?badge=stable) [![Documentation Status](https://readthedocs.org/projects/glide/badge/?version=latest)](http://glide.readthedocs.org/en/latest/?badge=latest) [![Join the chat at https://gitter.im/Masterminds/glide](https://badges.gitter.im/Masterminds/glide.svg)](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 d4e9a50..ff9ed7d 100644
--- a/action/get.go
+++ b/action/get.go
@@ -50,7 +50,7 @@
 	// don't want a get to just update all deps without the user explictly
 	// making that choice.
 	if gpath.HasLock(base) {
-		params.Lock, err = LoadLockfile(base, conf)
+		params.Lock, err = loadLockfile(base, conf)
 		if err != nil {
 			msg.Err("Could not load lockfile; aborting get. Existing dependency versions cannot be safely preserved without a lock file. Error was: %s", err)
 			return
diff --git a/action/install.go b/action/install.go
index 53599af..c10f5d3 100644
--- a/action/install.go
+++ b/action/install.go
@@ -49,7 +49,7 @@
 
 	var s gps.Solver
 	if gpath.HasLock(base) {
-		params.Lock, err = LoadLockfile(base, conf)
+		params.Lock, err = loadLockfile(base, conf)
 		if err != nil {
 			msg.Err("Could not load lockfile.")
 			return
@@ -334,10 +334,8 @@
 	return nil
 }
 
-// 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) {
+// loadLockfile loads the contents of a glide.lock file.
+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
diff --git a/action/project_info.go b/action/project_info.go
index 0662bbc..b82b41c 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.ProjectRoot)
 			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 33d616a..c008f98 100644
--- a/action/update.go
+++ b/action/update.go
@@ -52,7 +52,7 @@
 	}
 
 	if gpath.HasLock(base) {
-		params.Lock, err = LoadLockfile(base, conf)
+		params.Lock, err = loadLockfile(base, conf)
 		if err != nil {
 			msg.Err("Could not load lockfile, aborting: %s", err)
 			return
diff --git a/cfg/config.go b/cfg/config.go
index 54e60be..3046a74 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -465,6 +465,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{}
diff --git a/cfg/lock.go b/cfg/lock.go
index 0c798a6..ac03f91 100644
--- a/cfg/lock.go
+++ b/cfg/lock.go
@@ -153,6 +153,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
 
@@ -211,6 +224,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{
@@ -221,29 +247,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)
@@ -261,15 +271,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/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 951824d..e46c890 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,5 +1,5 @@
-hash: 607480f548198f86c4f4a5946960053afa74db4cd2d5c62b51d5954470922d3a
-updated: 2016-06-24T15:23:14.128213581-04:00
+hash: 0653c17bcbf6f1df79990f3d2211dbcbc920ca528c513b00f5cab0a508c984ab
+updated: 2016-06-30T10:51:49.633776379-04:00
 imports:
 - name: github.com/armon/go-radix
   version: 4239b77079c7b5d1243b7b4736304ce8ddb6f0f2
@@ -8,7 +8,7 @@
 - name: github.com/Masterminds/semver
   version: 0a2c9fc0eee2c4cbb9526877c4a54da047fdcadd
 - name: github.com/Masterminds/vcs
-  version: 7af28b64c5ec41b1558f5514fd938379822c237c
+  version: fbe9fb6ad5b5f35b3e82a7c21123cfc526cbf895
 - name: github.com/sdboyer/gps
   version: a868c10855893c21ed05d0f50d6f9acb12b6366d
 - name: github.com/termie/go-shutil
diff --git a/glide.yaml b/glide.yaml
index 7a966ad..cb185ed 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -12,7 +12,7 @@
 - package: gopkg.in/yaml.v2
   branch: 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
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/repo/installer.go b/repo/installer.go
index 8004da5..cce24ef 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
 }
 
@@ -317,6 +302,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 fc6c9df..ba84ca2 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/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
 
-[![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.png)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](http://goreportcard.com/badge/Masterminds/semver)](http://goreportcard.com/report/Masterminds/semver)
+[![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.png)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](https://goreportcard.com/badge/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/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.
 
-[![Build Status](https://travis-ci.org/Masterminds/vcs.svg)](https://travis-ci.org/Masterminds/vcs) [![GoDoc](https://godoc.org/github.com/Masterminds/vcs?status.png)](https://godoc.org/github.com/Masterminds/vcs) [![Go Report Card](http://goreportcard.com/badge/Masterminds/vcs)](http://goreportcard.com/report/Masterminds/vcs)
+[![Build Status](https://travis-ci.org/Masterminds/vcs.svg)](https://travis-ci.org/Masterminds/vcs) [![GoDoc](https://godoc.org/github.com/Masterminds/vcs?status.png)](https://godoc.org/github.com/Masterminds/vcs) [![Go Report Card](https://goreportcard.com/badge/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")
+	}
+}