Merge pull request #312 from thockin/dont-double-print-setversion-failure

Don't double-print SetVersion() failure
diff --git a/action/get.go b/action/get.go
index 22e0652..b1c0a46 100644
--- a/action/get.go
+++ b/action/get.go
@@ -26,8 +26,11 @@
 	}
 
 	// Add the packages to the config.
-	if err := addPkgsToConfig(conf, names, insecure); err != nil {
+	if count, err := addPkgsToConfig(conf, names, insecure); err != nil {
 		msg.Die("Failed to get new packages: %s", err)
+	} else if count == 0 {
+		msg.Warn("Nothing to do")
+		return
 	}
 
 	// Fetch the new packages. Can't resolve versions via installer.Update if
@@ -96,10 +99,11 @@
 // - separates repo from packages
 // - sets up insecure repo URLs where necessary
 // - generates a list of subpackages
-func addPkgsToConfig(conf *cfg.Config, names []string, insecure bool) error {
+func addPkgsToConfig(conf *cfg.Config, names []string, insecure bool) (int, error) {
 
 	msg.Info("Preparing to install %d package.", len(names))
 
+	numAdded := 0
 	for _, name := range names {
 		var version string
 		parts := strings.Split(name, "#")
@@ -110,7 +114,7 @@
 
 		root, subpkg := util.NormalizeName(name)
 		if len(root) == 0 {
-			return fmt.Errorf("Package name is required for %q.", name)
+			return 0, fmt.Errorf("Package name is required for %q.", name)
 		}
 
 		if conf.HasDependency(root) {
@@ -123,6 +127,7 @@
 				} else {
 					dep.Subpackages = append(dep.Subpackages, subpkg)
 					msg.Info("Adding sub-package %s to existing import %s", subpkg, root)
+					numAdded++
 				}
 			} else {
 				msg.Warn("Package %q is already in glide.yaml. Skipping", root)
@@ -160,6 +165,7 @@
 		}
 
 		conf.Imports = append(conf.Imports, dep)
+		numAdded++
 	}
-	return nil
+	return numAdded, nil
 }
diff --git a/dependency/resolver.go b/dependency/resolver.go
index 1d40cfa..6c00a41 100644
--- a/dependency/resolver.go
+++ b/dependency/resolver.go
@@ -460,7 +460,6 @@
 					} else {
 						msg.Warn("Error updating %s: %s", imp, err)
 					}
-					r.VersionHandler.SetVersion(imp)
 				}
 			case LocUnknown:
 				msg.Debug("Missing %s. Trying to resolve.", imp)
@@ -498,6 +497,12 @@
 		t := r.stripv(e.Value.(string))
 		root, sp := util.NormalizeName(t)
 
+		// Skip ignored packages
+		if r.Config.HasIgnore(e.Value.(string)) {
+			msg.Info("Ignoring: %s", e.Value.(string))
+			continue
+		}
+
 		// TODO(mattfarina): Need to eventually support devImport
 		existing := r.Config.Imports.Get(root)
 		if existing != nil {
diff --git a/glide.go b/glide.go
index 301c165..26dc1b5 100644
--- a/glide.go
+++ b/glide.go
@@ -219,14 +219,13 @@
 					msg.Warn("Only resolving dependencies for the current OS/Arch")
 				}
 
-				inst := &repo.Installer{
-					Force:           c.Bool("force"),
-					UseCache:        c.Bool("cache"),
-					UseGopath:       c.Bool("use-gopath"),
-					UseCacheGopath:  c.Bool("cache-gopath"),
-					UpdateVendored:  c.Bool("update-vendored"),
-					ResolveAllFiles: c.Bool("all-dependencies"),
-				}
+				inst := repo.NewInstaller()
+				inst.Force = c.Bool("force")
+				inst.UseCache = c.Bool("cache")
+				inst.UseGopath = c.Bool("use-gopath")
+				inst.UseCacheGopath = c.Bool("cache-gopath")
+				inst.UpdateVendored = c.Bool("update-vendored")
+				inst.ResolveAllFiles = c.Bool("all-dependencies")
 				packages := []string(c.Args())
 				insecure := c.Bool("insecure")
 				action.Get(packages, inst, insecure, c.Bool("no-recursive"))
@@ -259,10 +258,8 @@
 					// FIXME: Implement this in the installer.
 					fmt.Println("Delete is not currently implemented.")
 				}
-
-				inst := &repo.Installer{
-					Force: c.Bool("force"),
-				}
+				inst := repo.NewInstaller()
+				inst.Force = c.Bool("force")
 				packages := []string(c.Args())
 				action.Remove(packages, inst)
 			},
@@ -396,15 +393,14 @@
 				},
 			},
 			Action: func(c *cli.Context) {
-				installer := &repo.Installer{
-					DeleteUnused:   c.Bool("deleteOptIn"),
-					UpdateVendored: c.Bool("update-vendored"),
-					Force:          c.Bool("force"),
-					UseCache:       c.Bool("cache"),
-					UseCacheGopath: c.Bool("cache-gopath"),
-					UseGopath:      c.Bool("use-gopath"),
-					Home:           gpath.Home(),
-				}
+				installer := repo.NewInstaller()
+				installer.Force = c.Bool("force")
+				installer.UseCache = c.Bool("cache")
+				installer.UseGopath = c.Bool("use-gopath")
+				installer.UseCacheGopath = c.Bool("cache-gopath")
+				installer.UpdateVendored = c.Bool("update-vendored")
+				installer.Home = gpath.Home()
+				installer.DeleteUnused = c.Bool("deleteOptIn")
 
 				action.Install(installer)
 			},
