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

Commit df2c26b

Browse files
committed
dep: Get DeltaWriter into a working state
This encompasses the first pass at the new, more abstracted diffing system, and the DeltaWriter implementation on top of it. Tests are needed, but cursory testing indicates that we successfully capture all types of diffs and regenerate only the subset of projects that actually need to be touched.
1 parent 0b2482d commit df2c26b

23 files changed

+574
-233
lines changed

Gopkg.lock

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

cmd/dep/ensure.go

+59-64
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package main
66

77
import (
8-
"bytes"
98
"context"
109
"flag"
1110
"fmt"
@@ -21,6 +20,7 @@ import (
2120
"github.com/golang/dep/gps"
2221
"github.com/golang/dep/gps/paths"
2322
"github.com/golang/dep/gps/pkgtree"
23+
"github.com/golang/dep/gps/verify"
2424
"github.com/pkg/errors"
2525
)
2626

@@ -184,6 +184,33 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error {
184184
return cmd.runVendorOnly(ctx, args, p, sm, params)
185185
}
186186

187+
statchan := make(chan map[string]verify.VendorStatus)
188+
var lps []gps.LockedProject
189+
if p.Lock != nil {
190+
lps = p.Lock.Projects()
191+
}
192+
go func(vendorDir string, p []gps.LockedProject) {
193+
// Make sure vendor dir exists
194+
err := os.MkdirAll(vendorDir, os.FileMode(0777))
195+
if err != nil {
196+
ctx.Err.Printf("Error creating vendor directory: %q", err.Error())
197+
// TODO(sdboyer) handle these better
198+
os.Exit(1)
199+
}
200+
201+
sums := make(map[string]verify.VersionedDigest)
202+
for _, lp := range p {
203+
sums[string(lp.Ident().ProjectRoot)] = lp.(verify.VerifiableProject).Digest
204+
}
205+
206+
status, err := verify.VerifyDepTree(vendorDir, sums)
207+
if err != nil {
208+
ctx.Err.Printf("Error while verifying vendor directory: %q", err.Error())
209+
os.Exit(1)
210+
}
211+
statchan <- status
212+
}(filepath.Join(p.AbsRoot, "vendor"), lps)
213+
187214
params.RootPackageTree, err = p.ParseRootPackageTree()
188215
if err != nil {
189216
return err
@@ -212,11 +239,11 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error {
212239
}
213240

214241
if cmd.add {
215-
return cmd.runAdd(ctx, args, p, sm, params)
242+
return cmd.runAdd(ctx, args, p, sm, params, statchan)
216243
} else if cmd.update {
217-
return cmd.runUpdate(ctx, args, p, sm, params)
244+
return cmd.runUpdate(ctx, args, p, sm, params, statchan)
218245
}
219-
return cmd.runDefault(ctx, args, p, sm, params)
246+
return cmd.runDefault(ctx, args, p, sm, params, statchan)
220247
}
221248

222249
func (cmd *ensureCommand) validateFlags() error {
@@ -246,7 +273,7 @@ func (cmd *ensureCommand) vendorBehavior() dep.VendorBehavior {
246273
return dep.VendorOnChanged
247274
}
248275

249-
func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error {
276+
func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters, statchan chan map[string]verify.VendorStatus) error {
250277
// Bare ensure doesn't take any args.
251278
if len(args) != 0 {
252279
return errors.New("dep ensure only takes spec arguments with -add or -update")
@@ -256,52 +283,37 @@ func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project
256283
return err
257284
}
258285

259-
if lsat, err := p.LockSatisfiesInputs(sm); err != nil {
260-
return err
261-
} else if !lsat.Passes() {
262-
if ctx.Verbose {
263-
ctx.Out.Printf("%s was already in sync with imports and %s\n", dep.LockName, dep.ManifestName)
264-
}
286+
lock := p.Lock
287+
if lock != nil {
288+
lsat := verify.LockSatisfiesInputs(p.Lock, p.Lock.SolveMeta.InputImports, p.Manifest, params.RootPackageTree)
289+
if !lsat.Passed() {
290+
// TODO(sdboyer) print out what bits are unsatisfied here
291+
solver, err := gps.Prepare(params, sm)
292+
if err != nil {
293+
return errors.Wrap(err, "prepare solver")
294+
}
265295

266-
if cmd.noVendor {
296+
if cmd.noVendor && cmd.dryRun {
297+
return errors.New("Gopkg.lock was not up to date")
298+
}
299+
300+
solution, err := solver.Solve(context.TODO())
301+
if err != nil {
302+
return handleAllTheFailuresOfTheWorld(err)
303+
}
304+
lock = dep.LockFromSolution(solution, p.Manifest.PruneOptions)
305+
} else if cmd.noVendor {
267306
// The user said not to touch vendor/, so definitely nothing to do.
268307
return nil
269308
}
270309

271-
sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, dep.VendorOnChanged, p.Manifest.PruneOptions)
272-
if err != nil {
273-
return err
274-
}
275-
276-
if cmd.dryRun {
277-
return sw.PrintPreparedActions(ctx.Out, ctx.Verbose)
278-
}
279-
280-
var logger *log.Logger
281-
if ctx.Verbose {
282-
logger = ctx.Err
283-
}
284-
return errors.WithMessage(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor")
285310
}
286311

287-
solver, err := gps.Prepare(params, sm)
288-
if err != nil {
289-
return errors.Wrap(err, "prepare solver")
290-
}
291-
292-
if cmd.noVendor && cmd.dryRun {
293-
return errors.New("Gopkg.lock was not up to date")
294-
}
295-
296-
solution, err := solver.Solve(context.TODO())
297-
if err != nil {
298-
return handleAllTheFailuresOfTheWorld(err)
299-
}
300-
301-
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), cmd.vendorBehavior(), p.Manifest.PruneOptions)
312+
sw, err := dep.NewDeltaWriter(p.Lock, lock, <-statchan, p.Manifest.PruneOptions, filepath.Join(p.AbsRoot, "vendor"))
302313
if err != nil {
303314
return err
304315
}
316+
305317
if cmd.dryRun {
306318
return sw.PrintPreparedActions(ctx.Out, ctx.Verbose)
307319
}
@@ -310,7 +322,7 @@ func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project
310322
if ctx.Verbose {
311323
logger = ctx.Err
312324
}
313-
return errors.Wrap(sw.Write(p.AbsRoot, sm, false, logger), "grouped write of manifest, lock and vendor")
325+
return errors.WithMessage(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor")
314326
}
315327

316328
func (cmd *ensureCommand) runVendorOnly(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error {
@@ -339,7 +351,7 @@ func (cmd *ensureCommand) runVendorOnly(ctx *dep.Ctx, args []string, p *dep.Proj
339351
return errors.WithMessage(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor")
340352
}
341353

342-
func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error {
354+
func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters, statchan chan map[string]verify.VendorStatus) error {
343355
if p.Lock == nil {
344356
return errors.Errorf("-update works by updating the versions recorded in %s, but %s does not exist", dep.LockName, dep.LockName)
345357
}
@@ -348,14 +360,6 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
348360
return err
349361
}
350362

351-
// We'll need to discard this prepared solver as later work changes params,
352-
// but solver preparation is cheap and worth doing up front in order to
353-
// perform the fastpath check of hash comparison.
354-
solver, err := gps.Prepare(params, sm)
355-
if err != nil {
356-
return errors.Wrap(err, "fastpath solver prepare")
357-
}
358-
359363
// When -update is specified without args, allow every dependency to change
360364
// versions, regardless of the lock file.
361365
if len(args) == 0 {
@@ -367,7 +371,7 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
367371
}
368372

369373
// Re-prepare a solver now that our params are complete.
370-
solver, err = gps.Prepare(params, sm)
374+
solver, err := gps.Prepare(params, sm)
371375
if err != nil {
372376
return errors.Wrap(err, "fastpath solver prepare")
373377
}
@@ -379,7 +383,7 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
379383
return handleAllTheFailuresOfTheWorld(err)
380384
}
381385

382-
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), cmd.vendorBehavior(), p.Manifest.PruneOptions)
386+
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution, p.Manifest.PruneOptions), cmd.vendorBehavior(), p.Manifest.PruneOptions)
383387
if err != nil {
384388
return err
385389
}
@@ -394,7 +398,7 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
394398
return errors.Wrap(sw.Write(p.AbsRoot, sm, false, logger), "grouped write of manifest, lock and vendor")
395399
}
396400

