pkg/tool/exec: fix stdin processing
Change-Id: I192ac14ae1123fd115c048c44fec18cd37a626f7
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4600
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/custom.go b/cmd/cue/cmd/custom.go
index 7000921..4835153 100644
--- a/cmd/cue/cmd/custom.go
+++ b/cmd/cue/cmd/custom.go
@@ -298,7 +298,7 @@
// NOTE: ignore the linter warning for the following line:
// itask.Context is an internal type and we want to break if any
// fields are added.
- c := &itask.Context{ctx, stdout, stderr, obj, nil}
+ c := &itask.Context{ctx, stdin, stdout, stderr, obj, nil}
update, err := t.Run(c)
if c.Err != nil {
err = c.Err
diff --git a/cmd/cue/cmd/testdata/script/cmd_stdin.txt b/cmd/cue/cmd/testdata/script/cmd_stdin.txt
new file mode 100644
index 0000000..a397a47
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/cmd_stdin.txt
@@ -0,0 +1,27 @@
+stdin stdin.txt
+cue cmd echo
+cmp stdout expect-stdout
+
+
+-- expect-stdout --
+Hello World!
+
+-- stdin.txt --
+Hello World!
+-- hello_tool.cue --
+package hello
+
+command: echo: {
+ echo: {
+ kind: "exec"
+ cmd: "cat"
+ stdin: string
+ stdout: string
+ }
+
+ task: display: {
+ kind: "print"
+ text: echo.stdout
+ }
+}
+-- cue.mod --
diff --git a/internal/task/task.go b/internal/task/task.go
index a6e563c..a6a54d2 100644
--- a/internal/task/task.go
+++ b/internal/task/task.go
@@ -27,6 +27,7 @@
// A Context provides context for running a task.
type Context struct {
Context context.Context
+ Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Obj cue.Value
diff --git a/pkg/tool/exec/doc.go b/pkg/tool/exec/doc.go
index 484c361..ff150d0 100644
--- a/pkg/tool/exec/doc.go
+++ b/pkg/tool/exec/doc.go
@@ -26,8 +26,9 @@
// // stderr is like stdout, but for errors.
// stderr: *null | string | bytes
//
-// // stdin specifies the input for the process. If null, stdin of the current
-// // process is used.
+// // stdin specifies the input for the process. If stdin is not a concrete
+// // value, it will capture the input from stdin. Otherwise, if it is null,
+// // there is no input. Otherwise it will read from the given value.
// stdin: *null | string | bytes
//
// // success is set to true when the process terminates with with a zero exit
diff --git a/pkg/tool/exec/exec.cue b/pkg/tool/exec/exec.cue
index 7ab429a..be7843e 100644
--- a/pkg/tool/exec/exec.cue
+++ b/pkg/tool/exec/exec.cue
@@ -36,8 +36,9 @@
// stderr is like stdout, but for errors.
stderr: *null | string | bytes
- // stdin specifies the input for the process. If null, stdin of the current
- // process is used.
+ // stdin specifies the input for the process. If stdin is not a concrete
+ // value, it will capture the input from stdin. Otherwise, if it is null,
+ // there is no input. Otherwise it will read from the given value.
stdin: *null | string | bytes
// success is set to true when the process terminates with with a zero exit
diff --git a/pkg/tool/exec/exec.go b/pkg/tool/exec/exec.go
index eee4e3a..32f8d01 100644
--- a/pkg/tool/exec/exec.go
+++ b/pkg/tool/exec/exec.go
@@ -98,7 +98,9 @@
}
if v, ok := stream("stdin"); ok {
- if cmd.Stdin, err = v.Reader(); err != nil {
+ if !v.IsConcrete() {
+ cmd.Stdin = ctx.Stdin
+ } else if cmd.Stdin, err = v.Reader(); err != nil {
return nil, fmt.Errorf("cue: %v", err)
}
}