diff --git a/cmd/dep/ensure.go b/cmd/dep/ensure.go index 3eabb3482e..9a76fae748 100644 --- a/cmd/dep/ensure.go +++ b/cmd/dep/ensure.go @@ -144,8 +144,18 @@ 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) diff --git a/internal/gps/solve_failures.go b/internal/gps/solve_failures.go index e6a2c47a85..43f1ef4864 100644 --- a/internal/gps/solve_failures.go +++ b/internal/gps/solve_failures.go @@ -239,6 +239,13 @@ func (e badOptsFailure) Error() string { return string(e) } +// DeductionFailureErrs maps package import path to errors occurring during deduction. +type DeductionFailureErrs map[string]error + +func (e DeductionFailureErrs) Error() string { + return fmt.Sprintf("%v", e) +} + type sourceMismatchFailure struct { // The ProjectRoot over which there is disagreement about where it should be // sourced from diff --git a/internal/gps/solver.go b/internal/gps/solver.go index 06e6e9afa6..96994476ac 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" @@ -289,6 +290,28 @@ func Prepare(params SolveParameters, sm SourceManager) (Solver, error) { 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 {