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

Commit 8652f55

Browse files
committed
dep: Make noverify preserve excess vendor paths
This helps handle the not-uncommon case that you might need a metadata file or two in your vendor directory, and you want dep to ignore its existence.
1 parent affb4f6 commit 8652f55

File tree

4 files changed

+79
-42
lines changed

4 files changed

+79
-42
lines changed

cmd/dep/check.go

+35-14
Original file line numberDiff line numberDiff line change
@@ -141,62 +141,83 @@ func (cmd *checkCommand) Run(ctx *dep.Ctx, args []string) error {
141141
noverify[skip] = true
142142
}
143143

144-
var vendorfail bool
144+
var vendorfail, hasnoverify bool
145145
// One full pass through, to see if we need to print the header, and to
146146
// create an array of names to sort for deterministic output.
147147
var ordered []string
148148
for path, status := range statuses {
149149
ordered = append(ordered, path)
150150

151151
switch status {
152-
case verify.DigestMismatchInLock, verify.HashVersionMismatch, verify.EmptyDigestInLock:
153-
// NoVerify applies only to these three cases.
152+
case verify.DigestMismatchInLock, verify.HashVersionMismatch, verify.EmptyDigestInLock, verify.NotInLock:
154153
if noverify[path] {
154+
hasnoverify = true
155155
continue
156156
}
157157
fallthrough
158-
case verify.NotInTree, verify.NotInLock:
158+
case verify.NotInTree:
159+
// NoVerify cannot be used to make dep check ignore the absence
160+
// of a project entirely.
161+
if noverify[path] {
162+
delete(noverify, path)
163+
}
164+
159165
fail = true
160166
if !vendorfail {
161167
vendorfail = true
162-
logger.Println("# vendor is out of sync:")
163168
}
164-
165169
}
166170
}
167171
sort.Strings(ordered)
168172

173+
var vfbuf, novbuf bytes.Buffer
174+
var bufptr *bytes.Buffer
175+
176+
fmt.Fprintf(&vfbuf, "# vendor is out of sync:\n")
177+
fmt.Fprintf(&novbuf, "# out of sync, but ignored, due to noverify in Gopkg.toml:\n")
178+
169179
for _, pr := range ordered {
170-
var nvSuffix string
171180
if noverify[pr] {
172-
nvSuffix = " (CHECK IGNORED: marked noverify in Gopkg.toml)"
181+
bufptr = &novbuf
182+
} else {
183+
bufptr = &vfbuf
173184
}
174185

175186
status := statuses[pr]
176187
switch status {
177188
case verify.NotInTree:
178-
logger.Printf("%s: missing from vendor\n", pr)
189+
fmt.Fprintf(bufptr, "%s: missing from vendor\n", pr)
179190
case verify.NotInLock:
180191
fi, err := os.Stat(filepath.Join(p.AbsRoot, "vendor", pr))
181192
if err != nil {
182193
return errors.Wrap(err, "could not stat file that VerifyVendor claimed existed")
183194
}
184195
if fi.IsDir() {
185-
logger.Printf("%s: unused project\n", pr)
196+
fmt.Fprintf(bufptr, "%s: unused project\n", pr)
186197
} else {
187-
logger.Printf("%s: orphaned file\n", pr)
198+
fmt.Fprintf(bufptr, "%s: orphaned file\n", pr)
188199
}
189200
case verify.DigestMismatchInLock:
190-
logger.Printf("%s: hash of vendored tree not equal to digest in Gopkg.lock%s\n", pr, nvSuffix)
201+
fmt.Fprintf(bufptr, "%s: hash of vendored tree not equal to digest in Gopkg.lock\n", pr)
191202
case verify.EmptyDigestInLock:
192-
logger.Printf("%s: no digest in Gopkg.lock to compare against hash of vendored tree%s\n", pr, nvSuffix)
203+
fmt.Fprintf(bufptr, "%s: no digest in Gopkg.lock to compare against hash of vendored tree\n", pr)
193204
case verify.HashVersionMismatch:
194205
// This will double-print if the hash version is zero, but
195206
// that's a rare case that really only occurs before the first
196207
// run with a version of dep >=0.5.0, so it's fine.
197-
logger.Printf("%s: hash algorithm mismatch, want version %v%s\n", pr, verify.HashVersion, nvSuffix)
208+
fmt.Fprintf(bufptr, "%s: hash algorithm mismatch, want version %v\n", pr, verify.HashVersion)
198209
}
199210
}
211+
212+
if vendorfail {
213+
logger.Print(vfbuf.String())
214+
if hasnoverify {
215+
logger.Println()
216+
}
217+
}
218+
if hasnoverify {
219+
logger.Print(novbuf.String())
220+
}
200221
}
201222

