Merge pull request #385 from Masterminds/update/vcs-1.6.0

Updated dependencies:
diff --git a/glide.lock b/glide.lock
index 1bbde7a..eeae594 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,12 +1,12 @@
-hash: 83c7c3c86a8d50d46ac2731938195e348f2445e6106325a4f90976563c946bd8
-updated: 2016-03-23T21:38:59.47773549-04:00
+hash: 3a5b11283c409c77e79505c08a39550a966d62fb0896f4355c10d699482840a3
+updated: 2016-04-18T09:49:03.335458835-04:00
 imports:
 - name: github.com/codegangsta/cli
-  version: 9fec0fad02befc9209347cc6d620e68e1b45f74d
+  version: 71f57d300dd6a780ac1856c005c4b518cfd498ec
 - name: github.com/Masterminds/semver
   version: 808ed7761c233af2de3f9729a041d68c62527f3a
 - name: github.com/Masterminds/vcs
-  version: b22ee1673cdd03ef47bb0b422736a7f17ff0648c
+  version: fa85cceafacd29c84a8aa6e68967bb9f1754e5e3
 - name: gopkg.in/yaml.v2
   version: a83829b6f1293c91addabc89d0571c246397bbf4
 devImports: []
diff --git a/glide.yaml b/glide.yaml
index a8eb79a..e9e3a02 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -11,7 +11,7 @@
 import:
 - package: gopkg.in/yaml.v2
 - package: github.com/Masterminds/vcs
-  version: ^1.5.1
+  version: ^1.6.0
 - package: github.com/codegangsta/cli
 - package: github.com/Masterminds/semver
   version: ^1.0.0
diff --git a/vendor/github.com/Masterminds/vcs/CHANGELOG.md b/vendor/github.com/Masterminds/vcs/CHANGELOG.md
index 96af5ec..7a04e56 100644
--- a/vendor/github.com/Masterminds/vcs/CHANGELOG.md
+++ b/vendor/github.com/Masterminds/vcs/CHANGELOG.md
@@ -1,3 +1,17 @@
+# 1.6.0 (2016-04-18)
+
+- Issue #26: Added Init method to initialize a repo at the local location
+  (thanks tony).
+- Issue #19: Added method to retrieve tags for a commit.
+- Issue #24: Reworked errors returned from common methods. Now differing
+  VCS implementations return the same errors. The original VCS specific error
+  is available on the error. See the docs for more details.
+- Issue #25: Export the function RunFromDir which runs VCS commands from the
+  root of the local directory. This is useful for those that want to build and
+  extend on top of the vcs package (thanks tony).
+- Issue #22: Added Ping command to test if remote location is present and
+  accessible.
+
 # 1.5.1 (2016-03-23)
 
 - Fixing bug parsing some Git commit dates.
