...

Source file src/pkg/cmd/go/internal/modload/list.go

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

View as plain text