From 8a978e5a53fddeec40eabad00bd21914de1d95e5 Mon Sep 17 00:00:00 2001 From: Sunny Date: Wed, 6 Dec 2017 16:37:16 +0530 Subject: [PATCH] return slice of errors --- cmd/dep/status.go | 28 ++++++----- cmd/dep/status_test.go | 105 +++++++++++++++++++++++------------------ 2 files changed, 76 insertions(+), 57 deletions(-) diff --git a/cmd/dep/status.go b/cmd/dep/status.go index c957b436c6..1d8eaf8156 100644 --- a/cmd/dep/status.go +++ b/cmd/dep/status.go @@ -417,9 +417,11 @@ func runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceMana return false, 0, errors.Wrapf(err, "could not set up solver for input hashing") } - cm, err := collectConstraints(ctx, p, sm) - if err != nil { - return false, 0, err + // Errors while collecting constraints should not fail the whole status run. + // It should count the error and tell the user about incomplete results. + cm, ccerrs := collectConstraints(ctx, p, sm) + if len(ccerrs) > 0 { + errCount += len(ccerrs) } // Get the project list and sort it so that the printed output users see is @@ -569,7 +571,7 @@ func runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceMana // Count ListVersions error because we get partial results when // this happens. - errCount = len(errListVerCh) + errCount += len(errListVerCh) if ctx.Verbose { for err := range errListVerCh { ctx.Err.Println(err.Error()) @@ -687,7 +689,9 @@ type projectConstraint struct { type constraintsCollection map[string][]projectConstraint // collectConstraints collects constraints declared by all the dependencies. -func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (constraintsCollection, error) { +// It returns constraintsCollection and a slice of errors encountered while +// collecting the constraints, if any. +func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (constraintsCollection, []error) { logger := ctx.Err if !ctx.Verbose { logger = log.New(ioutil.Discard, "", 0) @@ -695,10 +699,14 @@ func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (con logger.Println("Collecting project constraints:") + var mutex sync.Mutex + constraintCollection := make(constraintsCollection) + // Get direct deps of the root project. _, directDeps, err := getDirectDependencies(sm, p) if err != nil { - return nil, err + // Return empty collection, not nil, if we fail here. + return constraintCollection, []error{errors.Wrap(err, "failed to get direct dependencies")} } // Create a root analyzer. @@ -706,9 +714,6 @@ func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (con lp := p.Lock.Projects() - var mutex sync.Mutex - constraintCollection := make(constraintsCollection) - // Channel for receiving all the errors. errCh := make(chan error, len(lp)) @@ -753,14 +758,15 @@ func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (con wg.Wait() close(errCh) + var errs []error if len(errCh) > 0 { - err = errors.New("failed to collect constraints") for e := range errCh { + errs = append(errs, e) logger.Println(e.Error()) } } - return constraintCollection, err + return constraintCollection, errs } type byProject []projectConstraint diff --git a/cmd/dep/status_test.go b/cmd/dep/status_test.go index fa5194facd..da6ea65317 100644 --- a/cmd/dep/status_test.go +++ b/cmd/dep/status_test.go @@ -8,6 +8,7 @@ import ( "bytes" "io/ioutil" "log" + "path/filepath" "reflect" "testing" "text/tabwriter" @@ -298,48 +299,50 @@ func TestCollectConstraints(t *testing.T) { ver2, _ := gps.NewSemverConstraintIC("v2.0.0") cases := []struct { - name string - project dep.Project + name string + // project dep.Project + lock dep.Lock wantConstraints constraintsCollection + wantErr bool }{ { name: "without any constraints", - project: dep.Project{ - Lock: &dep.Lock{ - P: []gps.LockedProject{ - gps.NewLockedProject( - gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/sdboyer/deptest")}, - gps.NewVersion("v1.0.0"), - []string{"."}, - ), - }, + // project: dep.Project{ + lock: dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/sdboyer/deptest")}, + gps.NewVersion("v1.0.0"), + []string{"."}, + ), }, }, + // }, wantConstraints: constraintsCollection{}, }, { name: "with multiple constraints", - project: dep.Project{ - Lock: &dep.Lock{ - P: []gps.LockedProject{ - gps.NewLockedProject( - gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/sdboyer/deptest")}, - gps.NewVersion("v1.0.0"), - []string{"."}, - ), - gps.NewLockedProject( - gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-1")}, - gps.NewVersion("v0.1.0"), - []string{"."}, - ), - gps.NewLockedProject( - gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-2")}, - gps.NewBranch("master").Pair(gps.Revision("824a8d56a4c6b2f4718824a98cd6d70d3dbd4c3e")), - []string{"."}, - ), - }, + // project: dep.Project{ + lock: dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/sdboyer/deptest")}, + gps.NewVersion("v1.0.0"), + []string{"."}, + ), + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-1")}, + gps.NewVersion("v0.1.0"), + []string{"."}, + ), + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-2")}, + gps.NewBranch("master").Pair(gps.Revision("824a8d56a4c6b2f4718824a98cd6d70d3dbd4c3e")), + []string{"."}, + ), }, }, + // }, wantConstraints: constraintsCollection{ "github.com/sdboyer/deptestdos": []projectConstraint{ {"github.com/darkowlzz/deptest-project-2", ver2}, @@ -355,27 +358,28 @@ func TestCollectConstraints(t *testing.T) { }, { name: "skip projects with invalid versions", - project: dep.Project{ - Lock: &dep.Lock{ - P: []gps.LockedProject{ - gps.NewLockedProject( - gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-1")}, - gps.NewVersion("v0.1.0"), - []string{"."}, - ), - gps.NewLockedProject( - gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-2")}, - gps.NewVersion("v1.0.0"), - []string{"."}, - ), - }, + // project: dep.Project{ + lock: dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-1")}, + gps.NewVersion("v0.1.0"), + []string{"."}, + ), + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-2")}, + gps.NewVersion("v1.0.0"), + []string{"."}, + ), }, }, + // }, wantConstraints: constraintsCollection{ "github.com/sdboyer/deptest": []projectConstraint{ {"github.com/darkowlzz/deptest-project-1", ver1}, }, }, + wantErr: true, }, } @@ -396,12 +400,21 @@ func TestCollectConstraints(t *testing.T) { h.Must(err) defer sm.Release() + p := new(dep.Project) + p.SetRoot(filepath.Join(pwd, "src")) + for _, c := range cases { t.Run(c.name, func(t *testing.T) { - gotConstraints, _ := collectConstraints(ctx, &c.project, sm) + p.Lock = &c.lock + gotConstraints, err := collectConstraints(ctx, p, sm) + if len(err) > 0 && !c.wantErr { + t.Fatalf("unexpected errors while collecting constraints: %v", err) + } else if len(err) == 0 && c.wantErr { + t.Fatalf("expected errors while collecting constraints, but got none") + } if !reflect.DeepEqual(gotConstraints, c.wantConstraints) { - t.Fatalf("Unexpected collected constraints: \n\t(GOT): %v\n\t(WNT): %v", gotConstraints, c.wantConstraints) + t.Fatalf("unexpected collected constraints: \n\t(GOT): %v\n\t(WNT): %v", gotConstraints, c.wantConstraints) } }) }