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 }