cmd/cue: support --force for all commands that allow output flags

Somewhat consolidates this logic.

Add tests for each for completeness (because not all codepaths are the
same).

Change-Id: If6296eef1bfd4f36a755546c9bb4de21a4c40cbc
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9567
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cmd/cue/cmd/common.go b/cmd/cue/cmd/common.go
index 996b977..7caf830 100644
--- a/cmd/cue/cmd/common.go
+++ b/cmd/cue/cmd/common.go
@@ -646,6 +646,7 @@
 		b.cfg.fileFilter = s
 	}
 	b.encConfig = &encoding.Config{
+		Force:     flagForce.Bool(b.cmd),
 		Mode:      b.cfg.outMode,
 		Stdin:     b.cmd.InOrStdin(),
 		Stdout:    b.cmd.OutOrStdout(),
diff --git a/cmd/cue/cmd/export.go b/cmd/cue/cmd/export.go
index f9b3037..a675261 100644
--- a/cmd/cue/cmd/export.go
+++ b/cmd/cue/cmd/export.go
@@ -96,9 +96,7 @@
 	addOrphanFlags(cmd.Flags())
 
 	cmd.Flags().Bool(string(flagEscape), false, "use HTML escaping")
-
 	cmd.Flags().StringArrayP(string(flagExpression), "e", nil, "export this expression only")
-
 	cmd.Flags().StringArrayP(string(flagInject), "t", nil,
 		"set the value of a tagged field")
 
diff --git a/cmd/cue/cmd/flags.go b/cmd/cue/cmd/flags.go
index e5e2588..f0ab776 100644
--- a/cmd/cue/cmd/flags.go
+++ b/cmd/cue/cmd/flags.go
@@ -56,6 +56,7 @@
 	}
 	f.StringP(string(flagOutFile), "o", "",
 		`filename or - for stdout with optional file prefix (run 'cue filetypes' for more info)`)
+	f.BoolP(string(flagForce), "f", false, "force overwriting existing files")
 }
 
 func addGlobalFlags(f *pflag.FlagSet) {
diff --git a/cmd/cue/cmd/import.go b/cmd/cue/cmd/import.go
index cd417c5..c57c3c0 100644
--- a/cmd/cue/cmd/import.go
+++ b/cmd/cue/cmd/import.go
@@ -247,7 +247,6 @@
 	addOrphanFlags(cmd.Flags())
 
 	cmd.Flags().Bool(string(flagFiles), false, "split multiple entries into different files")
-	cmd.Flags().BoolP(string(flagForce), "f", false, "force overwriting existing files")
 	cmd.Flags().Bool(string(flagDryrun), false, "only run simulation")
 	cmd.Flags().BoolP(string(flagRecursive), "R", false, "recursively parse string values")
 
diff --git a/cmd/cue/cmd/testdata/script/def_force.txt b/cmd/cue/cmd/testdata/script/def_force.txt
new file mode 100644
index 0000000..7a21be9
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/def_force.txt
@@ -0,0 +1,19 @@
+# Verify that def with --force works
+
+# First time should simply succeed
+cue def -o test.cue file.cue
+cmp test.cue file.cue
+
+# Second time will fail without --force
+! cue def -o test.cue file.cue
+stderr 'error writing "test.cue": file already exists'
+
+# Second time with --force should succeed
+cue def --force -o test.cue file.cue
+cmp test.cue file.cue
+
+-- file.cue --
+package hello
+
+#who:    "World"
+message: "Hello \(#who)!"
diff --git a/cmd/cue/cmd/testdata/script/eval_force.txt b/cmd/cue/cmd/testdata/script/eval_force.txt
new file mode 100644
index 0000000..3cff73d
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/eval_force.txt
@@ -0,0 +1,22 @@
+# Verify that eval with --force works
+
+# First time should simply succeed
+cue eval -o eval.cue file.cue
+cmp eval.cue eval.golden
+
+# Second time will fail without --force
+! cue eval -o eval.cue file.cue
+stderr 'error writing "eval.cue": file already exists'
+
+# Second time with --force should succeed
+cue eval --force -o eval.cue file.cue
+cmp eval.cue eval.golden
+
+-- file.cue --
+package hello
+
+#who:    "World"
+message: "Hello \(#who)!"
+-- eval.golden --
+#who:    "World"
+message: "Hello World!"
diff --git a/cmd/cue/cmd/testdata/script/export_force.txt b/cmd/cue/cmd/testdata/script/export_force.txt
new file mode 100644
index 0000000..7f6389c
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/export_force.txt
@@ -0,0 +1,21 @@
+# Verify that export with --force works
+
+# First time should simply succeed
+cue export -o test.yml file.cue
+cmp test.yml test.yml.golden
+
+# Second time will fail without --force
+!  cue export -o test.yml file.cue
+stderr 'error writing "test.yml": file already exists'
+
+# Second time with --force should succeed
+cue export --force -o test.yml file.cue
+cmp test.yml test.yml.golden
+
+-- file.cue --
+package hello
+
+#who: "World"
+message: "Hello \(#who)!"
+-- test.yml.golden --
+message: Hello World!
diff --git a/cmd/cue/cmd/testdata/script/trim_force.txt b/cmd/cue/cmd/testdata/script/trim_force.txt
new file mode 100644
index 0000000..b23500c
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/trim_force.txt
@@ -0,0 +1,19 @@
+# Verify that trim with --force works
+
+# First time should simply succeed
+cue trim -o test.cue file.cue
+cmp test.cue file.cue
+
+# Second time will fail without --force
+! cue trim -o test.cue file.cue
+stderr 'error writing "test.cue": file already exists'
+
+# Second time with --force should succeed
+cue trim --force -o test.cue file.cue
+cmp test.cue file.cue
+
+-- file.cue --
+package hello
+
+#who:    "World"
+message: "Hello \(#who)!"
diff --git a/cmd/cue/cmd/trim.go b/cmd/cue/cmd/trim.go
index 9ad5d30..8d171b7 100644
--- a/cmd/cue/cmd/trim.go
+++ b/cmd/cue/cmd/trim.go
@@ -100,12 +100,11 @@
 	instances := buildInstances(cmd, binst)
 
 	dst := flagOutFile.String(cmd)
-	if dst != "" && dst != "-" {
+	if dst != "" && dst != "-" && !flagForce.Bool(cmd) {
 		switch _, err := os.Stat(dst); {
 		case os.IsNotExist(err):
-		case err == nil:
 		default:
-			return fmt.Errorf("error creating file: %v", err)
+			return fmt.Errorf("error writing %q: file already exists", dst)
 		}
 	}