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
}