github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/modload/list.go (about)

     1  // Copyright 2018 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  	"errors"
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/base"
    14  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg"
    15  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/modinfo"
    16  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/par"
    17  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/search"
    18  
    19  	"golang.org/x/mod/module"
    20  )
    21  
    22  func ListModules(args []string, listU, listVersions bool) []*modinfo.ModulePublic {
    23  	mods := listModules(args, listVersions)
    24  	if listU || listVersions {
    25  		var work par.Work
    26  		for _, m := range mods {
    27  			work.Add(m)
    28  			if m.Replace != nil {
    29  				work.Add(m.Replace)
    30  			}
    31  		}
    32  		work.Do(10, func(item interface{}) {
    33  			m := item.(*modinfo.ModulePublic)
    34  			if listU {
    35  				addUpdate(m)
    36  			}
    37  			if listVersions {
    38  				addVersions(m)
    39  			}
    40  		})
    41  	}
    42  	return mods
    43  }
    44  
    45  func listModules(args []string, listVersions bool) []*modinfo.ModulePublic {
    46  	LoadBuildList()
    47  	if len(args) == 0 {
    48  		return []*modinfo.ModulePublic{moduleInfo(buildList[0], true)}
    49  	}
    50  
    51  	var mods []*modinfo.ModulePublic
    52  	matchedBuildList := make([]bool, len(buildList))
    53  	for _, arg := range args {
    54  		if strings.Contains(arg, `\`) {
    55  			base.Fatalf("go: module paths never use backslash")
    56  		}
    57  		if search.IsRelativePath(arg) {
    58  			base.Fatalf("go: cannot use relative path %s to specify module", arg)
    59  		}
    60  		if !HasModRoot() && (arg == "all" || strings.Contains(arg, "...")) {
    61  			base.Fatalf("go: cannot match %q: working directory is not part of a module", arg)
    62  		}
    63  		if i := strings.Index(arg, "@"); i >= 0 {
    64  			path := arg[:i]
    65  			vers := arg[i+1:]
    66  			var current string
    67  			for _, m := range buildList {
    68  				if m.Path == path {
    69  					current = m.Version
    70  					break
    71  				}
    72  			}
    73  
    74  			info, err := Query(path, vers, current, nil)
    75  			if err != nil {
    76  				mods = append(mods, &modinfo.ModulePublic{
    77  					Path:    path,
    78  					Version: vers,
    79  					Error:   modinfoError(path, vers, err),
    80  				})
    81  				continue
    82  			}
    83  			mods = append(mods, moduleInfo(module.Version{Path: path, Version: info.Version}, false))
    84  			continue
    85  		}
    86  
    87  		// Module path or pattern.
    88  		var match func(string) bool
    89  		var literal bool
    90  		if arg == "all" {
    91  			match = func(string) bool { return true }
    92  		} else if strings.Contains(arg, "...") {
    93  			match = search.MatchPattern(arg)
    94  		} else {
    95  			match = func(p string) bool { return arg == p }
    96  			literal = true
    97  		}
    98  		matched := false
    99  		for i, m := range buildList {
   100  			if i == 0 && !HasModRoot() {
   101  				// The root module doesn't actually exist: omit it.
   102  				continue
   103  			}
   104  			if match(m.Path) {
   105  				matched = true
   106  				if !matchedBuildList[i] {
   107  					matchedBuildList[i] = true
   108  					mods = append(mods, moduleInfo(m, true))
   109  				}
   110  			}
   111  		}
   112  		if !matched {
   113  			if literal {
   114  				if listVersions {
   115  					// Don't make the user provide an explicit '@latest' when they're
   116  					// explicitly asking what the available versions are.
   117  					// Instead, resolve the module, even if it isn't an existing dependency.
   118  					info, err := Query(arg, "latest", "", nil)
   119  					if err == nil {
   120  						mods = append(mods, moduleInfo(module.Version{Path: arg, Version: info.Version}, false))
   121  					} else {
   122  						mods = append(mods, &modinfo.ModulePublic{
   123  							Path:  arg,
   124  							Error: modinfoError(arg, "", err),
   125  						})
   126  					}
   127  					continue
   128  				}
   129  				if cfg.BuildMod == "vendor" {
   130  					// In vendor mode, we can't determine whether a missing module is “a
   131  					// known dependency” because the module graph is incomplete.
   132  					// Give a more explicit error message.
   133  					mods = append(mods, &modinfo.ModulePublic{
   134  						Path:  arg,
   135  						Error: modinfoError(arg, "", errors.New("can't resolve module using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")),
   136  					})
   137  				} else {
   138  					mods = append(mods, &modinfo.ModulePublic{
   139  						Path:  arg,
   140  						Error: modinfoError(arg, "", errors.New("not a known dependency")),
   141  					})
   142  				}
   143  			} else {
   144  				fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
   145  			}
   146  		}
   147  	}
   148  
   149  	return mods
   150  }
   151  
   152  // modinfoError wraps an error to create an error message in
   153  // modinfo.ModuleError with minimal redundancy.
   154  func modinfoError(path, vers string, err error) *modinfo.ModuleError {
   155  	var nerr *NoMatchingVersionError
   156  	var merr *module.ModuleError
   157  	if errors.As(err, &nerr) {
   158  		// NoMatchingVersionError contains the query, so we don't mention the
   159  		// query again in ModuleError.
   160  		err = &module.ModuleError{Path: path, Err: err}
   161  	} else if !errors.As(err, &merr) {
   162  		// If the error does not contain path and version, wrap it in a
   163  		// module.ModuleError.
   164  		err = &module.ModuleError{Path: path, Version: vers, Err: err}
   165  	}
   166  
   167  	return &modinfo.ModuleError{Err: err.Error()}
   168  }