Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit 1dce6b5

Browse files
committed
dep: Tell the user why we're solving
Add output to all of the information we assemble when checking if the Lock satisfies the current input set. Also some refactoring of the ctx.LoadProject() process to have fewer partial states.
1 parent b50a572 commit 1dce6b5

12 files changed

+253
-149
lines changed

Gopkg.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/dep/ensure.go

+30-33
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,6 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error {
211211
statchan <- status
212212
}(filepath.Join(p.AbsRoot, "vendor"), lps)
213213

214-
params.RootPackageTree, err = p.ParseRootPackageTree()
215-
if err != nil {
216-
return err
217-
}
218-
219214
if fatal, err := checkErrors(params.RootPackageTree.Packages, p.Manifest.IgnoredPackages()); err != nil {
220215
if fatal {
221216
return err
@@ -283,20 +278,32 @@ func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project
283278
return err
284279
}
285280

286-
lock := p.Lock
281+
lock := p.ChangedLock
287282
if lock != nil {
288-
lsat := verify.LockSatisfiesInputs(p.Lock, p.Lock.SolveMeta.InputImports, p.Manifest, params.RootPackageTree)
283+
lsat := verify.LockSatisfiesInputs(p.Lock, p.Manifest, params.RootPackageTree)
289284
if !lsat.Passed() {
290-
// TODO(sdboyer) print out what bits are unsatisfied here
285+
if ctx.Verbose {
286+
ctx.Out.Println("Gopkg.lock is out of sync with Gopkg.toml and project code:")
287+
for _, missing := range lsat.MissingImports() {
288+
ctx.Out.Printf("\t%s is missing from input-imports\n", missing)
289+
}
290+
for _, excess := range lsat.ExcessImports() {
291+
ctx.Out.Printf("\t%s is in input-imports, but isn't imported\n", excess)
292+
}
293+
for pr, unmatched := range lsat.UnmatchedOverrides() {
294+
ctx.Out.Printf("\t%s is at %s, which is not allowed by override %s\n", pr, unmatched.V, unmatched.C)
295+
}
296+
for pr, unmatched := range lsat.UnmatchedConstraints() {
297+
ctx.Out.Printf("\t%s is at %s, which is not allowed by constraint %s\n", pr, unmatched.V, unmatched.C)
298+
}
299+
ctx.Out.Println()
300+
}
301+
291302
solver, err := gps.Prepare(params, sm)
292303
if err != nil {
293304
return errors.Wrap(err, "prepare solver")
294305
}
295306

296-
if cmd.noVendor && cmd.dryRun {
297-
return errors.New("Gopkg.lock was not up to date")
298-
}
299-
300307
solution, err := solver.Solve(context.TODO())
301308
if err != nil {
302309
return handleAllTheFailuresOfTheWorld(err)
@@ -306,23 +313,22 @@ func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project
306313
// The user said not to touch vendor/, so definitely nothing to do.
307314
return nil
308315
}
309-
310316
}
311317

312-
sw, err := dep.NewDeltaWriter(p.Lock, lock, <-statchan, p.Manifest.PruneOptions, filepath.Join(p.AbsRoot, "vendor"))
318+
dw, err := dep.NewDeltaWriter(p.Lock, lock, <-statchan, p.Manifest.PruneOptions, filepath.Join(p.AbsRoot, "vendor"))
313319
if err != nil {
314320
return err
315321
}
316322

317323
if cmd.dryRun {
318-
return sw.PrintPreparedActions(ctx.Out, ctx.Verbose)
324+
return dw.PrintPreparedActions(ctx.Out, ctx.Verbose)
319325
}
320326

321327
var logger *log.Logger
322328
if ctx.Verbose {
323329
logger = ctx.Err
324330
}
325-
return errors.WithMessage(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor")
331+
return errors.WithMessage(dw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor")
326332
}
327333

328334
func (cmd *ensureCommand) runVendorOnly(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error {
@@ -333,9 +339,10 @@ func (cmd *ensureCommand) runVendorOnly(ctx *dep.Ctx, args []string, p *dep.Proj
333339
if p.Lock == nil {
334340
return errors.Errorf("no %s exists from which to populate vendor/", dep.LockName)
335341
}
342+
336343
// Pass the same lock as old and new so that the writer will observe no
337344
// difference and choose not to write it out.
338-
sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, dep.VendorAlways, p.Manifest.PruneOptions)
345+
sw, err := dep.NewSafeWriter(nil, p.Lock, p.ChangedLock, dep.VendorAlways, p.Manifest.PruneOptions)
339346
if err != nil {
340347
return err
341348
}
@@ -383,19 +390,19 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
383390
return handleAllTheFailuresOfTheWorld(err)
384391
}
385392

386-
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution, p.Manifest.PruneOptions), cmd.vendorBehavior(), p.Manifest.PruneOptions)
393+
dw, err := dep.NewDeltaWriter(p.Lock, dep.LockFromSolution(solution, p.Manifest.PruneOptions), <-statchan, p.Manifest.PruneOptions, filepath.Join(p.AbsRoot, "vendor"))
387394
if err != nil {
388395
return err
389396
}
390397
if cmd.dryRun {
391-
return sw.PrintPreparedActions(ctx.Out, ctx.Verbose)
398+
return dw.PrintPreparedActions(ctx.Out, ctx.Verbose)
392399
}
393400

394401
var logger *log.Logger
395402
if ctx.Verbose {
396403
logger = ctx.Err
397404
}
398-
return errors.Wrap(sw.Write(p.AbsRoot, sm, false, logger), "grouped write of manifest, lock and vendor")
405+
return errors.Wrap(dw.Write(p.AbsRoot, sm, false, logger), "grouped write of manifest, lock and vendor")
399406
}
400407

401408
func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters, statchan chan map[string]verify.VendorStatus) error {
@@ -417,16 +424,6 @@ func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm
417424

418425
rm, _ := params.RootPackageTree.ToReachMap(true, true, false, p.Manifest.IgnoredPackages())
419426

420-
// TODO(sdboyer) re-enable this once we ToReachMap() intelligently filters out normally-excluded (_*, .*), dirs from errmap
421-
//rm, errmap := params.RootPackageTree.ToReachMap(true, true, false, p.Manifest.IgnoredPackages())
422-
// Having some problematic internal packages isn't cause for termination,
423-
// but the user needs to be warned.
424-
//for fail, err := range errmap {
425-
//if _, is := err.Err.(*build.NoGoError); !is {
426-
//ctx.Err.Printf("Warning: %s, %s", fail, err)
427-
//}
428-
//}
429-
430427
// Compile unique sets of 1) all external packages imported or required, and
431428
// 2) the project roots under which they fall.
432429
exmap := make(map[string]bool)
@@ -673,20 +670,20 @@ func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm
673670
}
674671
sort.Strings(reqlist)
675672

