Merge branch 'files-refactor' into vsolver
diff --git a/action/config_wizard.go b/action/config_wizard.go
index 1257980..1cc6da7 100644
--- a/action/config_wizard.go
+++ b/action/config_wizard.go
@@ -13,10 +13,14 @@
 	gpath "github.com/Masterminds/glide/path"
 	"github.com/Masterminds/semver"
 	"github.com/Masterminds/vcs"
+	"github.com/sdboyer/gps"
 )
 
 // ConfigWizard reads configuration from a glide.yaml file and attempts to suggest
 // improvements. The wizard is interactive.
+//
+// TODO(sdboyer) the Dependency.Reference -> Dependency.Constraint conversion is
+// really awkward here and needs to be revisited
 func ConfigWizard(base string) {
 	_, err := gpath.Glide()
 	glidefile := gpath.GlideFile
@@ -76,7 +80,7 @@
 
 		// First check, ask if the tag should be used instead of the commit id for it.
 		cur := cache.MemCurrent(remote)
-		if cur != "" && cur != dep.Reference {
+		if cur != "" && cur != dep.Constraint.String() {
 			wizardSugOnce()
 			var dres bool
 			asked, use, val := wizardOnce("current")
@@ -93,15 +97,16 @@
 			}
 
 			if dres {
-				msg.Info("Updating %s to use the tag %s instead of commit id %s", dep.Name, cur, dep.Reference)
-				dep.Reference = cur
+				msg.Info("Updating %s to use the tag %s instead of commit id %s", dep.Name, cur, dep.Constraint)
+				// FIXME just wrong; have to disambiguate branches and versions
+				dep.Constraint = gps.NewVersion(cur)
 				changes++
 			}
 		}
 
 		// Second check, if no version is being used and there's a semver release ask about latest.
 		memlatest := cache.MemLatest(remote)
-		if dep.Reference == "" && memlatest != "" {
+		if dep.Constraint == nil && memlatest != "" {
 			wizardSugOnce()
 			var dres bool
 			asked, use, val := wizardOnce("latest")
@@ -119,14 +124,14 @@
 
 			if dres {
 				msg.Info("Updating %s to use the release %s instead of no release", dep.Name, memlatest)
-				dep.Reference = memlatest
+				dep.Constraint = gps.NewVersion(memlatest)
 				changes++
 			}
 		}
 
 		// Third check, if the version is semver offer to use a range instead.
-		sv, err := semver.NewVersion(dep.Reference)
-		if err == nil {
+		if v, ok := dep.Constraint.(gps.Version); ok && v.Type() == "semver" {
+			sv, _ := semver.NewVersion(v.String())
 			wizardSugOnce()
 			var res string
 			asked, use, val := wizardOnce("range")
@@ -144,13 +149,13 @@
 
 			if res == "m" {
 				r := "^" + sv.String()
-				msg.Info("Updating %s to use the range %s instead of commit id %s", dep.Name, r, dep.Reference)
-				dep.Reference = r
+				msg.Info("Updating %s to use the range %s instead of commit id %s", dep.Name, r, dep.Constraint)
+				dep.Constraint, _ = gps.NewSemverConstraint(r)
 				changes++
 			} else if res == "p" {
 				r := "~" + sv.String()
-				msg.Info("Updating %s to use the range %s instead of commit id %s", dep.Name, r, dep.Reference)
-				dep.Reference = r
+				msg.Info("Updating %s to use the range %s instead of commit id %s", dep.Name, r, dep.Constraint)
+				dep.Constraint, _ = gps.NewSemverConstraint(r)
 				changes++
 			}
 		}
@@ -229,7 +234,7 @@
 }
 
 func wizardAskCurrent(cur string, d *cfg.Dependency) bool {
-	msg.Info("The package %s is currently set to use the version %s.", d.Name, d.Reference)
+	msg.Info("The package %s is currently set to use the version %s.", d.Name, d.Constraint)
 	msg.Info("There is an equivalent semantic version (http://semver.org) release of %s. Would", cur)
 	msg.Info("you like to use that instead? Yes (Y) or No (N)")
 	return msg.PromptUntilYorN()
@@ -243,7 +248,7 @@
 }
 
 func wizardLookInto(d *cfg.Dependency) bool {
-	_, err := semver.NewConstraint(d.Reference)
+	_, err := semver.NewConstraint(d.Constraint.String())
 
 	// The existing version is already a valid semver constraint so we skip suggestions.
 	if err == nil {
@@ -302,7 +307,7 @@
 				if found := createGitParseVersion.FindString(ti); found != "" {
 					tg := strings.TrimPrefix(strings.TrimSuffix(found, "^{}"), "tags/")
 					cache.MemPut(remote, tg)
-					if d.Reference != "" && strings.HasPrefix(ti, d.Reference) {
+					if d.Constraint != nil && strings.HasPrefix(ti, d.Constraint.String()) {
 						cache.MemSetCurrent(remote, tg)
 					}
 				}
@@ -332,15 +337,17 @@
 				cache.MemPut(remote, v)
 			}
 		}
-		if d.Reference != "" && repo.IsReference(d.Reference) {
-			tgs, err = repo.TagsFromCommit(d.Reference)
-			if err != nil {
-				msg.Debug("Problem getting tags for commit: %s", err)
-			} else {
-				if len(tgs) > 0 {
-					for _, v := range tgs {
-						if !(repo.Vcs() == vcs.Hg && v == "tip") {
-							cache.MemSetCurrent(remote, v)
+		if d.Constraint != nil {
+			if rev, ok := d.Constraint.(gps.Revision); ok {
+				tgs, err = repo.TagsFromCommit(string(rev))
+				if err != nil {
+					msg.Debug("Problem getting tags for commit: %s", err)
+				} else {
+					if len(tgs) > 0 {
+						for _, v := range tgs {
+							if !(repo.Vcs() == vcs.Hg && v == "tip") {
+								cache.MemSetCurrent(remote, v)
+							}
 						}
 					}
 				}
diff --git a/action/create.go b/action/create.go
index 5d42199..e6cf2e4 100644
--- a/action/create.go
+++ b/action/create.go
@@ -129,32 +129,20 @@
 
 	for _, pa := range sortable {
 		n := strings.TrimPrefix(pa, vpath)
-		root, subpkg := util.NormalizeName(n)
+		root, _ := util.NormalizeName(n)
 
 		if !config.Imports.Has(root) && root != config.Name {
 			msg.Info("--> Found reference to %s\n", n)
 			d := &cfg.Dependency{
 				Name: root,
 			}
-			if len(subpkg) > 0 {
-				d.Subpackages = []string{subpkg}
-			}
 			config.Imports = append(config.Imports, d)
-		} else if config.Imports.Has(root) {
-			if len(subpkg) > 0 {
-				subpkg = strings.TrimPrefix(subpkg, "/")
-				d := config.Imports.Get(root)
-				if !d.HasSubpackage(subpkg) {
-					msg.Info("--> Adding sub-package %s to %s\n", subpkg, root)
-					d.Subpackages = append(d.Subpackages, subpkg)
-				}
-			}
 		}
 	}
 
 	for _, pa := range testSortable {
 		n := strings.TrimPrefix(pa, vpath)
-		root, subpkg := util.NormalizeName(n)
+		root, _ := util.NormalizeName(n)
 
 		if config.Imports.Has(root) && root != config.Name {
 			msg.Debug("--> Found test reference to %s already listed as an import", n)
@@ -163,19 +151,7 @@
 			d := &cfg.Dependency{
 				Name: root,
 			}
-			if len(subpkg) > 0 {
-				d.Subpackages = []string{subpkg}
-			}
 			config.DevImports = append(config.DevImports, d)
-		} else if config.DevImports.Has(root) {
-			if len(subpkg) > 0 {
-				subpkg = strings.TrimPrefix(subpkg, "/")
-				d := config.DevImports.Get(root)
-				if !d.HasSubpackage(subpkg) {
-					msg.Info("--> Adding test sub-package %s to %s\n", subpkg, root)
-					d.Subpackages = append(d.Subpackages, subpkg)
-				}
-			}
 		}
 	}
 
@@ -207,10 +183,10 @@
 	}
 
 	for _, i := range deps {
-		if i.Reference == "" {
+		if i.Constraint == nil {
 			msg.Info("--> Found imported reference to %s", i.Name)
 		} else {
-			msg.Info("--> Found imported reference to %s at revision %s", i.Name, i.Reference)
+			msg.Info("--> Found imported reference to %s with constraint %s", i.Name, i.Constraint)
 		}
 
 		config.Imports = append(config.Imports, i)
diff --git a/action/ensure.go b/action/ensure.go
index 2f5f5af..154b8ee 100644
--- a/action/ensure.go
+++ b/action/ensure.go
@@ -29,7 +29,10 @@
 		msg.ExitCode(2)
 		msg.Die("Failed to load %s: %s", yamlpath, err)
 	}
-	conf, err := cfg.ConfigFromYaml(yml)
+	conf, legacy, err := cfg.ConfigFromYaml(yml)
+	if legacy {
+		msg.Warn("glide.yaml was in a legacy format. An attempt will be made to automatically update it.")
+	}
 	if err != nil {
 		msg.ExitCode(3)
 		msg.Die("Failed to parse %s: %s", yamlpath, err)
diff --git a/action/get.go b/action/get.go
index bcb62f3..c7e58ac 100644
--- a/action/get.go
+++ b/action/get.go
@@ -49,7 +49,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
@@ -151,7 +151,7 @@
 
 		msg.Info("Attempting to get package %s", name)
 
-		root, subpkg := util.NormalizeName(name)
+		root, _ := util.NormalizeName(name)
 		if len(root) == 0 {
 			return 0, fmt.Errorf("Package name is required for %q.", name)
 		}
@@ -172,24 +172,7 @@
 				msg.Warn("--> Test dependency %s already listed as import", root)
 			}
 
-			// Check if the subpackage is present.
-			if subpkg != "" {
-				if dep == nil {
-					dep = conf.Imports.Get(root)
-					if dep == nil && testDeps {
-						dep = conf.DevImports.Get(root)
-					}
-				}
-				if dep.HasSubpackage(subpkg) {
-					if !moved {
-						msg.Warn("--> Package %q is already in glide.yaml. Skipping", name)
-					}
-				} else {
-					dep.Subpackages = append(dep.Subpackages, subpkg)
-					msg.Info("--> Adding sub-package %s to existing import %s", subpkg, root)
-					numAdded++
-				}
-			} else if !moved {
+			if !moved {
 				msg.Warn("--> Package %q is already in glide.yaml. Skipping", root)
 			}
 			continue
@@ -212,17 +195,14 @@
 		}
 
 		if version != "" {
-			dep.Reference = version
+			// TODO(sdboyer) set the right type...what is that here?
+			dep.Constraint = gps.NewVersion(version)
 		} else if !nonInteract {
 			getWizard(dep)
 		}
 
-		if len(subpkg) > 0 {
-			dep.Subpackages = []string{subpkg}
-		}
-
-		if dep.Reference != "" {
-			msg.Info("--> Adding %s to your configuration with the version %s", dep.Name, dep.Reference)
+		if dep.Constraint != nil {
+			msg.Info("--> Adding %s to your configuration with the version %s", dep.Name, dep.Constraint)
 		} else {
 			msg.Info("--> Adding %s to your configuration", dep.Name)
 		}
@@ -253,15 +233,20 @@
 	if memlatest != "" {
 		dres := wizardAskLatest(memlatest, dep)
 		if dres {
-			dep.Reference = memlatest
+			// TODO(sdboyer) set the right type...what is that here?
+			v := gps.NewVersion(memlatest)
+			dep.Constraint = v
 
-			sv, err := semver.NewVersion(dep.Reference)
-			if err == nil {
+			if v.Type() == "semver" {
+				sv, _ := semver.NewVersion(memlatest)
 				res := wizardAskRange(sv, dep)
+
 				if res == "m" {
-					dep.Reference = "^" + sv.String()
+					// no errors possible here, if init was valid semver version
+					dep.Constraint, _ = gps.NewSemverConstraint("^" + v.String())
 				} else if res == "p" {
-					dep.Reference = "~" + sv.String()
+					// no errors possible here, if init was valid semver version
+					dep.Constraint, _ = gps.NewSemverConstraint("~" + v.String())
 				}
 			}
 		}
diff --git a/action/get_test.go b/action/get_test.go
index 07dba0f..9e5d8f0 100644
--- a/action/get_test.go
+++ b/action/get_test.go
@@ -16,7 +16,6 @@
 	conf := new(cfg.Config)
 	dep := new(cfg.Dependency)
 	dep.Name = "github.com/Masterminds/cookoo"
-	dep.Subpackages = append(dep.Subpackages, "convert")
 	conf.Imports = append(conf.Imports, dep)
 
 	names := []string{
@@ -30,17 +29,6 @@
 		t.Error("addPkgsToConfig failed to add github.com/Masterminds/semver")
 	}
 
-	d := conf.Imports.Get("github.com/Masterminds/cookoo")
-	found := false
-	for _, s := range d.Subpackages {
-		if s == "fmt" {
-			found = true
-		}
-	}
-	if !found {
-		t.Error("addPkgsToConfig failed to add subpackage to existing import")
-	}
-
 	// Restore messaging to original location
 	msg.Default.Stderr = o
 }
diff --git a/action/install.go b/action/install.go
index d379544..2248460 100644
--- a/action/install.go
+++ b/action/install.go
@@ -48,7 +48,11 @@
 
 	var s gps.Solver
 	if gpath.HasLock(base) {
-		params.Lock, err = loadLockfile(base, conf)
+		var legacy bool
+		params.Lock, legacy, err = loadLockfile(base, conf)
+		if legacy {
+			msg.Warn("glide.lock was in a legacy format. An attempt will be made to automatically update it.")
+		}
 		if err != nil {
 			msg.Err("Could not load lockfile.")
 			return
@@ -334,15 +338,15 @@
 }
 
 // loadLockfile loads the contents of a glide.lock file.
-func loadLockfile(base string, conf *cfg.Config) (*cfg.Lockfile, error) {
+func loadLockfile(base string, conf *cfg.Config) (*cfg.Lockfile, bool, error) {
 	yml, err := ioutil.ReadFile(filepath.Join(base, gpath.LockFile))
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
-	lock, err := cfg.LockfileFromYaml(yml)
+	lock, legacy, err := cfg.LockfileFromYaml(yml)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 
-	return lock, nil
+	return lock, legacy, nil
 }
diff --git a/action/rebuild.go b/action/rebuild.go
index dffde39..6e76625 100644
--- a/action/rebuild.go
+++ b/action/rebuild.go
@@ -41,22 +41,23 @@
 }
 
 func buildDep(dep *cfg.Dependency, vpath string) error {
-	if len(dep.Subpackages) == 0 {
-		buildPath(dep.Name)
-	}
+	buildPath(dep.Name)
 
-	for _, pkg := range dep.Subpackages {
-		if pkg == "**" || pkg == "..." {
-			//Info("Building all packages in %s\n", dep.Name)
-			buildPath(path.Join(dep.Name, "..."))
-		} else {
-			paths, err := resolvePackages(vpath, dep.Name, pkg)
-			if err != nil {
-				msg.Warn("Error resolving packages: %s", err)
-			}
-			buildPaths(paths)
-		}
-	}
+	// TODO(sdboyer) to replace this, would need static analysis. But...rebuild
+	// is going away anyway, right?
+
+	//for _, pkg := range dep.Subpackages {
+	//if pkg == "**" || pkg == "..." {
+	////Info("Building all packages in %s\n", dep.Name)
+	//buildPath(path.Join(dep.Name, "..."))
+	//} else {
+	//paths, err := resolvePackages(vpath, dep.Name, pkg)
+	//if err != nil {
+	//msg.Warn("Error resolving packages: %s", err)
+	//}
+	//buildPaths(paths)
+	//}
+	//}
 
 	return nil
 }
diff --git a/action/update.go b/action/update.go
index feab38a..3221258 100644
--- a/action/update.go
+++ b/action/update.go
@@ -51,7 +51,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 0bcfb18..3f8381d 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -5,11 +5,10 @@
 	"encoding/hex"
 	"fmt"
 	"io/ioutil"
-	"reflect"
 	"sort"
+	"strconv"
 	"strings"
 
-	"github.com/Masterminds/glide/util"
 	"github.com/Masterminds/vcs"
 	"github.com/sdboyer/gps"
 	"gopkg.in/yaml.v2"
@@ -44,33 +43,21 @@
 	// those to skip.
 	Ignore []string `yaml:"ignore,omitempty"`
 
-	// Exclude contains a list of directories in the local application to
-	// exclude from scanning for dependencies.
-	Exclude []string `yaml:"excludeDirs,omitempty"`
-
-	// Imports contains a list of all non-development imports for a project. For
+	// Imports contains a list of all dependency constraints for a project. For
 	// more detail on how these are captured see the Dependency type.
-	Imports Dependencies `yaml:"import"`
+	// TODO rename
+	// TODO mapify
+	Imports Dependencies `yaml:"dependencies"`
 
-	// DevImports contains the test or other development imports for a project.
-	// See the Dependency type for more details on how this is recorded.
-	DevImports Dependencies `yaml:"testImport,omitempty"`
+	// DevImports contains the test or other development dependency constraints
+	// for a project. See the Dependency type for more details on how this is
+	// recorded.
+	// TODO rename
+	// TODO mapify
+	DevImports Dependencies `yaml:"testDependencies"`
 }
 
 // A transitive representation of a dependency for importing and exporting to yaml.
-type cf1 struct {
-	Name        string       `yaml:"package"`
-	Description string       `yaml:"description,omitempty"`
-	Home        string       `yaml:"homepage,omitempty"`
-	License     string       `yaml:"license,omitempty"`
-	Owners      Owners       `yaml:"owners,omitempty"`
-	Ignore      []string     `yaml:"ignore,omitempty"`
-	Exclude     []string     `yaml:"excludeDirs,omitempty"`
-	Imports     Dependencies `yaml:"dependencies"`
-	DevImports  Dependencies `yaml:"testdependencies,omitempty"`
-}
-
-// Legacy representation of a glide.yaml file.
 type cf struct {
 	Name        string       `yaml:"package"`
 	Description string       `yaml:"description,omitempty"`
@@ -78,16 +65,27 @@
 	License     string       `yaml:"license,omitempty"`
 	Owners      Owners       `yaml:"owners,omitempty"`
 	Ignore      []string     `yaml:"ignore,omitempty"`
-	Exclude     []string     `yaml:"excludeDirs,omitempty"`
-	Imports     Dependencies `yaml:"import"`
-	DevImports  Dependencies `yaml:"testImport,omitempty"`
+	Imports     Dependencies `yaml:"dependencies,omitempty"`
+	DevImports  Dependencies `yaml:"testDependencies,omitempty"`
+	// these fields guarantee that this struct fails to unmarshal legacy yamls
+	Compat  int `yaml:"import,omitempty"`
+	Compat2 int `yaml:"testImport,omitempty"`
 }
 
 // ConfigFromYaml returns an instance of Config from YAML
-func ConfigFromYaml(yml []byte) (*Config, error) {
-	cfg := &Config{}
-	err := yaml.Unmarshal([]byte(yml), &cfg)
-	return cfg, err
+func ConfigFromYaml(yml []byte) (cfg *Config, legacy bool, err error) {
+	cfg = &Config{}
+	err = yaml.Unmarshal(yml, cfg)
+	if err != nil {
+		lcfg := &lConfig1{}
+		err = yaml.Unmarshal(yml, &lcfg)
+		if err == nil {
+			legacy = true
+			cfg, err = lcfg.Convert()
+		}
+	}
+
+	return
 }
 
 // Marshal converts a Config instance to YAML
@@ -111,7 +109,6 @@
 	c.License = newConfig.License
 	c.Owners = newConfig.Owners
 	c.Ignore = newConfig.Ignore
-	c.Exclude = newConfig.Exclude
 	c.Imports = newConfig.Imports
 	c.DevImports = newConfig.DevImports
 
@@ -130,7 +127,6 @@
 		License:     c.License,
 		Owners:      c.Owners,
 		Ignore:      c.Ignore,
-		Exclude:     c.Exclude,
 	}
 	i, err := c.Imports.Clone().DeDupe()
 	if err != nil {
@@ -166,50 +162,24 @@
 // DependencyConstraints lists all the non-test dependency constraints
 // described in a glide manifest in a way gps will understand.
 func (c *Config) DependencyConstraints() []gps.ProjectConstraint {
-	return depsToVSolver(c.Imports)
+	return gpsifyDeps(c.Imports)
 }
 
 // TestDependencyConstraints lists all the test dependency constraints described
 // in a glide manifest in a way gps will understand.
 func (c *Config) TestDependencyConstraints() []gps.ProjectConstraint {
-	return depsToVSolver(c.DevImports)
+	return gpsifyDeps(c.DevImports)
 }
 
-func depsToVSolver(deps Dependencies) []gps.ProjectConstraint {
+func gpsifyDeps(deps Dependencies) []gps.ProjectConstraint {
 	cp := make([]gps.ProjectConstraint, len(deps))
 	for k, d := range deps {
-		var c gps.Constraint
-		var err error
-
-		// Support both old and new. TODO handle this earlier
-		if d.Constraint != nil {
-			c = d.Constraint
-		} else {
-			// TODO need to differentiate types of constraints so that we don't have
-			// this ambiguity
-			// Try semver first
-			c, err = gps.NewSemverConstraint(d.Reference)
-			if err != nil {
-				// Not a semver constraint. Super crappy heuristic that'll cover hg
-				// and git revs, but not bzr (svn, you say? lol, madame. lol)
-				if len(d.Reference) == 40 {
-					c = gps.Revision(d.Reference)
-				} else {
-					// Otherwise, assume a branch. This also sucks, because it could
-					// very well be a shitty, non-semver tag.
-					c = gps.NewBranch(d.Reference)
-				}
-			}
-		}
-
-		id := gps.ProjectIdentifier{
-			ProjectRoot: gps.ProjectRoot(d.Name),
-			NetworkName: d.Repository,
-		}
-
 		cp[k] = gps.ProjectConstraint{
-			Ident:      id,
-			Constraint: c,
+			Ident: gps.ProjectIdentifier{
+				ProjectRoot: gps.ProjectRoot(d.Name),
+				NetworkName: d.Repository,
+			},
+			Constraint: d.Constraint,
 		}
 	}
 
@@ -242,18 +212,6 @@
 	return false
 }
 
-// HasExclude returns true if the given name is listed on the exclude list.
-func (c *Config) HasExclude(ex string) bool {
-	ep := normalizeSlash(ex)
-	for _, v := range c.Exclude {
-		if vp := normalizeSlash(v); vp == ep {
-			return true
-		}
-	}
-
-	return false
-}
-
 // Clone performs a deep clone of the Config instance
 func (c *Config) Clone() *Config {
 	n := &Config{}
@@ -263,7 +221,6 @@
 	n.License = c.License
 	n.Owners = c.Owners.Clone()
 	n.Ignore = c.Ignore
-	n.Exclude = c.Exclude
 	n.Imports = c.Imports.Clone()
 	n.DevImports = c.DevImports.Clone()
 	return n
@@ -430,16 +387,13 @@
 			// In here we've encountered a dependency for the second time.
 			// Make sure the details are the same or return an error.
 			v := imports[val]
-			if dep.Reference != v.Reference {
-				return d, fmt.Errorf("Import %s repeated with different versions '%s' and '%s'", dep.Name, dep.Reference, v.Reference)
+			// Have to do string-based comparison
+			if dep.Constraint.String() != v.Constraint.String() {
+				return d, fmt.Errorf("Import %s repeated with different versions '%s' and '%s'", dep.Name, dep.Constraint, v.Constraint)
 			}
-			if dep.Repository != v.Repository || dep.VcsType != v.VcsType {
+			if dep.Repository != v.Repository {
 				return d, fmt.Errorf("Import %s repeated with different Repository details", dep.Name)
 			}
-			if !reflect.DeepEqual(dep.Os, v.Os) || !reflect.DeepEqual(dep.Arch, v.Arch) {
-				return d, fmt.Errorf("Import %s repeated with different OS or Architecture filtering", dep.Name)
-			}
-			imports[checked[dep.Name]].Subpackages = stringArrayDeDupe(v.Subpackages, dep.Subpackages...)
 		}
 	}
 
@@ -448,60 +402,52 @@
 
 // Dependency describes a package that the present package depends upon.
 type Dependency struct {
-	Name             string         `yaml:"package"`
-	Constraint       gps.Constraint `yaml:"-"` // TODO temporary, for experimenting; reconcile with other data
-	Reference        string         `yaml:"version,omitempty"`
-	Pin              string         `yaml:"-"`
-	Repository       string         `yaml:"repo,omitempty"`
-	VcsType          string         `yaml:"vcs,omitempty"`
-	Subpackages      []string       `yaml:"subpackages,omitempty"`
-	Arch             []string       `yaml:"arch,omitempty"`
-	Os               []string       `yaml:"os,omitempty"`
-	UpdateAsVendored bool           `yaml:"-"`
+	Name       string
+	VcsType    string // TODO remove
+	Constraint gps.Constraint
+	Repository string
 }
 
-// A transitive representation of a dependency for importing and exploting to yaml.
+// A transitive representation of a dependency for yaml import/export.
 type dep struct {
-	Name        string   `yaml:"package"`
-	Reference   string   `yaml:"version,omitempty"`
-	Branch      string   `yaml:"branch,omitempty"`
-	Ref         string   `yaml:"ref,omitempty"`
-	Repository  string   `yaml:"repo,omitempty"`
-	VcsType     string   `yaml:"vcs,omitempty"`
-	Subpackages []string `yaml:"subpackages,omitempty"`
-	Arch        []string `yaml:"arch,omitempty"`
-	Os          []string `yaml:"os,omitempty"`
+	Name       string `yaml:"package"`
+	Reference  string `yaml:"version,omitempty"` // TODO rename
+	Branch     string `yaml:"branch,omitempty"`
+	Repository string `yaml:"repo,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,
+	d := &Dependency{
+		Name:       lock.Name,
+		Repository: lock.Repository,
 	}
+
+	r := gps.Revision(lock.Revision)
+	if lock.Version != "" {
+		d.Constraint = gps.NewVersion(lock.Version).Is(r)
+	} else if lock.Branch != "" {
+		d.Constraint = gps.NewBranch(lock.Version).Is(r)
+	} else {
+		d.Constraint = r
+	}
+
+	return d
 }
 
 // UnmarshalYAML is a hook for gopkg.in/yaml.v2 in the unmarshaling process
 func (d *Dependency) UnmarshalYAML(unmarshal func(interface{}) error) error {
-	newDep := &dep{}
+	newDep := dep{}
 	err := unmarshal(&newDep)
 	if err != nil {
 		return err
 	}
+
 	d.Name = newDep.Name
-	d.Reference = newDep.Reference
+	d.Repository = newDep.Repository
 
-	if d.Reference == "" && newDep.Ref != "" {
-		d.Reference = newDep.Ref
-	}
-
-	if d.Reference != "" {
-		r := d.Reference
+	if newDep.Reference != "" {
+		r := newDep.Reference
 		// TODO(sdboyer) this covers git & hg; bzr and svn (??) need love
 		if len(r) == 40 {
 			if _, err := hex.DecodeString(r); err == nil {
@@ -527,44 +473,59 @@
 		d.Constraint = gps.Any()
 	}
 
-	d.Repository = newDep.Repository
-	d.VcsType = newDep.VcsType
-	d.Subpackages = newDep.Subpackages
-	d.Arch = newDep.Arch
-	d.Os = newDep.Os
-
-	// Make sure only legitimate VCS are listed.
-	d.VcsType = filterVcsType(d.VcsType)
-
-	// Get the root name for the package
-	tn, subpkg := util.NormalizeName(d.Name)
-	d.Name = tn
-	if subpkg != "" {
-		d.Subpackages = append(d.Subpackages, subpkg)
-	}
-
-	// Older versions of Glide had a / prefix on subpackages in some cases.
-	// Here that's cleaned up. Someday we should be able to remove this.
-	for k, v := range d.Subpackages {
-		d.Subpackages[k] = strings.TrimPrefix(v, "/")
-	}
-
 	return nil
 }
 
+// DeduceConstraint tries to puzzle out what kind of version is given in a string -
+// semver, a revision, or as a fallback, a plain tag
+func DeduceConstraint(s string) gps.Constraint {
+	// always semver if we can
+	c, err := gps.NewSemverConstraint(s)
+	if err == nil {
+		return c
+	}
+
+	slen := len(s)
+	if slen == 40 {
+		if _, err = hex.DecodeString(s); err == nil {
+			// Whether or not it's intended to be a SHA1 digest, this is a
+			// valid byte sequence for that, so go with Revision. This
+			// covers git and hg
+			return gps.Revision(s)
+		}
+	}
+	// Next, try for bzr, which has a three-component GUID separated by
+	// dashes. There should be two, but the email part could contain
+	// internal dashes
+	if strings.Count(s, "-") >= 2 {
+		// Work from the back to avoid potential confusion from the email
+		i3 := strings.LastIndex(s, "-")
+		// Skip if - is last char, otherwise this would panic on bounds err
+		if slen == i3+1 {
+			return gps.NewVersion(s)
+		}
+
+		if _, err = hex.DecodeString(s[i3+1:]); err == nil {
+			i2 := strings.LastIndex(s[:i3], "-")
+			if _, err = strconv.ParseUint(s[i2+1:i3], 10, 64); err == nil {
+				// Getting this far means it'd pretty much be nuts if it's not a
+				// bzr rev, so don't bother parsing the email.
+				return gps.Revision(s)
+			}
+		}
+	}
+
+	// If not a plain SHA1 or bzr custom GUID, assume a plain version.
+	//
+	// svn, you ask? lol, madame. lol.
+	return gps.NewVersion(s)
+}
+
 // MarshalYAML is a hook for gopkg.in/yaml.v2 in the marshaling process
 func (d *Dependency) MarshalYAML() (interface{}, error) {
-
-	// Make sure we only write the correct vcs type to file
-	t := filterVcsType(d.VcsType)
-
 	newDep := &dep{
-		Name:        d.Name,
-		Repository:  d.Repository,
-		VcsType:     t,
-		Subpackages: d.Subpackages,
-		Arch:        d.Arch,
-		Os:          d.Os,
+		Name:       d.Name,
+		Repository: d.Repository,
 	}
 
 	// Pull out the correct type of constraint
@@ -580,10 +541,9 @@
 	} else if gps.IsAny(d.Constraint) {
 		// We do nothing here, as the way any gets represented is with no
 		// constraint information at all
-		// TODO for now, probably until we add first-class 'default branch'
 	} else if d.Constraint != nil {
 		// The only other thing this could really be is a semver range. This
-		// will dump that up appropriately.
+		// will dump that appropriately.
 		newDep.Reference = d.Constraint.String()
 	}
 	// Just ignore any other case
@@ -593,8 +553,8 @@
 
 // GetRepo retrieves a Masterminds/vcs repo object configured for the root
 // of the package being retrieved.
+// TODO remove
 func (d *Dependency) GetRepo(dest string) (vcs.Repo, error) {
-
 	// The remote location is either the configured repo or the package
 	// name as an https url.
 	var remote string
@@ -626,30 +586,9 @@
 
 // Clone creates a clone of a Dependency
 func (d *Dependency) Clone() *Dependency {
-	return &Dependency{
-		Name:             d.Name,
-		Constraint:       d.Constraint,
-		Reference:        d.Reference,
-		Pin:              d.Pin,
-		Repository:       d.Repository,
-		VcsType:          d.VcsType,
-		Subpackages:      d.Subpackages,
-		Arch:             d.Arch,
-		Os:               d.Os,
-		UpdateAsVendored: d.UpdateAsVendored,
-	}
-}
-
-// HasSubpackage returns if the subpackage is present on the dependency
-func (d *Dependency) HasSubpackage(sub string) bool {
-
-	for _, v := range d.Subpackages {
-		if sub == v {
-			return true
-		}
-	}
-
-	return false
+	var d2 Dependency
+	d2 = *d
+	return &d2
 }
 
 // Owners is a list of owners for a project.
diff --git a/cfg/config_test.go b/cfg/config_test.go
index 6313ff0..09be399 100644
--- a/cfg/config_test.go
+++ b/cfg/config_test.go
@@ -1,12 +1,15 @@
 package cfg
 
 import (
+	"reflect"
 	"testing"
 
+	"github.com/sdboyer/gps"
+
 	"gopkg.in/yaml.v2"
 )
 
-var yml = `
+var lyml = `
 package: fake/testing
 description: foo bar baz
 homepage: https://example.com
@@ -34,6 +37,7 @@
       - i386
       - arm
   - package: github.com/Masterminds/structable
+    version: v1.0.0
   - package: github.com/Masterminds/cookoo/color
   - package: github.com/Masterminds/cookoo/convert
 
@@ -41,6 +45,33 @@
   - package: github.com/kylelemons/go-gypsy
 `
 
+var yml = `
+package: fake/testing
+description: foo bar baz
+homepage: https://example.com
+license: MIT
+owners:
+- name: foo
+  email: bar@example.com
+  homepage: https://example.com
+dependencies:
+  - package: github.com/kylelemons/go-gypsy
+    version: v1.0.0
+  - package: github.com/Masterminds/convert
+    repo: git@github.com:Masterminds/convert.git
+    version: a9949121a2e2192ca92fa6dddfeaaa4a4412d955
+  - package: github.com/Masterminds/structable
+    branch: master
+  - package: github.com/Masterminds/cookoo
+    repo: git://github.com/Masterminds/cookoo
+  - package: github.com/sdboyer/gps
+    version: ^v1.0.0
+
+testDependencies:
+  - package: github.com/Sirupsen/logrus
+    version: ~v1.0.0
+`
+
 func TestManualConfigFromYaml(t *testing.T) {
 	cfg := &Config{}
 	err := yaml.Unmarshal([]byte(yml), &cfg)
@@ -48,6 +79,103 @@
 		t.Errorf("Unable to Unmarshal config yaml")
 	}
 
+	found := make(map[string]bool)
+	for _, i := range cfg.Imports {
+		found[i.Name] = true
+
+		switch i.Name {
+		case "github.com/kylelemons/go-gypsy":
+			ref := gps.NewVersion("v1.0.0")
+			if i.Constraint != ref {
+				t.Errorf("(%s) Expected %q for constraint, got %q", i.Name, ref, i.Constraint)
+			}
+
+		case "github.com/Masterminds/convert":
+			ref := gps.Revision("a9949121a2e2192ca92fa6dddfeaaa4a4412d955")
+			if i.Constraint != ref {
+				t.Errorf("(%s) Expected %q for constraint, got %q", i.Name, ref, i.Constraint)
+			}
+
+			repo := "git@github.com:Masterminds/convert.git"
+			if i.Repository != repo {
+				t.Errorf("(%s) Expected %q for repository, got %q", i.Name, repo, i.Repository)
+			}
+
+		case "github.com/Masterminds/structable":
+			ref := gps.NewBranch("master")
+			if i.Constraint != ref {
+				t.Errorf("(%s) Expected %q for constraint, got %q", i.Name, ref, i.Constraint)
+			}
+
+		case "github.com/Masterminds/cookoo":
+			repo := "git://github.com/Masterminds/cookoo"
+			if i.Repository != repo {
+				t.Errorf("(%s) Expected %q for repository, got %q", i.Name, repo, i.Repository)
+			}
+
+		case "github.com/sdboyer/gps":
+			sv, _ := gps.NewSemverConstraint("^v1.0.0")
+			if !reflect.DeepEqual(sv, i.Constraint) {
+				t.Errorf("(%s) Expected %q for constraint, got %q", i.Name, sv, i.Constraint)
+			}
+		}
+	}
+
+	names := []string{
+		"github.com/Masterminds/convert",
+		"github.com/Masterminds/cookoo",
+		"github.com/Masterminds/structable",
+		"github.com/kylelemons/go-gypsy",
+		"github.com/sdboyer/gps",
+	}
+
+	for _, n := range names {
+		if !found[n] {
+			t.Errorf("Could not find config entry for %s", n)
+
+		}
+	}
+
+	if len(cfg.DevImports) != 1 {
+		t.Errorf("Expected 1 entry in DevImports, got %v", len(cfg.DevImports))
+	} else {
+		ti := cfg.DevImports[0]
+		n := "github.com/Sirupsen/logrus"
+		if ti.Name != n {
+			t.Errorf("Expected test dependency to be %s, got %s", n, ti.Name)
+		}
+
+		sv, _ := gps.NewSemverConstraint("~v1.0.0")
+		if !reflect.DeepEqual(sv, ti.Constraint) {
+			t.Errorf("(test dep: %s) Expected %q for constraint, got %q", ti.Name, sv, ti.Constraint)
+		}
+	}
+
+	if cfg.Name != "fake/testing" {
+		t.Errorf("Inaccurate name found %s", cfg.Name)
+	}
+
+	if cfg.Description != "foo bar baz" {
+		t.Errorf("Inaccurate description found %s", cfg.Description)
+	}
+
+	if cfg.Home != "https://example.com" {
+		t.Errorf("Inaccurate homepage found %s", cfg.Home)
+	}
+
+	if cfg.License != "MIT" {
+		t.Errorf("Inaccurate license found %s", cfg.License)
+	}
+
+}
+
+func TestLegacyManualConfigFromYaml(t *testing.T) {
+	cfg := &lConfig1{}
+	err := yaml.Unmarshal([]byte(lyml), &cfg)
+	if err != nil {
+		t.Errorf("Unable to Unmarshal config yaml")
+	}
+
 	if cfg.Name != "fake/testing" {
 		t.Errorf("Inaccurate name found %s", cfg.Name)
 	}
@@ -111,8 +239,60 @@
 	}
 }
 
+func TestLegacyConfigAutoconvert(t *testing.T) {
+	c, leg, err := ConfigFromYaml([]byte(lyml))
+	if err != nil {
+		t.Errorf("ConfigFromYaml failed to detect and autoconvert legacy yaml file with err %s", err)
+	}
+
+	if !leg {
+		t.Errorf("ConfigFromYaml failed to report autoconversion of legacy yaml file")
+	}
+
+	if c.Name != "fake/testing" {
+		t.Error("ConfigFromYaml failed to properly autoconvert legacy yaml file")
+	}
+
+	// Two should survive the conversion
+	if len(c.Imports) != 2 {
+		t.Error("Expected two dep clauses to survive conversion, but got ", len(c.Imports))
+	}
+
+	found := false
+	found2 := false
+	for _, i := range c.Imports {
+		if i.Name == "github.com/Masterminds/convert" {
+			found = true
+			ref := gps.Revision("a9949121a2e2192ca92fa6dddfeaaa4a4412d955")
+			if i.Constraint != ref {
+				t.Errorf("(%s) Expected %q for constraint, got %q", i.Name, ref, i.Constraint)
+			}
+
+			repo := "git@github.com:Masterminds/convert.git"
+			if i.Repository != repo {
+				t.Errorf("(%s) Expected %q for repository, got %q", i.Name, repo, i.Repository)
+			}
+		}
+
+		if i.Name == "github.com/Masterminds/structable" {
+			found2 = true
+			ref := gps.NewVersion("v1.0.0")
+			if i.Constraint != ref {
+				t.Errorf("(%s) Expected %q for constraint, got %q", i.Name, ref, i.Constraint)
+			}
+		}
+	}
+
+	if !found {
+		t.Error("Unable to find github.com/Masterminds/convert")
+	}
+	if !found2 {
+		t.Error("Unable to find github.com/Masterminds/structable")
+	}
+}
+
 func TestConfigFromYaml(t *testing.T) {
-	c, err := ConfigFromYaml([]byte(yml))
+	c, _, err := ConfigFromYaml([]byte(yml))
 	if err != nil {
 		t.Error("ConfigFromYaml failed to parse yaml")
 	}
@@ -123,12 +303,12 @@
 }
 
 func TestHasDependency(t *testing.T) {
-	c, err := ConfigFromYaml([]byte(yml))
+	c, _, err := ConfigFromYaml([]byte(yml))
 	if err != nil {
 		t.Error("ConfigFromYaml failed to parse yaml for HasDependency")
 	}
 
-	if c.HasDependency("github.com/Masterminds/convert") != true {
+	if !c.HasDependency("github.com/Masterminds/convert") {
 		t.Error("HasDependency failing to pickup depenency")
 	}
 
@@ -176,3 +356,47 @@
 		t.Error("Unable to parse owners from yaml")
 	}
 }
+
+func TestDeduceConstraint(t *testing.T) {
+	// First, valid semver
+	c := DeduceConstraint("v1.0.0")
+	if c.(gps.Version).Type() != "semver" {
+		t.Errorf("Got unexpected version type when passing valid semver string: %T %s", c, c)
+	}
+
+	// Now, 20 hex-encoded bytes (which should be assumed to be a SHA1 digest)
+	revin := "a9949121a2e2192ca92fa6dddfeaaa4a4412d955"
+	c = DeduceConstraint(revin)
+	if c != gps.Revision(revin) {
+		t.Errorf("Got unexpected version type/val when passing hex-encoded SHA1 digest: %T %s", c, c)
+	}
+
+	// Now, the weird bzr guid
+	bzrguid := "john@smith.org-20051026185030-93c7cad63ee570df"
+	c = DeduceConstraint(bzrguid)
+	if c != gps.Revision(bzrguid) {
+		t.Errorf("Expected revision with valid bzr guid, got: %T %s", c, c)
+	}
+
+	// Check fails if the bzr rev is malformed or weirdly formed
+	//
+	// chopping off a char should make the hex decode check fail
+	c = DeduceConstraint(bzrguid[:len(bzrguid)-1])
+	if c != gps.NewVersion(bzrguid[:len(bzrguid)-1]) {
+		t.Errorf("Expected plain version when bzr guid has truncated tail hex bits: %T %s", c, c)
+	}
+
+	// Extra dash in email doesn't mess us up
+	bzrguid2 := "john-smith@smith.org-20051026185030-93c7cad63ee570df"
+	c = DeduceConstraint(bzrguid2)
+	if c != gps.Revision(bzrguid2) {
+		t.Errorf("Expected revision when passing bzr guid has extra dash in email, got: %T %s", c, c)
+	}
+
+	// Non-numeric char in middle section bites it
+	bzrguid3 := "john-smith@smith.org-2005102a6185030-93c7cad63ee570df"
+	c = DeduceConstraint(bzrguid3)
+	if c != gps.NewVersion(bzrguid3) {
+		t.Errorf("Expected plain version when bzr guid has invalid second section, got: %T %s", c, c)
+	}
+}
diff --git a/cfg/legacy.go b/cfg/legacy.go
new file mode 100644
index 0000000..8f99d67
--- /dev/null
+++ b/cfg/legacy.go
@@ -0,0 +1,338 @@
+package cfg
+
+import (
+	"fmt"
+	"path"
+	"reflect"
+	"strings"
+	"time"
+
+	"github.com/Masterminds/glide/util"
+)
+
+// lConfig1 is a legacy Config file.
+type lConfig1 struct {
+	Name        string         `yaml:"package"`
+	Description string         `json:"description,omitempty"`
+	Home        string         `yaml:"homepage,omitempty"`
+	License     string         `yaml:"license,omitempty"`
+	Owners      Owners         `yaml:"owners,omitempty"`
+	Ignore      []string       `yaml:"ignore,omitempty"`
+	Exclude     []string       `yaml:"excludeDirs,omitempty"`
+	Imports     lDependencies1 `yaml:"import"`
+	DevImports  lDependencies1 `yaml:"testImport,omitempty"`
+}
+
+func (c *lConfig1) UnmarshalYAML(unmarshal func(interface{}) error) error {
+	newConfig := &lcf1{}
+	if err := unmarshal(&newConfig); err != nil {
+		return err
+	}
+	c.Name = newConfig.Name
+	c.Description = newConfig.Description
+	c.Home = newConfig.Home
+	c.License = newConfig.License
+	c.Owners = newConfig.Owners
+	c.Ignore = newConfig.Ignore
+	c.Exclude = newConfig.Exclude
+	c.Imports = newConfig.Imports
+	c.DevImports = newConfig.DevImports
+
+	// Cleanup the Config object now that we have it.
+	err := c.DeDupe()
+
+	return err
+}
+
+func (c *lConfig1) Convert() (*Config, error) {
+	// This is probably already done, but do it just in case
+	err := c.DeDupe()
+	if err != nil {
+		return nil, err
+	}
+
+	// Pull over the easy values
+	c2 := &Config{
+		Name:        c.Name,
+		Description: c.Description,
+		Home:        c.Home,
+		License:     c.License,
+		Owners:      c.Owners,
+		Ignore:      c.Ignore,
+	}
+
+	// _if_ the name is set, path-prepend it to exclude, and add that to ignore.
+	// Otherwise, we just skip excludes. Not that big a deal, since they're a
+	// root-only property anyway; the user can reasonably recreate.
+
+	if c.Name != "" {
+		for _, excl := range c.Exclude {
+			c.Ignore = append(c.Ignore, path.Join(c.Name, excl))
+			// The trailing * is interpreted by gps as an ignore on that and all
+			// child paths (or, soon - https://github.com/sdboyer/gps/issues/88)
+			c.Ignore = append(c.Ignore, path.Join(c.Name, excl, "*"))
+		}
+	}
+
+	// Quitting early on this might seem risky, but a) all possible errs
+	// _should_ have already been surfaced in the earlier DeDupe(), and b) there
+	// are no new errs introduced by the conversion itself, so this doesn't
+	// actually increase the surface area for failures vis-a-vis pre-gps glide.
+	c2.Imports, err = c.Imports.Convert()
+	if err != nil {
+		return nil, err
+	}
+	c2.DevImports, err = c.DevImports.Convert()
+	if err != nil {
+		return nil, err
+	}
+
+	return c2, nil
+}
+
+// DeDupe consolidates duplicate dependencies on a Config instance
+func (c *lConfig1) DeDupe() error {
+	// Remove duplicates in the imports
+	var err error
+	c.Imports, err = c.Imports.DeDupe()
+	if err != nil {
+		return err
+	}
+	c.DevImports, err = c.DevImports.DeDupe()
+	if err != nil {
+		return err
+	}
+
+	// If the name on the config object is part of the imports remove it.
+	found := -1
+	for i, dep := range c.Imports {
+		if dep.Name == c.Name {
+			found = i
+		}
+	}
+	if found >= 0 {
+		c.Imports = append(c.Imports[:found], c.Imports[found+1:]...)
+	}
+
+	found = -1
+	for i, dep := range c.DevImports {
+		if dep.Name == c.Name {
+			found = i
+		}
+	}
+	if found >= 0 {
+		c.DevImports = append(c.DevImports[:found], c.DevImports[found+1:]...)
+	}
+
+	// If something is on the ignore list remove it from the imports.
+	for _, v := range c.Ignore {
+		found = -1
+		for k, d := range c.Imports {
+			if v == d.Name {
+				found = k
+			}
+		}
+		if found >= 0 {
+			c.Imports = append(c.Imports[:found], c.Imports[found+1:]...)
+		}
+
+		found = -1
+		for k, d := range c.DevImports {
+			if v == d.Name {
+				found = k
+			}
+		}
+		if found >= 0 {
+			c.DevImports = append(c.DevImports[:found], c.DevImports[found+1:]...)
+		}
+	}
+
+	return nil
+}
+
+// Legacy representation of a glide.yaml file.
+type lcf1 struct {
+	Name        string         `yaml:"package"`
+	Description string         `yaml:"description,omitempty"`
+	Home        string         `yaml:"homepage,omitempty"`
+	License     string         `yaml:"license,omitempty"`
+	Owners      Owners         `yaml:"owners,omitempty"`
+	Ignore      []string       `yaml:"ignore,omitempty"`
+	Exclude     []string       `yaml:"excludeDirs,omitempty"`
+	Imports     lDependencies1 `yaml:"import"`
+	DevImports  lDependencies1 `yaml:"testImport,omitempty"`
+	// these fields guarantee that this struct fails to unmarshal the new yamls
+	Compat  int `yaml:"dependencies,omitempty"`
+	Compat2 int `yaml:"testDependencies,omitempty"`
+}
+
+type lDependencies1 []*lDependency1
+
+func (ds lDependencies1) Convert() (Dependencies, error) {
+	dds, err := ds.DeDupe()
+	if err != nil {
+		return nil, err
+	}
+
+	var ds2 Dependencies
+	for _, d := range dds {
+		// If we have neither a repo nor a reference, then it's pointless to
+		// include this dep in the list (it will add no information to gps)
+		if d.Repository == "" && d.Reference == "" {
+			continue
+		}
+
+		d2 := &Dependency{
+			Name:       d.Name,
+			Repository: d.Repository,
+		}
+
+		d2.Constraint = DeduceConstraint(d.Reference)
+		// TODO(sdboyer) if the above result is a plain version, the old
+		// semantics are ambiguous wrt if the user wants a branch or tag. Check
+		// the version list (via source manager) to convert most sanely?
+		ds2 = append(ds2, d2)
+	}
+
+	return ds2, nil
+}
+
+// DeDupe cleans up duplicates on a list of dependencies.
+func (d lDependencies1) DeDupe() (lDependencies1, error) {
+	checked := map[string]int{}
+	imports := make(lDependencies1, 0, 1)
+	i := 0
+	for _, dep := range d {
+		// The first time we encounter a dependency add it to the list
+		if val, ok := checked[dep.Name]; !ok {
+			checked[dep.Name] = i
+			imports = append(imports, dep)
+			i++
+		} else {
+			// In here we've encountered a dependency for the second time.
+			// Make sure the details are the same or return an error.
+			v := imports[val]
+			if dep.Reference != v.Reference {
+				return d, fmt.Errorf("Import %s repeated with different versions '%s' and '%s'", dep.Name, dep.Reference, v.Reference)
+			}
+			if dep.Repository != v.Repository || dep.VcsType != v.VcsType {
+				return d, fmt.Errorf("Import %s repeated with different Repository details", dep.Name)
+			}
+			if !reflect.DeepEqual(dep.Os, v.Os) || !reflect.DeepEqual(dep.Arch, v.Arch) {
+				return d, fmt.Errorf("Import %s repeated with different OS or Architecture filtering", dep.Name)
+			}
+			imports[checked[dep.Name]].Subpackages = stringArrayDeDupe(v.Subpackages, dep.Subpackages...)
+		}
+	}
+
+	return imports, nil
+}
+
+type lDependency1 struct {
+	Name        string   `yaml:"package"`
+	Reference   string   `yaml:"version,omitempty"`
+	Pin         string   `yaml:"-"`
+	Repository  string   `yaml:"repo,omitempty"`
+	VcsType     string   `yaml:"vcs,omitempty"`
+	Subpackages []string `yaml:"subpackages,omitempty"`
+	Arch        []string `yaml:"arch,omitempty"`
+	Os          []string `yaml:"os,omitempty"`
+}
+
+// Legacy unmarshaler for dependency component of yaml files
+func (d *lDependency1) UnmarshalYAML(unmarshal func(interface{}) error) error {
+	newDep := &ldep1{}
+	err := unmarshal(newDep)
+	if err != nil {
+		return err
+	}
+	d.Name = newDep.Name
+	d.Reference = newDep.Reference
+	d.Repository = newDep.Repository
+	d.VcsType = newDep.VcsType
+	d.Subpackages = newDep.Subpackages
+	d.Arch = newDep.Arch
+	d.Os = newDep.Os
+
+	if d.Reference == "" && newDep.Ref != "" {
+		d.Reference = newDep.Ref
+	}
+
+	// Make sure only legitimate VCS are listed.
+	d.VcsType = filterVcsType(d.VcsType)
+
+	// Get the root name for the package
+	tn, subpkg := util.NormalizeName(d.Name)
+	d.Name = tn
+	if subpkg != "" {
+		d.Subpackages = append(d.Subpackages, subpkg)
+	}
+
+	// Older versions of Glide had a / prefix on subpackages in some cases.
+	// Here that's cleaned up. Someday we should be able to remove this.
+	for k, v := range d.Subpackages {
+		d.Subpackages[k] = strings.TrimPrefix(v, "/")
+	}
+
+	return nil
+}
+
+// Legacy representation of a dep constraint
+type ldep1 struct {
+	Name        string   `yaml:"package"`
+	Reference   string   `yaml:"version,omitempty"`
+	Ref         string   `yaml:"ref,omitempty"`
+	Repository  string   `yaml:"repo,omitempty"`
+	VcsType     string   `yaml:"vcs,omitempty"`
+	Subpackages []string `yaml:"subpackages,omitempty"`
+	Arch        []string `yaml:"arch,omitempty"`
+	Os          []string `yaml:"os,omitempty"`
+}
+
+type lLockfile1 struct {
+	Hash       string    `yaml:"hash"`
+	Updated    time.Time `yaml:"updated"`
+	Imports    lLocks1   `yaml:"imports"`
+	DevImports lLocks1   `yaml:"testImports"` // TODO remove and fold in as prop
+	Compat     int       `yaml:"import,omitempty"`
+	Compat2    int       `yaml:"testImport,omitempty"`
+}
+
+func (l *lLockfile1) Convert() *Lockfile {
+	return &Lockfile{
+		Hash:       l.Hash,
+		Updated:    l.Updated,
+		Imports:    l.Imports.Convert(),
+		DevImports: l.DevImports.Convert(),
+	}
+}
+
+type lLocks1 []*lLock1
+
+func (ll lLocks1) Convert() Locks {
+	var ll2 Locks
+	for _, l := range ll {
+		// If they have no rev, just drop them
+		if l.Version == "" {
+			continue
+		}
+
+		ll2 = append(ll2, &Lock{
+			Name:       l.Name,
+			Repository: l.Repository,
+			Revision:   l.Version,
+		})
+	}
+
+	return ll2
+}
+
+type lLock1 struct {
+	Name        string   `yaml:"name"`
+	Version     string   `yaml:"version"`
+	Repository  string   `yaml:"repo,omitempty"`
+	VcsType     string   `yaml:"vcs,omitempty"`
+	Subpackages []string `yaml:"subpackages,omitempty"`
+	Arch        []string `yaml:"arch,omitempty"`
+	Os          []string `yaml:"os,omitempty"`
+}
diff --git a/cfg/lock.go b/cfg/lock.go
index b822f29..284cd51 100644
--- a/cfg/lock.go
+++ b/cfg/lock.go
@@ -9,7 +9,6 @@
 	"strings"
 	"time"
 
-	"github.com/Masterminds/semver"
 	"github.com/sdboyer/gps"
 
 	"gopkg.in/yaml.v2"
@@ -20,7 +19,7 @@
 	Hash       string    `yaml:"hash"`
 	Updated    time.Time `yaml:"updated"`
 	Imports    Locks     `yaml:"imports"`
-	DevImports Locks     `yaml:"testImports"`
+	DevImports Locks     `yaml:"testImports"` // TODO remove and fold in as prop
 }
 
 // LockfileFromSolverLock transforms a gps.Lock into a glide *Lockfile.
@@ -38,8 +37,7 @@
 	for _, p := range r.Projects() {
 		pi := p.Ident()
 		l := &Lock{
-			Name:    string(pi.ProjectRoot),
-			VcsType: "", // TODO allow this to be extracted from sm
+			Name: string(pi.ProjectRoot),
 		}
 
 		if l.Name != pi.NetworkName && pi.NetworkName != "" {
@@ -47,9 +45,16 @@
 		}
 
 		v := p.Version()
-		if pv, ok := v.(gps.PairedVersion); ok {
-			l.Version = pv.Underlying().String()
-		} else {
+		// There's (currently) no way gps can emit a non-paired version in a
+		// solution, so this unchecked type assertion should be safe.
+		//
+		// TODO might still be better to check and return out with an err if
+		// not, though
+		l.Revision = v.(gps.PairedVersion).Underlying().String()
+		switch v.Type() {
+		case "branch":
+			l.Branch = v.String()
+		case "semver", "version":
 			l.Version = v.String()
 		}
 
@@ -60,13 +65,22 @@
 }
 
 // LockfileFromYaml returns an instance of Lockfile from YAML
-func LockfileFromYaml(yml []byte) (*Lockfile, error) {
+func LockfileFromYaml(yml []byte) (*Lockfile, bool, error) {
 	lock := &Lockfile{}
-	err := yaml.Unmarshal([]byte(yml), &lock)
-	return lock, err
+	err := yaml.Unmarshal([]byte(yml), lock)
+	if err == nil {
+		return lock, false, nil
+	}
+
+	llock := &lLockfile1{}
+	err2 := yaml.Unmarshal([]byte(yml), llock)
+	if err2 != nil {
+		return nil, false, err2
+	}
+	return llock.Convert(), true, nil
 }
 
-// Marshal converts a Config instance to YAML
+// Marshal converts a Lockfile instance to YAML
 func (lf *Lockfile) Marshal() ([]byte, error) {
 	sort.Sort(lf.Imports)
 	sort.Sort(lf.DevImports)
@@ -80,10 +94,6 @@
 // MarshalYAML is a hook for gopkg.in/yaml.v2.
 // It sorts import subpackages lexicographically for reproducibility.
 func (lf *Lockfile) MarshalYAML() (interface{}, error) {
-	for _, imp := range lf.Imports {
-		sort.Strings(imp.Subpackages)
-	}
-
 	// Ensure elements on testImport don't already exist on import.
 	var newDI Locks
 	var found bool
@@ -104,9 +114,6 @@
 	}
 	lf.DevImports = newDI
 
-	for _, imp := range lf.DevImports {
-		sort.Strings(imp.Subpackages)
-	}
 	return lf, nil
 }
 
@@ -138,21 +145,15 @@
 	lp := make([]gps.LockedProject, len(all))
 
 	for k, l := range all {
-		// TODO guess the version type. ugh
-		var v gps.Version
+		r := gps.Revision(l.Revision)
 
-		// semver first
-		_, err := semver.NewVersion(l.Version)
-		if err == nil {
-			v = gps.NewVersion(l.Version)
+		var v gps.Version
+		if l.Version != "" {
+			v = gps.NewVersion(l.Version).Is(r)
+		} else if l.Branch != "" {
+			v = gps.NewBranch(l.Branch).Is(r)
 		} else {
-			// Crappy heuristic to cover hg and git, but not bzr. Or (lol) svn
-			if len(l.Version) == 40 {
-				v = gps.Revision(l.Version)
-			} else {
-				// Otherwise, assume it's a branch
-				v = gps.NewBranch(l.Version)
-			}
+			v = r
 		}
 
 		lp[k] = gps.NewLockedProject(gps.ProjectRoot(l.Name), v, l.Repository, nil)
@@ -174,6 +175,7 @@
 
 // Fingerprint returns a hash of the contents minus the date. This allows for
 // two lockfiles to be compared irrespective of their updated times.
+// TODO remove, or seriously re-adapt
 func (lf *Lockfile) Fingerprint() ([32]byte, error) {
 	c := lf.Clone()
 	c.Updated = time.Time{} // Set the time to be the nil equivalent
@@ -193,7 +195,7 @@
 	if err != nil {
 		return nil, err
 	}
-	lock, err := LockfileFromYaml(yml)
+	lock, _, err := LockfileFromYaml(yml)
 	if err != nil {
 		return nil, err
 	}
@@ -236,42 +238,62 @@
 
 // Lock represents an individual locked dependency.
 type Lock struct {
-	Name        string   `yaml:"name"`
-	Version     string   `yaml:"version"`
-	Repository  string   `yaml:"repo,omitempty"`
-	VcsType     string   `yaml:"vcs,omitempty"`
-	Subpackages []string `yaml:"subpackages,omitempty"`
-	Arch        []string `yaml:"arch,omitempty"`
-	Os          []string `yaml:"os,omitempty"`
+	Name       string `yaml:"name"`
+	Version    string `yaml:"version,omitempty"`
+	Branch     string `yaml:"branch,omitempty"`
+	Revision   string `yaml:"revision"`
+	Repository string `yaml:"repo,omitempty"`
+}
+
+func (l *Lock) UnmarshalYAML(unmarshal func(interface{}) error) error {
+	nl := struct {
+		Name       string `yaml:"name"`
+		Version    string `yaml:"version,omitempty"`
+		Branch     string `yaml:"branch,omitempty"`
+		Revision   string `yaml:"revision"`
+		Repository string `yaml:"repo,omitempty"`
+	}{}
+
+	err := unmarshal(&nl)
+	if err != nil {
+		return err
+	}
+
+	// If Revision field is empty, then we can be certain this is either a
+	// legacy file, or just plain invalid
+	if nl.Revision == "" {
+		return fmt.Errorf("dependency %s is missing a revision; is this a legacy glide.lock file?", nl.Name)
+	}
+
+	l.Name = nl.Name
+	l.Version = nl.Version
+	l.Branch = nl.Branch
+	l.Revision = nl.Revision
+	l.Repository = nl.Repository
+
+	return nil
 }
 
 // Clone creates a clone of a Lock.
 func (l *Lock) Clone() *Lock {
-	return &Lock{
-		Name:        l.Name,
-		Version:     l.Version,
-		Repository:  l.Repository,
-		VcsType:     l.VcsType,
-		Subpackages: l.Subpackages,
-		Arch:        l.Arch,
-		Os:          l.Os,
-	}
+	var l2 Lock
+	l2 = *l
+	return &l2
 }
 
 // LockFromDependency converts a Dependency to a Lock
+// TODO remove
 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,
+	l := &Lock{
+		Name:       dep.Name,
+		Repository: dep.Repository,
 	}
+
+	return l
 }
 
 // NewLockfile is used to create an instance of Lockfile.
+// TODO remove
 func NewLockfile(ds, tds Dependencies, hash string) (*Lockfile, error) {
 	lf := &Lockfile{
 		Hash:       hash,
@@ -292,8 +314,8 @@
 		for ii := 0; ii < len(ds); ii++ {
 			if ds[ii].Name == tds[i].Name {
 				found = true
-				if ds[ii].Reference != tds[i].Reference {
-					return &Lockfile{}, fmt.Errorf("Generating lock produced conflicting versions of %s. import (%s), testImport (%s)", tds[i].Name, ds[ii].Reference, tds[i].Reference)
+				if ds[ii].Constraint.String() != tds[i].Constraint.String() {
+					return &Lockfile{}, fmt.Errorf("Generating lock produced conflicting versions of %s. import (%s), testImport (%s)", tds[i].Name, ds[ii].Constraint, tds[i].Constraint)
 				}
 				break
 			}
@@ -309,6 +331,7 @@
 }
 
 // LockfileFromMap takes a map of dependencies and generates a lock Lockfile instance.
+// TODO remove
 func LockfileFromMap(ds map[string]*Dependency, hash string) *Lockfile {
 	lf := &Lockfile{
 		Hash:    hash,
diff --git a/cfg/lock_test.go b/cfg/lock_test.go
index 81edcd0..5d1b52a 100644
--- a/cfg/lock_test.go
+++ b/cfg/lock_test.go
@@ -1,112 +1,34 @@
 package cfg
 
 import (
-	"sort"
-	"strings"
 	"testing"
+
+	"github.com/kr/pretty"
 )
 
-func TestSortLocks(t *testing.T) {
-	c, err := ConfigFromYaml([]byte(yml))
-	if err != nil {
-		t.Error("ConfigFromYaml failed to parse yaml for TestSortDependencies")
-	}
+const lockFix = `
+imports:
+- name: github.com/gogo/protobuf
+  revision: 82d16f734d6d871204a3feb1a73cb220cc92574c
+`
 
-	ls := make(Locks, len(c.Imports))
-	for i := 0; i < len(c.Imports); i++ {
-		ls[i] = &Lock{
-			Name:    c.Imports[i].Name,
-			Version: c.Imports[i].Reference,
-		}
-	}
-
-	if ls[2].Name != "github.com/Masterminds/structable" {
-		t.Error("Initial dependencies are out of order prior to sort")
-	}
-
-	sort.Sort(ls)
-
-	if ls[0].Name != "github.com/kylelemons/go-gypsy" ||
-		ls[1].Name != "github.com/Masterminds/convert" ||
-		ls[2].Name != "github.com/Masterminds/cookoo" ||
-		ls[3].Name != "github.com/Masterminds/structable" {
-		t.Error("Sorting of dependencies failed")
-	}
-}
-
-const inputSubpkgYaml = `
+const llockFix = `
 imports:
 - name: github.com/gogo/protobuf
   version: 82d16f734d6d871204a3feb1a73cb220cc92574c
-  subpackages:
-  - plugin/equal
-  - sortkeys
-  - plugin/face
-  - plugin/gostring
-  - vanity
-  - plugin/grpc
-  - plugin/marshalto
-  - plugin/populate
-  - plugin/oneofcheck
-  - plugin/size
-  - plugin/stringer
-  - plugin/defaultcheck
-  - plugin/embedcheck
-  - plugin/description
-  - plugin/enumstringer
-  - gogoproto
-  - plugin/testgen
-  - plugin/union
-  - plugin/unmarshal
-  - protoc-gen-gogo/generator
-  - protoc-gen-gogo/plugin
-  - vanity/command
-  - protoc-gen-gogo/descriptor
-  - proto
-`
-const expectSubpkgYaml = `
-imports:
-- name: github.com/gogo/protobuf
-  version: 82d16f734d6d871204a3feb1a73cb220cc92574c
-  subpackages:
-  - gogoproto
-  - plugin/defaultcheck
-  - plugin/description
-  - plugin/embedcheck
-  - plugin/enumstringer
-  - plugin/equal
-  - plugin/face
-  - plugin/gostring
-  - plugin/grpc
-  - plugin/marshalto
-  - plugin/oneofcheck
-  - plugin/populate
-  - plugin/size
-  - plugin/stringer
-  - plugin/testgen
-  - plugin/union
-  - plugin/unmarshal
-  - proto
-  - protoc-gen-gogo/descriptor
-  - protoc-gen-gogo/generator
-  - protoc-gen-gogo/plugin
-  - sortkeys
-  - vanity
-  - vanity/command
 `
 
-func TestSortSubpackages(t *testing.T) {
-	lf, err := LockfileFromYaml([]byte(inputSubpkgYaml))
+func TestLegacyLockAutoconvert(t *testing.T) {
+	ll, legacy, err := LockfileFromYaml([]byte(llockFix))
 	if err != nil {
-		t.Fatal(err)
+		t.Errorf("LockfileFromYaml failed to detect and autoconvert legacy lock file with err %s", err)
+	}
+	pretty.Println(ll)
+	if !legacy {
+		t.Error("LockfileFromYaml failed to report autoconversion of legacy lock file")
 	}
 
-	out, err := lf.Marshal()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if !strings.Contains(string(out), expectSubpkgYaml) {
-		t.Errorf("Expected %q\nto contain\n%q")
+	if len(ll.Imports) != 1 {
+		t.Errorf("LockfileFromYaml autoconverted with wrong number of import stanzas; expected 1, got %v", len(ll.Imports))
 	}
 }
diff --git a/dependency/analyzer.go b/dependency/analyzer.go
index 0f88d7d..131b677 100644
--- a/dependency/analyzer.go
+++ b/dependency/analyzer.go
@@ -102,7 +102,8 @@
 		return nil, nil, fmt.Errorf("Error while reading glide manifest data: %s", root)
 	}
 
-	m, err := cfg.ConfigFromYaml(yml)
+	// We don't care here if it's legacy
+	m, _, err := cfg.ConfigFromYaml(yml)
 	if err != nil {
 		return nil, nil, fmt.Errorf("Error while parsing glide manifest data: %s", root)
 	}
@@ -120,7 +121,8 @@
 		return m, nil, nil
 	}
 
-	l, err := cfg.LockfileFromYaml(yml)
+	// Again, legacy doesn't matter here
+	l, _, err := cfg.LockfileFromYaml(yml)
 	if err != nil {
 		return m, nil, nil
 	}
diff --git a/dependency/resolver.go b/dependency/resolver.go
index 06dd2dc..a0cabf1 100644
--- a/dependency/resolver.go
+++ b/dependency/resolver.go
@@ -257,10 +257,10 @@
 		}
 		pt := strings.TrimPrefix(path, r.basedir+string(os.PathSeparator))
 		pt = strings.TrimSuffix(pt, string(os.PathSeparator))
-		if r.Config.HasExclude(pt) {
-			msg.Debug("Excluding %s", pt)
-			return filepath.SkipDir
-		}
+		//if r.Config.HasExclude(pt) {
+		//msg.Debug("Excluding %s", pt)
+		//return filepath.SkipDir
+		//}
 		if !fi.IsDir() {
 			return nil
 		}
@@ -588,7 +588,7 @@
 	// In addition to generating a list
 	for e := queue.Front(); e != nil; e = e.Next() {
 		t := r.Stripv(e.Value.(string))
-		root, sp := util.NormalizeName(t)
+		root, _ := util.NormalizeName(t)
 
 		// Skip ignored packages
 		if r.Config.HasIgnore(e.Value.(string)) {
@@ -598,25 +598,19 @@
 
 		// TODO(mattfarina): Need to eventually support devImport
 		existing := r.Config.Imports.Get(root)
-		if existing == nil && addTest {
-			existing = r.Config.DevImports.Get(root)
-		}
-		if existing != nil {
-			if sp != "" && !existing.HasSubpackage(sp) {
-				existing.Subpackages = append(existing.Subpackages, sp)
-			}
-		} else {
-			newDep := &cfg.Dependency{
-				Name: root,
-			}
-			if sp != "" {
-				newDep.Subpackages = []string{sp}
-			}
-
+		if existing == nil {
 			if addTest {
-				r.Config.DevImports = append(r.Config.DevImports, newDep)
+				existing = r.Config.DevImports.Get(root)
 			} else {
-				r.Config.Imports = append(r.Config.Imports, newDep)
+				newDep := &cfg.Dependency{
+					Name: root,
+				}
+
+				if addTest {
+					r.Config.DevImports = append(r.Config.DevImports, newDep)
+				} else {
+					r.Config.Imports = append(r.Config.Imports, newDep)
+				}
 			}
 		}
 		res = append(res, t)
@@ -685,29 +679,22 @@
 	// In addition to generating a list
 	for e := queue.Front(); e != nil; e = e.Next() {
 		t := strings.TrimPrefix(e.Value.(string), r.VendorDir+string(os.PathSeparator))
-		root, sp := util.NormalizeName(t)
+		root, _ := util.NormalizeName(t)
 
 		existing := r.Config.Imports.Get(root)
-		if existing == nil && addTest {
-			existing = r.Config.DevImports.Get(root)
-		}
-
-		if existing != nil {
-			if sp != "" && !existing.HasSubpackage(sp) {
-				existing.Subpackages = append(existing.Subpackages, sp)
-			}
-		} else {
-			newDep := &cfg.Dependency{
-				Name: root,
-			}
-			if sp != "" {
-				newDep.Subpackages = []string{sp}
-			}
-
+		if existing == nil {
 			if addTest {
-				r.Config.DevImports = append(r.Config.DevImports, newDep)
+				existing = r.Config.DevImports.Get(root)
 			} else {
-				r.Config.Imports = append(r.Config.Imports, newDep)
+				newDep := &cfg.Dependency{
+					Name: root,
+				}
+
+				if addTest {
+					r.Config.DevImports = append(r.Config.DevImports, newDep)
+				} else {
+					r.Config.Imports = append(r.Config.Imports, newDep)
+				}
 			}
 		}
 		res = append(res, e.Value.(string))
@@ -861,20 +848,8 @@
 func sliceToQueue(deps []*cfg.Dependency, basepath string) *list.List {
 	l := list.New()
 	for _, e := range deps {
-		if len(e.Subpackages) > 0 {
-			for _, v := range e.Subpackages {
-				ip := e.Name
-				if v != "." && v != "" {
-					ip = ip + "/" + v
-				}
-				msg.Debug("Adding local Import %s to queue", ip)
-				l.PushBack(filepath.Join(basepath, filepath.FromSlash(ip)))
-			}
-		} else {
-			msg.Debug("Adding local Import %s to queue", e.Name)
-			l.PushBack(filepath.Join(basepath, filepath.FromSlash(e.Name)))
-		}
-
+		msg.Debug("Adding local Import %s to queue", e.Name)
+		l.PushBack(filepath.Join(basepath, filepath.FromSlash(e.Name)))
 	}
 	return l
 }
diff --git a/gb/gb.go b/gb/gb.go
index ea64258..2f5612b 100644
--- a/gb/gb.go
+++ b/gb/gb.go
@@ -9,6 +9,7 @@
 	"github.com/Masterminds/glide/msg"
 	gpath "github.com/Masterminds/glide/path"
 	"github.com/Masterminds/glide/util"
+	"github.com/sdboyer/gps"
 )
 
 // Has returns true if this dir has a GB-flavored manifest file.
@@ -44,26 +45,16 @@
 	seen := map[string]bool{}
 
 	for _, d := range man.Dependencies {
-		pkg, sub := util.NormalizeName(d.Importpath)
-		if _, ok := seen[pkg]; ok {
-			if len(sub) == 0 {
-				continue
-			}
-			for _, dep := range buf {
-				if dep.Name == pkg {
-					dep.Subpackages = append(dep.Subpackages, sub)
-				}
-			}
-		} else {
+		// TODO(sdboyer) move to the corresponding SourceManager call...though
+		// that matters less once gps caches these results
+		pkg, _ := util.NormalizeName(d.Importpath)
+		if !seen[pkg] {
 			seen[pkg] = true
 			dep := &cfg.Dependency{
 				Name:       pkg,
-				Reference:  d.Revision,
+				Constraint: cfg.DeduceConstraint(d.Revision),
 				Repository: d.Repository,
 			}
-			if len(sub) > 0 {
-				dep.Subpackages = []string{sub}
-			}
 			buf = append(buf, dep)
 		}
 	}
@@ -94,16 +85,15 @@
 
 	for _, d := range man.Dependencies {
 		pkg, _ := util.NormalizeName(d.Importpath)
-		if _, ok := seen[pkg]; ok {
+		if !seen[pkg] {
 			seen[pkg] = true
 			dep := &cfg.Dependency{
-				Name: pkg,
-				// TODO we have the branch info here - maybe we should use that
-				Reference:  "*",
+				Name:       pkg,
+				Constraint: gps.Any(),
 				Repository: d.Repository,
 			}
 			m = append(m, dep)
-			l.Imports = append(l.Imports, &cfg.Lock{Name: pkg, Version: d.Revision})
+			l.Imports = append(l.Imports, &cfg.Lock{Name: pkg, Revision: d.Revision})
 		}
 	}
 	return
diff --git a/glide.lock b/glide.lock
index 9a968e2..a5d5c91 100644
--- a/glide.lock
+++ b/glide.lock
@@ -10,7 +10,7 @@
 - name: github.com/Masterminds/vcs
   version: fbe9fb6ad5b5f35b3e82a7c21123cfc526cbf895
 - name: github.com/sdboyer/gps
-  version: 278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0
+  version: f6e74e8d79b34ee6954d0cc8b770758ec99870ad
 - name: github.com/termie/go-shutil
   version: bcacb06fecaeec8dc42af03c87c6949f4a05c74c
 - name: gopkg.in/yaml.v2
diff --git a/godep/godep.go b/godep/godep.go
index 2b9ea41..82bc5e1 100644
--- a/godep/godep.go
+++ b/godep/godep.go
@@ -7,12 +7,12 @@
 	"encoding/json"
 	"os"
 	"path/filepath"
-	"strings"
 
 	"github.com/Masterminds/glide/cfg"
 	"github.com/Masterminds/glide/msg"
 	gpath "github.com/Masterminds/glide/path"
 	"github.com/Masterminds/glide/util"
+	"github.com/sdboyer/gps"
 )
 
 // This file contains commands for working with Godep.
@@ -75,23 +75,10 @@
 
 	seen := map[string]bool{}
 	for _, d := range godeps.Deps {
-		pkg, sub := util.NormalizeName(d.ImportPath)
-		if _, ok := seen[pkg]; ok {
-			if len(sub) == 0 {
-				continue
-			}
-			// Modify existing dep with additional subpackages.
-			for _, dep := range buf {
-				if dep.Name == pkg {
-					dep.Subpackages = append(dep.Subpackages, sub)
-				}
-			}
-		} else {
+		pkg, _ := util.NormalizeName(d.ImportPath)
+		if !seen[pkg] {
 			seen[pkg] = true
-			dep := &cfg.Dependency{Name: pkg, Reference: d.Rev}
-			if sub != "" {
-				dep.Subpackages = []string{sub}
-			}
+			dep := &cfg.Dependency{Name: pkg, Constraint: gps.Revision(d.Rev)}
 			buf = append(buf, dep)
 		}
 	}
@@ -134,8 +121,8 @@
 			// This approach does make for an uncomfortably wide possibility
 			// space where deps aren't getting what they expect, but that's
 			// better than just having the solver give up completely.
-			m = append(m, &cfg.Dependency{Name: pkg, Reference: "*"})
-			l.Imports = append(l.Imports, &cfg.Lock{Name: pkg, Version: d.Rev})
+			m = append(m, &cfg.Dependency{Name: pkg, Constraint: gps.Any()})
+			l.Imports = append(l.Imports, &cfg.Lock{Name: pkg, Revision: d.Rev})
 
 			// TODO this fails to differentiate between dev and non-dev imports;
 			// need static analysis for that
@@ -144,29 +131,3 @@
 
 	return m, l, nil
 }
-
-// RemoveGodepSubpackages strips subpackages from a cfg.Config dependencies that
-// contain "Godeps/_workspace/src" as part of the path.
-func RemoveGodepSubpackages(c *cfg.Config) *cfg.Config {
-	for _, d := range c.Imports {
-		n := []string{}
-		for _, v := range d.Subpackages {
-			if !strings.HasPrefix(v, "Godeps/_workspace/src") {
-				n = append(n, v)
-			}
-		}
-		d.Subpackages = n
-	}
-
-	for _, d := range c.DevImports {
-		n := []string{}
-		for _, v := range d.Subpackages {
-			if !strings.HasPrefix(v, "Godeps/_workspace/src") {
-				n = append(n, v)
-			}
-		}
-		d.Subpackages = n
-	}
-
-	return c
-}
diff --git a/gom/gom.go b/gom/gom.go
index 05785e6..46f27d2 100644
--- a/gom/gom.go
+++ b/gom/gom.go
@@ -56,33 +56,21 @@
 			}
 		}
 
-		pkg, sub := util.NormalizeName(gom.name)
+		pkg, _ := util.NormalizeName(gom.name)
 
 		dep := &cfg.Dependency{
 			Name: pkg,
 		}
 
-		if len(sub) > 0 {
-			dep.Subpackages = []string{sub}
-		}
-
 		// Check for a specific revision
 		if val, ok := gom.options["commit"]; ok {
-			dep.Reference = val.(string)
+			dep.Constraint = gps.Revision(val.(string))
 		}
 		if val, ok := gom.options["tag"]; ok {
-			dep.Reference = val.(string)
+			dep.Constraint = gps.NewVersion(val.(string))
 		}
 		if val, ok := gom.options["branch"]; ok {
-			dep.Reference = val.(string)
-		}
-
-		// Parse goos and goarch
-		if val, ok := gom.options["goos"]; ok {
-			dep.Os = toStringSlice(val)
-		}
-		if val, ok := gom.options["goarch"]; ok {
-			dep.Arch = toStringSlice(val)
+			dep.Constraint = gps.NewBranch(val.(string))
 		}
 
 		buf = append(buf, dep)
diff --git a/gpm/gpm.go b/gpm/gpm.go
index 00ca864..0f6c8ef 100644
--- a/gpm/gpm.go
+++ b/gpm/gpm.go
@@ -13,6 +13,7 @@
 	"github.com/Masterminds/glide/cfg"
 	"github.com/Masterminds/glide/msg"
 	gpath "github.com/Masterminds/glide/path"
+	"github.com/sdboyer/gps"
 )
 
 // Has indicates whether a Godeps file exists.
@@ -46,7 +47,7 @@
 		if ok {
 			dep := &cfg.Dependency{Name: parts[0]}
 			if len(parts) > 1 {
-				dep.Reference = parts[1]
+				dep.Constraint = cfg.DeduceConstraint(parts[1])
 			}
 			buf = append(buf, dep)
 		}
@@ -84,7 +85,7 @@
 			if len(parts) > 1 {
 				l.Imports = append(l.Imports, &cfg.Lock{Name: parts[0], Version: parts[1]})
 			}
-			m = append(m, &cfg.Dependency{Name: parts[0], Reference: "*"})
+			m = append(m, &cfg.Dependency{Name: parts[0], Constraint: gps.Any()})
 		}
 	}
 	if err := scanner.Err(); err != nil {
diff --git a/importer/importer.go b/importer/importer.go
index 9d5d2ac..9da292b 100644
--- a/importer/importer.go
+++ b/importer/importer.go
@@ -44,7 +44,7 @@
 		if err != nil {
 			return false, []*cfg.Dependency{}, err
 		}
-		conf, err := cfg.ConfigFromYaml(yml)
+		conf, _, err := cfg.ConfigFromYaml(yml)
 		if err != nil {
 			return false, []*cfg.Dependency{}, err
 		}
diff --git a/repo/installer.go b/repo/installer.go
index eec08df..de751bf 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -195,19 +195,13 @@
 		if conf.HasIgnore(n) {
 			continue
 		}
-		rt, sub := util.NormalizeName(n)
-		if sub == "" {
-			sub = "."
-		}
+		rt, _ := util.NormalizeName(n)
 		d := deps.Get(rt)
 		if d == nil {
 			nd := &cfg.Dependency{
-				Name:        rt,
-				Subpackages: []string{sub},
+				Name: rt,
 			}
 			deps = append(deps, nd)
-		} else if !d.HasSubpackage(sub) {
-			d.Subpackages = append(d.Subpackages, sub)
 		}
 	}
 	if i.ResolveTest {
@@ -216,22 +210,16 @@
 			if conf.HasIgnore(n) {
 				continue
 			}
-			rt, sub := util.NormalizeName(n)
-			if sub == "" {
-				sub = "."
-			}
+			rt, _ := util.NormalizeName(n)
 			d := deps.Get(rt)
 			if d == nil {
 				d = tdeps.Get(rt)
 			}
 			if d == nil {
 				nd := &cfg.Dependency{
-					Name:        rt,
-					Subpackages: []string{sub},
+					Name: rt,
 				}
 				tdeps = append(tdeps, nd)
-			} else if !d.HasSubpackage(sub) {
-				d.Subpackages = append(d.Subpackages, sub)
 			}
 		}
 	}
@@ -330,12 +318,12 @@
 			continue
 		}
 
-		if ver == dep.Reference {
-			msg.Info("--> Found desired version %s %s!", dep.Name, dep.Reference)
+		if ver == dep.Constraint.String() {
+			msg.Info("--> Found desired version %s %s!", dep.Name, dep.Constraint)
 			continue
 		}
 
-		msg.Debug("--> Queue %s for update (%s != %s).", dep.Name, ver, dep.Reference)
+		msg.Debug("--> Queue %s for update (%s != %s).", dep.Name, ver, dep.Constraint)
 		newDeps = append(newDeps, dep)
 	}
 	if len(newDeps) > 0 {
@@ -621,7 +609,7 @@
 
 				// The fist one wins. Would something smater than this be better?
 				exists, _ := d.Use.Get(dep.Name)
-				if exists == nil && (dep.Reference != "" || dep.Repository != "") {
+				if exists == nil && (dep.Constraint != nil || dep.Repository != "") {
 					d.Use.Add(dep.Name, dep, root)
 				}
 			}
@@ -656,8 +644,8 @@
 			// There are import chains (because the import tree is resolved
 			// before the test tree) that can cause this.
 			tempD := d.Config.DevImports.Get(root)
-			if tempD.Reference != v.Reference {
-				msg.Warn("Using import %s (version %s) for test instead of testImport (version %s).", v.Name, v.Reference, tempD.Reference)
+			if tempD.Constraint.String() != v.Constraint.String() {
+				msg.Warn("Using import %s (version %s) for test instead of testImport (version %s).", v.Name, v.Constraint, tempD.Constraint)
 			}
 			// TODO(mattfarina): Note repo difference in a warning.
 		}
@@ -665,12 +653,12 @@
 
 	dep, req := d.Use.Get(root)
 	if dep != nil && v != nil {
-		if v.Reference == "" && dep.Reference != "" {
-			v.Reference = dep.Reference
+		if v.Constraint == nil && dep.Constraint != nil {
+			v.Constraint = dep.Constraint
 			// Clear the pin, if set, so the new version can be used.
-			v.Pin = ""
+			//v.Pin = ""
 			dep = v
-		} else if v.Reference != "" && dep.Reference != "" && v.Reference != dep.Reference {
+		} else if v.Constraint != nil && dep.Constraint != nil && v.Constraint.String() != dep.Constraint.String() {
 			dest := filepath.Join(d.Destination, filepath.FromSlash(v.Name))
 			dep = determineDependency(v, dep, dest, req)
 		} else {
@@ -689,13 +677,10 @@
 		}
 	} else {
 		// If we've gotten here we don't have any depenency objects.
-		r, sp := util.NormalizeName(pkg)
+		r, _ := util.NormalizeName(pkg)
 		dep = &cfg.Dependency{
 			Name: r,
 		}
-		if sp != "" {
-			dep.Subpackages = []string{sp}
-		}
 		if addTest {
 			d.Config.DevImports = append(d.Config.DevImports, dep)
 		} else {
@@ -705,7 +690,7 @@
 
 	err := VcsVersion(dep, d.Destination)
 	if err != nil {
-		msg.Warn("Unable to set version on %s to %s. Err: %s", root, dep.Reference, err)
+		msg.Warn("Unable to set version on %s to %s. Err: %s", root, dep.Constraint, err)
 		e = err
 	}
 
@@ -716,110 +701,110 @@
 	repo, err := v.GetRepo(dest)
 	if err != nil {
 		singleWarn("Unable to access repo for %s\n", v.Name)
-		singleInfo("Keeping %s %s", v.Name, v.Reference)
+		singleInfo("Keeping %s %s", v.Name, v.Constraint)
 		return v
 	}
 
-	vIsRef := repo.IsReference(v.Reference)
-	depIsRef := repo.IsReference(dep.Reference)
+	vIsRef := repo.IsReference(v.Constraint.String())
+	depIsRef := repo.IsReference(dep.Constraint.String())
 
 	// Both are references and they are different ones.
 	if vIsRef && depIsRef {
-		singleWarn("Conflict: %s rev is currently %s, but %s wants %s\n", v.Name, v.Reference, req, dep.Reference)
+		singleWarn("Conflict: %s rev is currently %s, but %s wants %s\n", v.Name, v.Constraint, req, dep.Constraint)
 
 		displayCommitInfo(repo, v)
 		displayCommitInfo(repo, dep)
 
-		singleInfo("Keeping %s %s", v.Name, v.Reference)
+		singleInfo("Keeping %s %s", v.Name, v.Constraint)
 		return v
 	} else if vIsRef {
 		// The current one is a reference and the suggestion is a SemVer constraint.
-		con, err := semver.NewConstraint(dep.Reference)
+		con, err := semver.NewConstraint(dep.Constraint.String())
 		if err != nil {
-			singleWarn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", dep.Name, dep.Reference)
-			singleInfo("Keeping %s %s", v.Name, v.Reference)
+			singleWarn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", dep.Name, dep.Constraint)
+			singleInfo("Keeping %s %s", v.Name, v.Constraint)
 			return v
 		}
 
-		ver, err := semver.NewVersion(v.Reference)
+		ver, err := semver.NewVersion(v.Constraint.String())
 		if err != nil {
 			// The existing version is not a semantic version.
-			singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Reference, dep.Reference)
+			singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Constraint, dep.Constraint)
 			displayCommitInfo(repo, v)
-			singleInfo("Keeping %s %s", v.Name, v.Reference)
+			singleInfo("Keeping %s %s", v.Name, v.Constraint)
 			return v
 		}
 
 		if con.Matches(ver) == nil {
-			singleInfo("Keeping %s %s because it fits constraint '%s'", v.Name, v.Reference, dep.Reference)
+			singleInfo("Keeping %s %s because it fits constraint '%s'", v.Name, v.Constraint, dep.Constraint)
 			return v
 		}
-		singleWarn("Conflict: %s version is %s but does not meet constraint '%s'\n", v.Name, v.Reference, dep.Reference)
-		singleInfo("Keeping %s %s", v.Name, v.Reference)
+		singleWarn("Conflict: %s version is %s but does not meet constraint '%s'\n", v.Name, v.Constraint, dep.Constraint)
+		singleInfo("Keeping %s %s", v.Name, v.Constraint)
 		return v
 	} else if depIsRef {
 
-		con, err := semver.NewConstraint(v.Reference)
+		con, err := semver.NewConstraint(v.Constraint.String())
 		if err != nil {
-			singleWarn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", v.Name, v.Reference)
-			singleInfo("Keeping %s %s", v.Name, v.Reference)
+			singleWarn("Version issue for %s: '%s' is neither a reference or semantic version constraint\n", v.Name, v.Constraint)
+			singleInfo("Keeping %s %s", v.Name, v.Constraint)
 			return v
 		}
 
-		ver, err := semver.NewVersion(dep.Reference)
+		ver, err := semver.NewVersion(dep.Constraint.String())
 		if err != nil {
-			singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Reference, dep.Reference)
+			singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Constraint, dep.Constraint)
 			displayCommitInfo(repo, dep)
-			singleInfo("Keeping %s %s", v.Name, v.Reference)
+			singleInfo("Keeping %s %s", v.Name, v.Constraint)
 			return v
 		}
 
 		if con.Matches(ver) == nil {
-			v.Reference = dep.Reference
-			singleInfo("Using %s %s because it fits constraint '%s'", v.Name, v.Reference, v.Reference)
+			v.Constraint = dep.Constraint
+			singleInfo("Using %s %s because it fits constraint '%s'", v.Name, v.Constraint, v.Constraint)
 			return v
 		}
-		singleWarn("Conflict: %s semantic version constraint is %s but '%s' does not meet the constraint\n", v.Name, v.Reference, v.Reference)
-		singleInfo("Keeping %s %s", v.Name, v.Reference)
+		singleWarn("Conflict: %s semantic version constraint is %s but '%s' does not meet the constraint\n", v.Name, v.Constraint, v.Constraint)
+		singleInfo("Keeping %s %s", v.Name, v.Constraint)
 		return v
 	}
 	// Neither is a vcs reference and both could be semantic version
 	// constraints that are different.
 
-	_, err = semver.NewConstraint(dep.Reference)
+	_, err = semver.NewConstraint(dep.Constraint.String())
 	if err != nil {
-		// dd.Reference is not a reference or a valid constraint.
-		singleWarn("Version %s %s is not a reference or valid semantic version constraint\n", dep.Name, dep.Reference)
-		singleInfo("Keeping %s %s", v.Name, v.Reference)
+		// dd.Constraint is not a reference or a valid constraint.
+		singleWarn("Version %s %s is not a reference or valid semantic version constraint\n", dep.Name, dep.Constraint)
+		singleInfo("Keeping %s %s", v.Name, v.Constraint)
 		return v
 	}
 
-	_, err = semver.NewConstraint(v.Reference)
+	_, err = semver.NewConstraint(v.Constraint.String())
 	if err != nil {
-		// existing.Reference is not a reference or a valid constraint.
+		// existing.Constraint is not a reference or a valid constraint.
 		// We really should never end up here.
-		singleWarn("Version %s %s is not a reference or valid semantic version constraint\n", v.Name, v.Reference)
+		singleWarn("Version %s %s is not a reference or valid semantic version constraint\n", v.Name, v.Constraint)
 
-		v.Reference = dep.Reference
-		v.Pin = ""
-		singleInfo("Using %s %s because it is a valid version", v.Name, v.Reference)
+		v.Constraint = dep.Constraint
+		//v.Pin = ""
+		singleInfo("Using %s %s because it is a valid version", v.Name, v.Constraint)
 		return v
 	}
 
 	// Both versions are constraints. Try to merge them.
 	// If either comparison has an || skip merging. That's complicated.
-	ddor := strings.Index(dep.Reference, "||")
-	eor := strings.Index(v.Reference, "||")
+	ddor := strings.Index(dep.Constraint.String(), "||")
+	eor := strings.Index(v.Constraint.String(), "||")
 	if ddor == -1 && eor == -1 {
 		// Add the comparisons together.
-		newRef := v.Reference + ", " + dep.Reference
-		v.Reference = newRef
-		v.Pin = ""
-		singleInfo("Combining %s semantic version constraints %s and %s", v.Name, v.Reference, dep.Reference)
+		// TODO(sdboyer) this all just reeeeeally needs to go
+		v.Constraint = v.Constraint.Intersect(dep.Constraint)
+		//v.Pin = ""
+		singleInfo("Combining %s semantic version constraints %s and %s", v.Name, v.Constraint, dep.Constraint)
 		return v
 	}
-	singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Reference, dep.Reference)
-	singleInfo("Keeping %s %s", v.Name, v.Reference)
+	singleWarn("Conflict: %s version is %s, but also asked for %s\n", v.Name, v.Constraint, dep.Constraint)
+	singleInfo("Keeping %s %s", v.Name, v.Constraint)
 	return v
 }
 
@@ -877,13 +862,13 @@
 	displayCommitInfoPrefix + "- subject (first line): %s\n"
 
 func displayCommitInfo(repo vcs.Repo, dep *cfg.Dependency) {
-	c, err := repo.CommitInfo(dep.Reference)
-	ref := dep.Reference
+	ref := dep.Constraint.String()
+	c, err := repo.CommitInfo(ref)
 
 	if err == nil {
 		tgs, err2 := repo.TagsFromCommit(c.Commit)
 		if err2 == nil && len(tgs) > 0 {
-			if tgs[0] != dep.Reference {
+			if tgs[0] != ref {
 				ref = ref + " (" + tgs[0] + ")"
 			}
 		}
diff --git a/repo/set_reference.go b/repo/set_reference.go
index f5891ac..e4367e3 100644
--- a/repo/set_reference.go
+++ b/repo/set_reference.go
@@ -47,7 +47,7 @@
 					}
 					cache.Lock(key)
 					if err := VcsVersion(dep, cwd); err != nil {
-						msg.Err("Failed to set version on %s to %s: %s\n", dep.Name, dep.Reference, err)
+						msg.Err("Failed to set version on %s to %s: %s\n", dep.Name, dep.Constraint, err)
 
 						// Capture the error while making sure the concurrent
 						// operations don't step on each other.
diff --git a/repo/vcs.go b/repo/vcs.go
index ba84ca2..2f3b0cf 100644
--- a/repo/vcs.go
+++ b/repo/vcs.go
@@ -18,6 +18,7 @@
 	gpath "github.com/Masterminds/glide/path"
 	"github.com/Masterminds/semver"
 	v "github.com/Masterminds/vcs"
+	"github.com/sdboyer/gps"
 )
 
 // VcsUpdate updates to a particular checkout based on the VCS setting.
@@ -25,10 +26,10 @@
 
 	// If the dependency has already been pinned we can skip it. This is a
 	// faster path so we don't need to resolve it again.
-	if dep.Pin != "" {
-		msg.Debug("Dependency %s has already been pinned. Fetching updates skipped.", dep.Name)
-		return nil
-	}
+	//if dep.Pin != "" {
+	//msg.Debug("Dependency %s has already been pinned. Fetching updates skipped.", dep.Name)
+	//return nil
+	//}
 
 	if updated.Check(dep.Name) {
 		msg.Debug("%s was already updated, skipping.", dep.Name)
@@ -83,7 +84,7 @@
 					msg.Err("Unable to update vendored dependency %s.\n", dep.Name)
 					return err
 				}
-				dep.UpdateAsVendored = true
+				//dep.UpdateAsVendored = true
 
 				if err = VcsGet(dep, dest, home, cache, cacheGopath, useGopath); err != nil {
 					msg.Warn("Unable to checkout %s\n", dep.Name)
@@ -132,21 +133,22 @@
 			// and that version is already checked out we can skip updating
 			// which is faster than going out to the Internet to perform
 			// an update.
-			if dep.Reference != "" {
+			if dep.Constraint != nil {
 				version, err := repo.Version()
 				if err != nil {
 					return err
 				}
-				ib, err := isBranch(dep.Reference, repo)
-				if err != nil {
-					return err
+
+				var ib bool
+				if cv, ok := dep.Constraint.(gps.Version); ok {
+					ib = cv.Type() == "branch"
 				}
 
 				// If the current version equals the ref and it's not a
 				// branch it's a tag or commit id so we can skip
 				// performing an update.
-				if version == dep.Reference && !ib {
-					msg.Debug("%s is already set to version %s. Skipping update.", dep.Name, dep.Reference)
+				if version == dep.Constraint.String() && !ib {
+					msg.Debug("%s is already set to version %s. Skipping update.", dep.Name, dep.Constraint)
 					return nil
 				}
 			}
@@ -166,24 +168,24 @@
 
 	// If the dependency has already been pinned we can skip it. This is a
 	// faster path so we don't need to resolve it again.
-	if dep.Pin != "" {
-		msg.Debug("Dependency %s has already been pinned. Setting version skipped.", dep.Name)
-		return nil
-	}
+	//if dep.Pin != "" {
+	//msg.Debug("Dependency %s has already been pinned. Setting version skipped.", dep.Name)
+	//return nil
+	//}
 
 	cwd := filepath.Join(vend, dep.Name)
 
 	// If there is no reference configured there is nothing to set.
-	if dep.Reference == "" {
+	if dep.Constraint == nil {
 		// Before exiting update the pinned version
-		repo, err := dep.GetRepo(cwd)
-		if err != nil {
-			return err
-		}
-		dep.Pin, err = repo.Version()
-		if err != nil {
-			return err
-		}
+		//_, err := dep.GetRepo(cwd)
+		//if err != nil {
+		//return err
+		//}
+		//dep.Pin, err = repo.Version()
+		//if err != nil {
+		//return err
+		//}
 		return nil
 	}
 
@@ -202,7 +204,7 @@
 			return err
 		}
 
-		ver := dep.Reference
+		ver := dep.Constraint.String()
 		// 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.
@@ -250,10 +252,10 @@
 		if err := repo.UpdateVersion(ver); err != nil {
 			return err
 		}
-		dep.Pin, err = repo.Version()
-		if err != nil {
-			return err
-		}
+		//dep.Pin, err = repo.Version()
+		//if err != nil {
+		//return err
+		//}
 	}
 
 	return nil
@@ -306,7 +308,7 @@
 
 				// If there is no reference set on the dep we try to checkout
 				// the default branch.
-				if dep.Reference == "" {
+				if dep.Constraint == nil {
 					db := defaultBranch(repo, home)
 					if db != "" {
 						err = repo.UpdateVersion(db)
@@ -477,32 +479,6 @@
 //
 // FIXME: Should this be moved to the dependency package?
 func filterArchOs(dep *cfg.Dependency) bool {
-	found := false
-	if len(dep.Arch) > 0 {
-		for _, a := range dep.Arch {
-			if a == runtime.GOARCH {
-				found = true
-			}
-		}
-		// If it's not found, it should be filtered out.
-		if !found {
-			return true
-		}
-	}
-
-	found = false
-	if len(dep.Os) > 0 {
-		for _, o := range dep.Os {
-			if o == runtime.GOOS {
-				found = true
-			}
-		}
-		if !found {
-			return true
-		}
-
-	}
-
 	return false
 }
 
diff --git a/repo/vendored_cleanup.go b/repo/vendored_cleanup.go
index acbab91..1db6de9 100644
--- a/repo/vendored_cleanup.go
+++ b/repo/vendored_cleanup.go
@@ -20,23 +20,22 @@
 	}
 
 	for _, dep := range conf.Imports {
-		if dep.UpdateAsVendored == true {
-			msg.Info("Cleaning up vendored package %s\n", dep.Name)
+		//if dep.UpdateAsVendored == true {
+		msg.Info("Cleaning up vendored package %s\n", dep.Name)
 
-			// Remove the VCS directory
-			cwd := filepath.Join(vend, dep.Name)
-			repo, err := dep.GetRepo(cwd)
-			if err != nil {
-				msg.Err("Error cleaning up %s:%s", dep.Name, err)
-				continue
-			}
-			t := repo.Vcs()
-			err = os.RemoveAll(cwd + string(os.PathSeparator) + "." + string(t))
-			if err != nil {
-				msg.Err("Error cleaning up VCS dir for %s:%s", dep.Name, err)
-			}
+		// Remove the VCS directory
+		cwd := filepath.Join(vend, dep.Name)
+		repo, err := dep.GetRepo(cwd)
+		if err != nil {
+			msg.Err("Error cleaning up %s:%s", dep.Name, err)
+			continue
 		}
-
+		t := repo.Vcs()
+		err = os.RemoveAll(cwd + string(os.PathSeparator) + "." + string(t))
+		if err != nil {
+			msg.Err("Error cleaning up VCS dir for %s:%s", dep.Name, err)
+		}
+		//}
 	}
 
 	return nil
diff --git a/vendor/github.com/sdboyer/gps/constraints.go b/vendor/github.com/sdboyer/gps/constraints.go
index affde86..794100e 100644
--- a/vendor/github.com/sdboyer/gps/constraints.go
+++ b/vendor/github.com/sdboyer/gps/constraints.go
@@ -46,6 +46,11 @@
 	if err != nil {
 		return nil, err
 	}
+	// If we got a simple semver.Version, simplify by returning our
+	// corresponding type
+	if sv, ok := c.(*semver.Version); ok {
+		return semVersion{sv: sv}, nil
+	}
 	return semverConstraint{c: c}, nil
 }