internal/filetypes: expose package test internally
Change-Id: Ia76a84d6123c37c42bf57a0028aae27c4d92227c
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5402
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/load/loader.go b/cue/load/loader.go
index 405fa39..3e3c789 100644
--- a/cue/load/loader.go
+++ b/cue/load/loader.go
@@ -25,7 +25,6 @@
"strings"
"unicode"
- "cuelang.org/go/cue/ast"
"cuelang.org/go/cue/build"
"cuelang.org/go/cue/errors"
"cuelang.org/go/cue/token"
@@ -54,7 +53,7 @@
// TODO: require packages to be placed before files. At some point this
// could be relaxed.
i := 0
- for ; i < len(args) && isPkg(args[i]); i++ {
+ for ; i < len(args) && filetypes.IsPackage(args[i]); i++ {
}
a := []*build.Instance{}
@@ -81,40 +80,6 @@
return a
}
-func isPkg(s string) bool {
- if s == "." || s == ".." {
- return true
- }
- if s == "-" {
- return false
- }
-
- // This goes of the assumption that file names may not have a `:` in their
- // name in cue.
- // A filename must have an extension or be preceded by a qualifier argument.
- // So strings of the form foo/bar:baz, where bar is a valid identifier and
- // absolute package
- if p := strings.LastIndexByte(s, ':'); p > 0 {
- if !ast.IsValidIdent(s[p+1:]) {
- return false
- }
- // For a non-pkg, the part before : may only be lowercase and '+'.
- // In addition, a package necessarily must have a slash of some form.
- return strings.ContainsAny(s[:p], `/.\`)
- }
-
- // Assuming we terminate search for packages once a scoped qualifier is
- // found, we know that any file without an extension (except maybe '-')
- // is invalid. We can therefore assume it is a package.
- // The section may still contain a dot, for instance ./foo/. or ./foo/...
- return strings.TrimLeft(filepath.Ext(s), ".") == ""
-
- // NOTE/TODO: we have not needed to check whether it is an absolute package
- // or whether the package starts with a dot. Potentially we could thus relax
- // the requirement that packages be dots if it is clear that the package
- // name will not interfere with command names in all circumstances.
-}
-
// Mode flags for loadImport and download (in get.go).
const (
// resolveImport means that loadImport should do import path expansion.
diff --git a/cue/load/loader_test.go b/cue/load/loader_test.go
index 524333a..4a05f0c 100644
--- a/cue/load/loader_test.go
+++ b/cue/load/loader_test.go
@@ -351,34 +351,3 @@
}
}
}
-
-func TestIsPkg(t *testing.T) {
- testCases := []struct {
- in string
- out bool
- }{
- {".", true},
- {"..", true},
- {"../.../foo", true},
- {".../foo", true},
- {"./:foo", true},
- {"foo.bar/foo", true},
-
- // Not supported yet, but could be and isn't anything else valid.
- {":foo", true},
-
- {"foo.bar", false},
- {"foo:", false},
- {"foo:bar:baz", false},
- {"-", false},
- {"-:foo", false},
- }
- for _, tc := range testCases {
- t.Run(tc.in, func(t *testing.T) {
- got := isPkg(tc.in)
- if got != tc.out {
- t.Errorf("got %v; want %v", got, tc.out)
- }
- })
- }
-}
diff --git a/internal/filetypes/util.go b/internal/filetypes/util.go
new file mode 100644
index 0000000..01d2760
--- /dev/null
+++ b/internal/filetypes/util.go
@@ -0,0 +1,58 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filetypes
+
+import (
+ "path/filepath"
+ "strings"
+
+ "cuelang.org/go/cue/ast"
+)
+
+// IsPackage reports whether a command-line argument is a package based on its
+// lexical representation alone.
+func IsPackage(s string) bool {
+ if s == "." || s == ".." {
+ return true
+ }
+ if s == "-" {
+ return false
+ }
+
+ // This goes of the assumption that file names may not have a `:` in their
+ // name in cue.
+ // A filename must have an extension or be preceded by a qualifier argument.
+ // So strings of the form foo/bar:baz, where bar is a valid identifier and
+ // absolute package
+ if p := strings.LastIndexByte(s, ':'); p > 0 {
+ if !ast.IsValidIdent(s[p+1:]) {
+ return false
+ }
+ // For a non-pkg, the part before : may only be lowercase and '+'.
+ // In addition, a package necessarily must have a slash of some form.
+ return strings.ContainsAny(s[:p], `/.\`)
+ }
+
+ // Assuming we terminate search for packages once a scoped qualifier is
+ // found, we know that any file without an extension (except maybe '-')
+ // is invalid. We can therefore assume it is a package.
+ // The section may still contain a dot, for instance ./foo/. or ./foo/...
+ return strings.TrimLeft(filepath.Ext(s), ".") == ""
+
+ // NOTE/TODO: we have not needed to check whether it is an absolute package
+ // or whether the package starts with a dot. Potentially we could thus relax
+ // the requirement that packages be dots if it is clear that the package
+ // name will not interfere with command names in all circumstances.
+}
diff --git a/internal/filetypes/util_test.go b/internal/filetypes/util_test.go
new file mode 100644
index 0000000..4c92316
--- /dev/null
+++ b/internal/filetypes/util_test.go
@@ -0,0 +1,48 @@
+// Copyright 2020 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filetypes
+
+import "testing"
+
+func TestIsPackage(t *testing.T) {
+ testCases := []struct {
+ in string
+ out bool
+ }{
+ {".", true},
+ {"..", true},
+ {"../.../foo", true},
+ {".../foo", true},
+ {"./:foo", true},
+ {"foo.bar/foo", true},
+
+ // Not supported yet, but could be and isn't anything else valid.
+ {":foo", true},
+
+ {"foo.bar", false},
+ {"foo:", false},
+ {"foo:bar:baz", false},
+ {"-", false},
+ {"-:foo", false},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.in, func(t *testing.T) {
+ got := IsPackage(tc.in)
+ if got != tc.out {
+ t.Errorf("got %v; want %v", got, tc.out)
+ }
+ })
+ }
+}