1  
     2  
     3  
     4  
     5  package modload
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  	"sync"
    15  	"unicode"
    16  
    17  	"cmd/go/internal/base"
    18  	"cmd/go/internal/cfg"
    19  	"cmd/go/internal/fsys"
    20  	"cmd/go/internal/gover"
    21  	"cmd/go/internal/lockedfile"
    22  	"cmd/go/internal/modfetch"
    23  	"cmd/go/internal/trace"
    24  	"cmd/internal/par"
    25  
    26  	"golang.org/x/mod/modfile"
    27  	"golang.org/x/mod/module"
    28  )
    29  
    30  
    31  
    32  func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfile.File, err error) {
    33  	if fsys.Replaced(gomod) {
    34  		
    35  		
    36  		
    37  		data, err = os.ReadFile(fsys.Actual(gomod))
    38  	} else {
    39  		data, err = lockedfile.Read(gomod)
    40  	}
    41  	if err != nil {
    42  		return nil, nil, err
    43  	}
    44  
    45  	f, err = modfile.Parse(gomod, data, fix)
    46  	if err != nil {
    47  		f, laxErr := modfile.ParseLax(gomod, data, fix)
    48  		if laxErr == nil {
    49  			if f.Go != nil && gover.Compare(f.Go.Version, gover.Local()) > 0 {
    50  				toolchain := ""
    51  				if f.Toolchain != nil {
    52  					toolchain = f.Toolchain.Name
    53  				}
    54  				return nil, nil, &gover.TooNewError{What: base.ShortPath(gomod), GoVersion: f.Go.Version, Toolchain: toolchain}
    55  			}
    56  		}
    57  
    58  		
    59  		return nil, nil, fmt.Errorf("errors parsing %s:\n%w", base.ShortPath(gomod), shortPathErrorList(err))
    60  	}
    61  	if f.Go != nil && gover.Compare(f.Go.Version, gover.Local()) > 0 {
    62  		toolchain := ""
    63  		if f.Toolchain != nil {
    64  			toolchain = f.Toolchain.Name
    65  		}
    66  		return nil, nil, &gover.TooNewError{What: base.ShortPath(gomod), GoVersion: f.Go.Version, Toolchain: toolchain}
    67  	}
    68  	if f.Module == nil {
    69  		
    70  		return nil, nil, fmt.Errorf("error reading %s: missing module declaration. To specify the module path:\n\tgo mod edit -module=example.com/mod", base.ShortPath(gomod))
    71  	}
    72  
    73  	return data, f, err
    74  }
    75  
    76  func shortPathErrorList(err error) error {
    77  	var el modfile.ErrorList
    78  	if errors.As(err, &el) {
    79  		for i := range el {
    80  			el[i].Filename = base.ShortPath(el[i].Filename)
    81  		}
    82  	}
    83  	return err
    84  }
    85  
    86  
    87  
    88  type modFileIndex struct {
    89  	data         []byte
    90  	dataNeedsFix bool 
    91  	module       module.Version
    92  	goVersion    string 
    93  	toolchain    string
    94  	require      map[module.Version]requireMeta
    95  	replace      map[module.Version]module.Version
    96  	exclude      map[module.Version]bool
    97  	ignore       []string
    98  }
    99  
   100  type requireMeta struct {
   101  	indirect bool
   102  }
   103  
   104  
   105  
   106  
   107  type modPruning uint8
   108  
   109  const (
   110  	pruned    modPruning = iota 
   111  	unpruned                    
   112  	workspace                   
   113  )
   114  
   115  func (p modPruning) String() string {
   116  	switch p {
   117  	case pruned:
   118  		return "pruned"
   119  	case unpruned:
   120  		return "unpruned"
   121  	case workspace:
   122  		return "workspace"
   123  	default:
   124  		return fmt.Sprintf("%T(%d)", p, p)
   125  	}
   126  }
   127  
   128  func pruningForGoVersion(goVersion string) modPruning {
   129  	if gover.Compare(goVersion, gover.ExplicitIndirectVersion) < 0 {
   130  		
   131  		
   132  		return unpruned
   133  	}
   134  	return pruned
   135  }
   136  
   137  
   138  
   139  
   140  func CheckAllowed(ctx context.Context, m module.Version) error {
   141  	if err := CheckExclusions(ctx, m); err != nil {
   142  		return err
   143  	}
   144  	if err := CheckRetractions(ctx, m); err != nil {
   145  		return err
   146  	}
   147  	return nil
   148  }
   149  
   150  
   151  
   152  var ErrDisallowed = errors.New("disallowed module version")
   153  
   154  
   155  
   156  func CheckExclusions(ctx context.Context, m module.Version) error {
   157  	for _, mainModule := range MainModules.Versions() {
   158  		if index := MainModules.Index(mainModule); index != nil && index.exclude[m] {
   159  			return module.VersionError(m, errExcluded)
   160  		}
   161  	}
   162  	return nil
   163  }
   164  
   165  var errExcluded = &excludedError{}
   166  
   167  type excludedError struct{}
   168  
   169  func (e *excludedError) Error() string     { return "excluded by go.mod" }
   170  func (e *excludedError) Is(err error) bool { return err == ErrDisallowed }
   171  
   172  
   173  
   174  func CheckRetractions(ctx context.Context, m module.Version) (err error) {
   175  	defer func() {
   176  		if retractErr := (*ModuleRetractedError)(nil); err == nil || errors.As(err, &retractErr) {
   177  			return
   178  		}
   179  		
   180  		
   181  		if mErr := (*module.ModuleError)(nil); errors.As(err, &mErr) {
   182  			err = mErr.Err
   183  		}
   184  		err = &retractionLoadingError{m: m, err: err}
   185  	}()
   186  
   187  	if m.Version == "" {
   188  		
   189  		
   190  		return nil
   191  	}
   192  	if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" {
   193  		
   194  		
   195  		return nil
   196  	}
   197  
   198  	
   199  	
   200  	
   201  	
   202  	
   203  	
   204  	
   205  	
   206  	
   207  	
   208  	
   209  	rm, err := queryLatestVersionIgnoringRetractions(ctx, m.Path)
   210  	if err != nil {
   211  		return err
   212  	}
   213  	summary, err := rawGoModSummary(rm)
   214  	if err != nil && !errors.Is(err, gover.ErrTooNew) {
   215  		return err
   216  	}
   217  
   218  	var rationale []string
   219  	isRetracted := false
   220  	for _, r := range summary.retract {
   221  		if gover.ModCompare(m.Path, r.Low, m.Version) <= 0 && gover.ModCompare(m.Path, m.Version, r.High) <= 0 {
   222  			isRetracted = true
   223  			if r.Rationale != "" {
   224  				rationale = append(rationale, r.Rationale)
   225  			}
   226  		}
   227  	}
   228  	if isRetracted {
   229  		return module.VersionError(m, &ModuleRetractedError{Rationale: rationale})
   230  	}
   231  	return nil
   232  }
   233  
   234  type ModuleRetractedError struct {
   235  	Rationale []string
   236  }
   237  
   238  func (e *ModuleRetractedError) Error() string {
   239  	msg := "retracted by module author"
   240  	if len(e.Rationale) > 0 {
   241  		
   242  		
   243  		msg += ": " + ShortMessage(e.Rationale[0], "retracted by module author")
   244  	}
   245  	return msg
   246  }
   247  
   248  func (e *ModuleRetractedError) Is(err error) bool {
   249  	return err == ErrDisallowed
   250  }
   251  
   252  type retractionLoadingError struct {
   253  	m   module.Version
   254  	err error
   255  }
   256  
   257  func (e *retractionLoadingError) Error() string {
   258  	return fmt.Sprintf("loading module retractions for %v: %v", e.m, e.err)
   259  }
   260  
   261  func (e *retractionLoadingError) Unwrap() error {
   262  	return e.err
   263  }
   264  
   265  
   266  
   267  
   268  
   269  
   270  
   271  func ShortMessage(message, emptyDefault string) string {
   272  	const maxLen = 500
   273  	if i := strings.Index(message, "\n"); i >= 0 {
   274  		message = message[:i]
   275  	}
   276  	message = strings.TrimSpace(message)
   277  	if message == "" {
   278  		return emptyDefault
   279  	}
   280  	if len(message) > maxLen {
   281  		return "(message omitted: too long)"
   282  	}
   283  	for _, r := range message {
   284  		if !unicode.IsGraphic(r) && !unicode.IsSpace(r) {
   285  			return "(message omitted: contains non-printable characters)"
   286  		}
   287  	}
   288  	
   289  	return message
   290  }
   291  
   292  
   293  
   294  
   295  
   296  
   297  
   298  
   299  func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string, err error) {
   300  	defer func() {
   301  		if err != nil {
   302  			err = fmt.Errorf("loading deprecation for %s: %w", m.Path, err)
   303  		}
   304  	}()
   305  
   306  	if m.Version == "" {
   307  		
   308  		
   309  		return "", nil
   310  	}
   311  	if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" {
   312  		
   313  		
   314  		return "", nil
   315  	}
   316  
   317  	latest, err := queryLatestVersionIgnoringRetractions(ctx, m.Path)
   318  	if err != nil {
   319  		return "", err
   320  	}
   321  	summary, err := rawGoModSummary(latest)
   322  	if err != nil && !errors.Is(err, gover.ErrTooNew) {
   323  		return "", err
   324  	}
   325  	return summary.deprecated, nil
   326  }
   327  
   328  func replacement(mod module.Version, replace map[module.Version]module.Version) (fromVersion string, to module.Version, ok bool) {
   329  	if r, ok := replace[mod]; ok {
   330  		return mod.Version, r, true
   331  	}
   332  	if r, ok := replace[module.Version{Path: mod.Path}]; ok {
   333  		return "", r, true
   334  	}
   335  	return "", module.Version{}, false
   336  }
   337  
   338  
   339  
   340  
   341  func Replacement(mod module.Version) module.Version {
   342  	r, foundModRoot, _ := replacementFrom(mod)
   343  	return canonicalizeReplacePath(r, foundModRoot)
   344  }
   345  
   346  
   347  
   348  func replacementFrom(mod module.Version) (r module.Version, modroot string, fromFile string) {
   349  	foundFrom, found, foundModRoot := "", module.Version{}, ""
   350  	if MainModules == nil {
   351  		return module.Version{}, "", ""
   352  	} else if MainModules.Contains(mod.Path) && mod.Version == "" {
   353  		
   354  		return module.Version{}, "", ""
   355  	}
   356  	if _, r, ok := replacement(mod, MainModules.WorkFileReplaceMap()); ok {
   357  		return r, "", workFilePath
   358  	}
   359  	for _, v := range MainModules.Versions() {
   360  		if index := MainModules.Index(v); index != nil {
   361  			if from, r, ok := replacement(mod, index.replace); ok {
   362  				modRoot := MainModules.ModRoot(v)
   363  				if foundModRoot != "" && foundFrom != from && found != r {
   364  					base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v",
   365  						mod, modFilePath(foundModRoot), modFilePath(modRoot))
   366  					return found, foundModRoot, modFilePath(foundModRoot)
   367  				}
   368  				found, foundModRoot = r, modRoot
   369  			}
   370  		}
   371  	}
   372  	return found, foundModRoot, modFilePath(foundModRoot)
   373  }
   374  
   375  func replaceRelativeTo() string {
   376  	if workFilePath := WorkFilePath(); workFilePath != "" {
   377  		return filepath.Dir(workFilePath)
   378  	}
   379  	return MainModules.ModRoot(MainModules.mustGetSingleMainModule())
   380  }
   381  
   382  
   383  
   384  
   385  func canonicalizeReplacePath(r module.Version, modRoot string) module.Version {
   386  	if filepath.IsAbs(r.Path) || r.Version != "" || modRoot == "" {
   387  		return r
   388  	}
   389  	workFilePath := WorkFilePath()
   390  	if workFilePath == "" {
   391  		return r
   392  	}
   393  	abs := filepath.Join(modRoot, r.Path)
   394  	if rel, err := filepath.Rel(filepath.Dir(workFilePath), abs); err == nil {
   395  		return module.Version{Path: ToDirectoryPath(rel), Version: r.Version}
   396  	}
   397  	
   398  	
   399  	return module.Version{Path: ToDirectoryPath(abs), Version: r.Version}
   400  }
   401  
   402  
   403  
   404  
   405  
   406  func resolveReplacement(m module.Version) module.Version {
   407  	if r := Replacement(m); r.Path != "" {
   408  		return r
   409  	}
   410  	return m
   411  }
   412  
   413  func toReplaceMap(replacements []*modfile.Replace) map[module.Version]module.Version {
   414  	replaceMap := make(map[module.Version]module.Version, len(replacements))
   415  	for _, r := range replacements {
   416  		if prev, dup := replaceMap[r.Old]; dup && prev != r.New {
   417  			base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New)
   418  		}
   419  		replaceMap[r.Old] = r.New
   420  	}
   421  	return replaceMap
   422  }
   423  
   424  
   425  
   426  
   427  func indexModFile(data []byte, modFile *modfile.File, mod module.Version, needsFix bool) *modFileIndex {
   428  	i := new(modFileIndex)
   429  	i.data = data
   430  	i.dataNeedsFix = needsFix
   431  
   432  	i.module = module.Version{}
   433  	if modFile.Module != nil {
   434  		i.module = modFile.Module.Mod
   435  	}
   436  
   437  	i.goVersion = ""
   438  	if modFile.Go == nil {
   439  		rawGoVersion.Store(mod, "")
   440  	} else {
   441  		i.goVersion = modFile.Go.Version
   442  		rawGoVersion.Store(mod, modFile.Go.Version)
   443  	}
   444  	if modFile.Toolchain != nil {
   445  		i.toolchain = modFile.Toolchain.Name
   446  	}
   447  
   448  	i.require = make(map[module.Version]requireMeta, len(modFile.Require))
   449  	for _, r := range modFile.Require {
   450  		i.require[r.Mod] = requireMeta{indirect: r.Indirect}
   451  	}
   452  
   453  	i.replace = toReplaceMap(modFile.Replace)
   454  
   455  	i.exclude = make(map[module.Version]bool, len(modFile.Exclude))
   456  	for _, x := range modFile.Exclude {
   457  		i.exclude[x.Mod] = true
   458  	}
   459  	if modFile.Ignore != nil {
   460  		for _, x := range modFile.Ignore {
   461  			i.ignore = append(i.ignore, x.Path)
   462  		}
   463  	}
   464  	return i
   465  }
   466  
   467  
   468  
   469  
   470  
   471  func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool {
   472  	if i == nil {
   473  		return modFile != nil
   474  	}
   475  
   476  	if i.dataNeedsFix {
   477  		return true
   478  	}
   479  
   480  	if modFile.Module == nil {
   481  		if i.module != (module.Version{}) {
   482  			return true
   483  		}
   484  	} else if modFile.Module.Mod != i.module {
   485  		return true
   486  	}
   487  
   488  	var goV, toolchain string
   489  	if modFile.Go != nil {
   490  		goV = modFile.Go.Version
   491  	}
   492  	if modFile.Toolchain != nil {
   493  		toolchain = modFile.Toolchain.Name
   494  	}
   495  
   496  	if goV != i.goVersion ||
   497  		toolchain != i.toolchain ||
   498  		len(modFile.Require) != len(i.require) ||
   499  		len(modFile.Replace) != len(i.replace) ||
   500  		len(modFile.Exclude) != len(i.exclude) {
   501  		return true
   502  	}
   503  
   504  	for _, r := range modFile.Require {
   505  		if meta, ok := i.require[r.Mod]; !ok {
   506  			return true
   507  		} else if r.Indirect != meta.indirect {
   508  			if cfg.BuildMod == "readonly" {
   509  				
   510  				
   511  				
   512  				
   513  			} else {
   514  				return true
   515  			}
   516  		}
   517  	}
   518  
   519  	for _, r := range modFile.Replace {
   520  		if r.New != i.replace[r.Old] {
   521  			return true
   522  		}
   523  	}
   524  
   525  	for _, x := range modFile.Exclude {
   526  		if !i.exclude[x.Mod] {
   527  			return true
   528  		}
   529  	}
   530  
   531  	return false
   532  }
   533  
   534  
   535  
   536  
   537  
   538  var rawGoVersion sync.Map 
   539  
   540  
   541  
   542  
   543  type modFileSummary struct {
   544  	module     module.Version
   545  	goVersion  string
   546  	toolchain  string
   547  	ignore     []string
   548  	pruning    modPruning
   549  	require    []module.Version
   550  	retract    []retraction
   551  	deprecated string
   552  }
   553  
   554  
   555  
   556  type retraction struct {
   557  	modfile.VersionInterval
   558  	Rationale string
   559  }
   560  
   561  
   562  
   563  
   564  
   565  
   566  
   567  
   568  
   569  
   570  
   571  
   572  func goModSummary(m module.Version) (*modFileSummary, error) {
   573  	if m.Version == "" && !inWorkspaceMode() && MainModules.Contains(m.Path) {
   574  		panic("internal error: goModSummary called on a main module")
   575  	}
   576  	if gover.IsToolchain(m.Path) {
   577  		return rawGoModSummary(m)
   578  	}
   579  
   580  	if cfg.BuildMod == "vendor" {
   581  		summary := &modFileSummary{
   582  			module: module.Version{Path: m.Path},
   583  		}
   584  
   585  		readVendorList(VendorDir())
   586  		if vendorVersion[m.Path] != m.Version {
   587  			
   588  			
   589  			return summary, nil
   590  		}
   591  
   592  		
   593  		
   594  		
   595  		
   596  		summary.require = vendorList
   597  		return summary, nil
   598  	}
   599  
   600  	actual := resolveReplacement(m)
   601  	if mustHaveSums() && actual.Version != "" {
   602  		key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"}
   603  		if !modfetch.HaveSum(key) {
   604  			suggestion := fmt.Sprintf(" for go.mod file; to add it:\n\tgo mod download %s", m.Path)
   605  			return nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion})
   606  		}
   607  	}
   608  	summary, err := rawGoModSummary(actual)
   609  	if err != nil {
   610  		return nil, err
   611  	}
   612  
   613  	if actual.Version == "" {
   614  		
   615  		
   616  		
   617  		
   618  		
   619  		
   620  	} else {
   621  		if summary.module.Path == "" {
   622  			return nil, module.VersionError(actual, errors.New("parsing go.mod: missing module line"))
   623  		}
   624  
   625  		
   626  		
   627  		
   628  		
   629  		
   630  		
   631  		
   632  		if mpath := summary.module.Path; mpath != m.Path && mpath != actual.Path {
   633  			return nil, module.VersionError(actual,
   634  				fmt.Errorf("parsing go.mod:\n"+
   635  					"\tmodule declares its path as: %s\n"+
   636  					"\t        but was required as: %s", mpath, m.Path))
   637  		}
   638  	}
   639  
   640  	for _, mainModule := range MainModules.Versions() {
   641  		if index := MainModules.Index(mainModule); index != nil && len(index.exclude) > 0 {
   642  			
   643  			
   644  			
   645  			haveExcludedReqs := false
   646  			for _, r := range summary.require {
   647  				if index.exclude[r] {
   648  					haveExcludedReqs = true
   649  					break
   650  				}
   651  			}
   652  			if haveExcludedReqs {
   653  				s := new(modFileSummary)
   654  				*s = *summary
   655  				s.require = make([]module.Version, 0, len(summary.require))
   656  				for _, r := range summary.require {
   657  					if !index.exclude[r] {
   658  						s.require = append(s.require, r)
   659  					}
   660  				}
   661  				summary = s
   662  			}
   663  		}
   664  	}
   665  	return summary, nil
   666  }
   667  
   668  
   669  
   670  
   671  
   672  
   673  
   674  
   675  func rawGoModSummary(m module.Version) (*modFileSummary, error) {
   676  	if gover.IsToolchain(m.Path) {
   677  		if m.Path == "go" && gover.Compare(m.Version, gover.GoStrictVersion) >= 0 {
   678  			
   679  			
   680  			
   681  			return &modFileSummary{module: m, require: []module.Version{{Path: "toolchain", Version: "go" + m.Version}}}, nil
   682  		}
   683  		return &modFileSummary{module: m}, nil
   684  	}
   685  	if m.Version == "" && !inWorkspaceMode() && MainModules.Contains(m.Path) {
   686  		
   687  		
   688  		
   689  		
   690  		
   691  		panic("internal error: rawGoModSummary called on a main module")
   692  	}
   693  	if m.Version == "" && inWorkspaceMode() && m.Path == "command-line-arguments" {
   694  		
   695  		
   696  		
   697  		return &modFileSummary{module: m}, nil
   698  	} else if m.Version == "" && inWorkspaceMode() && MainModules.Contains(m.Path) {
   699  		
   700  		
   701  		
   702  		
   703  		if mf := MainModules.ModFile(m); mf != nil {
   704  			return summaryFromModFile(m, MainModules.modFiles[m])
   705  		}
   706  	}
   707  	return rawGoModSummaryCache.Do(m, func() (*modFileSummary, error) {
   708  		name, data, err := rawGoModData(m)
   709  		if err != nil {
   710  			return nil, err
   711  		}
   712  		f, err := modfile.ParseLax(name, data, nil)
   713  		if err != nil {
   714  			return nil, module.VersionError(m, fmt.Errorf("parsing %s: %v", base.ShortPath(name), err))
   715  		}
   716  		return summaryFromModFile(m, f)
   717  	})
   718  }
   719  
   720  func summaryFromModFile(m module.Version, f *modfile.File) (*modFileSummary, error) {
   721  	summary := new(modFileSummary)
   722  	if f.Module != nil {
   723  		summary.module = f.Module.Mod
   724  		summary.deprecated = f.Module.Deprecated
   725  	}
   726  	if f.Go != nil {
   727  		rawGoVersion.LoadOrStore(m, f.Go.Version)
   728  		summary.goVersion = f.Go.Version
   729  		summary.pruning = pruningForGoVersion(f.Go.Version)
   730  	} else {
   731  		summary.pruning = unpruned
   732  	}
   733  	if f.Toolchain != nil {
   734  		summary.toolchain = f.Toolchain.Name
   735  	}
   736  	if f.Ignore != nil {
   737  		for _, i := range f.Ignore {
   738  			summary.ignore = append(summary.ignore, i.Path)
   739  		}
   740  	}
   741  	if len(f.Require) > 0 {
   742  		summary.require = make([]module.Version, 0, len(f.Require)+1)
   743  		for _, req := range f.Require {
   744  			summary.require = append(summary.require, req.Mod)
   745  		}
   746  	}
   747  
   748  	if len(f.Retract) > 0 {
   749  		summary.retract = make([]retraction, 0, len(f.Retract))
   750  		for _, ret := range f.Retract {
   751  			summary.retract = append(summary.retract, retraction{
   752  				VersionInterval: ret.VersionInterval,
   753  				Rationale:       ret.Rationale,
   754  			})
   755  		}
   756  	}
   757  
   758  	
   759  	
   760  	
   761  	if summary.goVersion != "" && gover.Compare(summary.goVersion, gover.GoStrictVersion) >= 0 {
   762  		summary.require = append(summary.require, module.Version{Path: "go", Version: summary.goVersion})
   763  		if gover.Compare(summary.goVersion, gover.Local()) > 0 {
   764  			return summary, &gover.TooNewError{What: "module " + m.String(), GoVersion: summary.goVersion}
   765  		}
   766  	}
   767  
   768  	return summary, nil
   769  }
   770  
   771  var rawGoModSummaryCache par.ErrCache[module.Version, *modFileSummary]
   772  
   773  
   774  
   775  
   776  
   777  
   778  
   779  
   780  func rawGoModData(m module.Version) (name string, data []byte, err error) {
   781  	if m.Version == "" {
   782  		dir := m.Path
   783  		if !filepath.IsAbs(dir) {
   784  			if inWorkspaceMode() && MainModules.Contains(m.Path) {
   785  				dir = MainModules.ModRoot(m)
   786  			} else {
   787  				
   788  				dir = filepath.Join(replaceRelativeTo(), dir)
   789  			}
   790  		}
   791  		name = filepath.Join(dir, "go.mod")
   792  		if fsys.Replaced(name) {
   793  			
   794  			
   795  			
   796  			data, err = os.ReadFile(fsys.Actual(name))
   797  		} else {
   798  			data, err = lockedfile.Read(name)
   799  		}
   800  		if err != nil {
   801  			return "", nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(name), err))
   802  		}
   803  	} else {
   804  		if !gover.ModIsValid(m.Path, m.Version) {
   805  			
   806  			base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version)
   807  		}
   808  		name = "go.mod"
   809  		data, err = modfetch.GoMod(context.TODO(), m.Path, m.Version)
   810  	}
   811  	return name, data, err
   812  }
   813  
   814  
   815  
   816  
   817  
   818  
   819  
   820  
   821  
   822  
   823  
   824  func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, err error) {
   825  	return latestVersionIgnoringRetractionsCache.Do(path, func() (module.Version, error) {
   826  		ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path)
   827  		defer span.Done()
   828  
   829  		if repl := Replacement(module.Version{Path: path}); repl.Path != "" {
   830  			
   831  			
   832  			return repl, nil
   833  		}
   834  
   835  		
   836  		
   837  		const ignoreSelected = ""
   838  		var allowAll AllowedFunc
   839  		rev, err := Query(ctx, path, "latest", ignoreSelected, allowAll)
   840  		if err != nil {
   841  			return module.Version{}, err
   842  		}
   843  		latest := module.Version{Path: path, Version: rev.Version}
   844  		if repl := resolveReplacement(latest); repl.Path != "" {
   845  			latest = repl
   846  		}
   847  		return latest, nil
   848  	})
   849  }
   850  
   851  var latestVersionIgnoringRetractionsCache par.ErrCache[string, module.Version] 
   852  
   853  
   854  
   855  
   856  func ToDirectoryPath(path string) string {
   857  	if modfile.IsDirectoryPath(path) {
   858  		return path
   859  	}
   860  	
   861  	
   862  	return "./" + filepath.ToSlash(filepath.Clean(path))
   863  }
   864  
View as plain text