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

Commit 6b47f58

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 13ec211 commit 6b47f58

File tree

12 files changed

+253
-149
lines changed

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
@@ -329,13 +329,13 @@ type dotOutput struct {
329329
func (out *dotOutput) BasicHeader() error {
330330
out.g = new(graphviz).New()
331331

332-
ptree, err := out.p.ParseRootPackageTree()
332+
ptree := out.p.RootPackageTree
333333
// TODO(sdboyer) should be true, true, false, out.p.Manifest.IgnoredPackages()
334334
prm, _ := ptree.ToReachMap(true, false, false, nil)
335335

336336
out.g.createNode(string(out.p.ImportRoot), "", prm.FlattenFn(paths.IsStandardImportPath))
337337

338-
return err
338+
return nil
339339
}
340340

341341
func (out *dotOutput) BasicFooter() error {
@@ -649,10 +649,7 @@ func (os OldStatus) marshalJSON() *rawOldStatus {
649649
func (cmd *statusCommand) runOld(ctx *dep.Ctx, out oldOutputter, p *dep.Project, sm gps.SourceManager) error {
650650
// While the network churns on ListVersions() requests, statically analyze
651651
// code from the current project.
652-
ptree, err := p.ParseRootPackageTree()
653-
if err != nil {
654-
return err
655-
}
652+
ptree := p.RootPackageTree
656653

657654
// Set up a solver in order to check the InputHash.
658655
params := gps.SolveParameters{
@@ -888,10 +885,7 @@ type MissingStatus struct {
888885
func (cmd *statusCommand) runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceManager) (hasMissingPkgs bool, errCount int, err error) {
889886
// While the network churns on ListVersions() requests, statically analyze
890887
// code from the current project.
891-
ptree, err := p.ParseRootPackageTree()
892-
if err != nil {
893-
return false, 0, err
894-
}
888+
ptree := p.RootPackageTree
895889

896890
// Set up a solver in order to check the InputHash.
897891
params := gps.SolveParameters{
@@ -928,7 +922,7 @@ func (cmd *statusCommand) runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Proje
928922
return slp[i].Ident().Less(slp[j].Ident())
929923
})
930924

931-
lsat := verify.LockSatisfiesInputs(p.Lock, p.Lock.SolveMeta.InputImports, p.Manifest, params.RootPackageTree)
925+
lsat := verify.LockSatisfiesInputs(p.Lock, p.Manifest, params.RootPackageTree)
932926
if lsat.Passed() {
933927
// If these are equal, we're guaranteed that the lock is a transitively
934928
// complete picture of all deps. That eliminates the need for at least
@@ -1305,7 +1299,7 @@ func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (con
13051299

13061300
// Collect the complete set of direct project dependencies, incorporating
13071301
// requireds and ignores appropriately.
1308-
_, directDeps, err := p.GetDirectDependencyNames(sm)
1302+
directDeps, err := p.GetDirectDependencyNames(sm)
13091303
if err != nil {
13101304
// Return empty collection, not nil, if we fail here.
13111305
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
)
@@ -188,9 +192,55 @@ func (c *Ctx) LoadProject() (*Project, error) {
188192
return nil, errors.Wrapf(err, "error while parsing %s", lp)
189193
}
190194

195+
// Parse in the root package tree.
196+
ptree, err := p.parseRootPackageTree()
197+
if err != nil {
198+
return nil, err
199+
}
200+
201+
// If there's a current Lock, apply the input and pruneopt changes that we
202+
// can know without solving.
203+
if p.Lock != nil {
204+
p.ChangedLock = p.Lock.dup()
205+
p.ChangedLock.SolveMeta.InputImports = externalImportList(ptree, p.Manifest)
206+
207+
for k, lp := range p.ChangedLock.Projects() {
208+
vp := lp.(verify.VerifiableProject)
209+
vp.PruneOpts = p.Manifest.PruneOptions.PruneOptionsFor(lp.Ident().ProjectRoot)
210+
p.ChangedLock.P[k] = vp
211+
}
212+
}
213+
191214
return p, nil
192215
}
193216

217+
func externalImportList(rpt pkgtree.PackageTree, m gps.RootManifest) []string {
218+
rm, _ := rpt.ToReachMap(true, true, false, m.IgnoredPackages())
219+
reach := rm.FlattenFn(paths.IsStandardImportPath)
220+
req := m.RequiredPackages()
221+
222+
// If there are any requires, slide them into the reach list, as well.
223+
if len(req) > 0 {
224+
// Make a map of imports that are both in the import path list and the
225+
// required list to avoid duplication.
226+
skip := make(map[string]bool, len(req))
227+
for _, r := range reach {
228+
if req[r] {
229+
skip[r] = true
230+
}
231+
}
232+
233+
for r := range req {
234+
if !skip[r] {
235+
reach = append(reach, r)
236+
}
237+
}
238+
}
239+
240+
sort.Strings(reach)
241+
return reach
242+
}
243+
194244
// DetectProjectGOPATH attempt to find the GOPATH containing the project.
195245
//
196246
// 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)