diff --git a/api/client/commands.go b/api/client/commands.go index f4ced5ecff..95d9aba796 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -5,6 +5,7 @@ import ( "bytes" "encoding/base64" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -2411,7 +2412,10 @@ func (cli *DockerCli) CmdSave(args ...string) error { if err != nil { return err } + } else if cli.isTerminalOut { + return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.") } + if len(cmd.Args()) == 1 { image := cmd.Arg(0) if err := cli.stream("GET", "/images/"+image+"/get", nil, output, nil); err != nil { diff --git a/integration-cli/docker_cli_save_load_test.go b/integration-cli/docker_cli_save_load_test.go index 8bc0ec1c53..351f249fd0 100644 --- a/integration-cli/docker_cli_save_load_test.go +++ b/integration-cli/docker_cli_save_load_test.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "io/ioutil" "os" @@ -8,6 +9,8 @@ import ( "path/filepath" "reflect" "testing" + + "github.com/docker/docker/vendor/src/github.com/kr/pty" ) // save a repo and try to load it using stdout @@ -70,6 +73,34 @@ func TestSaveAndLoadRepoStdout(t *testing.T) { logDone("save - save a repo using stdout") logDone("load - load a repo using stdout") + + pty, tty, err := pty.Open() + if err != nil { + t.Fatalf("Could not open pty: %v", err) + } + cmd := exec.Command(dockerBinary, "save", repoName) + cmd.Stdin = tty + cmd.Stdout = tty + cmd.Stderr = tty + if err := cmd.Start(); err != nil { + t.Fatalf("start err: %v", err) + } + if err := cmd.Wait(); err == nil { + t.Fatal("did not break writing to a TTY") + } + + buf := make([]byte, 1024) + + n, err := pty.Read(buf) + if err != nil { + t.Fatal("could not read tty output") + } + + if !bytes.Contains(buf[:n], []byte("Cowardly refusing")) { + t.Fatal("help output is not being yielded", out) + } + + logDone("save - do not save to a tty") } func TestSaveSingleTag(t *testing.T) {