From f1d5b483ccbefd8fc4c25c64e3964bc7063bf0ca Mon Sep 17 00:00:00 2001 From: Ibrahim AshShohail Date: Thu, 15 Jun 2017 23:27:38 +0300 Subject: [PATCH] internal/gps: ensure packages are deducible before attempting to solve Add gps.ValidateParams to ensure all packages in SolverParams are deducible. Signed-off-by: Ibrahim AshShohail --- cmd/dep/ensure.go | 12 +++++++ internal/gps/hash_test.go | 3 +- internal/gps/solver.go | 48 ++++++++++++++++++++++++++-- internal/gps/solver_test.go | 62 +++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 internal/gps/solver_test.go diff --git a/cmd/dep/ensure.go b/cmd/dep/ensure.go index dd558b9047..5310cf275e 100644 --- a/cmd/dep/ensure.go +++ b/cmd/dep/ensure.go @@ -142,6 +142,18 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error { } } + err = gps.ValidateParams(params, sm) + if err != nil { + if deduceErrs, ok := err.(gps.DeductionErrs); ok { + ctx.Err.Println("The following errors occurred while deducing packages:") + for ip, dErr := range deduceErrs { + ctx.Err.Printf(" * \"%s\": %s", ip, dErr) + } + ctx.Err.Println() + } + return errors.Wrap(err, "validateParams") + } + solver, err := gps.Prepare(params, sm) if err != nil { return errors.Wrap(err, "ensure Prepare") diff --git a/internal/gps/hash_test.go b/internal/gps/hash_test.go index 220eebae5d..ac2300a6df 100644 --- a/internal/gps/hash_test.go +++ b/internal/gps/hash_test.go @@ -528,7 +528,8 @@ func TestHashInputsOverrides(t *testing.T) { s, err := Prepare(params, newdepspecSM(basefix.ds, nil)) if err != nil { - t.Fatalf("(fix: %q) Unexpected error while prepping solver: %s", fix.name, err) + t.Errorf("(fix: %q) Unexpected error while prepping solver: %s", fix.name, err) + continue } h := sha256.New() diff --git a/internal/gps/solver.go b/internal/gps/solver.go index fd8695fd13..c2354fbc38 100644 --- a/internal/gps/solver.go +++ b/internal/gps/solver.go @@ -10,6 +10,7 @@ import ( "log" "sort" "strings" + "sync" "github.com/armon/go-radix" "github.com/golang/dep/internal/gps/paths" @@ -381,6 +382,50 @@ func (s *solver) Version() int { return 1 } +// DeductionErrs maps package import path to errors occurring during deduction. +type DeductionErrs map[string]error + +func (e DeductionErrs) Error() string { + return "could not deduce external imports' project roots" +} + +// ValidateParams validates the solver parameters to ensure solving can be completed. +func ValidateParams(params SolveParameters, sm SourceManager) error { + // Ensure that all packages are deducible without issues. + var deducePkgsGroup sync.WaitGroup + deductionErrs := make(DeductionErrs) + var errsMut sync.Mutex + + rd, err := params.toRootdata() + if err != nil { + return err + } + + deducePkg := func(ip string, sm SourceManager) { + fmt.Println(ip) + _, err := sm.DeduceProjectRoot(ip) + if err != nil { + errsMut.Lock() + deductionErrs[ip] = err + errsMut.Unlock() + } + deducePkgsGroup.Done() + } + + for _, ip := range rd.externalImportList(paths.IsStandardImportPath) { + deducePkgsGroup.Add(1) + go deducePkg(ip, sm) + } + + deducePkgsGroup.Wait() + + if len(deductionErrs) > 0 { + return deductionErrs + } + + return nil +} + // Solve attempts to find a dependency solution for the given project, as // represented by the SolveParameters with which this Solver was created. // @@ -391,8 +436,7 @@ func (s *solver) Solve() (Solution, error) { s.vUnify.mtr = s.mtr // Prime the queues with the root project - err := s.selectRoot() - if err != nil { + if err := s.selectRoot(); err != nil { return nil, err } diff --git a/internal/gps/solver_test.go b/internal/gps/solver_test.go new file mode 100644 index 0000000000..f0032a154d --- /dev/null +++ b/internal/gps/solver_test.go @@ -0,0 +1,62 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gps + +import ( + "testing" + + "github.com/golang/dep/internal/gps/pkgtree" + "github.com/golang/dep/internal/test" +) + +func TestValidateParams(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + cacheDir := "gps-cache" + h.TempDir(cacheDir) + sm, err := NewSourceManager(h.Path(cacheDir)) + h.Must(err) + defer sm.Release() + + h.TempDir("src") + + testcases := []struct { + imports []string + err bool + }{ + {[]string{"google.com/non-existing/package"}, true}, + {[]string{"google.com/non-existing/package/subpkg"}, true}, + {[]string{"github.com/sdboyer/testrepo"}, false}, + {[]string{"github.com/sdboyer/testrepo/subpkg"}, false}, + } + + params := SolveParameters{ + ProjectAnalyzer: naiveAnalyzer{}, + RootDir: h.Path("src"), + RootPackageTree: pkgtree.PackageTree{ + ImportRoot: "github.com/sdboyer/dep", + }, + } + + for _, tc := range testcases { + params.RootPackageTree.Packages = map[string]pkgtree.PackageOrErr{ + "github.com/sdboyer/dep": { + P: pkgtree.Package{ + Name: "github.com/sdboyer/dep", + ImportPath: "github.com/sdboyer/dep", + Imports: tc.imports, + }, + }, + } + + err = ValidateParams(params, sm) + if tc.err && err == nil { + t.Fatalf("expected an error when deducing package fails, got none") + } else if !tc.err && err != nil { + t.Fatalf("deducing packges should have succeeded, got err: %#v", err) + } + } +}