diff --git a/manifest.go b/manifest.go index f63b67a490..034a82ef07 100644 --- a/manifest.go +++ b/manifest.go @@ -11,6 +11,7 @@ import ( "reflect" "regexp" "sort" + "sync" "github.com/golang/dep/internal/gps" "github.com/pelletier/go-toml" @@ -22,10 +23,11 @@ const ManifestName = "Gopkg.toml" // Errors var ( - errInvalidConstraint = errors.New("\"constraint\" must be a TOML array of tables") - errInvalidOverride = errors.New("\"override\" must be a TOML array of tables") - errInvalidRequired = errors.New("\"required\" must be a TOML list of strings") - errInvalidIgnored = errors.New("\"ignored\" must be a TOML list of strings") + errInvalidConstraint = errors.New("\"constraint\" must be a TOML array of tables") + errInvalidOverride = errors.New("\"override\" must be a TOML array of tables") + errInvalidRequired = errors.New("\"required\" must be a TOML list of strings") + errInvalidIgnored = errors.New("\"ignored\" must be a TOML list of strings") + errInvalidProjectRoot = errors.New("ProjectRoot name validation failed") ) // Manifest holds manifest file data and implements gps.RootManifest. @@ -166,17 +168,37 @@ func ValidateProjectRoots(c *Ctx, m *Manifest, sm gps.SourceManager) error { projectRoots = append(projectRoots, pr) } + // Channel to receive all the errors + errorCh := make(chan error, len(projectRoots)) + + var wg sync.WaitGroup for _, pr := range projectRoots { - origPR, err := sm.DeduceProjectRoot(string(pr)) - if err != nil { - return errors.Wrapf(err, "could not deduce project root for %s", pr) - } - if origPR != pr { - c.Err.Printf("dep: WARNING: the name for %q in Gopkg.toml should be changed to %q", pr, origPR) + wg.Add(1) + go func(pr gps.ProjectRoot) { + defer wg.Done() + origPR, err := sm.DeduceProjectRoot(string(pr)) + if err != nil { + errorCh <- err + } else if origPR != pr { + errorCh <- fmt.Errorf("the name for %q should be changed to %q", pr, origPR) + } + }(pr) + } + + wg.Wait() + close(errorCh) + + var valErr error + if len(errorCh) > 0 { + valErr = errInvalidProjectRoot + c.Err.Printf("The Following issues were found in Gopkg.toml:\n\n") + for err := range errorCh { + c.Err.Println(" ✗", err.Error()) } + c.Err.Println() } - return nil + return valErr } // readManifest returns a Manifest read from r and a slice of validation warnings. diff --git a/manifest_test.go b/manifest_test.go index 227f511558..b751c9561d 100644 --- a/manifest_test.go +++ b/manifest_test.go @@ -380,13 +380,13 @@ func TestValidateProjectRoots(t *testing.T) { cases := []struct { name string manifest Manifest - wantError bool + wantError error wantWarn []string }{ { name: "empty Manifest", manifest: Manifest{}, - wantError: false, + wantError: nil, wantWarn: []string{}, }, { @@ -398,7 +398,7 @@ func TestValidateProjectRoots(t *testing.T) { }, }, }, - wantError: false, + wantError: nil, wantWarn: []string{}, }, { @@ -424,11 +424,11 @@ func TestValidateProjectRoots(t *testing.T) { }, }, }, - wantError: false, + wantError: errInvalidProjectRoot, wantWarn: []string{ - "the name for \"github.com/golang/dep/foo\" in Gopkg.toml should be changed to \"github.com/golang/dep\"", - "the name for \"github.com/golang/mock/bar\" in Gopkg.toml should be changed to \"github.com/golang/mock\"", - "the name for \"github.com/golang/go/xyz\" in Gopkg.toml should be changed to \"github.com/golang/go\"", + "the name for \"github.com/golang/dep/foo\" should be changed to \"github.com/golang/dep\"", + "the name for \"github.com/golang/mock/bar\" should be changed to \"github.com/golang/mock\"", + "the name for \"github.com/golang/go/xyz\" should be changed to \"github.com/golang/go\"", }, }, { @@ -440,7 +440,7 @@ func TestValidateProjectRoots(t *testing.T) { }, }, }, - wantError: true, + wantError: errInvalidProjectRoot, wantWarn: []string{}, }, } @@ -469,14 +469,14 @@ func TestValidateProjectRoots(t *testing.T) { // Empty the buffer for every case stderrOutput.Reset() err := ValidateProjectRoots(ctx, &c.manifest, sm) - if err != nil && !c.wantError { - t.Fatalf("Unexpected error while validating project roots: %q", err) + if err != c.wantError { + t.Fatalf("Unexpected error while validating project roots:\n\t(GOT): %v\n\t(WNT): %v", err, c.wantError) } warnings := stderrOutput.String() for _, warn := range c.wantWarn { if !strings.Contains(warnings, warn) { - t.Fatalf("Expected ValidateProjectRoot warnings to contain: %q", warn) + t.Fatalf("Expected ValidateProjectRoot errors to contain: %q", warn) } } })