397-
func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error {
401+
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 {
398402
if len(args) == 0 {
399403
return errors.New("must specify at least one project or package to -add")
400404
}
@@ -411,15 +415,6 @@ func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm
411415
return errors.Wrap(err, "fastpath solver prepare")
412416
}
413417

414-
// Compare the hashes. If they're not equal, bail out and ask the user to
415-
// run a straight `dep ensure` before updating. This is handholding the
416-
// user a bit, but the extra effort required is minimal, and it ensures the
417-
// user is isolating variables in the event of solve problems (was it the
418-
// "pending" changes, or the -add that caused the problem?).
419-
if p.Lock != nil && !bytes.Equal(p.Lock.InputsDigest(), solver.HashInputs()) {
420-
ctx.Out.Printf("Warning: %s is out of sync with %s or the project's imports.", dep.LockName, dep.ManifestName)
421-
}
422-
423418
rm, _ := params.RootPackageTree.ToReachMap(true, true, false, p.Manifest.IgnoredPackages())
424419

425420
// TODO(sdboyer) re-enable this once we ToReachMap() intelligently filters out normally-excluded (_*, .*), dirs from errmap
@@ -678,7 +673,7 @@ func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm
678673
}
679674
sort.Strings(reqlist)
680675

681-
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), dep.VendorOnChanged, p.Manifest.PruneOptions)
676+
sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution, p.Manifest.PruneOptions), dep.VendorOnChanged, p.Manifest.PruneOptions)
682677
if err != nil {
683678
return err
684679
}

