Skip to content

Commit 2c18c7c

Browse files
committed
cue/load: allow storing module in cue.mod
Analogous to the module in go.mod, but using CUE syntax. This is to be used for modules where CUE files import within the module root but the module name cannot be derived from the context. Change-Id: I4befd7cecb33c980c478bbe13e49534642b1aaa6 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2370 Reviewed-by: Marcel van Lohuizen <[email protected]>
1 parent eadbea7 commit 2c18c7c

File tree

4 files changed

+57
-13
lines changed

4 files changed

+57
-13
lines changed

cue/load/config.go

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"path/filepath"
2020
"runtime"
2121

22+
"cuelang.org/go/cue"
2223
"cuelang.org/go/cue/build"
2324
"cuelang.org/go/cue/errors"
2425
"cuelang.org/go/cue/token"
@@ -75,7 +76,14 @@ type Config struct {
7576

7677
loader *loader
7778

78-
modRoot string // module root for package paths ("" if unknown)
79+
// A Module is a collection of packages and instances that are within the
80+
// directory hierarchy rooted at the module root. The module root can be
81+
// marked with a cue.mod file.
82+
ModuleRoot string
83+
84+
// Module specifies the module prefix. If not empty, this value must match
85+
// the module field of an existing cue.mod file.
86+
Module string
7987

8088
// cache specifies the package cache in which to look for packages.
8189
cache string
@@ -173,13 +181,13 @@ func (c Config) complete() (cfg *Config, err error) {
173181
// TODO: determine root on a package basis. Maybe we even need a
174182
// pkgname.cue.mod
175183
// Look to see if there is a cue.mod.
176-
if c.modRoot == "" {
184+
if c.ModuleRoot == "" {
177185
abs, err := c.findRoot(c.Dir)
178186
if err != nil {
179187
// Not using modules: only consider the current directory.
180-
c.modRoot = c.Dir
188+
c.ModuleRoot = c.Dir
181189
} else {
182-
c.modRoot = abs
190+
c.ModuleRoot = abs
183191
}
184192
}
185193

@@ -193,6 +201,32 @@ func (c Config) complete() (cfg *Config, err error) {
193201
c.cache = filepath.Join(home(), defaultDir)
194202
}
195203

204+
// TODO: also make this work if run from outside the module?
205+
switch {
206+
case true:
207+
mod := filepath.Join(c.ModuleRoot, modFile)
208+
f, cerr := c.fileSystem.openFile(mod)
209+
if cerr != nil {
210+
break
211+
}
212+
var r cue.Runtime
213+
inst, err := r.Parse(mod, f)
214+
if err != nil {
215+
return nil, errors.Wrapf(err, token.NoPos, "invalid cue.mod file")
216+
}
217+
prefix := inst.Lookup("module")
218+
if prefix.IsValid() {
219+
name, err := prefix.String()
220+
if err != nil {
221+
return nil, err
222+
}
223+
if c.Module == "" || c.Module != name {
224+
return nil, errors.Newf(prefix.Pos(), "inconsistent modules: got %q, want %q", name, c.Module)
225+
}
226+
c.Module = name
227+
}
228+
}
229+
196230
return &c, nil
197231
}
198232

cue/load/import.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ func (l *loader) importPkg(pos token.Pos, path, srcDir string) *build.Instance {
8181
p.DisplayPath = path
8282

8383
isLocal := isLocalImport(path)
84+
85+
if cfg.Module != "" && isLocal {
86+
p.ImportPath = filepath.Join(cfg.Module, path)
87+
}
88+
8489
var modDir string
8590
// var modErr error
8691
if !isLocal {
@@ -125,7 +130,7 @@ func (l *loader) importPkg(pos token.Pos, path, srcDir string) *build.Instance {
125130
}
126131
}
127132

128-
if rootFound || dir == p.Root || fp.pkg.PkgName == "" {
133+
if rootFound || filepath.Clean(dir) == l.cfg.ModuleRoot || fp.pkg.PkgName == "" {
129134
break
130135
}
131136

@@ -176,13 +181,19 @@ func (l *loader) loadFunc(parentPath string) build.LoadFunc {
176181
}
177182
return nil
178183
}
179-
if cfg.modRoot == "" {
184+
if cfg.ModuleRoot == "" {
180185
i := cfg.newInstance(path)
181186
report(i, l.errPkgf(nil,
182187
"import %q not found in the pkg directory", path))
183188
return i
184189
}
185-
return l.importPkg(pos, path, filepath.Join(cfg.modRoot, "pkg"))
190+
root := cfg.ModuleRoot
191+
if mod := cfg.Module; path == mod || strings.HasPrefix(path, mod+"/") {
192+
path = path[len(mod)+1:]
193+
} else {
194+
root = filepath.Join(root, "pkg")
195+
}
196+
return l.importPkg(pos, path, root)
186197
}
187198

188199
if strings.Contains(path, "@") {

cue/load/loader.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func Instances(args []string, c *Config) []*build.Instance {
4242

4343
c, err := c.complete()
4444
if err != nil {
45-
return nil
45+
return []*build.Instance{c.newErrInstance(nil, "", err)}
4646
}
4747

4848
l := c.loader
@@ -57,8 +57,7 @@ func Instances(args []string, c *Config) []*build.Instance {
5757
a := []*build.Instance{}
5858
for _, m := range l.importPaths(args) {
5959
if m.Err != nil {
60-
inst := c.newErrInstance(m, "",
61-
errors.Wrapf(m.Err, token.NoPos, "no match"))
60+
inst := c.newErrInstance(m, "", m.Err)
6261
a = append(a, inst)
6362
continue
6463
}

cue/load/search.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ func (l *loader) matchPackagesInFS(pattern string) *match {
148148

149149
root := l.abs(dir)
150150

151-
if c.modRoot != "" {
152-
if !hasFilepathPrefix(root, c.modRoot) {
151+
if c.ModuleRoot != "" {
152+
if !hasFilepathPrefix(root, c.ModuleRoot) {
153153
m.Err = errors.Newf(token.NoPos,
154154
"cue: pattern %s refers to dir %s, outside module root %s",
155-
pattern, root, c.modRoot)
155+
pattern, root, c.ModuleRoot)
156156
return m
157157
}
158158
}

0 commit comments

Comments
 (0)