Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/go/internal/modload/mvs.go

Documentation: cmd/go/internal/modload

     1  // Copyright 2020 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  package modload
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"os"
    11  	"sort"
    12  
    13  	"cmd/go/internal/modfetch"
    14  
    15  	"golang.org/x/mod/module"
    16  	"golang.org/x/mod/semver"
    17  )
    18  
    19  // mvsReqs implements mvs.Reqs for module semantic versions,
    20  // with any exclusions or replacements applied internally.
    21  type mvsReqs struct {
    22  	buildList []module.Version
    23  }
    24  
    25  func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
    26  	if mod == Target {
    27  		// Use the build list as it existed when r was constructed, not the current
    28  		// global build list.
    29  		return r.buildList[1:], nil
    30  	}
    31  
    32  	if mod.Version == "none" {
    33  		return nil, nil
    34  	}
    35  
    36  	summary, err := goModSummary(mod)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	return summary.require, nil
    41  }
    42  
    43  // Max returns the maximum of v1 and v2 according to semver.Compare.
    44  //
    45  // As a special case, the version "" is considered higher than all other
    46  // versions. The main module (also known as the target) has no version and must
    47  // be chosen over other versions of the same module in the module dependency
    48  // graph.
    49  func (*mvsReqs) Max(v1, v2 string) string {
    50  	if v1 != "" && (v2 == "" || semver.Compare(v1, v2) == -1) {
    51  		return v2
    52  	}
    53  	return v1
    54  }
    55  
    56  // Upgrade is a no-op, here to implement mvs.Reqs.
    57  // The upgrade logic for go get -u is in ../modget/get.go.
    58  func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) {
    59  	return m, nil
    60  }
    61  
    62  func versions(ctx context.Context, path string, allowed AllowedFunc) ([]string, error) {
    63  	// Note: modfetch.Lookup and repo.Versions are cached,
    64  	// so there's no need for us to add extra caching here.
    65  	var versions []string
    66  	err := modfetch.TryProxies(func(proxy string) error {
    67  		repo, err := lookupRepo(proxy, path)
    68  		if err != nil {
    69  			return err
    70  		}
    71  		allVersions, err := repo.Versions("")
    72  		if err != nil {
    73  			return err
    74  		}
    75  		allowedVersions := make([]string, 0, len(allVersions))
    76  		for _, v := range allVersions {
    77  			if err := allowed(ctx, module.Version{Path: path, Version: v}); err == nil {
    78  				allowedVersions = append(allowedVersions, v)
    79  			} else if !errors.Is(err, ErrDisallowed) {
    80  				return err
    81  			}
    82  		}
    83  		versions = allowedVersions
    84  		return nil
    85  	})
    86  	return versions, err
    87  }
    88  
    89  // Previous returns the tagged version of m.Path immediately prior to
    90  // m.Version, or version "none" if no prior version is tagged.
    91  //
    92  // Since the version of Target is not found in the version list,
    93  // it has no previous version.
    94  func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
    95  	// TODO(golang.org/issue/38714): thread tracing context through MVS.
    96  
    97  	if m == Target {
    98  		return module.Version{Path: m.Path, Version: "none"}, nil
    99  	}
   100  
   101  	list, err := versions(context.TODO(), m.Path, CheckAllowed)
   102  	if err != nil {
   103  		if errors.Is(err, os.ErrNotExist) {
   104  			return module.Version{Path: m.Path, Version: "none"}, nil
   105  		}
   106  		return module.Version{}, err
   107  	}
   108  	i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 })
   109  	if i > 0 {
   110  		return module.Version{Path: m.Path, Version: list[i-1]}, nil
   111  	}
   112  	return module.Version{Path: m.Path, Version: "none"}, nil
   113  }
   114  

View as plain text