cmd/dep/ensure_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ func TestInvalidEnsureFlagCombinations(t *testing.T) {
5050
// anything other than the error being non-nil. For now, it works well
5151
// because a panic will quickly result if the initial arg length validation
5252
// checks are incorrectly handled.
53-
if err := ec.runDefault(nil, []string{"foo"}, nil, nil, gps.SolveParameters{}); err == nil {
53+
if err := ec.runDefault(nil, []string{"foo"}, nil, nil, gps.SolveParameters{}, nil); err == nil {
5454
t.Errorf("no args to plain ensure with -vendor-only")
5555
}
5656
ec.vendorOnly = false
57-
if err := ec.runDefault(nil, []string{"foo"}, nil, nil, gps.SolveParameters{}); err == nil {
57+
if err := ec.runDefault(nil, []string{"foo"}, nil, nil, gps.SolveParameters{}, nil); err == nil {
5858
t.Errorf("no args to plain ensure")
5959
}
6060
}

cmd/dep/init.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
157157
err = handleAllTheFailuresOfTheWorld(err)
158158
return errors.Wrap(err, "init failed: unable to solve the dependency graph")
159159
}
160-
p.Lock = dep.LockFromSolution(soln)
160+
p.Lock = dep.LockFromSolution(soln, p.Manifest.PruneOptions)
161161

162162
rootAnalyzer.FinalizeRootManifestAndLock(p.Manifest, p.Lock, copyLock)
163163

@@ -168,7 +168,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
168168
return errors.Wrap(err, "init failed: unable to recalculate the lock digest")
169169
}
170170

171-
p.Lock.SolveMeta.InputsDigest = s.HashInputs()
171+
//p.Lock.SolveMeta.InputsDigest = s.HashInputs()
172172

173173
// Pass timestamp (yyyyMMddHHmmss format) as suffix to backup name.
174174
vendorbak, err := dep.BackupVendor(filepath.Join(root, "vendor"), time.Now().Format("20060102150405"))

0 commit comments

Comments
 (0)