676-
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution, p.Manifest.PruneOptions), dep.VendorOnChanged, p.Manifest.PruneOptions)
673+
dw, err := dep.NewDeltaWriter(p.Lock, dep.LockFromSolution(solution, p.Manifest.PruneOptions), <-statchan, p.Manifest.PruneOptions, filepath.Join(p.AbsRoot, "vendor"))
677674
if err != nil {
678675
return err
679676
}
680677

681678
if cmd.dryRun {
682-
return sw.PrintPreparedActions(ctx.Out, ctx.Verbose)
679+
return dw.PrintPreparedActions(ctx.Out, ctx.Verbose)
683680
}
684681

685682
var logger *log.Logger
686683
if ctx.Verbose {
687684
logger = ctx.Err
688685
}
689-
if err := errors.Wrap(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor"); err != nil {
686+
if err := errors.Wrap(dw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor"); err != nil {
690687
return err
691688
}
692689

cmd/dep/init.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,12 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
102102
ctx.Out.Println("Getting direct dependencies...")
103103
}
104104

105-
ptree, directDeps, err := p.GetDirectDependencyNames(sm)
105+
directDeps, err := p.GetDirectDependencyNames(sm)
106106
if err != nil {
107107
return errors.Wrap(err, "init failed: unable to determine direct dependencies")
108108
}
109109
if ctx.Verbose {
110-
ctx.Out.Printf("Checked %d directories for packages.\nFound %d direct dependencies.\n", len(ptree.Packages), len(directDeps))
110+
ctx.Out.Printf("Checked %d directories for packages.\nFound %d direct dependencies.\n", len(p.RootPackageTree.Packages), len(directDeps))
111111
}
112112

113113
// Initialize with imported data, then fill in the gaps using the GOPATH
@@ -133,7 +133,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
133133

