1 package modload
2
3 import (
4 "context"
5 "fmt"
6 "path"
7 "runtime"
8 "sync"
9
10 "cuelang.org/go/internal/mod/modpkgload"
11 "cuelang.org/go/internal/mod/modrequirements"
12 "cuelang.org/go/internal/mod/semver"
13 "cuelang.org/go/internal/par"
14 "cuelang.org/go/mod/module"
15 )
16
17
18
19
20
21
22
23
24 func (ld *loader) queryImport(ctx context.Context, pkgPath string, rs *modrequirements.Requirements) (candidates []module.Version, needsDefault bool, err error) {
25 if modpkgload.IsStdlibPackage(pkgPath) {
26
27
28
29
30
31
32
33 return nil, false, &modpkgload.ImportMissingError{Path: pkgPath}
34 }
35
36
37
38
39
40
41 logf("cue: finding module for package %s", pkgPath)
42
43 candidates, needsDefault, err = ld.queryLatestModules(ctx, pkgPath, rs)
44 if err != nil {
45 return nil, false, err
46 }
47 if len(candidates) == 0 {
48 return nil, false, fmt.Errorf("%v", &modpkgload.ImportMissingError{Path: pkgPath})
49 }
50 return candidates, needsDefault, nil
51 }
52
53
54
55
56
57 func (ld *loader) queryLatestModules(ctx context.Context, pkgPath string, rs *modrequirements.Requirements) ([]module.Version, bool, error) {
58 parts := module.ParseImportPath(pkgPath)
59 latestModuleForPrefix := func(prefix string) (module.Version, error) {
60 mv := parts.Version
61 if mv == "" {
62 var status modrequirements.MajorVersionDefaultStatus
63 mv, status = rs.DefaultMajorVersion(prefix)
64 if status == modrequirements.AmbiguousDefault {
65
66
67 return module.Version{}, nil
68 }
69 }
70 mpath := prefix
71 if mv != "" {
72 mpath = prefix + "@" + mv
73 if _, ok := rs.RootSelected(mpath); ok {
74
75 return module.Version{}, nil
76 }
77 }
78
79 versions, err := ld.registry.ModuleVersions(ctx, mpath)
80 logf("getting module versions for %q (prefix %q) -> %q, %v", mpath, prefix, versions, err)
81 if err != nil {
82 return module.Version{}, err
83 }
84 logf("-> %q", versions)
85 if v := latestVersion(versions); v != "" {
86 return module.NewVersion(prefix, v)
87 }
88 return module.Version{}, nil
89 }
90 work := par.NewQueue(runtime.GOMAXPROCS(0))
91 var (
92 mu sync.Mutex
93 candidates []module.Version
94 queryErr error
95 )
96 logf("initial module path %q", parts.Path)
97 for prefix := parts.Path; prefix != "."; prefix = path.Dir(prefix) {
98 prefix := prefix
99 work.Add(func() {
100 v, err := latestModuleForPrefix(prefix)
101 mu.Lock()
102 defer mu.Unlock()
103 if err != nil {
104 if queryErr == nil {
105 queryErr = err
106 }
107 return
108 }
109 if v.IsValid() {
110 candidates = append(candidates, v)
111 }
112 })
113 }
114 <-work.Idle()
115 return candidates, parts.Version == "", queryErr
116 }
117
118
119
120 func latestVersion(versions []string) string {
121 maxStable := ""
122 maxAny := ""
123 for _, v := range versions {
124 if semver.Prerelease(v) == "" && (maxStable == "" || semver.Compare(v, maxStable) > 0) {
125 maxStable = v
126 }
127 if maxAny == "" || semver.Compare(v, maxAny) > 0 {
128 maxAny = v
129 }
130 }
131 if maxStable != "" {
132 return maxStable
133 }
134 return maxAny
135 }
136
View as plain text