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) {