diff --git a/vendor/github.com/Masterminds/vcs/bzr.go b/vendor/github.com/Masterminds/vcs/bzr.go
index 965b598..1d36137 100644
--- a/vendor/github.com/Masterminds/vcs/bzr.go
+++ b/vendor/github.com/Masterminds/vcs/bzr.go
@@ -1,6 +1,8 @@
 package vcs
 
 import (
+	"fmt"
+	"net/url"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -39,7 +41,7 @@
 		c.Env = envForDir(c.Dir)
 		out, err := c.CombinedOutput()
 		if err != nil {
-			return nil, err
+			return nil, NewLocalError("Unable to retrieve local repo information", err, string(out))
 		}
 		m := bzrDetectURL.FindStringSubmatch(string(out))
 
@@ -70,36 +72,76 @@
 	if _, err := os.Stat(basePath); os.IsNotExist(err) {
 		err = os.MkdirAll(basePath, 0755)
 		if err != nil {
-			return err
+			return NewLocalError("Unable to create directory", err, "")
 		}
 	}
 
-	_, err := s.run("bzr", "branch", s.Remote(), s.LocalPath())
-	return err
+	out, err := s.run("bzr", "branch", s.Remote(), s.LocalPath())
+	if err != nil {
+		return NewRemoteError("Unable to get repository", err, string(out))
+	}
+
+	return nil
+}
+
+// Init initializes a bazaar repository at local location.
+func (s *BzrRepo) Init() error {
+	out, err := s.run("bzr", "init", s.LocalPath())
+
+	// There are some windows cases where bazaar cannot create the parent
+	// directory if it does not already exist, to the location it's trying
+	// to create the repo. Catch that error and try to handle it.
+	if err != nil && s.isUnableToCreateDir(err) {
+
+		basePath := filepath.Dir(filepath.FromSlash(s.LocalPath()))
+		if _, err := os.Stat(basePath); os.IsNotExist(err) {
+			err = os.MkdirAll(basePath, 0755)
+			if err != nil {
+				return NewLocalError("Unable to initialize repository", err, "")
+			}
+
+			out, err = s.run("bzr", "init", s.LocalPath())
+			if err != nil {
+				return NewLocalError("Unable to initialize repository", err, string(out))
+			}
+			return nil
+		}
+
+	} else if err != nil {
+		return NewLocalError("Unable to initialize repository", err, string(out))
+	}
+
+	return nil
 }
 
 // Update performs a Bzr pull and update to an existing checkout.
 func (s *BzrRepo) Update() error {
-	_, err := s.runFromDir("bzr", "pull")
+	out, err := s.RunFromDir("bzr", "pull")
 	if err != nil {
-		return err
+		return NewRemoteError("Unable to update repository", err, string(out))
 	}
-	_, err = s.runFromDir("bzr", "update")
-	return err
+	out, err = s.RunFromDir("bzr", "update")
+	if err != nil {
+		return NewRemoteError("Unable to update repository", err, string(out))
+	}
+	return nil
 }
 
 // UpdateVersion sets the version of a package currently checked out via Bzr.
 func (s *BzrRepo) UpdateVersion(version string) error {
-	_, err := s.runFromDir("bzr", "update", "-r", version)
-	return err
+	out, err := s.RunFromDir("bzr", "update", "-r", version)
+	if err != nil {
+		return NewLocalError("Unable to update checked out version", err, string(out))
+	}
+	return nil
 }
 
 // Version retrieves the current version.
 func (s *BzrRepo) Version() (string, error) {
 
-	out, err := s.runFromDir("bzr", "revno", "--tree")
+	out, err := s.RunFromDir("bzr", "revno", "--tree")
 	if err != nil {
-		return "", err
+		return "", NewLocalError("Unable to retrieve checked out version", err, string(out))
 	}
 
 	return strings.TrimSpace(string(out)), nil
@@ -107,13 +149,13 @@
 
 // Date retrieves the date on the latest commit.
 func (s *BzrRepo) Date() (time.Time, error) {
-	out, err := s.runFromDir("bzr", "version-info", "--custom", "--template={date}")
+	out, err := s.RunFromDir("bzr", "version-info", "--custom", "--template={date}")
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	t, err := time.Parse(longForm, string(out))
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	return t, nil
 }
@@ -138,9 +180,9 @@
 
 // Tags returns a list of available tags on the repository.
 func (s *BzrRepo) Tags() ([]string, error) {
-	out, err := s.runFromDir("bzr", "tags")
+	out, err := s.RunFromDir("bzr", "tags")
 	if err != nil {
-		return []string{}, err
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
 	}
 	tags := s.referenceList(string(out), `(?m-s)^(\S+)`)
 	return tags, nil
@@ -149,7 +191,7 @@
 // IsReference returns if a string is a reference. A reference can be a
 // commit id or tag.
 func (s *BzrRepo) IsReference(r string) bool {
-	_, err := s.runFromDir("bzr", "revno", "-r", r)
+	_, err := s.RunFromDir("bzr", "revno", "-r", r)
 	if err == nil {
 		return true
 	}
@@ -160,14 +202,14 @@
 // IsDirty returns if the checkout has been modified from the checked
 // out reference.
 func (s *BzrRepo) IsDirty() bool {
-	out, err := s.runFromDir("bzr", "diff")
+	out, err := s.RunFromDir("bzr", "diff")
 	return err != nil || len(out) != 0
 }
 
 // CommitInfo retrieves metadata about a commit.
 func (s *BzrRepo) CommitInfo(id string) (*CommitInfo, error) {
 	r := "-r" + id
-	out, err := s.runFromDir("bzr", "log", r, "--log-format=long")
+	out, err := s.RunFromDir("bzr", "log", r, "--log-format=long")
 	if err != nil {
 		return nil, ErrRevisionUnavailable
 	}
@@ -188,7 +230,7 @@
 			ts := strings.TrimSpace(strings.TrimPrefix(l, "timestamp:"))
 			ci.Date, err = time.Parse(format, ts)
 			if err != nil {
-				return nil, err
+				return nil, NewLocalError("Unable to retrieve commit information", err, string(out))
 			}
 		} else if strings.TrimSpace(l) == "message:" {
 			track = i
@@ -206,3 +248,60 @@
 
 	return ci, nil
 }
+
+// TagsFromCommit retrieves tags from a commit id.
+func (s *BzrRepo) TagsFromCommit(id string) ([]string, error) {
+	out, err := s.RunFromDir("bzr", "tags", "-r", id)
+	if err != nil {
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
+	}
+
+	tags := s.referenceList(string(out), `(?m-s)^(\S+)`)
+	return tags, nil
+}
+
+// Ping returns if remote location is accessible.
+func (s *BzrRepo) Ping() bool {
+
+	// Running bzr info is slow. Many of the projects are on launchpad which
+	// has a public 1.0 API we can use.
+	u, err := url.Parse(s.Remote())
+	if err == nil {
+		if u.Host == "launchpad.net" {
+			try := strings.TrimPrefix(u.Path, "/")
+
+			// get returns the body and an err. If the status code is not a 200
+			// an error is returned. Launchpad returns a 404 for a codebase that
+			// does not exist. Otherwise it returns a JSON object describing it.
+			_, er := get("https://api.launchpad.net/1.0/" + try)
+			if er == nil {
+				return true
+			}
+			return false
+		}
+	}
+
+	// This is the same command that Go itself uses but it's not fast (or fast
+	// enough by my standards). A faster method would be useful.
+	_, err = s.run("bzr", "info", s.Remote())
+	if err != nil {
+		return false
+	}
+
+	return true
+}
+
+// Multi-lingual manner check for the VCS error that it couldn't create directory.
+// https://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev/files/head:/po/
+func (s *BzrRepo) isUnableToCreateDir(err error) bool {
+	msg := err.Error()
+	if strings.HasPrefix(msg, fmt.Sprintf("Parent directory of %s does not exist.", s.LocalPath())) ||
+		strings.HasPrefix(msg, fmt.Sprintf("Nadřazený adresář %s neexistuje.", s.LocalPath())) ||
+		strings.HasPrefix(msg, fmt.Sprintf("El directorio padre de %s no existe.", s.LocalPath())) ||
+		strings.HasPrefix(msg, fmt.Sprintf("%s の親ディレクトリがありません。", s.LocalPath())) ||
+		strings.HasPrefix(msg, fmt.Sprintf("Родительская директория для %s не существует.", s.LocalPath())) {
+		return true
+	}
+
+	return false
+}
diff --git a/vendor/github.com/Masterminds/vcs/bzr_test.go b/vendor/github.com/Masterminds/vcs/bzr_test.go
index ce61d75..6125444 100644
--- a/vendor/github.com/Masterminds/vcs/bzr_test.go
+++ b/vendor/github.com/Masterminds/vcs/bzr_test.go
@@ -123,6 +123,22 @@
 		t.Error("Bzr tags is not reporting the correct version")
 	}
 
+	tags, err = repo.TagsFromCommit("2")
+	if err != nil {
+		t.Error(err)
+	}
+	if len(tags) != 0 {
+		t.Error("Bzr is incorrectly returning tags for a commit")
+	}
+
+	tags, err = repo.TagsFromCommit("3")
+	if err != nil {
+		t.Error(err)
+	}
+	if len(tags) != 1 || tags[0] != "1.0.0" {
+		t.Error("Bzr is incorrectly returning tags for a commit")
+	}
+
 	branches, err := repo.Branches()
 	if err != nil {
 		t.Error(err)
@@ -196,3 +212,68 @@
 		t.Error(nrerr)
 	}
 }
+
+func TestBzrPing(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests")
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewBzrRepo("https://launchpad.net/govcstestbzrrepo", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping := repo.Ping()
+	if !ping {
+		t.Error("Bzr unable to ping working repo")
+	}
+
+	repo, err = NewBzrRepo("https://launchpad.net/ihopethisneverexistsbecauseitshouldnt", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping = repo.Ping()
+	if ping {
+		t.Error("Bzr got a ping response from when it should not have")
+	}
+}
+
+func TestBzrInit(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests")
+	repoDir := tempDir + "/repo"
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewBzrRepo(repoDir, repoDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = repo.Init()
+	if err != nil {
+		t.Error(err)
+	}
+
+	v, err := repo.Version()
+	if err != nil {
+		t.Error(err)
+	}
+	if v != "0" {
+		t.Errorf("Bzr Init returns wrong version: %s", v)
+	}
+}
diff --git a/vendor/github.com/Masterminds/vcs/errors.go b/vendor/github.com/Masterminds/vcs/errors.go
new file mode 100644
index 0000000..ea8c5fc
--- /dev/null
+++ b/vendor/github.com/Masterminds/vcs/errors.go
@@ -0,0 +1,107 @@
+package vcs
+
+import "errors"
+
+// The vcs package provides ways to work with errors that hide the underlying
+// implementation details but make them accessible if needed. For basic errors
+// that do not have underlying implementation specific details or the underlying
+// details are likely not necessairy there are errors for comparison.
+//
+// For example:
+//
+//     ci, err := repo.CommitInfo("123")
+//     if err == vcs.ErrRevisionUnavailable {
+//         // The commit id was not available in the VCS.
+//     }
+//
+// There are other times where getting the details are more useful. For example,
+// if you're performing a repo.Get() and an error occurs. In general you'll want
+// to consistently know it failed. But, you may want to know the underlying
+// details (opt-in) to them. For those cases there is a different form of error
+// handling.
+//
+// For example:
+//
+//     err := repo.Get()
+//     if err != nil {
+//         // A RemoteError was returned. This has access to the output of the
+//         // vcs command, original error, and has a consistent cross vcs message.
+//     }
+//
+// The errors returned here can be used in type switches to detect the underlying
+// error. For example:
+//
+//     switch err.(type) {
+//     case *vcs.RemoteError:
+//         // This an error connecting to a remote system.
+//     }
+//
+// For more information on using type switches to detect error types you can
+// read the Go wiki at https://github.com/golang/go/wiki/Errors
+
+var (
+	// ErrWrongVCS is returned when an action is tried on the wrong VCS.
+	ErrWrongVCS = errors.New("Wrong VCS detected")
+
+	// ErrCannotDetectVCS is returned when VCS cannot be detected from URI string.
+	ErrCannotDetectVCS = errors.New("Cannot detect VCS")
+
+	// ErrWrongRemote occurs when the passed in remote does not match the VCS
+	// configured endpoint.
+	ErrWrongRemote = errors.New("The Remote does not match the VCS endpoint")
+
+	// ErrRevisionUnavailable happens when commit revision information is
+	// unavailable.
+	ErrRevisionUnavailable = errors.New("Revision unavailable")
+)
+
+// RemoteError is returned when an operation fails against a remote repo
+type RemoteError struct {
+	vcsError
+}
+
+// NewRemoteError constructs a RemoteError
+func NewRemoteError(msg string, err error, out string) error {
+	e := &RemoteError{}
+	e.s = msg
+	e.e = err
+	e.o = out
+
+	return e
+}
+
+// LocalError is returned when a local operation has an error
+type LocalError struct {
+	vcsError
+}
+
+// NewLocalError constructs a LocalError
+func NewLocalError(msg string, err error, out string) error {
+	e := &LocalError{}
+	e.s = msg
+	e.e = err
+	e.o = out
+
+	return e
+}
+
+type vcsError struct {
+	s string
+	e error  // The original error
+	o string // The output from executing the command
+}
+
+// Error implements the Error interface
+func (e *vcsError) Error() string {
+	return e.s
+}
+
+// Original retrieves the underlying implementation specific error.
+func (e *vcsError) Original() error {
+	return e.e
+}
+
+// Out retrieves the output of the original command that was run.
+func (e *vcsError) Out() string {
+	return e.o
+}
diff --git a/vendor/github.com/Masterminds/vcs/errors_test.go b/vendor/github.com/Masterminds/vcs/errors_test.go
new file mode 100644
index 0000000..2effd7c
--- /dev/null
+++ b/vendor/github.com/Masterminds/vcs/errors_test.go
@@ -0,0 +1,36 @@
+package vcs
+
+import (
+	"errors"
+	"testing"
+)
+
+func TestNewRemoteError(t *testing.T) {
+	base := errors.New("Foo error")
+	out := "This is a test"
+	msg := "remote error msg"
+
+	e := NewRemoteError(msg, base, out)
+
+	switch e.(type) {
+	case *RemoteError:
+		// This is the right error type
+	default:
+		t.Error("Wrong error type returned from NewRemoteError")
+	}
+}
+
+func TestNewLocalError(t *testing.T) {
+	base := errors.New("Foo error")
+	out := "This is a test"
+	msg := "local error msg"
+
+	e := NewLocalError(msg, base, out)
+
+	switch e.(type) {
+	case *LocalError:
+		// This is the right error type
+	default:
+		t.Error("Wrong error type returned from NewLocalError")
+	}
+}
diff --git a/vendor/github.com/Masterminds/vcs/git.go b/vendor/github.com/Masterminds/vcs/git.go
index 636ddc7..5d4b956 100644
--- a/vendor/github.com/Masterminds/vcs/git.go
+++ b/vendor/github.com/Masterminds/vcs/git.go
@@ -33,7 +33,7 @@
 		c.Env = envForDir(c.Dir)
 		out, err := c.CombinedOutput()
 		if err != nil {
-			return nil, err
+			return nil, NewLocalError("Unable to retrieve local repo information", err, string(out))
 		}
 
 		localRemote := strings.TrimSpace(string(out))
@@ -64,7 +64,7 @@
 
 // Get is used to perform an initial clone of a repository.
 func (s *GitRepo) Get() error {
-	_, err := s.run("git", "clone", s.Remote(), s.LocalPath())
+	out, err := s.run("git", "clone", s.Remote(), s.LocalPath())
 
 	// There are some windows cases where Git cannot create the parent directory,
 	// if it does not already exist, to the location it's trying to create the
@@ -75,53 +75,93 @@
 		if _, err := os.Stat(basePath); os.IsNotExist(err) {
 			err = os.MkdirAll(basePath, 0755)
 			if err != nil {
-				return err
+				return NewLocalError("Unable to create directory", err, "")
 			}
 
-			_, err = s.run("git", "clone", s.Remote(), s.LocalPath())
+			out, err = s.run("git", "clone", s.Remote(), s.LocalPath())
+			if err != nil {
+				return NewRemoteError("Unable to get repository", err, string(out))
+			}
 			return err
 		}
 
+	} else if err != nil {
+		return NewRemoteError("Unable to get repository", err, string(out))
 	}
 
-	return err
+	return nil
+}
+
+// Init initializes a git repository at local location.
+func (s *GitRepo) Init() error {
+	out, err := s.run("git", "init", s.LocalPath())
+
+	// There are some windows cases where Git cannot create the parent directory,
+	// if it does not already exist, to the location it's trying to create the
+	// repo. Catch that error and try to handle it.
+	if err != nil && s.isUnableToCreateDir(err) {
+
+		basePath := filepath.Dir(filepath.FromSlash(s.LocalPath()))
+		if _, err := os.Stat(basePath); os.IsNotExist(err) {
+			err = os.MkdirAll(basePath, 0755)
+			if err != nil {
+				return NewLocalError("Unable to initialize repository", err, "")
+			}
+
+			out, err = s.run("git", "init", s.LocalPath())
+			if err != nil {
+				return NewLocalError("Unable to initialize repository", err, string(out))
+			}
+			return nil
+		}
+
+	} else if err != nil {
+		return NewLocalError("Unable to initialize repository", err, string(out))
+	}
+
+	return nil
 }
 
 // Update performs an Git fetch and pull to an existing checkout.
 func (s *GitRepo) Update() error {
 	// Perform a fetch to make sure everything is up to date.
-	_, err := s.runFromDir("git", "fetch", s.RemoteLocation)
+	out, err := s.RunFromDir("git", "fetch", s.RemoteLocation)
 	if err != nil {
-		return err
+		return NewRemoteError("Unable to update repository", err, string(out))
 	}
 
 	// When in a detached head state, such as when an individual commit is checked
 	// out do not attempt a pull. It will cause an error.
 	detached, err := isDetachedHead(s.LocalPath())
-
 	if err != nil {
-		return err
+		return NewLocalError("Unable to update repository", err, "")
 	}
 
 	if detached == true {
 		return nil
 	}
 
-	_, err = s.runFromDir("git", "pull")
-	return err
+	out, err = s.RunFromDir("git", "pull")
+	if err != nil {
+		return NewRemoteError("Unable to update repository", err, string(out))
+	}
+	return nil
 }
 
 // UpdateVersion sets the version of a package currently checked out via Git.
 func (s *GitRepo) UpdateVersion(version string) error {
-	_, err := s.runFromDir("git", "checkout", version)
-	return err
+	out, err := s.RunFromDir("git", "checkout", version)
+	if err != nil {
+		return NewLocalError("Unable to update checked out version", err, string(out))
+	}
+	return nil
 }
 
 // Version retrieves the current version.
 func (s *GitRepo) Version() (string, error) {
-	out, err := s.runFromDir("git", "rev-parse", "HEAD")
+	out, err := s.RunFromDir("git", "rev-parse", "HEAD")
 	if err != nil {
-		return "", err
+		return "", NewLocalError("Unable to retrieve checked out version", err, string(out))
 	}
 
 	return strings.TrimSpace(string(out)), nil
@@ -129,22 +169,22 @@
 
 // Date retrieves the date on the latest commit.
 func (s *GitRepo) Date() (time.Time, error) {
-	out, err := s.runFromDir("git", "log", "-1", "--date=iso", "--pretty=format:%cd")
+	out, err := s.RunFromDir("git", "log", "-1", "--date=iso", "--pretty=format:%cd")
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	t, err := time.Parse(longForm, string(out))
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	return t, nil
 }
 
 // Branches returns a list of available branches on the RemoteLocation
 func (s *GitRepo) Branches() ([]string, error) {
-	out, err := s.runFromDir("git", "show-ref")
+	out, err := s.RunFromDir("git", "show-ref")
 	if err != nil {
-		return []string{}, err
+		return []string{}, NewLocalError("Unable to retrieve branches", err, string(out))
 	}
 	branches := s.referenceList(string(out), `(?m-s)(?:`+s.RemoteLocation+`)/(\S+)$`)
 	return branches, nil
@@ -152,9 +192,9 @@
 
 // Tags returns a list of available tags on the RemoteLocation
 func (s *GitRepo) Tags() ([]string, error) {
-	out, err := s.runFromDir("git", "show-ref")
+	out, err := s.RunFromDir("git", "show-ref")
 	if err != nil {
-		return []string{}, err
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
 	}
 	tags := s.referenceList(string(out), `(?m-s)(?:tags)/(\S+)$`)
 	return tags, nil
@@ -172,7 +212,7 @@
 // IsReference returns if a string is a reference. A reference can be a
 // commit id, branch, or tag.
 func (s *GitRepo) IsReference(r string) bool {
-	_, err := s.runFromDir("git", "rev-parse", "--verify", r)
+	_, err := s.RunFromDir("git", "rev-parse", "--verify", r)
 	if err == nil {
 		return true
 	}
@@ -180,7 +220,7 @@
 	// Some refs will fail rev-parse. For example, a remote branch that has
 	// not been checked out yet. This next step should pickup the other
 	// possible references.
-	_, err = s.runFromDir("git", "show-ref", r)
+	_, err = s.RunFromDir("git", "show-ref", r)
 	if err == nil {
 		return true
 	}
@@ -191,14 +231,14 @@
 // IsDirty returns if the checkout has been modified from the checked
 // out reference.
 func (s *GitRepo) IsDirty() bool {
-	out, err := s.runFromDir("git", "diff")
+	out, err := s.RunFromDir("git", "diff")
 	return err != nil || len(out) != 0
 }
 
 // CommitInfo retrieves metadata about a commit.
 func (s *GitRepo) CommitInfo(id string) (*CommitInfo, error) {
 	fm := `--pretty=format:"<logentry><commit>%H</commit><author>%an &lt;%ae&gt;</author><date>%aD</date><message>%s</message></logentry>"`
-	out, err := s.runFromDir("git", "log", id, fm, "-1")
+	out, err := s.RunFromDir("git", "log", id, fm, "-1")
 	if err != nil {
 		return nil, ErrRevisionUnavailable
 	}
@@ -211,12 +251,12 @@
 	}{}
 	err = xml.Unmarshal(out, &cis)
 	if err != nil {
-		return nil, err
+		return nil, NewLocalError("Unable to retrieve commit information", err, string(out))
 	}
 
 	t, err := time.Parse("Mon, _2 Jan 2006 15:04:05 -0700", cis.Date)
 	if err != nil {
-		return nil, err
+		return nil, NewLocalError("Unable to retrieve commit information", err, string(out))
 	}
 
 	ci := &CommitInfo{
@@ -229,6 +269,49 @@
 	return ci, nil
 }
 
+// TagsFromCommit retrieves tags from a commit id.
+func (s *GitRepo) TagsFromCommit(id string) ([]string, error) {
+	// This is imperfect and a better method would be great.
+
+	var re []string
+
+	out, err := s.RunFromDir("git", "show-ref", "-d")
+	if err != nil {
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
+	}
+
+	lines := strings.Split(string(out), "\n")
+	var list []string
+	for _, i := range lines {
+		if strings.HasPrefix(strings.TrimSpace(i), id) {
+			list = append(list, i)
+		}
+	}
+	tags := s.referenceList(strings.Join(list, "\n"), `(?m-s)(?:tags)/(\S+)$`)
+	for _, t := range tags {
+		re = append(re, t)
+	}
+
+	return re, nil
+}
+
+// Ping returns if remote location is accessible.
+func (s *GitRepo) Ping() bool {
+	c := exec.Command("git", "ls-remote", s.Remote())
+
+	// If prompted for a username and password, which GitHub does for all things
+	// not public, it's considered not available. To make it available the
+	// remote needs to be different.
+	c.Env = mergeEnvLists([]string{"GIT_TERMINAL_PROMPT=0"}, os.Environ())
+	_, err := c.CombinedOutput()
+	if err != nil {
+		return false
+	}
+
+	return true
+}
+
+// isDetachedHead will detect if git repo is in "detached head" state.
 func isDetachedHead(dir string) (bool, error) {
 	c := exec.Command("git", "status", "-uno")
 	c.Dir = dir
@@ -242,8 +325,9 @@
 	return detached, nil
 }
 
-// In a multi-langual manner check for the Git error that it couldn't create
-// the directory.
+// isUnableToCreateDir checks for an error in Init() to see if an error
+// where the parent directory of the VCS local path doesn't exist. This is
+// done in a multi-lingual manner.
 func (s *GitRepo) isUnableToCreateDir(err error) bool {
 	msg := err.Error()
 	if strings.HasPrefix(msg, "could not create work tree dir") ||
diff --git a/vendor/github.com/Masterminds/vcs/git_test.go b/vendor/github.com/Masterminds/vcs/git_test.go
index a1a4f93..5fe6259 100644
--- a/vendor/github.com/Masterminds/vcs/git_test.go
+++ b/vendor/github.com/Masterminds/vcs/git_test.go
@@ -15,7 +15,6 @@
 // with a known git service.
 
 func TestGit(t *testing.T) {
-
 	tempDir, err := ioutil.TempDir("", "go-vcs-git-tests")
 	if err != nil {
 		t.Error(err)
@@ -141,6 +140,22 @@
 		t.Error("Git tags is not reporting the correct version")
 	}
 
+	tags, err = repo.TagsFromCommit("74dd547545b7df4aa285bcec1b54e2b76f726395")
+	if err != nil {
+		t.Error(err)
+	}
+	if len(tags) != 0 {
+		t.Error("Git is incorrectly returning tags for a commit")
+	}
+
+	tags, err = repo.TagsFromCommit("30605f6ac35fcb075ad0bfa9296f90a7d891523e")
+	if err != nil {
+		t.Error(err)
+	}
+	if len(tags) != 1 || tags[0] != "1.0.0" {
+		t.Error("Git is incorrectly returning tags for a commit")
+	}
+
 	branches, err := repo.Branches()
 	if err != nil {
 		t.Error(err)
@@ -215,3 +230,65 @@
 		t.Error(nrerr)
 	}
 }
+
+func TestGitPing(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-git-tests")
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewGitRepo("https://github.com/Masterminds/VCSTestRepo", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping := repo.Ping()
+	if !ping {
+		t.Error("Git unable to ping working repo")
+	}
+
+	repo, err = NewGitRepo("https://github.com/Masterminds/ihopethisneverexistsbecauseitshouldnt", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping = repo.Ping()
+	if ping {
+		t.Error("Git got a ping response from when it should not have")
+	}
+}
+
+func TestGitInit(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-git-tests")
+	repoDir := tempDir + "/repo"
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewGitRepo(repoDir, repoDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = repo.Init()
+	if err != nil {
+		t.Error(err)
+	}
+
+	_, err = repo.RunFromDir("git", "status")
+	if err != nil {
+		t.Error(err)
+	}
+}
diff --git a/vendor/github.com/Masterminds/vcs/hg.go b/vendor/github.com/Masterminds/vcs/hg.go
index e3fe575..4ce055c 100644
--- a/vendor/github.com/Masterminds/vcs/hg.go
+++ b/vendor/github.com/Masterminds/vcs/hg.go
@@ -36,7 +36,7 @@
 		c.Env = envForDir(c.Dir)
 		out, err := c.CombinedOutput()
 		if err != nil {
-			return nil, err
+			return nil, NewLocalError("Unable to retrieve local repo information", err, string(out))
 		}
 
 		m := hgDetectURL.FindStringSubmatch(string(out))
@@ -66,31 +66,49 @@
 
 // Get is used to perform an initial clone of a repository.
 func (s *HgRepo) Get() error {
-	_, err := s.run("hg", "clone", s.Remote(), s.LocalPath())
-	return err
+	out, err := s.run("hg", "clone", s.Remote(), s.LocalPath())
+	if err != nil {
+		return NewRemoteError("Unable to get repository", err, string(out))
+	}
+	return nil
+}
+
+// Init will initialize a mercurial repository at local location.
+func (s *HgRepo) Init() error {
+	out, err := s.run("hg", "init", s.LocalPath())
+	if err != nil {
+		return NewLocalError("Unable to initialize repository", err, string(out))
+	}
+	return nil
 }
 
 // Update performs a Mercurial pull to an existing checkout.
 func (s *HgRepo) Update() error {
-	_, err := s.runFromDir("hg", "update")
-	return err
+	out, err := s.RunFromDir("hg", "update")
+	if err != nil {
+		return NewRemoteError("Unable to update repository", err, string(out))
+	}
+	return nil
 }
 
 // UpdateVersion sets the version of a package currently checked out via Hg.
 func (s *HgRepo) UpdateVersion(version string) error {
-	_, err := s.runFromDir("hg", "pull")
+	out, err := s.RunFromDir("hg", "pull")
 	if err != nil {
-		return err
+		return NewLocalError("Unable to update checked out version", err, string(out))
 	}
-	_, err = s.runFromDir("hg", "update", version)
-	return err
+	out, err = s.RunFromDir("hg", "update", version)
+	if err != nil {
+		return NewLocalError("Unable to update checked out version", err, string(out))
+	}
+	return nil
 }
 
 // Version retrieves the current version.
 func (s *HgRepo) Version() (string, error) {
-	out, err := s.runFromDir("hg", "identify")
+	out, err := s.RunFromDir("hg", "identify")
 	if err != nil {
-		return "", err
+		return "", NewLocalError("Unable to retrieve checked out version", err, string(out))
 	}
 
 	parts := strings.SplitN(string(out), " ", 2)
@@ -102,15 +120,15 @@
 func (s *HgRepo) Date() (time.Time, error) {
 	version, err := s.Version()
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, "")
 	}
-	out, err := s.runFromDir("hg", "log", "-r", version, "--template", "{date|isodatesec}")
+	out, err := s.RunFromDir("hg", "log", "-r", version, "--template", "{date|isodatesec}")
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	t, err := time.Parse(longForm, string(out))
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	return t, nil
 }
@@ -126,9 +144,9 @@
 
 // Branches returns a list of available branches
 func (s *HgRepo) Branches() ([]string, error) {
-	out, err := s.runFromDir("hg", "branches")
+	out, err := s.RunFromDir("hg", "branches")
 	if err != nil {
-		return []string{}, err
+		return []string{}, NewLocalError("Unable to retrieve branches", err, string(out))
 	}
 	branches := s.referenceList(string(out), `(?m-s)^(\S+)`)
 	return branches, nil
@@ -136,9 +154,9 @@
 
 // Tags returns a list of available tags
 func (s *HgRepo) Tags() ([]string, error) {
-	out, err := s.runFromDir("hg", "tags")
+	out, err := s.RunFromDir("hg", "tags")
 	if err != nil {
-		return []string{}, err
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
 	}
 	tags := s.referenceList(string(out), `(?m-s)^(\S+)`)
 	return tags, nil
@@ -147,7 +165,7 @@
 // IsReference returns if a string is a reference. A reference can be a
 // commit id, branch, or tag.
 func (s *HgRepo) IsReference(r string) bool {
-	_, err := s.runFromDir("hg", "log", "-r", r)
+	_, err := s.RunFromDir("hg", "log", "-r", r)
 	if err == nil {
 		return true
 	}
@@ -158,13 +176,13 @@
 // IsDirty returns if the checkout has been modified from the checked
 // out reference.
 func (s *HgRepo) IsDirty() bool {
-	out, err := s.runFromDir("hg", "diff")
+	out, err := s.RunFromDir("hg", "diff")
 	return err != nil || len(out) != 0
 }
 
 // CommitInfo retrieves metadata about a commit.
 func (s *HgRepo) CommitInfo(id string) (*CommitInfo, error) {
-	out, err := s.runFromDir("hg", "log", "-r", id, "--style=xml")
+	out, err := s.RunFromDir("hg", "log", "-r", id, "--style=xml")
 	if err != nil {
 		return nil, ErrRevisionUnavailable
 	}
@@ -187,7 +205,7 @@
 	logs := &Log{}
 	err = xml.Unmarshal(out, &logs)
 	if err != nil {
-		return nil, err
+		return nil, NewLocalError("Unable to retrieve commit information", err, string(out))
 	}
 	if len(logs.Logs) == 0 {
 		return nil, ErrRevisionUnavailable
@@ -202,9 +220,53 @@
 	if logs.Logs[0].Date != "" {
 		ci.Date, err = time.Parse(time.RFC3339, logs.Logs[0].Date)
 		if err != nil {
-			return nil, err
+			return nil, NewLocalError("Unable to retrieve commit information", err, string(out))
 		}
 	}
 
 	return ci, nil
 }
+
+// TagsFromCommit retrieves tags from a commit id.
+func (s *HgRepo) TagsFromCommit(id string) ([]string, error) {
+	// Hg has a single tag per commit. If a second tag is added to a commit a
+	// new commit is created and the tag is attached to that new commit.
+	out, err := s.RunFromDir("hg", "log", "-r", id, "--style=xml")
+	if err != nil {
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
+	}
+
+	type Logentry struct {
+		Node string `xml:"node,attr"`
+		Tag  string `xml:"tag"`
+	}
+	type Log struct {
+		XMLName xml.Name   `xml:"log"`
+		Logs    []Logentry `xml:"logentry"`
+	}
+
+	logs := &Log{}
+	err = xml.Unmarshal(out, &logs)
+	if err != nil {
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
+	}
+	if len(logs.Logs) == 0 {
+		return []string{}, NewLocalError("Unable to retrieve tags", err, string(out))
+	}
+
+	t := strings.TrimSpace(logs.Logs[0].Tag)
+	if t != "" {
+		return []string{t}, nil
+	}
+	return []string{}, nil
+}
+
+// Ping returns if remote location is accessible.
+func (s *HgRepo) Ping() bool {
+	_, err := s.run("hg", "identify", s.Remote())
+	if err != nil {
+		return false
+	}
+
+	return true
+}
diff --git a/vendor/github.com/Masterminds/vcs/hg_test.go b/vendor/github.com/Masterminds/vcs/hg_test.go
index 9b81937..d63f0d8 100644
--- a/vendor/github.com/Masterminds/vcs/hg_test.go
+++ b/vendor/github.com/Masterminds/vcs/hg_test.go
@@ -2,6 +2,7 @@
 
 import (
 	"io/ioutil"
+	"strings"
 	"time"
 	//"log"
 	"os"
@@ -123,6 +124,22 @@
 		t.Error("Hg tags is not reporting the correct version")
 	}
 
+	tags, err = repo.TagsFromCommit("a5494ba2177f")
+	if err != nil {
+		t.Error(err)
+	}
+	if len(tags) != 0 {
+		t.Error("Hg is incorrectly returning tags for a commit")
+	}
+
+	tags, err = repo.TagsFromCommit("d680e82228d2")
+	if err != nil {
+		t.Error(err)
+	}
+	if len(tags) != 1 || tags[0] != "1.0.0" {
+		t.Error("Hg is incorrectly returning tags for a commit")
+	}
+
 	branches, err := repo.Branches()
 	if err != nil {
 		t.Error(err)
@@ -199,3 +216,68 @@
 		t.Error(nrerr)
 	}
 }
+
+func TestHgPing(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests")
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewHgRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping := repo.Ping()
+	if !ping {
+		t.Error("Hg unable to ping working repo")
+	}
+
+	repo, err = NewHgRepo("https://bitbucket.org/mattfarina/ihopethisneverexistsbecauseitshouldnt", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping = repo.Ping()
+	if ping {
+		t.Error("Hg got a ping response from when it should not have")
+	}
+}
+
+func TestHgInit(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests")
+	repoDir := tempDir + "/repo"
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewHgRepo(repoDir, repoDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = repo.Init()
+	if err != nil {
+		t.Error(err)
+	}
+
+	v, err := repo.Version()
+	if err != nil {
+		t.Error(err)
+	}
+	if !strings.HasPrefix(v, "000000") {
+		t.Errorf("Hg Init reporting wrong initial version: %s", v)
+	}
+}
diff --git a/vendor/github.com/Masterminds/vcs/repo.go b/vendor/github.com/Masterminds/vcs/repo.go
index 318d1ec..61a39a0 100644
--- a/vendor/github.com/Masterminds/vcs/repo.go
+++ b/vendor/github.com/Masterminds/vcs/repo.go
@@ -26,7 +26,6 @@
 package vcs
 
 import (
-	"errors"
 	"fmt"
 	"io/ioutil"
 	"log"
@@ -37,22 +36,6 @@
 	"time"
 )
 
-var (
-	// ErrWrongVCS is returned when an action is tried on the wrong VCS.
-	ErrWrongVCS = errors.New("Wrong VCS detected")
-
-	// ErrCannotDetectVCS is returned when VCS cannot be detected from URI string.
-	ErrCannotDetectVCS = errors.New("Cannot detect VCS")
-
-	// ErrWrongRemote occurs when the passed in remote does not match the VCS
-	// configured endpoint.
-	ErrWrongRemote = errors.New("The Remote does not match the VCS endpoint")
-
-	// ErrRevisionUnavailable happens when commit revision information is
-	// unavailable.
-	ErrRevisionUnavailable = errors.New("Revision unavailable")
-)
-
 // Logger is where you can provide a logger, implementing the log.Logger interface,
 // where verbose output from each VCS will be written. The default logger does
 // not log data. To log data supply your own logger or change the output location
@@ -97,6 +80,9 @@
 	// Get is used to perform an initial clone/checkout of a repository.
 	Get() error
 
+	// Initializes a new repository locally.
+	Init() error
+
 	// Update performs an update to an existing checkout of a repository.
 	Update() error
 
@@ -118,9 +104,6 @@
 	// Tags returns a list of available tags on the repository.
 	Tags() ([]string, error)
 
-	// TODO: Provide a consistent manner to get reference information across
-	// multiple VCS.
-
 	// IsReference returns if a string is a reference. A reference can be a
 	// commit id, branch, or tag.
 	IsReference(string) bool
@@ -131,6 +114,15 @@
 
 	// CommitInfo retrieves metadata about a commit.
 	CommitInfo(string) (*CommitInfo, error)
+
+	// TagsFromCommit retrieves tags from a commit id.
+	TagsFromCommit(string) ([]string, error)
+
+	// Ping returns if remote location is accessible.
+	Ping() bool
+
+	// RunFromDir executes a command from repo's directory.
+	RunFromDir(cmd string, args ...string) ([]byte, error)
 }
 
 // NewRepo returns a Repo based on trying to detect the source control from the
@@ -219,7 +211,7 @@
 	return out, err
 }
 
-func (b *base) runFromDir(cmd string, args ...string) ([]byte, error) {
+func (b *base) RunFromDir(cmd string, args ...string) ([]byte, error) {
 	c := exec.Command(cmd, args...)
 	c.Dir = b.local
 	c.Env = envForDir(c.Dir)
diff --git a/vendor/github.com/Masterminds/vcs/svn.go b/vendor/github.com/Masterminds/vcs/svn.go
index f14ccf9..85f60b5 100644
--- a/vendor/github.com/Masterminds/vcs/svn.go
+++ b/vendor/github.com/Masterminds/vcs/svn.go
@@ -4,6 +4,7 @@
 	"encoding/xml"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"regexp"
 	"strings"
 	"time"
@@ -35,7 +36,7 @@
 		// the repo passed in here.
 		out, err := exec.Command("svn", "info", local).CombinedOutput()
 		if err != nil {
-			return nil, err
+			return nil, NewLocalError("Unable to retrieve local repo information", err, string(out))
 		}
 
 		m := svnDetectURL.FindStringSubmatch(string(out))
@@ -67,28 +68,68 @@
 // Note, because SVN isn't distributed this is a checkout without
 // a clone.
 func (s *SvnRepo) Get() error {
-	_, err := s.run("svn", "checkout", s.Remote(), s.LocalPath())
-	return err
+	remote := s.Remote()
+	if strings.HasPrefix(remote, "/") {
+		remote = "file://" + remote
+	}
+	out, err := s.run("svn", "checkout", remote, s.LocalPath())
+	if err != nil {
+		return NewRemoteError("Unable to get repository", err, string(out))
+	}
+	return nil
+}
+
+// Init will create a svn repository at remote location.
+func (s *SvnRepo) Init() error {
+	out, err := s.run("svnadmin", "create", s.Remote())
+
+	if err != nil && s.isUnableToCreateDir(err) {
+
+		basePath := filepath.Dir(filepath.FromSlash(s.Remote()))
+		if _, err := os.Stat(basePath); os.IsNotExist(err) {
+			err = os.MkdirAll(basePath, 0755)
+			if err != nil {
+				return NewLocalError("Unable to initialize repository", err, "")
+			}
+
+			out, err = s.run("svnadmin", "create", s.Remote())
+			if err != nil {
+				return NewLocalError("Unable to initialize repository", err, string(out))
+			}
+			return nil
+		}
+
+	} else if err != nil {
+		return NewLocalError("Unable to initialize repository", err, string(out))
+	}
+
+	return nil
 }
 
 // Update performs an SVN update to an existing checkout.
 func (s *SvnRepo) Update() error {
-	_, err := s.runFromDir("svn", "update")
+	out, err := s.RunFromDir("svn", "update")
+	if err != nil {
+		return NewRemoteError("Unable to update repository", err, string(out))
+	}
 	return err
 }
 
 // UpdateVersion sets the version of a package currently checked out via SVN.
 func (s *SvnRepo) UpdateVersion(version string) error {
-	_, err := s.runFromDir("svn", "update", "-r", version)
-	return err
+	out, err := s.RunFromDir("svn", "update", "-r", version)
+	if err != nil {
+		return NewRemoteError("Unable to update checked out version", err, string(out))
+	}
+	return nil
 }
 
 // Version retrieves the current version.
 func (s *SvnRepo) Version() (string, error) {
-	out, err := s.runFromDir("svnversion", ".")
+	out, err := s.RunFromDir("svnversion", ".")
 	s.log(out)
 	if err != nil {
-		return "", err
+		return "", NewLocalError("Unable to retrieve checked out version", err, string(out))
 	}
 	return strings.TrimSpace(string(out)), nil
 }
@@ -97,16 +138,16 @@
 func (s *SvnRepo) Date() (time.Time, error) {
 	version, err := s.Version()
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, "")
 	}
-	out, err := s.runFromDir("svn", "pget", "svn:date", "--revprop", "-r", version)
+	out, err := s.RunFromDir("svn", "pget", "svn:date", "--revprop", "-r", version)
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	const longForm = "2006-01-02T15:04:05.000000Z\n"
 	t, err := time.Parse(longForm, string(out))
 	if err != nil {
-		return time.Time{}, err
+		return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out))
 	}
 	return t, nil
 }
@@ -144,7 +185,7 @@
 // IsReference returns if a string is a reference. A reference is a commit id.
 // Branches and tags are part of the path.
 func (s *SvnRepo) IsReference(r string) bool {
-	out, err := s.runFromDir("svn", "log", "-r", r)
+	out, err := s.RunFromDir("svn", "log", "-r", r)
 
 	// This is a complete hack. There must be a better way to do this. Pull
 	// requests welcome. When the reference isn't real you get a line of
@@ -162,15 +203,15 @@
 // IsDirty returns if the checkout has been modified from the checked
 // out reference.
 func (s *SvnRepo) IsDirty() bool {
-	out, err := s.runFromDir("svn", "diff")
+	out, err := s.RunFromDir("svn", "diff")
 	return err != nil || len(out) != 0
 }
 
 // CommitInfo retrieves metadata about a commit.
 func (s *SvnRepo) CommitInfo(id string) (*CommitInfo, error) {
-	out, err := s.runFromDir("svn", "log", "-r", id, "--xml")
+	out, err := s.RunFromDir("svn", "log", "-r", id, "--xml")
 	if err != nil {
-		return nil, err
+		return nil, NewRemoteError("Unable to retrieve commit information", err, string(out))
 	}
 
 	type Logentry struct {
@@ -186,7 +227,7 @@
 	logs := &Log{}
 	err = xml.Unmarshal(out, &logs)
 	if err != nil {
-		return nil, err
+		return nil, NewLocalError("Unable to retrieve commit information", err, string(out))
 	}
 	if len(logs.Logs) == 0 {
 		return nil, ErrRevisionUnavailable
@@ -201,9 +242,37 @@
 	if len(logs.Logs[0].Date) > 0 {
 		ci.Date, err = time.Parse(time.RFC3339Nano, logs.Logs[0].Date)
 		if err != nil {
-			return nil, err
+			return nil, NewLocalError("Unable to retrieve commit information", err, string(out))
 		}
 	}
 
 	return ci, nil
 }
+
+// TagsFromCommit retrieves tags from a commit id.
+func (s *SvnRepo) TagsFromCommit(id string) ([]string, error) {
+	// Svn tags are a convention implemented as paths. See the details on the
+	// Tag() method for more information.
+	return []string{}, nil
+}
+
+// Ping returns if remote location is accessible.
+func (s *SvnRepo) Ping() bool {
+	_, err := s.run("svn", "--non-interactive", "info", s.Remote())
+	if err != nil {
+		return false
+	}
+
+	return true
+}
+
+// isUnableToCreateDir checks for an error in Init() to see if an error
+// where the parent directory of the VCS local path doesn't exist.
+func (s *SvnRepo) isUnableToCreateDir(err error) bool {
+	msg := err.Error()
+	if strings.HasPrefix(msg, "E000002") {
+		return true
+	}
+
+	return false
+}
diff --git a/vendor/github.com/Masterminds/vcs/svn_test.go b/vendor/github.com/Masterminds/vcs/svn_test.go
index 8c8d0ee..349b072 100644
--- a/vendor/github.com/Masterminds/vcs/svn_test.go
+++ b/vendor/github.com/Masterminds/vcs/svn_test.go
@@ -134,6 +134,14 @@
 		t.Error("Svn is incorrectly returning tags")
 	}
 
+	tags, err = repo.TagsFromCommit("2")
+	if err != nil {
+		t.Error(err)
+	}
+	if len(tags) != 0 {
+		t.Error("Svn is incorrectly returning tags for a commit")
+	}
+
 	branches, err := repo.Branches()
 	if err != nil {
 		t.Error(err)
@@ -207,3 +215,74 @@
 		t.Error(nrerr)
 	}
 }
+
+func TestSvnPing(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests")
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping := repo.Ping()
+	if !ping {
+		t.Error("Svn unable to ping working repo")
+	}
+
+	repo, err = NewSvnRepo("https://github.com/Masterminds/ihopethisneverexistsbecauseitshouldnt", tempDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	ping = repo.Ping()
+	if ping {
+		t.Error("Svn got a ping response from when it should not have")
+	}
+}
+
+func TestSvnInit(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests")
+	remoteDir := tempDir + "/remoteDir"
+	localDir := tempDir + "/localDir"
+	if err != nil {
+		t.Error(err)
+	}
+	defer func() {
+		err = os.RemoveAll(tempDir)
+		if err != nil {
+			t.Error(err)
+		}
+	}()
+
+	repo, err := NewSvnRepo(remoteDir, localDir)
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = repo.Init()
+	if err != nil {
+		t.Error(err)
+	}
+
+	err = repo.Get()
+	if err != nil {
+		t.Error(err)
+	}
+
+	v, err := repo.Version()
+	if err != nil {
+		t.Error(err)
+	}
+	if v != "0" {
+		t.Errorf("Svn Init returns wrong version: %s", v)
+	}
+}
diff --git a/vendor/github.com/codegangsta/cli/README.md b/vendor/github.com/codegangsta/cli/README.md
index bb769fe..d9371cf 100644
--- a/vendor/github.com/codegangsta/cli/README.md
+++ b/vendor/github.com/codegangsta/cli/README.md
@@ -329,6 +329,45 @@
 ...
 ```
 
+### Subcommands categories
+
+For additional organization in apps that have many subcommands, you can
+associate a category for each command to group them together in the help
+output.
+
+E.g.
+
+```go
+...
+	app.Commands = []cli.Command{
+		{
+			Name: "noop",
+		},
+		{
+			Name:     "add",
+			Category: "template",
+		},
+		{
+			Name:     "remove",
+			Category: "template",
+		},
+	}
+...
+```
+
+Will include:
+
+```
+...
+COMMANDS:
+    noop
+
+  Template actions:
+    add
+    remove
+...
+```
+
 ### Bash Completion
 
 You can enable completion commands by setting the `EnableBashCompletion`
diff --git a/vendor/github.com/codegangsta/cli/app.go b/vendor/github.com/codegangsta/cli/app.go
index 6632ec0..bd20a2d 100644
--- a/vendor/github.com/codegangsta/cli/app.go
+++ b/vendor/github.com/codegangsta/cli/app.go
@@ -5,7 +5,8 @@
 	"io"
 	"io/ioutil"
 	"os"
-	"path"
+	"path/filepath"
+	"sort"
 	"time"
 )
 
@@ -34,6 +35,8 @@
 	HideHelp bool
 	// Boolean to hide built-in version flag and the VERSION section of help
 	HideVersion bool
+	// Populate on app startup, only gettable throught method Categories()
+	categories CommandCategories
 	// An action to execute when the bash-completion flag is set
 	BashComplete func(context *Context)
 	// An action to execute before any subcommands are run, but after the context is ready
@@ -77,8 +80,8 @@
 // Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.
 func NewApp() *App {
 	return &App{
-		Name:         path.Base(os.Args[0]),
-		HelpName:     path.Base(os.Args[0]),
+		Name:         filepath.Base(os.Args[0]),
+		HelpName:     filepath.Base(os.Args[0]),
 		Usage:        "A new cli application",
 		UsageText:    "",
 		Version:      "0.0.0",
@@ -104,6 +107,12 @@
 	}
 	a.Commands = newCmds
 
+	a.categories = CommandCategories{}
+	for _, command := range a.Commands {
+		a.categories = a.categories.AddCommand(command.Category, command)
+	}
+	sort.Sort(a.categories)
+
 	// append help to commands
 	if a.Command(helpCommand.Name) == nil && !a.HideHelp {
 		a.Commands = append(a.Commands, helpCommand)
@@ -316,6 +325,11 @@
 	return nil
 }
 
+// Returnes the array containing all the categories with the commands they contain
+func (a *App) Categories() CommandCategories {
+	return a.categories
+}
+
 func (a *App) hasFlag(flag Flag) bool {
 	for _, f := range a.Flags {
 		if flag == f {
diff --git a/vendor/github.com/codegangsta/cli/app_test.go b/vendor/github.com/codegangsta/cli/app_test.go
index 7feaf1f..ebf26c7 100644
--- a/vendor/github.com/codegangsta/cli/app_test.go
+++ b/vendor/github.com/codegangsta/cli/app_test.go
@@ -8,6 +8,7 @@
 	"io"
 	"io/ioutil"
 	"os"
+	"reflect"
 	"strings"
 	"testing"
 )
@@ -939,6 +940,55 @@
 	}
 }
 
+func TestApp_Run_Categories(t *testing.T) {
+	app := NewApp()
+	app.Name = "categories"
+	app.Commands = []Command{
+		Command{
+			Name:     "command1",
+			Category: "1",
+		},
+		Command{
+			Name:     "command2",
+			Category: "1",
+		},
+		Command{
+			Name:     "command3",
+			Category: "2",
+		},
+	}
+	buf := new(bytes.Buffer)
+	app.Writer = buf
+
+	app.Run([]string{"categories"})
+
+	expect := CommandCategories{
+		&CommandCategory{
+			Name: "1",
+			Commands: []Command{
+				app.Commands[0],
+				app.Commands[1],
+			},
+		},
+		&CommandCategory{
+			Name: "2",
+			Commands: []Command{
+				app.Commands[2],
+			},
+		},
+	}
+	if !reflect.DeepEqual(app.Categories(), expect) {
+		t.Fatalf("expected categories %#v, to equal %#v", app.Categories(), expect)
+	}
+
+	output := buf.String()
+	t.Logf("output: %q\n", buf.Bytes())
+
+	if !strings.Contains(output, "1:\n    command1") {
+		t.Errorf("want buffer to include category %q, did not: \n%q", "1:\n    command1", output)
+	}
+}
+
 func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
 	app := NewApp()
 	app.Action = func(c *Context) {}
diff --git a/vendor/github.com/codegangsta/cli/category.go b/vendor/github.com/codegangsta/cli/category.go
new file mode 100644
index 0000000..7dbf218
--- /dev/null
+++ b/vendor/github.com/codegangsta/cli/category.go
@@ -0,0 +1,30 @@
+package cli
+
+type CommandCategories []*CommandCategory
+
+type CommandCategory struct {
+	Name     string
+	Commands Commands
+}
+
+func (c CommandCategories) Less(i, j int) bool {
+	return c[i].Name < c[j].Name
+}
+
+func (c CommandCategories) Len() int {
+	return len(c)
+}
+
+func (c CommandCategories) Swap(i, j int) {
+	c[i], c[j] = c[j], c[i]
+}
+
+func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
+	for _, commandCategory := range c {
+		if commandCategory.Name == category {
+			commandCategory.Commands = append(commandCategory.Commands, command)
+			return c
+		}
+	}
+	return append(c, &CommandCategory{Name: category, Commands: []Command{command}})
+}
diff --git a/vendor/github.com/codegangsta/cli/command.go b/vendor/github.com/codegangsta/cli/command.go
index 0153713..1a05b54 100644
--- a/vendor/github.com/codegangsta/cli/command.go
+++ b/vendor/github.com/codegangsta/cli/command.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"io/ioutil"
+	"sort"
 	"strings"
 )
 
@@ -22,6 +23,8 @@
 	Description string
 	// A short description of the arguments of this command
 	ArgsUsage string
+	// The category the command is part of
+	Category string
 	// The function to call when checking for bash command completions
 	BashComplete func(context *Context)
 	// An action to execute before any sub-subcommands are run, but after the context is ready
@@ -37,7 +40,7 @@
 	// If this function is not set, the "Incorrect usage" is displayed and the execution is interrupted.
 	OnUsageError func(context *Context, err error) error
 	// List of child commands
-	Subcommands []Command
+	Subcommands Commands
 	// List of flags to parse
 	Flags []Flag
 	// Treat all flags as normal arguments if true
@@ -59,6 +62,8 @@
 	return strings.Join(c.commandNamePath, " ")
 }
 
+type Commands []Command
+
 // Invokes the command given the context, parses ctx.Args() to generate command-specific flags
 func (c Command) Run(ctx *Context) (err error) {
 	if len(c.Subcommands) > 0 {
@@ -227,6 +232,13 @@
 	app.Email = ctx.App.Email
 	app.Writer = ctx.App.Writer
 
+	app.categories = CommandCategories{}
+	for _, command := range c.Subcommands {
+		app.categories = app.categories.AddCommand(command.Category, command)
+	}
+
+	sort.Sort(app.categories)
+
 	// bash completion
 	app.EnableBashCompletion = ctx.App.EnableBashCompletion
 	if c.BashComplete != nil {
diff --git a/vendor/github.com/codegangsta/cli/help.go b/vendor/github.com/codegangsta/cli/help.go
index d3a12a2..adf157d 100644
--- a/vendor/github.com/codegangsta/cli/help.go
+++ b/vendor/github.com/codegangsta/cli/help.go
@@ -23,9 +23,10 @@
 AUTHOR(S):
    {{range .Authors}}{{ . }}{{end}}
    {{end}}{{if .Commands}}
-COMMANDS:
-   {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
-   {{end}}{{end}}{{if .Flags}}
+COMMANDS:{{range .Categories}}{{if .Name}}
+  {{.Name}}{{ ":" }}{{end}}{{range .Commands}}
+    {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}}
+{{end}}{{end}}{{if .Flags}}
 GLOBAL OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}{{end}}{{if .Copyright }}
@@ -41,7 +42,10 @@
    {{.HelpName}} - {{.Usage}}
 
 USAGE:
-   {{.HelpName}}{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Description}}
+   {{.HelpName}}{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
+
+CATEGORY:
+   {{.Category}}{{end}}{{if .Description}}
 
 DESCRIPTION:
    {{.Description}}{{end}}{{if .Flags}}
@@ -60,9 +64,10 @@
 USAGE:
    {{.HelpName}} command{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
 
-COMMANDS:
-   {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
-   {{end}}{{if .Flags}}
+COMMANDS:{{range .Categories}}{{if .Name}}
+  {{.Name}}{{ ":" }}{{end}}{{range .Commands}}
+    {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}}
+{{end}}{{if .Flags}}
 OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}{{end}}