Skip to content

Commit 3aa0948

Browse files
author
Bryan C. Mills
committed
cmd/go: add a '-e' flag to 'mod tidy' and 'mod vendor'
This flag, like the -e flag to 'go list', instructs the command to make a best effort to continue in spite of errors for specific packages. Fixes #26603 Change-Id: I5ee2f50c71870ae8ef3f9b3e5b045474adcca525 Reviewed-on: https://go-review.googlesource.com/c/go/+/255960 Trust: Bryan C. Mills <[email protected]> Trust: Jay Conrod <[email protected]> Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Michael Matloob <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 4e1d812 commit 3aa0948

File tree

9 files changed

+150
-21
lines changed

9 files changed

+150
-21
lines changed

doc/go1.16.html

+7
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ <h4 id="modules">Modules</h4>
6666
TODO: write and link to tutorial or blog post
6767
</p>
6868

69+
<p><!-- golang.org/issue/26603 -->
70+
The <code>go</code> <code>mod</code> <code>vendor</code>
71+
and <code>go</code> <code>mod</code> <code>tidy</code> subcommands now accept
72+
the <code>-e</code> flag, which instructs them to proceed despite errors in
73+
resolving missing packages.
74+
</p>
75+
6976
<h4 id="go-test"><code>go</code> <code>test</code></h4>
7077

7178
<p><!-- golang.org/issue/29062 -->

src/cmd/go/alldocs.go

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

src/cmd/go/internal/load/pkg.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2164,7 +2164,7 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
21642164
loadOpts := modload.PackageOpts{
21652165
ResolveMissingImports: true,
21662166
LoadTests: ModResolveTests,
2167-
AllowErrors: true,
2167+
SilenceErrors: true,
21682168
}
21692169
matches, _ = modload.LoadPackages(ctx, loadOpts, patterns...)
21702170
} else {

src/cmd/go/internal/modcmd/tidy.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
)
1616

1717
var cmdTidy = &base.Command{
18-
UsageLine: "go mod tidy [-v]",
18+
UsageLine: "go mod tidy [-e] [-v]",
1919
Short: "add missing and remove unused modules",
2020
Long: `
2121
Tidy makes sure go.mod matches the source code in the module.
@@ -26,12 +26,18 @@ to go.sum and removes any unnecessary ones.
2626
2727
The -v flag causes tidy to print information about removed modules
2828
to standard error.
29+
30+
The -e flag causes tidy to attempt to proceed despite errors
31+
encountered while loading packages.
2932
`,
33+
Run: runTidy,
3034
}
3135

36+
var tidyE bool // if true, report errors but proceed anyway.
37+
3238
func init() {
33-
cmdTidy.Run = runTidy // break init cycle
3439
cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "")
40+
cmdTidy.Flag.BoolVar(&tidyE, "e", false, "")
3541
base.AddModCommonFlags(&cmdTidy.Flag)
3642
}
3743

@@ -57,8 +63,9 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
5763
Tags: imports.AnyTags(),
5864
ResolveMissingImports: true,
5965
LoadTests: true,
60-
AllowErrors: false, // TODO(#26603): Make this a flag.
66+
AllowErrors: tidyE,
6167
}, "all")
68+
6269
modload.TidyBuildList()
6370
modload.TrimGoSum()
6471
modload.WriteGoMod()

src/cmd/go/internal/modcmd/vendor.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
)
2626

2727
var cmdVendor = &base.Command{
28-
UsageLine: "go mod vendor [-v]",
28+
UsageLine: "go mod vendor [-e] [-v]",
2929
Short: "make vendored copy of dependencies",
3030
Long: `
3131
Vendor resets the main module's vendor directory to include all packages
@@ -34,12 +34,18 @@ It does not include test code for vendored packages.
3434
3535
The -v flag causes vendor to print the names of vendored
3636
modules and packages to standard error.
37+
38+
The -e flag causes vendor to attempt to proceed despite errors
39+
encountered while loading packages.
3740
`,
3841
Run: runVendor,
3942
}
4043

44+
var vendorE bool // if true, report errors but proceed anyway
45+
4146
func init() {
4247
cmdVendor.Flag.BoolVar(&cfg.BuildV, "v", false, "")
48+
cmdVendor.Flag.BoolVar(&vendorE, "e", false, "")
4349
base.AddModCommonFlags(&cmdVendor.Flag)
4450
}
4551

@@ -54,6 +60,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) {
5460
Tags: imports.AnyTags(),
5561
ResolveMissingImports: true,
5662
UseVendorAll: true,
63+
AllowErrors: vendorE,
5764
}
5865
_, pkgs := modload.LoadPackages(ctx, loadOpts, "all")
5966

