1
2
3
4
5
6
7 package modcmd
8
9 import (
10 "cmd/go/internal/base"
11 "cmd/go/internal/cfg"
12 "cmd/go/internal/imports"
13 "cmd/go/internal/modload"
14 "context"
15 "fmt"
16
17 "golang.org/x/mod/modfile"
18 "golang.org/x/mod/semver"
19 )
20
21 var cmdTidy = &base.Command{
22 UsageLine: "go mod tidy [-e] [-v] [-go=version] [-compat=version]",
23 Short: "add missing and remove unused modules",
24 Long: `
25 Tidy makes sure go.mod matches the source code in the module.
26 It adds any missing modules necessary to build the current module's
27 packages and dependencies, and it removes unused modules that
28 don't provide any relevant packages. It also adds any missing entries
29 to go.sum and removes any unnecessary ones.
30
31 The -v flag causes tidy to print information about removed modules
32 to standard error.
33
34 The -e flag causes tidy to attempt to proceed despite errors
35 encountered while loading packages.
36
37 The -go flag causes tidy to update the 'go' directive in the go.mod
38 file to the given version, which may change which module dependencies
39 are retained as explicit requirements in the go.mod file.
40 (Go versions 1.17 and higher retain more requirements in order to
41 support lazy module loading.)
42
43 The -compat flag preserves any additional checksums needed for the
44 'go' command from the indicated major Go release to successfully load
45 the module graph, and causes tidy to error out if that version of the
46 'go' command would load any imported package from a different module
47 version. By default, tidy acts as if the -compat flag were set to the
48 version prior to the one indicated by the 'go' directive in the go.mod
49 file.
50
51 See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'.
52 `,
53 Run: runTidy,
54 }
55
56 var (
57 tidyE bool
58 tidyGo goVersionFlag
59 tidyCompat goVersionFlag
60 )
61
62 func init() {
63 cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "")
64 cmdTidy.Flag.BoolVar(&tidyE, "e", false, "")
65 cmdTidy.Flag.Var(&tidyGo, "go", "")
66 cmdTidy.Flag.Var(&tidyCompat, "compat", "")
67 base.AddModCommonFlags(&cmdTidy.Flag)
68 }
69
70
71
72
73
74 type goVersionFlag struct {
75 v string
76 }
77
78 func (f *goVersionFlag) String() string { return f.v }
79 func (f *goVersionFlag) Get() any { return f.v }
80
81 func (f *goVersionFlag) Set(s string) error {
82 if s != "" {
83 latest := modload.LatestGoVersion()
84 if !modfile.GoVersionRE.MatchString(s) {
85 return fmt.Errorf("expecting a Go version like %q", latest)
86 }
87 if semver.Compare("v"+s, "v"+latest) > 0 {
88 return fmt.Errorf("maximum supported Go version is %s", latest)
89 }
90 }
91
92 f.v = s
93 return nil
94 }
95
96 func runTidy(ctx context.Context, cmd *base.Command, args []string) {
97 if len(args) > 0 {
98 base.Fatalf("go: 'go mod tidy' accepts no arguments")
99 }
100
101
102
103
104
105
106
107
108
109
110
111 modload.ForceUseModules = true
112 modload.RootMode = modload.NeedRoot
113
114 modload.LoadPackages(ctx, modload.PackageOpts{
115 GoVersion: tidyGo.String(),
116 Tags: imports.AnyTags(),
117 Tidy: true,
118 TidyCompatibleVersion: tidyCompat.String(),
119 VendorModulesInGOROOTSrc: true,
120 ResolveMissingImports: true,
121 LoadTests: true,
122 AllowErrors: tidyE,
123 SilenceMissingStdImports: true,
124 }, "all")
125 }
126
View as plain text