Implements #39: Method for overriding aliases

Aliases are stored in an overrides.yaml file in the GLIDE_HOME
diff --git a/Makefile b/Makefile
index 340fd63..917c951 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@
 	install -m 755 ./glide ${DESTDIR}/usr/local/bin/glide
 
 test:
-	${GLIDE_GO_EXECUTABLE} test . ./gb ./path ./action ./tree ./util ./godep ./godep/strip ./gpm ./cfg ./dependency ./importer ./msg ./repo
+	${GLIDE_GO_EXECUTABLE} test . ./gb ./path ./action ./tree ./util ./godep ./godep/strip ./gpm ./cfg ./dependency ./importer ./msg ./repo ./overrides
 
 clean:
 	rm -f ./glide.test
diff --git a/action/ensure.go b/action/ensure.go
index 2f5f5af..a2254a6 100644
--- a/action/ensure.go
+++ b/action/ensure.go
@@ -10,6 +10,7 @@
 
 	"github.com/Masterminds/glide/cfg"
 	"github.com/Masterminds/glide/msg"
+	"github.com/Masterminds/glide/overrides"
 	gpath "github.com/Masterminds/glide/path"
 	"github.com/Masterminds/glide/util"
 )
@@ -56,6 +57,11 @@
 		}
 	}
 
+	err = overrides.Load()
+	if err != nil {
+		msg.Err("Unable to load overrides: %s", err)
+	}
+
 	return conf
 }
 
diff --git a/action/install.go b/action/install.go
index 2247e1f..c8e7253 100644
--- a/action/install.go
+++ b/action/install.go
@@ -53,7 +53,7 @@
 
 	// Set reference
 	if err := repo.SetReference(newConf, installer.ResolveTest); err != nil {
-		msg.Err("Failed to set references: %s (Skip to cleanup)", err)
+		msg.Die("Failed to set references: %s (Skip to cleanup)", err)
 	}
 
 	err = installer.Export(newConf)
diff --git a/action/overrides.go b/action/overrides.go
new file mode 100644
index 0000000..de87f61
--- /dev/null
+++ b/action/overrides.go
@@ -0,0 +1,146 @@
+package action
+
+import (
+	"os"
+	"path/filepath"
+
+	"github.com/Masterminds/glide/msg"
+	"github.com/Masterminds/glide/overrides"
+	gpath "github.com/Masterminds/glide/path"
+)
+
+// OverridesList displays a list of currently setup overrides.
+func OverridesList() error {
+	home := gpath.Home()
+
+	op := filepath.Join(home, "overrides.yaml")
+
+	if _, err := os.Stat(op); os.IsNotExist(err) {
+		msg.Info("No overrides exist. No overrides.yaml file not found")
+		return nil
+	}
+
+	ov, err := overrides.ReadOverridesFile(op)
+	if err != nil {
+		msg.Die("Unable to read overrides.yaml file: %s", err)
+	}
+
+	if len(ov.Repos) == 0 {
+		msg.Info("No overrides found")
+		return nil
+	}
+
+	msg.Info("Overrides...")
+	for _, r := range ov.Repos {
+		if r.Vcs == "" {
+			msg.Info("--> %s replaced by %s", r.Original, r.Repo)
+		} else {
+			msg.Info("--> %s replaced by %s (%s)", r.Original, r.Repo, r.Vcs)
+		}
+	}
+
+	return nil
+}
+
+// OverridesSet sets an override to use
+func OverridesSet(o, r, v string) error {
+	if o == "" || r == "" {
+		msg.Err("Both the original and overriding values are required")
+		return nil
+	}
+
+	home := gpath.Home()
+
+	op := filepath.Join(home, "overrides.yaml")
+
+	var ov *overrides.Overrides
+	if _, err := os.Stat(op); os.IsNotExist(err) {
+		msg.Info("No overrides.yaml file exists. Creating new one")
+		ov = &overrides.Overrides{
+			Repos: make(overrides.OverrideRepos, 0),
+		}
+	} else {
+		ov, err = overrides.ReadOverridesFile(op)
+		if err != nil {
+			msg.Die("Error reading existing overrides.yaml file: %s", err)
+		}
+	}
+
+	found := false
+	for i, re := range ov.Repos {
+		if re.Original == o {
+			found = true
+			msg.Info("%s found in overrides. Replacing with new settings", o)
+			ov.Repos[i].Repo = r
+			ov.Repos[i].Vcs = v
+		}
+	}
+
+	if !found {
+		nr := &overrides.OverrideRepo{
+			Original: o,
+			Repo:     r,
+			Vcs:      v,
+		}
+		ov.Repos = append(ov.Repos, nr)
+	}
+
+	msg.Info("%s being set to %s", o, r)
+
+	err := ov.WriteFile(op)
+	if err != nil {
+		msg.Err("Error writing overrides.yaml file: %s", err)
+	} else {
+		msg.Info("overrides.yaml written with changes")
+	}
+
+	return nil
+}
+
+// OverridesRemove removes an override setting
+func OverridesRemove(k string) error {
+	if k == "" {
+		msg.Err("The override to remove is required")
+		return nil
+	}
+
+	home := gpath.Home()
+
+	op := filepath.Join(home, "overrides.yaml")
+
+	if _, err := os.Stat(op); os.IsNotExist(err) {
+		msg.Err("overrides.yaml file not found")
+		return nil
+	}
+
+	ov, err := overrides.ReadOverridesFile(op)
+	if err != nil {
+		msg.Die("Unable to read overrides.yaml file: %s", err)
+	}
+
+	var nre overrides.OverrideRepos
+	var found bool
+	for _, re := range ov.Repos {
+		if re.Original != k {
+			nre = append(nre, re)
+		} else {
+			found = true
+		}
+	}
+
+	if !found {
+		msg.Warn("%s was not found in overrides", k)
+	} else {
+		msg.Info("%s was removed from overrides", k)
+		ov.Repos = nre
+
+		err = ov.WriteFile(op)
+		if err != nil {
+			msg.Err("Error writing overrides.yaml file: %s", err)
+		} else {
+			msg.Info("overrides.yaml written with changes")
+		}
+	}
+
+	return nil
+}
diff --git a/cfg/config.go b/cfg/config.go
index 06ba9b9..49b3c65 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -8,6 +8,7 @@
 	"sort"
 	"strings"
 