src/cmd/go/internal/modcmd/why.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) {
6666
modload.RootMode = modload.NeedRoot
6767

6868
loadOpts := modload.PackageOpts{
69-
Tags: imports.AnyTags(),
70-
LoadTests: !*whyVendor,
71-
AllowErrors: true,
72-
UseVendorAll: *whyVendor,
69+
Tags: imports.AnyTags(),
70+
LoadTests: !*whyVendor,
71+
SilenceErrors: true,
72+
UseVendorAll: *whyVendor,
7373
}
7474

7575
if *whyM {

src/cmd/go/internal/modget/get.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
406406
Tags: imports.AnyTags(),
407407
ResolveMissingImports: true, // dubious; see https://golang.org/issue/32567
408408
LoadTests: *getT,
409-
AllowErrors: true, // Errors may be fixed by subsequent upgrades or downgrades.
409+
SilenceErrors: true, // Errors may be fixed by subsequent upgrades or downgrades.
410410
SilenceUnmatchedWarnings: true, // We will warn after iterating below.
411411
}
412412
matches, _ = modload.LoadPackages(ctx, loadOpts, pkgPatterns...)

src/cmd/go/internal/modload/load.go

+22-9
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,14 @@ type PackageOpts struct {
151151
// declare 'go 1.16' or higher.
152152
UseVendorAll bool
153153

154-
// AllowErrors indicates that LoadPackages should not log errors in resolving
155-
// patterns or imports, and should not terminate the process if such an error
156-
// occurs.
154+
// AllowErrors indicates that LoadPackages should not terminate the process if
155+
// an error occurs.
157156
AllowErrors bool
158157

158+
// SilenceErrors indicates that LoadPackages should not print errors
159+
// that occur while loading packages. SilenceErrors implies AllowErrors.
160+
SilenceErrors bool
161+
159162
// SilenceUnmatchedWarnings suppresses the warnings normally emitted for
160163
// patterns that did not match any packages.
161164
SilenceUnmatchedWarnings bool
@@ -263,23 +266,31 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
263266

264267
// One last pass to finalize wildcards.
265268
updateMatches(loaded)
266-
checkMultiplePaths()
267-
WriteGoMod()
268269

270+
// Report errors, if any.
271+
checkMultiplePaths()
269272
for _, pkg := range loaded.pkgs {
270-
if pkg.err != nil && !opts.AllowErrors {
271-
base.Errorf("%s: %v", pkg.stackText(), pkg.err)
273+
if pkg.err != nil && !opts.SilenceErrors {
274+
if opts.AllowErrors {
275+
fmt.Fprintf(os.Stderr, "%s: %v\n", pkg.stackText(), pkg.err)
276+
} else {
277+
base.Errorf("%s: %v", pkg.stackText(), pkg.err)
278+
}
272279
}
273280
if !pkg.isTest() {
274281
loadedPackages = append(loadedPackages, pkg.path)
275282
}
276283
}
277-
if !opts.AllowErrors {
284+
if !opts.SilenceErrors {
278285
// Also list errors in matching patterns (such as directory permission
279286
// errors for wildcard patterns).
280287
for _, match := range matches {
281288
for _, err := range match.Errs {
282-
base.Errorf("%v", err)
289+
if opts.AllowErrors {
290+
fmt.Fprintf(os.Stderr, "%v\n", err)
291+
} else {
292+
base.Errorf("%v", err)
293+
}
283294
}
284295
}
285296
}
@@ -289,6 +300,8 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
289300
search.WarnUnmatched(matches)
290301
}
291302

303+
// Success! Update go.mod (if needed) and return the results.
304+
WriteGoMod()
292305
sort.Strings(loadedPackages)
293306
return matches, loadedPackages
294307
}

src/cmd/go/testdata/script/mod_e.txt

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
cp go.mod go.mod.orig
2+
3+
4+
# If a dependency cannot be resolved, 'go mod tidy' fails with an error message
5+
# explaining the problem and does not update the go.mod file.
6+
# TODO(bcmills): Ideally, with less redundancy than these error messages!
7+
8+
! go mod tidy
9+
10+
stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$'
11+
12+
stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$'
13+
14+
stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$'
15+
16+
stderr '^example.com/untidy imports\n\texample.net/m tested by\n\texample.net/m.test imports\n\texample.net/indirecttestnotfound: cannot find module providing package example.net/indirecttestnotfound: module example.net/indirecttestnotfound: reading http://.*: 404 Not Found$'
17+
18+
cmp go.mod.orig go.mod
19+
20+
21+
# If a dependency cannot be resolved, 'go mod vendor' fails with an error message
22+
# explaining the problem, does not update the go.mod file, and does not create
23+
# the vendor directory.
24+
25+
! go mod vendor
26+
27+
stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$'
28+
29+
stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$'
30+
31+
stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$'
32+
33+
! stderr 'indirecttestnotfound' # Vendor prunes test dependencies.
34+
35+
cmp go.mod.orig go.mod
36+
! exists vendor
37+
38+
39+
# 'go mod tidy' still logs the errors, but succeeds and updates go.mod.
40+
41+
go mod tidy -e
42+
stderr -count=4 'cannot find module providing package'
43+
cmp go.mod.final go.mod
44+
45+
46+
# 'go mod vendor -e' still logs the errors, but succeeds and updates go.mod.
47+
48+
cp go.mod.orig go.mod
49+
go mod vendor -e
50+
stderr -count=3 'cannot find module providing package'
51+
cmp go.mod.final go.mod
52+
exists vendor/modules.txt
53+
exists vendor/example.net/m/m.go
54+
55+
56+
-- go.mod --
57+
module example.com/untidy
58+
go 1.16
59+
replace example.net/m v0.1.0 => ./m
60+
-- go.mod.final --
61+
module example.com/untidy
62+
63+
go 1.16
64+
65+
replace example.net/m v0.1.0 => ./m
66+
67+
require example.net/m v0.1.0
68+
-- untidy.go --
69+
package untidy
70+
71+
import (
72+
_ "example.net/m"
73+
_ "example.net/directnotfound"
74+
)
75+
-- untidy_test.go --
76+
package untidy_test
77+
78+
import _ "example.net/directtestnotfound"
79+
-- m/go.mod --
80+
module example.net/m
81+
go 1.16
82+
-- m/m.go --
83+
package m
84+
85+
import _ "example.net/indirectnotfound"
86+
-- m/m_test.go --
87+
package m_test
88+
89+
import _ "example.net/indirecttestnotfound"

0 commit comments

Comments
 (0)