diff --git a/cmd/cue/cmd/testdata/script/load_underscore.txtar b/cmd/cue/cmd/testdata/script/load_underscore.txtar index 3e669aa9e8e..8a412ed3ddf 100644 --- a/cmd/cue/cmd/testdata/script/load_underscore.txtar +++ b/cmd/cue/cmd/testdata/script/load_underscore.txtar @@ -1,18 +1,17 @@ # Test whether an import with a _ qualifer is allowed or not. -# TODO(rog): this should fail; see https://cuelang.org/issue/3167 -exec cue export ./foo -cmp stdout want-stdout +! exec cue export ./foo +cmp stderr want-stderr # Check that it also fails with an explicit _ qualifier -# specified on the command line. -# TODO(rog): this should fail similarly. -exec cue export other.example/m:_ -cmp stdout want-stdout --- want-stdout -- -{ - "x": 20 -} +# specified on the command line +! exec cue export other.example/m:_ +cmp stderr want-stderr-2 +-- want-stderr -- +test.example/foo/foo@v0: import failed: cannot find package "other.example/m": _ is not a valid import path qualifier in "other.example/m:_": + ./foo/foo.cue:8:8 +-- want-stderr-2 -- +invalid import path qualifier _ in "other.example/m:_" -- cue.mod/gen/other.example/m/m.cue -- package _ x: 20 diff --git a/cue/load/config.go b/cue/load/config.go index b047e39b32a..4debe5379bf 100644 --- a/cue/load/config.go +++ b/cue/load/config.go @@ -316,6 +316,9 @@ func addImportQualifier(pkg importPath, name string) (importPath, error) { return pkg, nil } ip := module.ParseImportPath(string(pkg)) + if ip.Qualifier == "_" { + return "", fmt.Errorf("invalid import qualifier _ in %q", pkg) + } if ip.ExplicitQualifier && ip.Qualifier != name { return "", fmt.Errorf("non-matching package names (%s != %s)", ip.Qualifier, name) } diff --git a/cue/load/import.go b/cue/load/import.go index 8140dfaccf9..81fac5accbb 100644 --- a/cue/load/import.go +++ b/cue/load/import.go @@ -374,6 +374,8 @@ func (l *loader) newInstance(pos token.Pos, p importPath) *build.Instance { i.PkgName = parts.Qualifier if i.PkgName == "" { i.Err = errors.Append(i.Err, l.errPkgf([]token.Pos{pos}, "cannot determine package name for %q; set it explicitly with ':'", p)) + } else if i.PkgName == "" { + i.Err = errors.Append(i.Err, l.errPkgf([]token.Pos{pos}, "_ is not a valid import path qualifier in %q", p)) } i.DisplayPath = string(p) i.ImportPath = string(p) diff --git a/cue/load/search.go b/cue/load/search.go index 622382c4347..76cbec07e46 100644 --- a/cue/load/search.go +++ b/cue/load/search.go @@ -304,6 +304,9 @@ func appendExpandedPackageArg(c *Config, pkgPaths []resolvedPackageArg, p string p = filepath.ToSlash(p) ip := module.ParseImportPath(p) + if ip.Qualifier == "_" { + return nil, fmt.Errorf("invalid import path qualifier _ in %q", origp) + } isRel := strings.HasPrefix(ip.Path, "./") // Put argument in canonical form. diff --git a/internal/mod/modpkgload/pkgload.go b/internal/mod/modpkgload/pkgload.go index 05d5235b4c2..ec403e016b2 100644 --- a/internal/mod/modpkgload/pkgload.go +++ b/internal/mod/modpkgload/pkgload.go @@ -252,6 +252,10 @@ func (pkgs *Packages) load(ctx context.Context, pkg *Package) { pkg.err = fmt.Errorf("cannot determine package name from import path %q", pkg.path) return } + if pkgQual == "_" { + pkg.err = fmt.Errorf("_ is not a valid import path qualifier in %q", pkg.path) + return + } importsMap := make(map[string]bool) foundPackageFile := false for _, loc := range pkg.locs { diff --git a/mod/module/path.go b/mod/module/path.go index d6e6865231a..a3727c633e3 100644 --- a/mod/module/path.go +++ b/mod/module/path.go @@ -482,7 +482,7 @@ func ParseImportPath(p string) ImportPath { } else { parts.Qualifier = parts.Path } - if !ast.IsValidIdent(parts.Qualifier) || strings.HasPrefix(parts.Qualifier, "#") { + if !ast.IsValidIdent(parts.Qualifier) || strings.HasPrefix(parts.Qualifier, "#") || parts.Qualifier == "_" { parts.Qualifier = "" } }