+	"github.com/Masterminds/glide/overrides"
 	"github.com/Masterminds/glide/util"
 	"github.com/Masterminds/vcs"
 	"gopkg.in/yaml.v2"
@@ -462,11 +463,38 @@
 // Remote returns the remote location to fetch source from. This location is
 // the central place where overrides happen from.
 func (d *Dependency) Remote() string {
+	var r string
+
 	if d.Repository != "" {
-		return d.Repository
+		r = d.Repository
+	} else {
+		r = "https://" + d.Name
 	}
 
-	return "https://" + d.Name
+	f, nr, _ := overrides.Get(r)
+	if f {
+		return nr
+	}
+
+	return r
+}
+
+// Vcs returns the VCS type to fetch source from.
+func (d *Dependency) Vcs() string {
+	var r string
+
+	if d.Repository != "" {
+		r = d.Repository
+	} else {
+		r = "https://" + d.Name
+	}
+
+	f, _, nv := overrides.Get(r)
+	if f {
+		return nv
+	}
+
+	return d.VcsType
 }
 
 // GetRepo retrieves a Masterminds/vcs repo object configured for the root
@@ -475,16 +503,13 @@
 
 	// The remote location is either the configured repo or the package
 	// name as an https url.
-	var remote string
-	if len(d.Repository) > 0 {
-		remote = d.Repository
-	} else {
-		remote = "https://" + d.Name
-	}
+	remote := d.Remote()
+
+	VcsType := d.Vcs()
 
 	// If the VCS type has a value we try that first.
-	if len(d.VcsType) > 0 && d.VcsType != "None" {
-		switch vcs.Type(d.VcsType) {
+	if len(VcsType) > 0 && VcsType != "None" {
+		switch vcs.Type(VcsType) {
 		case vcs.Git:
 			return vcs.NewGitRepo(remote, dest)
 		case vcs.Svn:
@@ -494,7 +519,7 @@
 		case vcs.Bzr:
 			return vcs.NewBzrRepo(remote, dest)
 		default:
-			return nil, fmt.Errorf("Unknown VCS type %s set for %s", d.VcsType, d.Name)
+			return nil, fmt.Errorf("Unknown VCS type %s set for %s", VcsType, d.Name)
 		}
 	}
 
diff --git a/glide.go b/glide.go
index e138505..2609a24 100644
--- a/glide.go
+++ b/glide.go
@@ -760,6 +760,90 @@
 				return nil
 			},
 		},
