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