202223
if fail {
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
github.com/sdboyer/deptest: hash of vendored tree not equal to digest in Gopkg.lock (CHECK IGNORED: marked noverify in Gopkg.toml)
1+
# out of sync, but ignored, due to noverify in Gopkg.toml:
2+
github.com/sdboyer/deptest: hash of vendored tree not equal to digest in Gopkg.lock
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
github.com/sdboyer/deptest: hash algorithm mismatch, want version 1 (CHECK IGNORED: marked noverify in Gopkg.toml)
1+
# out of sync, but ignored, due to noverify in Gopkg.toml:
2+
github.com/sdboyer/deptest: hash algorithm mismatch, want version 1

txn_writer.go

+40-26
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ const (
432432
missingFromTree
433433
projectAdded
434434
projectRemoved
435+
pathPreserved
435436
)
436437

437438
// NewDeltaWriter prepares a vendor writer that will construct a vendor
@@ -510,17 +511,26 @@ func NewDeltaWriter(p *Project, newLock *Lock, behavior VendorBehavior) (TreeWri
510511
// We don't validate this field elsewhere as it can be difficult to know
511512
// at the beginning of a dep ensure command whether or not the noverify
512513
// project actually will exist as part of the Lock by the end of the
513-
// run. So, only apply if it's in the lockdiff, and isn't a removal.
514+
// run. So, only apply if it's in the lockdiff.
514515
if _, has := dw.lockDiff.ProjectDeltas[pr]; has {
515-
if typ, has := dw.changed[pr]; has && typ < noVerify {
516-
// Avoid writing noverify projects at all for the lower change
517-
// types.
518-
delete(dw.changed, pr)
519-
520-
// Uncomment this if we want to switch to the safer behavior,
521-
// where we ALWAYS write noverify projects.
522-
//dw.changed[pr] = noVerify
516+
if typ, has := dw.changed[pr]; has {
517+
if typ < noVerify {
518+
// Avoid writing noverify projects at all for the lower change
519+
// types.
520+
delete(dw.changed, pr)
521+
522+
// Uncomment this if we want to switch to the safer behavior,
523+
// where we ALWAYS write noverify projects.
524+
//dw.changed[pr] = noVerify
525+
} else if typ == projectRemoved {
526+
// noverify can also be used to preserve files that would
527+
// otherwise be removed.
528+
dw.changed[pr] = pathPreserved
529+
}
523530
}
531+
// It's also allowed to preserve entirely unknown paths using noverify.
532+
} else if _, has := status[spr]; has {
533+
dw.changed[pr] = pathPreserved
524534
}
525535
}
526536

@@ -564,29 +574,28 @@ func (dw *DeltaWriter) Write(path string, sm gps.SourceManager, examples bool, l
564574
projs[lp.Ident().ProjectRoot] = lp
565575
}
566576

567-
dropped := []gps.ProjectRoot{}
577+
var dropped, preserved []gps.ProjectRoot
568578
i := 0
569579
tot := len(dw.changed)
570-
if len(dw.changed) > 0 {
571-
logger.Println("# Bringing vendor into sync")
580+
for _, reason := range dw.changed {
581+
if reason != pathPreserved {
582+
logger.Println("# Bringing vendor into sync")
583+
break
584+
}
572585
}
586+
573587
for pr, reason := range dw.changed {
574-
if reason == projectRemoved {
588+
switch reason {
589+
case projectRemoved:
575590
dropped = append(dropped, pr)
576591
continue
592+
case pathPreserved:
593+
preserved = append(preserved, pr)
594+
continue
577595
}
578596

579597
to := filepath.FromSlash(filepath.Join(vnewpath, string(pr)))
580-
proj, has := projs[pr]
581-
if !has {
582-
// This shouldn't be reachable, but it's preferable to print an
583-
// error and continue rather than panic. https://github.com/golang/dep/issues/1945
584-
// TODO(sdboyer) remove this once we've increased confidence around
585-
// this case.
586-
fmt.Fprintf(os.Stderr, "Internal error - %s had change code %v but was not in new Gopkg.lock. Re-running dep ensure should fix this. Please file a bug at https://github.com/golang/dep/issues/new!\n", pr, reason)
587-
continue
588-
}
589-
po := proj.(verify.VerifiableProject).PruneOpts
598+
po := projs[pr].(verify.VerifiableProject).PruneOpts
590599
if err := sm.ExportPrunedProject(context.TODO(), projs[pr], po, to); err != nil {
591600
return errors.Wrapf(err, "failed to export %s", pr)
592601
}
@@ -666,13 +675,18 @@ func (dw *DeltaWriter) Write(path string, sm gps.SourceManager, examples bool, l
666675
}
667676
}
668677

669-
// Ensure vendor/.git is preserved if present
678+
// Special case: ensure vendor/.git is preserved if present
670679
if hasDotGit(vpath) {
671-
err = fs.RenameWithFallback(filepath.Join(vpath, ".git"), filepath.Join(vnewpath, ".git"))
680+
preserved = append(preserved, ".git")
681+
}
682+
683+
for _, path := range preserved {
684+
err = fs.RenameWithFallback(filepath.Join(vpath, string(path)), filepath.Join(vnewpath, string(path)))
672685
if err != nil {
673-
return errors.Wrap(err, "failed to preserve vendor/.git")
686+
return errors.Wrapf(err, "failed to preserve vendor/%s", path)
674687
}
675688
}
689+
676690
err = os.RemoveAll(vpath)
677691
if err != nil {
678692
return errors.Wrap(err, "failed to remove original vendor directory")

0 commit comments

Comments
 (0)