+		{
+			Name:  "override",
+			Usage: "Manage overrides",
+			Description: `Overrides provide the ability to replace a repo location with
+   another location. This is useful when you want to have a cache for your
+   continious integration (CI) system or if you want to work on a dependency
+   in a local location, such as the GOPATH.
+
+   The overrides are stored in an overrides.yaml file in your GLIDE_HOME.
+
+   The three commands to manager overrides are 'list', 'set', and 'remove'.
+
+   Use 'set' in the form:
+
+       glide override set [original] [replacement]
+
+   or
+
+       glide override set [original] [replacement] --vcs [type]
+
+   for example,
+
+       glide override set https://github.com/example/foo https://git.example.com/example/foo.git
+
+       glide override set https://github.com/example/foo file:///path/to/local/repo --vcs git
+
+   Use 'remove' in the form:
+
+       glide override remove [original]
+
+   for example,
+
+       glide override remove https://github.com/example/foo`,
+			Subcommands: []cli.Command{
+				{
+					Name:  "list",
+					Usage: "List the current overrides",
+					Action: func(c *cli.Context) error {
+						return action.OverridesList()
+					},
+				},
+				{
+					Name:  "set",
+					Usage: "Set an override. This overwrites an existing entry if one exists",
+					Description: `Use 'set' in the form:
+
+       glide override set [original] [replacement]
+
+   or
+
+       glide override set [original] [replacement] --vcs [type]
+
+   for example,
+
+       glide override set https://github.com/example/foo https://git.example.com/example/foo.git
+
+       glide override set https://github.com/example/foo file:///path/to/local/repo --vcs git`,
+					Flags: []cli.Flag{
+						cli.StringFlag{
+							Name:  "vcs",
+							Usage: "The VCS type to use. Autodiscovery is attempted when not supplied. Can be one of git, svn, bzr, or hg",
+						},
+					},
+					Action: func(c *cli.Context) error {
+						return action.OverridesSet(c.Args().Get(0), c.Args().Get(1), c.String("vcs"))
+					},
+				},
+				{
+					Name:      "remove",
+					ShortName: "rm",
+					Usage:     "Remove an override",
+					Description: `Use 'remove' in the form:
+
+       glide override remove [original]
+
+   for example,
+
+       glide override remove https://github.com/example/foo`,
+					Action: func(c *cli.Context) error {
+						return action.OverridesRemove(c.Args().Get(0))
+					},
+				},
+			},
+		},
 	}
 }
 
