github.com/bir3/gocompiler@v0.9.2202/src/cmd/gocmd/internal/workcmd/sync.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // go work sync 6 7 package workcmd 8 9 import ( 10 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/base" 11 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/gover" 12 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/imports" 13 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/modload" 14 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/toolchain" 15 "context" 16 17 "github.com/bir3/gocompiler/src/xvendor/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{} // reset 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 // r has a known version, so force that version. 86 mustSelect = append(mustSelect, r) 87 inMustSelect[r] = true 88 } 89 } 90 gover.ModSort(mustSelect) // ensure determinism 91 mustSelectFor[m] = mustSelect 92 } 93 94 workFilePath := modload.WorkFilePath() // save go.work path because EnterModule clobbers it. 95 96 var goV string 97 for _, m := range mms.Versions() { 98 if mms.ModRoot(m) == "" && m.Path == "command-line-arguments" { 99 // This is not a real module. 100 // TODO(#49228): Remove this special case once the special 101 // command-line-arguments module is gone. 102 continue 103 } 104 105 // Use EnterModule to reset the global state in modload to be in 106 // single-module mode using the modroot of m. 107 modload.EnterModule(ctx, mms.ModRoot(m)) 108 109 // Edit the build list in the same way that 'go get' would if we 110 // requested the relevant module versions explicitly. 111 // TODO(#57001): Do we need a toolchain.SwitchOrFatal here, 112 // and do we need to pass a toolchain.Switcher in LoadPackages? 113 // If so, think about saving the WriteGoMods for after the loop, 114 // so we don't write some go.mods with the "before" toolchain 115 // and others with the "after" toolchain. If nothing else, that 116 // discrepancy could show up in auto-recorded toolchain lines. 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 }