Track updated packages to avoid dup work
diff --git a/cfg/config.go b/cfg/config.go
index 88bdc71..9a9bb64 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -48,6 +48,17 @@
// 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:"devimport,omitempty"`
+
+ // Updated tracks which packages have already been updated, so we don't
+ // duplicate work.
+ Updated map[string]bool `yaml:"-"`
+}
+
+// NewConfig allocates a Config structure with all fields properly initialized.
+func NewConfig() *Config {
+ cfg := &Config{}
+ cfg.Updated = map[string]bool{}
+ return cfg
}
// A transitive representation of a dependency for importing and exporting to yaml.
@@ -64,7 +75,7 @@
// ConfigFromYaml returns an instance of Config from YAML
func ConfigFromYaml(yml []byte) (*Config, error) {
- cfg := &Config{}
+ cfg := NewConfig()
err := yaml.Unmarshal([]byte(yml), &cfg)
return cfg, err
}
@@ -156,7 +167,7 @@
// Clone performs a deep clone of the Config instance
func (c *Config) Clone() *Config {
- n := &Config{}
+ n := NewConfig()
n.Name = c.Name
n.Description = c.Description
n.Home = c.Home
@@ -165,6 +176,9 @@
n.Ignore = c.Ignore
n.Imports = c.Imports.Clone()
n.DevImports = c.DevImports.Clone()
+ for k, v := range c.Updated {
+ n.Updated[k] = v
+ }
return n
}
diff --git a/repo/installer.go b/repo/installer.go
index 1ceaec1..74b7532 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -109,8 +109,8 @@
return newConf, nil
}
- ConcurrentUpdate(newConf.Imports, cwd, i)
- ConcurrentUpdate(newConf.DevImports, cwd, i)
+ ConcurrentUpdate(newConf.Imports, cwd, i, conf.Updated)
+ ConcurrentUpdate(newConf.DevImports, cwd, i, conf.Updated)
return newConf, nil
}
@@ -122,12 +122,12 @@
dest := i.VendorPath()
- if err := ConcurrentUpdate(conf.Imports, dest, i); err != nil {
+ if err := ConcurrentUpdate(conf.Imports, dest, i, conf.Updated); err != nil {
return err
}
if useDev {
- return ConcurrentUpdate(conf.DevImports, dest, i)
+ return ConcurrentUpdate(conf.DevImports, dest, i, conf.Updated)
}
return nil
@@ -186,7 +186,7 @@
msg.Warn("dev imports not resolved.")
}
- err = ConcurrentUpdate(conf.Imports, vpath, i)
+ err = ConcurrentUpdate(conf.Imports, vpath, i, conf.Updated)
return err
}
@@ -229,7 +229,7 @@
}
// ConcurrentUpdate takes a list of dependencies and updates in parallel.
-func ConcurrentUpdate(deps []*cfg.Dependency, cwd string, i *Installer) error {
+func ConcurrentUpdate(deps []*cfg.Dependency, cwd string, i *Installer, updated map[string]bool) error {
done := make(chan struct{}, concurrentWorkers)
in := make(chan *cfg.Dependency, concurrentWorkers)
var wg sync.WaitGroup
@@ -244,7 +244,7 @@
select {
case dep := <-ch:
dest := filepath.Join(i.VendorPath(), dep.Name)
- if err := VcsUpdate(dep, dest, i.Home, i.UseCache, i.UseCacheGopath, i.UseGopath, i.Force, i.UpdateVendored); err != nil {
+ if err := VcsUpdate(dep, dest, i.Home, i.UseCache, i.UseCacheGopath, i.UseGopath, i.Force, i.UpdateVendored, updated); err != nil {
msg.Err("Update failed for %s: %s\n", dep.Name, err)
// Capture the error while making sure the concurrent
// operations don't step on each other.
@@ -429,7 +429,7 @@
m.Config.Imports = append(m.Config.Imports, d)
}
- if err := VcsUpdate(d, dest, m.home, m.cache, m.cacheGopath, m.useGopath, m.force, m.updateVendored); err != nil {
+ if err := VcsUpdate(d, dest, m.home, m.cache, m.cacheGopath, m.useGopath, m.force, m.updateVendored, m.Config.Updated); err != nil {
return err
}
diff --git a/repo/vcs.go b/repo/vcs.go
index 257340a..992b883 100644
--- a/repo/vcs.go
+++ b/repo/vcs.go
@@ -21,7 +21,7 @@
)
// VcsUpdate updates to a particular checkout based on the VCS setting.
-func VcsUpdate(dep *cfg.Dependency, dest, home string, cache, cacheGopath, useGopath, force, updateVendored bool) error {
+func VcsUpdate(dep *cfg.Dependency, dest, home string, cache, cacheGopath, useGopath, force, updateVendored bool, updated map[string]bool) error {
// 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.
@@ -30,6 +30,12 @@
return nil
}
+ if updated[dep.Name] {
+ msg.Debug("%s was already updated, skipping.\n", dep.Name)
+ return nil
+ }
+ updated[dep.Name] = true
+
msg.Info("Fetching updates for %s.\n", dep.Name)
if filterArchOs(dep) {