134134
params := gps.SolveParameters{
135135
RootDir: root,
136-
RootPackageTree: ptree,
136+
RootPackageTree: p.RootPackageTree,
137137
Manifest: p.Manifest,
138138
Lock: p.Lock,
139139
ProjectAnalyzer: rootAnalyzer,

cmd/dep/status.go

+6-12
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,13 @@ type dotOutput struct {
250250
func (out *dotOutput) BasicHeader() error {
251251
out.g = new(graphviz).New()
252252

253-
ptree, err := out.p.ParseRootPackageTree()
253+
ptree := out.p.RootPackageTree
254254
// TODO(sdboyer) should be true, true, false, out.p.Manifest.IgnoredPackages()
255255
prm, _ := ptree.ToReachMap(true, false, false, nil)
256256

257257
out.g.createNode(string(out.p.ImportRoot), "", prm.FlattenFn(paths.IsStandardImportPath))
258258

259-
return err
259+
return nil
260260
}
261261

262262
func (out *dotOutput) BasicFooter() error {
@@ -491,10 +491,7 @@ func (os OldStatus) marshalJSON() *rawOldStatus {
491491
func (cmd *statusCommand) runOld(ctx *dep.Ctx, out oldOutputter, p *dep.Project, sm gps.SourceManager) error {
492492
// While the network churns on ListVersions() requests, statically analyze
493493
// code from the current project.
494-
ptree, err := p.ParseRootPackageTree()
495-
if err != nil {
496-
return err
497-
}
494+
ptree := p.RootPackageTree
498495

499496
// Set up a solver in order to check the InputHash.
500497
params := gps.SolveParameters{
@@ -662,10 +659,7 @@ type MissingStatus struct {
662659
func runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceManager) (hasMissingPkgs bool, errCount int, err error) {
663660
// While the network churns on ListVersions() requests, statically analyze
664661
// code from the current project.
665-
ptree, err := p.ParseRootPackageTree()
666-
if err != nil {
667-
return false, 0, err
668-
}
662+
ptree := p.RootPackageTree
669663

670664
// Set up a solver in order to check the InputHash.
671665
params := gps.SolveParameters{
@@ -702,7 +696,7 @@ func runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceMana
702696
return slp[i].Ident().Less(slp[j].Ident())
703697
})
704698

705-
lsat := verify.LockSatisfiesInputs(p.Lock, p.Lock.SolveMeta.InputImports, p.Manifest, params.RootPackageTree)
699+
lsat := verify.LockSatisfiesInputs(p.Lock, p.Manifest, params.RootPackageTree)
706700
if lsat.Passed() {
707701
// If these are equal, we're guaranteed that the lock is a transitively
708702
// complete picture of all deps. That eliminates the need for at least
@@ -997,7 +991,7 @@ func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (con
997991

998992
// Collect the complete set of direct project dependencies, incorporating
999993
// requireds and ignores appropriately.
1000-
_, directDeps, err := p.GetDirectDependencyNames(sm)
994+
directDeps, err := p.GetDirectDependencyNames(sm)
1001995
if err != nil {
1002996
// Return empty collection, not nil, if we fail here.
1003997
return constraintCollection, []error{errors.Wrap(err, "failed to get direct dependencies")}

context.go

+50
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ import (
99
"os"
1010
"path/filepath"
1111
"runtime"
12+
"sort"
1213
"time"
1314

1415
"github.com/golang/dep/gps"
16+
"github.com/golang/dep/gps/paths"
17+
"github.com/golang/dep/gps/pkgtree"
18+
"github.com/golang/dep/gps/verify"
1519
"github.com/golang/dep/internal/fs"
1620
"github.com/pkg/errors"
1721
)
@@ -181,9 +185,55 @@ func (c *Ctx) LoadProject() (*Project, error) {
181185
return nil, errors.Wrapf(err, "error while parsing %s", lp)
182186
}
183187

188+
// Parse in the root package tree.
189+
ptree, err := p.parseRootPackageTree()
190+
if err != nil {
191+
return nil, err
192+
}
193+
194+
// If there's a current Lock, apply the input and pruneopt changes that we
195+
// can know without solving.
196+
if p.Lock != nil {
197+
p.ChangedLock = p.Lock.dup()
198+
p.ChangedLock.SolveMeta.InputImports = externalImportList(ptree, p.Manifest)
199+
200+
for k, lp := range p.ChangedLock.Projects() {
201+
vp := lp.(verify.VerifiableProject)
202+
vp.PruneOpts = p.Manifest.PruneOptions.PruneOptionsFor(lp.Ident().ProjectRoot)
203+
p.ChangedLock.P[k] = vp
204+
}
205+
}
206+
184207
return p, nil
185208
}
186209

210+
func externalImportList(rpt pkgtree.PackageTree, m gps.RootManifest) []string {
211+
rm, _ := rpt.ToReachMap(true, true, false, m.IgnoredPackages())
212+
reach := rm.FlattenFn(paths.IsStandardImportPath)
213+
req := m.RequiredPackages()
214+
215+
// If there are any requires, slide them into the reach list, as well.
216+
if len(req) > 0 {
217+
// Make a map of imports that are both in the import path list and the
218+
// required list to avoid duplication.
219+
skip := make(map[string]bool, len(req))
220+
for _, r := range reach {
221+
if req[r] {
222+
skip[r] = true
223+
}
224+
}
225+
226+
for r := range req {
227+
if !skip[r] {
228+
reach = append(reach, r)
229+
}
230+
}
231+
}
232+
233+
sort.Strings(reach)
234+
return reach
235+
}
236+
187237
// DetectProjectGOPATH attempt to find the GOPATH containing the project.
188238
//
189239
// If p.AbsRoot is not a symlink and is within a GOPATH, the GOPATH containing p.AbsRoot is returned.

gps/verify/digest.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,9 @@ func VerifyDepTree(osDirname string, wantDigests map[string]VersionedDigest) (ma
461461
if expectedSum, ok := wantDigests[slashPathname]; ok {
462462
ls := EmptyDigestInLock
463463
if expectedSum.HashVersion != HashVersion {
464-
ls = HashVersionMismatch
464+
if !expectedSum.IsEmpty() {
465+
ls = HashVersionMismatch
466+
}
465467
} else if len(expectedSum.Digest) > 0 {
466468
projectSum, err := DigestFromDirectory(osPathname)
467469
if err != nil {

0 commit comments

Comments
 (0)