cmd/cue/cmd: allow fmt to pass with errors

Also fixes use of internal `*` to match all packages.

Fixes #653
Fixes #644

Change-Id: I3f507c8a7d8013372972cbb11c9eeac01a50ce9f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8301
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/common.go b/cmd/cue/cmd/common.go
index 637238b..e8effa6 100644
--- a/cmd/cue/cmd/common.go
+++ b/cmd/cue/cmd/common.go
@@ -361,7 +361,7 @@
 	loadCfg *load.Config
 }
 
-func parseArgs(cmd *Command, args []string, cfg *config) (p *buildPlan, err error) {
+func newBuildPlan(cmd *Command, args []string, cfg *config) (p *buildPlan, err error) {
 	if cfg == nil {
 		cfg = &defaultConfig
 	}
@@ -378,6 +378,15 @@
 
 	cfg.loadCfg.Tags = flagInject.StringArray(cmd)
 
+	return p, nil
+}
+
+func parseArgs(cmd *Command, args []string, cfg *config) (p *buildPlan, err error) {
+	p, err = newBuildPlan(cmd, args, cfg)
+	if err != nil {
+		return nil, err
+	}
+
 	builds := loadFromArgs(cmd, args, cfg.loadCfg)
 	if builds == nil {
 		return nil, errors.Newf(token.NoPos, "invalid args")
diff --git a/cmd/cue/cmd/fmt.go b/cmd/cue/cmd/fmt.go
index 659619c..6eec40a 100644
--- a/cmd/cue/cmd/fmt.go
+++ b/cmd/cue/cmd/fmt.go
@@ -19,8 +19,10 @@
 
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/build"
+	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/load"
+	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal/encoding"
 	"cuelang.org/go/tools/fix"
 )
@@ -32,7 +34,7 @@
 		Long: `Fmt formats the given files or the files for the given packages in place
 `,
 		RunE: mkRunE(c, func(cmd *Command, args []string) error {
-			plan, err := parseArgs(cmd, args, &config{loadCfg: &load.Config{
+			plan, err := newBuildPlan(cmd, args, &config{loadCfg: &load.Config{
 				Tests:       true,
 				Tools:       true,
 				AllCUEFiles: true,
@@ -40,6 +42,11 @@
 			}})
 			exitOnErr(cmd, err, true)
 
+			builds := loadFromArgs(cmd, args, plan.cfg.loadCfg)
+			if builds == nil {
+				exitOnErr(cmd, errors.Newf(token.NoPos, "invalid args"), true)
+			}
+
 			opts := []format.Option{}
 			if flagSimplify.Bool(cmd) {
 				opts = append(opts, format.Simplify())
@@ -49,10 +56,15 @@
 			cfg.Format = opts
 			cfg.Force = true
 
-			for _, inst := range plan.insts {
+			for _, inst := range builds {
 				if inst.Err != nil {
-					exitOnErr(cmd, inst.Err, false)
-					continue
+					var p *load.PackageError
+					switch {
+					case errors.As(inst.Err, &p):
+					default:
+						exitOnErr(cmd, inst.Err, false)
+						continue
+					}
 				}
 				for _, file := range inst.BuildFiles {
 					files := []*ast.File{}
diff --git a/cmd/cue/cmd/testdata/script/fmt_err.txt b/cmd/cue/cmd/testdata/script/fmt_err.txt
new file mode 100644
index 0000000..cefc9a9
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/fmt_err.txt
@@ -0,0 +1,23 @@
+# ignore certain errors for cue fmt
+cue fmt x.cue
+
+# Issue #644
+cue fmt ./...
+
+cmp x.cue out/x_cue
+-- cue.mod/module.cue --
+module: "example.com/x"
+-- x.cue --
+package x
+
+import   "blah.com/rubbish"
+
+x: 5
+y: unresolved
+-- out/x_cue --
+package x
+
+import "blah.com/rubbish"
+
+x: 5
+y: unresolved
diff --git a/cue/load/config.go b/cue/load/config.go
index cbc0fb4..535b6b6 100644
--- a/cue/load/config.go
+++ b/cue/load/config.go
@@ -324,7 +324,7 @@
 			"non-canonical import path: %q should be %q", path, pathpkg.Clean(path)))
 	}
 
-	if importPath, e := c.importPathFromAbsDir(fsPath(dir), path, c.Package); e != nil {
+	if importPath, e := c.importPathFromAbsDir(fsPath(dir), path); e != nil {
 		// Detect later to keep error messages consistent.
 	} else {
 		p.ImportPath = string(importPath)
@@ -358,7 +358,7 @@
 
 type fsPath string
 
-func (c *Config) importPathFromAbsDir(absDir fsPath, key, name string) (importPath, errors.Error) {
+func (c *Config) importPathFromAbsDir(absDir fsPath, key string) (importPath, errors.Error) {
 	if c.ModuleRoot == "" {
 		return "", errors.Newf(token.NoPos,
 			"cannot determine import path for %q (root undefined)", key)
@@ -394,6 +394,12 @@
 		pkg = c.Module + pkg
 	}
 
+	name := c.Package
+	switch name {
+	case "_", "*":
+		name = ""
+	}
+
 	return addImportQualifier(importPath(pkg), name)
 }
 
diff --git a/cue/load/import.go b/cue/load/import.go
index fd4787a..9f6e9ad 100644
--- a/cue/load/import.go
+++ b/cue/load/import.go
@@ -151,7 +151,10 @@
 
 	if !found {
 		return retErr(
-			errors.Newf(token.NoPos, "cannot find package %q", p.DisplayPath))
+			&PackageError{
+				Message: errors.NewMessage("cannot find package %q",
+					[]interface{}{p.DisplayPath}),
+			})
 	}
 
 	// This algorithm assumes that multiple directories within cue.mod/*/