github.com/bir3/gocompiler@v0.3.205/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/imports"
    12  	"github.com/bir3/gocompiler/src/cmd/gocmd/internal/modload"
    13  	"context"
    14  
    15  	"github.com/bir3/gocompiler/src/xvendor/golang.org/x/mod/module"
    16  )
    17  
    18  var cmdSync = &base.Command{
    19  	UsageLine: "go work sync",
    20  	Short:     "sync workspace build list to modules",
    21  	Long: `Sync syncs the workspace's build list back to the
    22  workspace's modules
    23  
    24  The workspace's build list is the set of versions of all the
    25  (transitive) dependency modules used to do builds in the workspace. go
    26  work sync generates that build list using the Minimal Version Selection
    27  algorithm, and then syncs those versions back to each of modules
    28  specified in the workspace (with use directives).
    29  
    30  The syncing is done by sequentially upgrading each of the dependency
    31  modules specified in a workspace module to the version in the build list
    32  if the dependency module's version is not already the same as the build
    33  list's version. Note that Minimal Version Selection guarantees that the
    34  build list's version of each module is always the same or higher than
    35  that in each workspace module.
    36  
    37  See the workspaces reference at https://go.dev/ref/mod#workspaces
    38  for more information.
    39  `,
    40  	Run: runSync,
    41  }
    42  
    43  func init() {
    44  	base.AddChdirFlag(&cmdSync.Flag)
    45  	base.AddModCommonFlags(&cmdSync.Flag)
    46  }
    47  
    48  func runSync(ctx context.Context, cmd *base.Command, args []string) {
    49  	modload.ForceUseModules = true
    50  	modload.InitWorkfile()
    51  	if modload.WorkFilePath() == "" {
    52  		base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
    53  	}
    54  
    55  	workGraph := modload.LoadModGraph(ctx, "")
    56  	_ = workGraph
    57  	mustSelectFor := map[module.Version][]module.Version{}
    58  
    59  	mms := modload.MainModules
    60  
    61  	opts := modload.PackageOpts{
    62  		Tags:                     imports.AnyTags(),
    63  		VendorModulesInGOROOTSrc: true,
    64  		ResolveMissingImports:    false,
    65  		LoadTests:                true,
    66  		AllowErrors:              true,
    67  		SilencePackageErrors:     true,
    68  		SilenceUnmatchedWarnings: true,
    69  	}
    70  	for _, m := range mms.Versions() {
    71  		opts.MainModule = m
    72  		_, pkgs := modload.LoadPackages(ctx, opts, "all")
    73  		opts.MainModule = module.Version{} // reset
    74  
    75  		var (
    76  			mustSelect   []module.Version
    77  			inMustSelect = map[module.Version]bool{}
    78  		)
    79  		for _, pkg := range pkgs {
    80  			if r := modload.PackageModule(pkg); r.Version != "" && !inMustSelect[r] {
    81  				// r has a known version, so force that version.
    82  				mustSelect = append(mustSelect, r)
    83  				inMustSelect[r] = true
    84  			}
    85  		}
    86  		module.Sort(mustSelect) // ensure determinism
    87  		mustSelectFor[m] = mustSelect
    88  	}
    89  
    90  	workFilePath := modload.WorkFilePath() // save go.work path because EnterModule clobbers it.
    91  
    92  	for _, m := range mms.Versions() {
    93  		if mms.ModRoot(m) == "" && m.Path == "command-line-arguments" {
    94  			// This is not a real module.
    95  			// TODO(#49228): Remove this special case once the special
    96  			// command-line-arguments module is gone.
    97  			continue
    98  		}
    99  
   100  		// Use EnterModule to reset the global state in modload to be in
   101  		// single-module mode using the modroot of m.
   102  		modload.EnterModule(ctx, mms.ModRoot(m))
   103  
   104  		// Edit the build list in the same way that 'go get' would if we
   105  		// requested the relevant module versions explicitly.
   106  		changed, err := modload.EditBuildList(ctx, nil, mustSelectFor[m])
   107  		if err != nil {
   108  			base.Errorf("go: %v", err)
   109  		}
   110  		if !changed {
   111  			continue
   112  		}
   113  
   114  		modload.LoadPackages(ctx, modload.PackageOpts{
   115  			Tags:                     imports.AnyTags(),
   116  			Tidy:                     true,
   117  			VendorModulesInGOROOTSrc: true,
   118  			ResolveMissingImports:    false,
   119  			LoadTests:                true,
   120  			AllowErrors:              true,
   121  			SilenceMissingStdImports: true,
   122  			SilencePackageErrors:     true,
   123  		}, "all")
   124  		modload.WriteGoMod(ctx)
   125  	}
   126  
   127  	wf, err := modload.ReadWorkFile(workFilePath)
   128  	if err != nil {
   129  		base.Fatalf("go: %v", err)
   130  	}
   131  	modload.UpdateWorkFile(wf)
   132  	if err := modload.WriteWorkFile(workFilePath, wf); err != nil {
   133  		base.Fatalf("go: %v", err)
   134  	}
   135  }