1
2
3
4
5
6
7 package workcmd
8
9 import (
10 "cmd/go/internal/base"
11 "cmd/go/internal/gover"
12 "cmd/go/internal/imports"
13 "cmd/go/internal/modload"
14 "cmd/go/internal/toolchain"
15 "context"
16
17 "golang.org/x/mod/module"
18 )
19
20 var cmdSync = &base.Command{
21 UsageLine: "go work sync",
22 Short: "sync workspace build list to modules",
23 Long: `Sync syncs the workspace's build list back to the
24 workspace's modules
25
26 The workspace's build list is the set of versions of all the
27 (transitive) dependency modules used to do builds in the workspace. go
28 work sync generates that build list using the Minimal Version Selection
29 algorithm, and then syncs those versions back to each of modules
30 specified in the workspace (with use directives).
31
32 The syncing is done by sequentially upgrading each of the dependency
33 modules specified in a workspace module to the version in the build list
34 if the dependency module's version is not already the same as the build
35 list's version. Note that Minimal Version Selection guarantees that the
36 build list's version of each module is always the same or higher than
37 that in each workspace module.
38
39 See the workspaces reference at https://go.dev/ref/mod#workspaces
40 for more information.
41 `,
42 Run: runSync,
43 }
44
45 func init() {
46 base.AddChdirFlag(&cmdSync.Flag)
47 base.AddModCommonFlags(&cmdSync.Flag)
48 }
49
50 func runSync(ctx context.Context, cmd *base.Command, args []string) {
51 moduleLoader := modload.NewLoader()
52 moduleLoader.ForceUseModules = true
53 moduleLoader.InitWorkfile()
54 if modload.WorkFilePath(moduleLoader) == "" {
55 base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
56 }
57
58 _, err := modload.LoadModGraph(moduleLoader, ctx, "")
59 if err != nil {
60 toolchain.SwitchOrFatal(moduleLoader, ctx, err)
61 }
62 addFor := map[module.Version][]module.Version{}
63
64 mms := moduleLoader.MainModules
65
66 opts := modload.PackageOpts{
67 Tags: imports.AnyTags(),
68 VendorModulesInGOROOTSrc: true,
69 ResolveMissingImports: false,
70 LoadTests: true,
71 AllowErrors: true,
72 SilencePackageErrors: true,
73 SilenceUnmatchedWarnings: true,
74 }
75 for _, m := range mms.Versions() {
76 opts.MainModule = m
77 _, pkgs := modload.LoadPackages(moduleLoader, ctx, opts, "all")
78 opts.MainModule = module.Version{}
79
80 var (
81 addReq []module.Version
82 inAddReq = map[module.Version]bool{}
83 )
84 for _, pkg := range pkgs {
85 if r := moduleLoader.PackageModule(pkg); r.Version != "" && !inAddReq[r] {
86
87 addReq = append(addReq, r)
88 inAddReq[r] = true
89 }
90 }
91 gover.ModSort(addReq)
92 addFor[m] = addReq
93 }
94
95 workFilePath := modload.WorkFilePath(moduleLoader)
96
97 var loaders []*modload.Loader
98 var goV string
99 for _, m := range mms.Versions() {
100 if mms.ModRoot(m) == "" && m.Path == "command-line-arguments" {
101
102
103
104 continue
105 }
106
107
108 loader := modload.NewLoader()
109 modload.EnterModule(loader, ctx, mms.ModRoot(m))
110
111
112
113
114
115
116
117
118
119 changed, err := modload.EditBuildList(loader, ctx, addFor[m], nil)
120 if err != nil {
121 base.Fatal(err)
122 }
123 if changed {
124 modload.LoadPackages(loader, ctx, modload.PackageOpts{
125 Tags: imports.AnyTags(),
126 Tidy: true,
127 VendorModulesInGOROOTSrc: true,
128 ResolveMissingImports: false,
129 LoadTests: true,
130 AllowErrors: true,
131 SilenceMissingStdImports: true,
132 SilencePackageErrors: true,
133 }, "all")
134
135 if _, _, _, err := modload.UpdateGoModFromReqs(loader, ctx, modload.WriteOpts{}); err != nil {
136 base.Fatal(err)
137 }
138 loaders = append(loaders, loader)
139 }
140 goV = gover.Max(goV, loader.MainModules.GoVersion(loader))
141 }
142 base.ExitIfErrors()
143 for _, loader := range loaders {
144 modload.WriteGoMod(loader, ctx, modload.WriteOpts{})
145 }
146
147 wf, err := modload.ReadWorkFile(workFilePath)
148 if err != nil {
149 base.Fatal(err)
150 }
151 modload.UpdateWorkGoVersion(wf, goV)
152 modload.UpdateWorkFile(wf)
153 if err := modload.WriteWorkFile(workFilePath, wf); err != nil {
154 base.Fatal(err)
155 }
156 }
157
View as plain text