diff --git a/overrides/cfg.go b/overrides/cfg.go
new file mode 100644
index 0000000..d79284e
--- /dev/null
+++ b/overrides/cfg.go
@@ -0,0 +1,98 @@
+package overrides
+
+import (
+	"io/ioutil"
+	"sort"
+	"strings"
+
+	"gopkg.in/yaml.v2"
+)
+
+// Overrides contains global overrides to local configuration
+type Overrides struct {
+
+	// Repos contains repo override configuration
+	Repos OverrideRepos `yaml:"repos"`
+}
+
+// Marshal converts an Overrides instance to YAML
+func (ov *Overrides) Marshal() ([]byte, error) {
+	yml, err := yaml.Marshal(&ov)
+	if err != nil {
+		return []byte{}, err
+	}
+	return yml, nil
+}
+
+// WriteFile writes an overrides.yaml file
+//
+// This is a convenience function that marshals the YAML and then writes it to
+// the given file. If the file exists, it will be clobbered.
+func (ov *Overrides) WriteFile(opath string) error {
+	o, err := ov.Marshal()
+	if err != nil {
+		return err
+	}
+	return ioutil.WriteFile(opath, o, 0666)
+}
+
+// ReadOverridesFile loads the contents of an overrides.yaml file.
+func ReadOverridesFile(opath string) (*Overrides, error) {
+	yml, err := ioutil.ReadFile(opath)
+	if err != nil {
+		return nil, err
+	}
+	ov, err := FromYaml(yml)
+	if err != nil {
+		return nil, err
+	}
+	return ov, nil
+}
+
+// FromYaml returns an instance of Overrides from YAML
+func FromYaml(yml []byte) (*Overrides, error) {
+	ov := &Overrides{}
+	err := yaml.Unmarshal([]byte(yml), &ov)
+	return ov, err
+}
+
+// MarshalYAML is a hook for gopkg.in/yaml.v2.
+// It sorts override repos lexicographically for reproducibility.
+func (ov *Overrides) MarshalYAML() (interface{}, error) {
+
+	sort.Sort(ov.Repos)
+
+	return ov, nil
+}
+
+// OverrideRepos is a slice of Override pointers
+type OverrideRepos []*OverrideRepo
+
+// Len returns the length of the OverrideRepos. This is needed for sorting with
+// the sort package.
+func (o OverrideRepos) Len() int {
+	return len(o)
+}
+
+// Less is needed for the sort interface. It compares two OverrideRepos based on
+// their original value.
+func (o OverrideRepos) Less(i, j int) bool {
+
+	// Names are normalized to lowercase because case affects sorting order. For
+	// example, Masterminds comes before kylelemons. Making them lowercase
+	// causes kylelemons to come first which is what is expected.
+	return strings.ToLower(o[i].Original) < strings.ToLower(o[j].Original)
+}
+
+// Swap is needed for the sort interface. It swaps the position of two
+// OverrideRepos.
+func (o OverrideRepos) Swap(i, j int) {
+	o[i], o[j] = o[j], o[i]
+}
+
+// OverrideRepo represents a single repo override
+type OverrideRepo struct {
+	Original string `yaml:"original"`
+	Repo     string `yaml:"repo"`
+	Vcs      string `yaml:"vcs,omitempty"`
+}
diff --git a/overrides/overrides.go b/overrides/overrides.go
new file mode 100644
index 0000000..8299ede
--- /dev/null
+++ b/overrides/overrides.go
@@ -0,0 +1,66 @@
+// Package overrides handles managing overrides in the running application
+package overrides
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/Masterminds/glide/msg"
+	gpath "github.com/Masterminds/glide/path"
+)
+
+var overrides map[string]*override
+
+func init() {
+	overrides = make(map[string]*override)
+}
+
+type override struct {
+	Repo, Vcs string
+}
+
+// Get retrieves informtion about an override. It returns.
+// - bool if found
+// - new repo location
+// - vcs type
+func Get(k string) (bool, string, string) {
+	o, f := overrides[k]
+	if !f {
+		return false, "", ""
+	}
+
+	return true, o.Repo, o.Vcs
+}
+
+// Load pulls the overrides into memory
+func Load() error {
+	home := gpath.Home()
+
+	op := filepath.Join(home, "overrides.yaml")
+
+	var ov *Overrides
+	if _, err := os.Stat(op); os.IsNotExist(err) {
+		msg.Debug("No overrides.yaml file exists")
+		ov = &Overrides{
+			Repos: make(OverrideRepos, 0),
+		}
+	} else {
+		ov, err = ReadOverridesFile(op)
+		if err != nil {
+			return fmt.Errorf("Error reading existing overrides.yaml file: %s", err)
+		}
+	}
+
+	msg.Info("Loading overrides from overrides.yaml file")
+	for _, o := range ov.Repos {
+		msg.Debug("Found override: %s to %s (%s)", o.Original, o.Repo, o.Vcs)
+		no := &override{
+			Repo: o.Repo,
+			Vcs:  o.Vcs,
+		}
+		overrides[o.Original] = no
+	}
+
+	return nil
+}
diff --git a/overrides/overrides_test.go b/overrides/overrides_test.go
new file mode 100644
index 0000000..dddc500
--- /dev/null
+++ b/overrides/overrides_test.go
@@ -0,0 +1,36 @@
+package overrides
+
+import "testing"
+
+var oyml = `
+repos:
+- original: github.com/Masterminds/semver
+  repo: file:///path/to/local/repo
+  vcs: git
+- original: github.com/Masterminds/atest
+  repo: github.com/example/atest
+`
+
+var ooutyml = `repos:
+- original: github.com/Masterminds/atest
+  repo: github.com/example/atest
+- original: github.com/Masterminds/semver
+  repo: file:///path/to/local/repo
+  vcs: git
+`
+
+func TestSortOverrides(t *testing.T) {
+	ov, err := FromYaml([]byte(oyml))
+	if err != nil {
+		t.Error("Unable to read overrides yaml")
+	}
+
+	out, err := ov.Marshal()
+	if err != nil {
+		t.Error("Unable to marshal overrides yaml")
+	}
+
+	if string(out) != ooutyml {
+		t.Error("Output overrides sorting failed")
+	}
+}
diff --git a/repo/installer.go b/repo/installer.go
index 9d7d722..433dca2 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -92,9 +92,13 @@
 
 	msg.Info("Downloading dependencies. Please wait...")
 
-	LazyConcurrentUpdate(newConf.Imports, i, newConf)
-	LazyConcurrentUpdate(newConf.DevImports, i, newConf)
-	return newConf, nil
+	err := LazyConcurrentUpdate(newConf.Imports, i, newConf)
+	if err != nil {
+		return newConf, err
+	}
+	err = LazyConcurrentUpdate(newConf.DevImports, i, newConf)
+
+	return newConf, err
 }
 
 // Checkout reads the config file and checks out all dependencies mentioned there.