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