cmd/cue: allow help to work without cue files

Change-Id: Id6d0fb9c40c5b714c45f970350705e3b9b67f64f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2946
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/common.go b/cmd/cue/cmd/common.go
index 0a8e36a..9908328 100644
--- a/cmd/cue/cmd/common.go
+++ b/cmd/cue/cmd/common.go
@@ -118,6 +118,23 @@
 	return instances
 }
 
+func buildToolInstances(cmd *cobra.Command, binst []*build.Instance) ([]*cue.Instance, error) {
+	instances := cue.Build(binst)
+	for _, inst := range instances {
+		if inst.Err != nil {
+			return nil, inst.Err
+		}
+	}
+
+	// TODO check errors after the fact in case of ignore.
+	for _, inst := range instances {
+		if err := inst.Value().Validate(); err != nil {
+			return nil, err
+		}
+	}
+	return instances, nil
+}
+
 func buildTools(cmd *cobra.Command, args []string) (*cue.Instance, error) {
 	binst := loadFromArgs(cmd, args)
 	if len(binst) == 0 {
@@ -136,6 +153,11 @@
 		}
 	}
 
-	inst := cue.Merge(buildInstances(cmd, binst)...).Build(ti)
+	insts, err := buildToolInstances(cmd, binst)
+	if err != nil {
+		return nil, err
+	}
+
+	inst := cue.Merge(insts...).Build(ti)
 	return inst, inst.Err
 }
diff --git a/cmd/cue/cmd/root.go b/cmd/cue/cmd/root.go
index 6dfefa1..e34a40a 100644
--- a/cmd/cue/cmd/root.go
+++ b/cmd/cue/cmd/root.go
@@ -161,7 +161,9 @@
 	}
 
 	if args[0] == "help" {
-		return cmd, addSubcommands(cmd, sub, args[1:])
+		// Allow errors.
+		_ = addSubcommands(cmd, sub, args[1:])
+		return cmd, nil
 	}
 
 	if _, ok := sub[args[0]]; ok {
diff --git a/cmd/cue/cmd/root_test.go b/cmd/cue/cmd/root_test.go
new file mode 100644
index 0000000..1a5a14f
--- /dev/null
+++ b/cmd/cue/cmd/root_test.go
@@ -0,0 +1,24 @@
+// Copyright 2019 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 cmd
+
+import "testing"
+
+func TestHelp(t *testing.T) {
+	cmd, err := New([]string{"help", "cmd"})
+	if err != nil || cmd == nil {
+		t.Error("help command failed unexpectedly")
+	}
+}