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 modload.ForceUseModules = true
52 modload.InitWorkfile()
53 if modload.WorkFilePath() == "" {
54 base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
55 }
56
57 _, err := modload.LoadModGraph(ctx, "")
58 if err != nil {
59 toolchain.SwitchOrFatal(ctx, err)
60 }
61 mustSelectFor := map[module.Version][]module.Version{}
62
63 mms := modload.MainModules
64
65 opts := modload.PackageOpts{
66 Tags: imports.AnyTags(),
67 VendorModulesInGOROOTSrc: true,
68 ResolveMissingImports: false,
69 LoadTests: true,
70 AllowErrors: true,
71 SilencePackageErrors: true,
72 SilenceUnmatchedWarnings: true,
73 }
74 for _, m := range mms.Versions() {
75 opts.MainModule = m
76 _, pkgs := modload.LoadPackages(ctx, opts, "all")
77 opts.MainModule = module.Version{}
78
79 var (
80 mustSelect []module.Version
81 inMustSelect = map[module.Version]bool{}
82 )
83 for _, pkg := range pkgs {
84 if r := modload.PackageModule(pkg); r.Version != "" && !inMustSelect[r] {
85
86 mustSelect = append(mustSelect, r)
87 inMustSelect[r] = true
88 }
89 }
90 gover.ModSort(mustSelect)
91 mustSelectFor[m] = mustSelect
92 }
93
94 workFilePath := modload.WorkFilePath()
95
96 var goV string
97 for _, m := range mms.Versions() {
98 if mms.ModRoot(m) == "" && m.Path == "command-line-arguments" {
99
100
101
102 continue
103 }
104
105
106
107 modload.EnterModule(ctx, mms.ModRoot(m))
108
109
110
111
112
113
114
115
116
117 changed, err := modload.EditBuildList(ctx, nil, mustSelectFor[m])
118 if err != nil {
119 continue
120 }
121 if changed {
122 modload.LoadPackages(ctx, modload.PackageOpts{
123 Tags: imports.AnyTags(),
124 Tidy: true,
125 VendorModulesInGOROOTSrc: true,
126 ResolveMissingImports: false,
127 LoadTests: true,
128 AllowErrors: true,
129 SilenceMissingStdImports: true,
130 SilencePackageErrors: true,
131 }, "all")
132 modload.WriteGoMod(ctx, modload.WriteOpts{})
133 }
134 goV = gover.Max(goV, modload.MainModules.GoVersion())
135 }
136
137 wf, err := modload.ReadWorkFile(workFilePath)
138 if err != nil {
139 base.Fatal(err)
140 }
141 modload.UpdateWorkGoVersion(wf, goV)
142 modload.UpdateWorkFile(wf)
143 if err := modload.WriteWorkFile(workFilePath, wf); err != nil {
144 base.Fatal(err)
145 }
146 }
147
View as plain text