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

Updated dependencies:
diff --git a/action/get.go b/action/get.go
index e5135e8..5665ef6 100644
--- a/action/get.go
+++ b/action/get.go
@@ -37,7 +37,10 @@
 	// Fetch the new packages. Can't resolve versions via installer.Update if
 	// get is called while the vendor/ directory is empty so we checkout
 	// everything.
-	installer.Checkout(conf, false)
+	err = installer.Checkout(conf, false)
+	if err != nil {
+		msg.Die("Failed to checkout packages: %s", err)
+	}
 
 	// Prior to resolving dependencies we need to start working with a clone
 	// of the conf because we'll be making real changes to it.
diff --git a/action/list.go b/action/list.go
index a2d35c7..8ff6c69 100644
--- a/action/list.go
+++ b/action/list.go
@@ -1,6 +1,7 @@
 package action
 
 import (
+	"encoding/json"
 	"path/filepath"
 	"sort"
 
@@ -13,8 +14,8 @@
 // Params:
 //  - dir (string): basedir
 //  - deep (bool): whether to do a deep scan or a shallow scan
-func List(basedir string, deep bool) {
-
+//  - format (string): The format to output (text, json, json-pretty)
+func List(basedir string, deep bool, format string) {
 	basedir, err := filepath.Abs(basedir)
 	if err != nil {
 		msg.Die("Could not read directory: %s", err)
@@ -27,34 +28,71 @@
 	h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}}
 	r.Handler = h
 
-	sortable, err := r.ResolveLocal(deep)
+	localPkgs, err := r.ResolveLocal(deep)
 	if err != nil {
 		msg.Die("Error listing dependencies: %s", err)
 	}
-
-	msg.Info("Sorting...")
-	sort.Strings(sortable)
-
-	msg.Puts("INSTALLED packages:")
-	for _, k := range sortable {
-		v, err := filepath.Rel(basedir, k)
+	sort.Strings(localPkgs)
+	installed := make([]string, len(localPkgs))
+	for i, pkg := range localPkgs {
+		relPkg, err := filepath.Rel(basedir, pkg)
 		if err != nil {
-			//msg.Warn("Failed to Rel path: %s", err)
-			v = k
+			// msg.Warn("Failed to Rel path: %s", err)
+			relPkg = pkg
 		}
-		msg.Puts("\t%s", v)
+		installed[i] = relPkg
+	}
+	l := PackageList{
+		Installed: installed,
+		Missing:   h.Missing,
+		Gopath:    h.Gopath,
 	}
 
-	if len(h.Missing) > 0 {
-		msg.Puts("\nMISSING packages:")
-		for _, pkg := range h.Missing {
+	outputList(l, format)
+}
+
+// PackageList contains the packages being used by their location
+type PackageList struct {
+	Installed []string `json:"installed"`
+	Missing   []string `json:"missing"`
+	Gopath    []string `json:"gopath"`
+}
+
+const (
+	textFormat       = "text"
+	jsonFormat       = "json"
+	jsonPrettyFormat = "json-pretty"
+)
+
+func outputList(l PackageList, format string) {
+	switch format {
+	case textFormat:
+		msg.Puts("INSTALLED packages:")
+		for _, pkg := range l.Installed {
 			msg.Puts("\t%s", pkg)
 		}
-	}
-	if len(h.Gopath) > 0 {
-		msg.Puts("\nGOPATH packages:")
-		for _, pkg := range h.Gopath {
-			msg.Puts("\t%s", pkg)
+
+		if len(l.Missing) > 0 {
+			msg.Puts("\nMISSING packages:")
+			for _, pkg := range l.Missing {
+				msg.Puts("\t%s", pkg)
+			}
 		}
+		if len(l.Gopath) > 0 {
+			msg.Puts("\nGOPATH packages:")
+			for _, pkg := range l.Gopath {
+				msg.Puts("\t%s", pkg)
+			}
+		}
+	case jsonFormat:
+		json.NewEncoder(msg.Default.Stdout).Encode(l)
+	case jsonPrettyFormat:
+		b, err := json.MarshalIndent(l, "", "  ")
+		if err != nil {
+			msg.Die("could not unmarshal package list: %s", err)
+		}
+		msg.Puts(string(b))
+	default:
+		msg.Die("invalid output format: must be one of: json|json-pretty|text")
 	}
 }
diff --git a/action/list_test.go b/action/list_test.go
index 6792210..69e3eaf 100644
--- a/action/list_test.go
+++ b/action/list_test.go
@@ -2,20 +2,49 @@
 
 import (
 	"bytes"
+	"encoding/json"
 	"testing"
 
 	"github.com/Masterminds/glide/msg"
 )
 
 func TestList(t *testing.T) {
-	var buf bytes.Buffer
-	old := msg.Default.Stdout
 	msg.Default.PanicOnDie = true
+	old := msg.Default.Stdout
+	defer func() {
+		msg.Default.Stdout = old
+	}()
+
+	var buf bytes.Buffer
 	msg.Default.Stdout = &buf
-	List("../", false)
+	List("../", false, "text")
 	if buf.Len() < 5 {
 		t.Error("Expected some data to be found.")
 	}
-	// TODO: We should capture and test output.
-	msg.Default.Stdout = old
+
+	var buf2 bytes.Buffer
+	msg.Default.Stdout = &buf2
+	List("../", false, "json")
+	j := buf2.Bytes()
+	var o PackageList
+	err := json.Unmarshal(j, &o)
+	if err != nil {
+		t.Errorf("Error unmarshaling json list: %s", err)
+	}
+	if len(o.Installed) == 0 {
+		t.Error("No packages found on json list")
+	}
+
+	var buf3 bytes.Buffer
+	msg.Default.Stdout = &buf3
+	List("../", false, "json-pretty")
+	j = buf3.Bytes()
+	var o2 PackageList
+	err = json.Unmarshal(j, &o2)
+	if err != nil {
+		t.Errorf("Error unmarshaling json-pretty list: %s", err)
+	}
+	if len(o2.Installed) == 0 {
+		t.Error("No packages found on json-pretty list")
+	}
 }
diff --git a/action/project_info.go b/action/project_info.go
new file mode 100644
index 0000000..5e0995e
--- /dev/null
+++ b/action/project_info.go
@@ -0,0 +1,39 @@
+package action
+
+import (
+	"bytes"
+
+	"github.com/Masterminds/glide/msg"
+)
+
+func Info(format string) {
+	conf := EnsureConfig()
+	var buffer bytes.Buffer
+	varInit := false
+	for _, var_format := range format {
+		if varInit {
+			switch var_format {
+			case 'n':
+				buffer.WriteString(conf.Name)
+			case 'd':
+				buffer.WriteString(conf.Description)
+			case 'h':
+				buffer.WriteString(conf.Home)
+			case 'l':
+				buffer.WriteString(conf.License)
+			default:
+				msg.Die("Invalid format %s", string(var_format))
+			}
+		} else {
+			switch var_format {
+			case '%':
+				varInit = true
+				continue
+			default:
+				buffer.WriteString(string(var_format))
+			}
+		}
+		varInit = false
+	}
+	msg.Puts(buffer.String())
+}
diff --git a/glide.go b/glide.go
index e13a8d9..e205796 100644
--- a/glide.go
+++ b/glide.go
@@ -52,7 +52,7 @@
 	"os/user"
 )
 
-var version = "0.10.2"
+var version = "0.11.0-dev"
 
 const usage = `The lightweight vendor package manager for your Go projects.
 
@@ -134,12 +134,12 @@
 			ShortName: "init",
 			Usage:     "Initialize a new project, creating a glide.yaml file",
 			Description: `This command starts from a project without Glide and
-	sets it up. It generates a glide.yaml file, parsing your codebase to guess
-	the dependencies to include. Once this step is done you may edit the
-	glide.yaml file to update imported dependency properties such as the version
-	or version range to include.
+   sets it up. It generates a glide.yaml file, parsing your codebase to guess
+   the dependencies to include. Once this step is done you may edit the
+   glide.yaml file to update imported dependency properties such as the version
+   or version range to include.
 
-	To fetch the dependencies you may run 'glide install'.`,
+   To fetch the dependencies you may run 'glide install'.`,
 			Flags: []cli.Flag{
 				cli.BoolFlag{
 					Name:  "skip-import",
@@ -154,33 +154,33 @@
 			Name:  "get",
 			Usage: "Install one or more packages into `vendor/` and add dependency to glide.yaml.",
 			Description: `Gets one or more package (like 'go get') and then adds that file
-	to the glide.yaml file. Multiple package names can be specified on one line.
+   to the glide.yaml file. Multiple package names can be specified on one line.
 
-		$ glide get github.com/Masterminds/cookoo/web
+   	$ glide get github.com/Masterminds/cookoo/web
 
-	The above will install the project github.com/Masterminds/cookoo and add
-	the subpackage 'web'.
+   The above will install the project github.com/Masterminds/cookoo and add
+   the subpackage 'web'.
 
-	If a fetched dependency has a glide.yaml file, configuration from Godep,
-	GPM, or GB Glide that configuration will be used to find the dependencies
-	and versions to fetch. If those are not available the dependent packages will
-	be fetched as either a version specified elsewhere or the latest version.
+   If a fetched dependency has a glide.yaml file, configuration from Godep,
+   GPM, or GB Glide that configuration will be used to find the dependencies
+   and versions to fetch. If those are not available the dependent packages will
+   be fetched as either a version specified elsewhere or the latest version.
 
-	When adding a new dependency Glide will perform an update to work out the
-	the versions to use from the dependency tree. This will generate an updated
-	glide.lock file with specific locked versions to use.
+   When adding a new dependency Glide will perform an update to work out the
+   the versions to use from the dependency tree. This will generate an updated
+   glide.lock file with specific locked versions to use.
 
-	If you are storing the outside dependencies in your version control system
-	(VCS), also known as vendoring, there are a few flags that may be useful.
-	The '--update-vendored' flag will cause Glide to update packages when VCS
-	information is unavailable. This can be used with the '--strip-vcs' flag which
-	will strip VCS data found in the vendor directory. This is useful for
-	removing VCS data from transitive dependencies and initial setups. The
-	'--strip-vendor' flag will remove any nested 'vendor' folders and
-	'Godeps/_workspace' folders after an update (along with undoing any Godep
-	import rewriting). Note, The Godeps specific functionality is deprecated and
-	will be removed when most Godeps users have migrated to using the vendor
-	folder.`,
+   If you are storing the outside dependencies in your version control system
+   (VCS), also known as vendoring, there are a few flags that may be useful.
+   The '--update-vendored' flag will cause Glide to update packages when VCS
+   information is unavailable. This can be used with the '--strip-vcs' flag which
+   will strip VCS data found in the vendor directory. This is useful for
+   removing VCS data from transitive dependencies and initial setups. The
+   '--strip-vendor' flag will remove any nested 'vendor' folders and
+   'Godeps/_workspace' folders after an update (along with undoing any Godep
+   import rewriting). Note, The Godeps specific functionality is deprecated and
+   will be removed when most Godeps users have migrated to using the vendor
+   folder.`,
 			Flags: []cli.Flag{
 				cli.BoolFlag{
 					Name:  "insecure",
@@ -259,12 +259,11 @@
 			ShortName: "rm",
 			Usage:     "Remove a package from the glide.yaml file, and regenerate the lock file.",
 			Description: `This takes one or more package names, and removes references from the glide.yaml file.
-	This will rebuild the glide lock file with the following constraints:
+   This will rebuild the glide lock file with the following constraints:
 
-	- Dependencies are re-negotiated. Any that are no longer used are left out of the lock.
-	- Minor version re-nogotiation is performed on remaining dependencies.
-	- No updates are peformed. You may want to run 'glide up' to accomplish that.
-`,
+   - Dependencies are re-negotiated. Any that are no longer used are left out of the lock.
+   - Minor version re-nogotiation is performed on remaining dependencies.
+   - No updates are peformed. You may want to run 'glide up' to accomplish that.`,
 			Flags: []cli.Flag{
 				cli.BoolFlag{
 					Name:  "delete,d",
@@ -360,9 +359,7 @@
 			Description: `Given a directory, list all the relevant Go paths that are not vendored.
 
 Example:
-
-			$ go test $(glide novendor)
-`,
+   $ go test $(glide novendor)`,
 			Flags: []cli.Flag{
 				cli.StringFlag{
 					Name:  "dir,d",
@@ -392,12 +389,12 @@
 			ShortName: "i",
 			Usage:     "Install a project's dependencies",
 			Description: `This uses the native VCS of each packages to install
-		the appropriate version. There are two ways a projects dependencies can
-	be installed. When there is a glide.yaml file defining the dependencies but
-	no lock file (glide.lock) the dependencies are installed using the "update"
-	command and a glide.lock file is generated pinning all dependencies. If a
-	glide.lock file is already present the dependencies are installed or updated
-	from the lock file.`,
+   the appropriate version. There are two ways a projects dependencies can
+   be installed. When there is a glide.yaml file defining the dependencies but
+   no lock file (glide.lock) the dependencies are installed using the "update"
+   command and a glide.lock file is generated pinning all dependencies. If a
+   glide.lock file is already present the dependencies are installed or updated
+   from the lock file.`,
 			Flags: []cli.Flag{
 				cli.BoolFlag{
 					Name:  "delete",
@@ -458,42 +455,41 @@
 			ShortName: "up",
 			Usage:     "Update a project's dependencies",
 			Description: `This uses the native VCS of each package to try to
-	pull the most applicable updates. Packages with fixed refs (Versions or
-	tags) will not be updated. Packages with no ref or with a branch ref will
-	be updated as expected.
+   pull the most applicable updates. Packages with fixed refs (Versions or
+   tags) will not be updated. Packages with no ref or with a branch ref will
+   be updated as expected.
 
-	If a dependency has a glide.yaml file, update will read that file and
-	update those dependencies accordingly. Those dependencies are maintained in
-	a the top level 'vendor/' directory. 'vendor/foo/bar' will have its
-	dependencies stored in 'vendor/'. This behavior can be disabled with
-	'--no-recursive'. When this behavior is skipped a glide.lock file is not
-	generated because the full dependency tree cannot be known.
+   If a dependency has a glide.yaml file, update will read that file and
+   update those dependencies accordingly. Those dependencies are maintained in
+   a the top level 'vendor/' directory. 'vendor/foo/bar' will have its
+   dependencies stored in 'vendor/'. This behavior can be disabled with
+   '--no-recursive'. When this behavior is skipped a glide.lock file is not
+   generated because the full dependency tree cannot be known.
 
-	Glide will also import Godep, GB, and GPM files as it finds them in dependencies.
-	It will create a glide.yaml file from the Godeps data, and then update. This
-	has no effect if '--no-recursive' is set.
+   Glide will also import Godep, GB, and GPM files as it finds them in dependencies.
+   It will create a glide.yaml file from the Godeps data, and then update. This
+   has no effect if '--no-recursive' is set.
 
-	If you are storing the outside dependencies in your version control system
-	(VCS), also known as vendoring, there are a few flags that may be useful.
-	The '--update-vendored' flag will cause Glide to update packages when VCS
-	information is unavailable. This can be used with the '--strip-vcs' flag which
-	will strip VCS data found in the vendor directory. This is useful for
-	removing VCS data from transitive dependencies and initial setups. The
-	'--strip-vendor' flag will remove any nested 'vendor' folders and
-	'Godeps/_workspace' folders after an update (along with undoing any Godep
-	import rewriting). Note, The Godeps specific functionality is deprecated and
-	will be removed when most Godeps users have migrated to using the vendor
-	folder.
+   If you are storing the outside dependencies in your version control system
+   (VCS), also known as vendoring, there are a few flags that may be useful.
+   The '--update-vendored' flag will cause Glide to update packages when VCS
+   information is unavailable. This can be used with the '--strip-vcs' flag which
+   will strip VCS data found in the vendor directory. This is useful for
+   removing VCS data from transitive dependencies and initial setups. The
+   '--strip-vendor' flag will remove any nested 'vendor' folders and
+   'Godeps/_workspace' folders after an update (along with undoing any Godep
+   import rewriting). Note, The Godeps specific functionality is deprecated and
+   will be removed when most Godeps users have migrated to using the vendor
+   folder.
 
-	Note, Glide detects vendored dependencies. With the '--update-vendored' flag
-	Glide will update vendored dependencies leaving them in a vendored state.
-	Tertiary dependencies will not be vendored automatically unless the
-	'--strip-vcs' flag is used along with it.
+   Note, Glide detects vendored dependencies. With the '--update-vendored' flag
+   Glide will update vendored dependencies leaving them in a vendored state.
+   Tertiary dependencies will not be vendored automatically unless the
+   '--strip-vcs' flag is used along with it.
 
-	By default, packages that are discovered are considered transient, and are
-	not stored in the glide.yaml file. The --file=NAME.yaml flag allows you
-	to save the discovered dependencies to a YAML file.
-	`,
+   By default, packages that are discovered are considered transient, and are
+   not stored in the glide.yaml file. The --file=NAME.yaml flag allows you
+   to save the discovered dependencies to a YAML file.`,
 			Flags: []cli.Flag{
 				cli.BoolFlag{
 					Name:  "delete",
@@ -571,11 +567,11 @@
 			Name:  "tree",
 			Usage: "Tree prints the dependencies of this project as a tree.",
 			Description: `This scans a project's source files and builds a tree
-	representation of the import graph.
+   representation of the import graph.
 
-	It ignores testdata/ and directories that begin with . or _. Packages in
-	vendor/ are only included if they are referenced by the main project or
-	one of its dependencies.`,
+   It ignores testdata/ and directories that begin with . or _. Packages in
+   vendor/ are only included if they are referenced by the main project or
+   one of its dependencies.`,
 			Action: func(c *cli.Context) {
 				action.Tree(".", false)
 			},
@@ -585,14 +581,62 @@
 			Usage: "List prints all dependencies that the present code references.",
 			Description: `List scans your code and lists all of the packages that are used.
 
-			It does not use the glide.yaml. Instead, it inspects the code to determine what packages are
-			imported.
+   It does not use the glide.yaml. Instead, it inspects the code to determine what packages are
+   imported.
 
-			Directories that begin with . or _ are ignored, as are testdata directories. Packages in
-			vendor are only included if they are used by the project.
-			`,
+   Directories that begin with . or _ are ignored, as are testdata directories. Packages in
+   vendor are only included if they are used by the project.`,
 			Action: func(c *cli.Context) {
-				action.List(".", true)
+				action.List(".", true, c.String("output"))
+			},
+			Flags: []cli.Flag{
+				cli.StringFlag{
+					Name:  "output, o",
+					Usage: "Output format. One of: json|json-pretty|text",
+					Value: "text",
+				},
+			},
+		},
+		{
+			Name:  "info",
+			Usage: "Info prints information about this project",
+			Flags: []cli.Flag{
+				cli.StringFlag{
+					Name:  "format, f",
+					Usage: `Format of the information wanted (required).`,
+				},
+			},
+			Description: `A format containing the text with replacement variables
+   has to be passed in. Those variables are:
+
+       %n - name
+       %d - description
+       %h - homepage
+       %l - license
+
+   For example, given a project with the following glide.yaml:
+
+       package: foo
+       homepage: https://example.com
+       license: MIT
+       description: Some example description
+
+   Then running the following commands:
+
+       glide info -f %n
+          prints 'foo'
+
+       glide info -f "License: %l"
+          prints 'License: MIT'
+
+       glide info -f "%n - %d - %h - %l"
+          prints 'foo - Some example description - https://example.com - MIT'`,
+			Action: func(c *cli.Context) {
+				if c.IsSet("format") {
+					action.Info(c.String("format"))
+				} else {
+					cli.ShowCommandHelp(c, c.Command.Name)
+				}
 			},
 		},
 		{