diff --git a/cmd/dep/ensure.go b/cmd/dep/ensure.go index 9a76fae748..a11b449a0a 100644 --- a/cmd/dep/ensure.go +++ b/cmd/dep/ensure.go @@ -144,21 +144,19 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error { solver, err := gps.Prepare(params, sm) if err != nil { - if deduceErrs, ok := err.(gps.DeductionFailureErrs); ok { - ctx.Loggers.Err.Println("The following errors occurred while deducing packages:") - for ip, error := range deduceErrs { - ctx.Loggers.Err.Printf(" * \"%s\": %s", ip, error) - } - ctx.Loggers.Err.Println() - - return errors.New("could not deduce packages to ensure constraints") - } return errors.Wrap(err, "ensure Prepare") } solution, err := solver.Solve() if err != nil { handleAllTheFailuresOfTheWorld(err) + if deduceErrs, ok := err.(gps.DeductionFailureErrs); ok { + ctx.Loggers.Err.Println("The following errors occurred while deducing packages:") + for ip, dErr := range deduceErrs { + ctx.Loggers.Err.Printf(" * \"%s\": %s", ip, dErr) + } + ctx.Loggers.Err.Println() + } return errors.Wrap(err, "ensure Solve()") } diff --git a/internal/gps/solve_failures.go b/internal/gps/solve_failures.go index 43f1ef4864..b46bf98e73 100644 --- a/internal/gps/solve_failures.go +++ b/internal/gps/solve_failures.go @@ -243,7 +243,7 @@ func (e badOptsFailure) Error() string { type DeductionFailureErrs map[string]error func (e DeductionFailureErrs) Error() string { - return fmt.Sprintf("%v", e) + return "could not deduce packages to ensure constraints are solvable" } type sourceMismatchFailure struct { diff --git a/internal/gps/solver.go b/internal/gps/solver.go index 96994476ac..78b5abbcfb 100644 --- a/internal/gps/solver.go +++ b/internal/gps/solver.go @@ -284,34 +284,17 @@ func Prepare(params SolveParameters, sm SourceManager) (Solver, error) { params.stdLibFn = paths.IsStandardImportPath } + // Validate the solver parameters + if err := validateParams(sm, rd, params.stdLibFn); err != nil { + return nil, err + } + s := &solver{ tl: params.TraceLogger, stdLibFn: params.stdLibFn, rd: rd, } - var deducePkgsGroup sync.WaitGroup - deductionErrs := make(DeductionFailureErrs) - - checkPkg := func(ip string, sm SourceManager) { - _, err := sm.DeduceProjectRoot(ip) - if err != nil { - deductionErrs[ip] = err - } - deducePkgsGroup.Done() - } - - for _, ip := range rd.externalImportList(params.stdLibFn) { - deducePkgsGroup.Add(1) - go checkPkg(ip, sm) - } - - deducePkgsGroup.Wait() - - if len(deductionErrs) > 0 { - return nil, deductionErrs - } - // Set up the bridge and ensure the root dir is in good, working order // before doing anything else. if params.mkBridgeFn == nil { @@ -414,8 +397,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 } @@ -556,6 +538,37 @@ func (s *solver) solve() (map[atom]map[string]struct{}, error) { return projs, nil } +// validateParams validates the solver parameters to ensure solving can be completed. +func validateParams(sm SourceManager, rd rootdata, stdLibFn func(string) bool) error { + // Ensure that all packages are deducible without issues. + var deducePkgsGroup sync.WaitGroup + deductionErrs := make(DeductionFailureErrs) + var errsMut sync.Mutex + + deducePkg := func(ip string, sm SourceManager) { + _, err := sm.DeduceProjectRoot(ip) + if err != nil { + errsMut.Lock() + deductionErrs[ip] = err + errsMut.Unlock() + } + deducePkgsGroup.Done() + } + + for _, ip := range rd.externalImportList(stdLibFn) { + deducePkgsGroup.Add(1) + go deducePkg(ip, sm) + } + + deducePkgsGroup.Wait() + + if len(deductionErrs) > 0 { + return deductionErrs + } + + return nil +} + // selectRoot is a specialized selectAtom, used solely to initially // populate the queues at the beginning of a solve run. func (s *solver) selectRoot() error {