@@ -487,16 +483,15 @@
 					msg.Warn("Only resolving dependencies for the current OS/Arch")
 				}
 
-				installer := &repo.Installer{
-					DeleteUnused:    c.Bool("deleteOptIn"),
-					UpdateVendored:  c.Bool("update-vendored"),
-					ResolveAllFiles: c.Bool("all-dependencies"),
-					Force:           c.Bool("force"),
-					UseCache:        c.Bool("cache"),
-					UseCacheGopath:  c.Bool("cache-gopath"),
-					UseGopath:       c.Bool("use-gopath"),
-					Home:            gpath.Home(),
-				}
+				installer := repo.NewInstaller()
+				installer.Force = c.Bool("force")
+				installer.UseCache = c.Bool("cache")
+				installer.UseGopath = c.Bool("use-gopath")
+				installer.UseCacheGopath = c.Bool("cache-gopath")
+				installer.UpdateVendored = c.Bool("update-vendored")
+				installer.ResolveAllFiles = c.Bool("all-dependencies")
+				installer.Home = gpath.Home()
+				installer.DeleteUnused = c.Bool("deleteOptIn")
 
 				action.Update(installer, c.Bool("no-recursive"))
 			},
diff --git a/repo/installer.go b/repo/installer.go
index 1ceaec1..bebc3df 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -47,6 +47,15 @@
 	// of every file of every package, rather than only following imported
 	// packages.
 	ResolveAllFiles bool
+
+	// Updated tracks the packages that have been remotely fetched.
+	Updated *UpdateTracker
+}
+
+func NewInstaller() *Installer {
+	i := &Installer{}
+	i.Updated = NewUpdateTracker()
+	return i
 }
 
 // VendorPath returns the path to the location to put vendor packages
@@ -157,6 +166,7 @@
 		updateVendored: i.UpdateVendored,
 		Config:         conf,
 		Use:            ic,
+		updated:        i.Updated,
 	}
 
 	v := &VersionHandler{
@@ -244,7 +254,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, i.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.
@@ -312,6 +322,7 @@
 	cache, cacheGopath, useGopath, force, updateVendored bool
 	Config                                               *cfg.Config
 	Use                                                  *importCache
+	updated                                              *UpdateTracker
 }
 
 // NotFound attempts to retrieve a package when not found in the local vendor/
@@ -429,7 +440,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.updated); err != nil {
 		return err
 	}
 
diff --git a/repo/tracker.go b/repo/tracker.go
new file mode 100644
index 0000000..c017ffd
--- /dev/null
+++ b/repo/tracker.go
@@ -0,0 +1,42 @@
+package repo
+
+import (
+	"sync"
+)
+
+// UpdateTracker holds a list of all the packages that have been updated from
+// an external source. This is a concurrency safe implementation.
+type UpdateTracker struct {
+	sync.RWMutex
+
+	updated map[string]bool
+}
+
+// NewUpdateTracker creates a new instance of UpdateTracker ready for use.
+func NewUpdateTracker() *UpdateTracker {
+	u := &UpdateTracker{}
+	u.updated = map[string]bool{}
+	return u
+}
+
+// Add adds a name to the list of items being tracked.
+func (u *UpdateTracker) Add(name string) {
+	u.Lock()
+	u.updated[name] = true
+	u.Unlock()
+}
+
+// Check returns if an item is on the list or not.
+func (u *UpdateTracker) Check(name string) bool {
+	u.RLock()
+	_, f := u.updated[name]
+	u.RUnlock()
+	return f
+}
+
+// Remove takes a package off the list
+func (u *UpdateTracker) Remove(name string) {
+	u.Lock()
+	delete(u.updated, name)
+	u.Unlock()
+}
diff --git a/repo/tracker_test.go b/repo/tracker_test.go
new file mode 100644
index 0000000..94150f2
--- /dev/null
+++ b/repo/tracker_test.go
@@ -0,0 +1,23 @@
+package repo
+
+import "testing"
+
+func TestUpdateTracker(t *testing.T) {
+	tr := NewUpdateTracker()
+
+	if f := tr.Check("github.com/foo/bar"); f != false {
+		t.Error("Error, package Check passed on empty tracker")
+	}
+
+	tr.Add("github.com/foo/bar")
+
+	if f := tr.Check("github.com/foo/bar"); f != true {
+		t.Error("Error, failed to add package to tracker")
+	}
+
+	tr.Remove("github.com/foo/bar")
+
+	if f := tr.Check("github.com/foo/bar"); f != false {
+		t.Error("Error, failed to remove package from tracker")
+	}
+}
diff --git a/repo/vcs.go b/repo/vcs.go
index 50e6bb7..5cc0f42 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 *UpdateTracker) 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.Check(dep.Name) {
+		msg.Debug("%s was already updated, skipping.", dep.Name)
+		return nil
+	}
+	updated.Add(dep.Name)
+
 	msg.Info("Fetching updates for %s.\n", dep.Name)
 
 	if filterArchOs(dep) {
@@ -140,7 +146,7 @@
 				// branch it's a tag or commit id so we can skip
 				// performing an update.
 				if version == dep.Reference && !ib {
-					msg.Info("%s is already set to version %s. Skipping update.", dep.Name, dep.Reference)
+					msg.Debug("%s is already set to version %s. Skipping update.", dep.Name, dep.Reference)
 					return nil
 				}
 			}