From 39f3e1010df1591390462cc96da6230e315de7b6 Mon Sep 17 00:00:00 2001
From: Kristoffer Ahl <git@77dynamite.com>
Date: Fri, 17 May 2019 21:11:38 +0200
Subject: [PATCH] - Refactoring io.

---
 cmd/centry/main.go          |  6 +-----
 pkg/centry/runtime_test.go  |  6 +-----
 pkg/centry/serve_command.go |  9 ++------
 pkg/io/io.go                | 41 +++++++++++++++++++++++++++++++++++++
 pkg/shell/bash.go           |  8 +-------
 5 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/cmd/centry/main.go b/cmd/centry/main.go
index b218de4..6d8e51f 100644
--- a/cmd/centry/main.go
+++ b/cmd/centry/main.go
@@ -11,11 +11,7 @@ func main() {
 	args := os.Args[1:]
 
 	// Create the context
-	context := centry.NewContext(centry.CLI, io.InputOutput{
-		Stdin:  os.Stdin,
-		Stdout: os.Stdout,
-		Stderr: os.Stderr,
-	})
+	context := centry.NewContext(centry.CLI, io.Standard())
 
 	// Create the runtime
 	runtime := centry.Create(args, context)
diff --git a/pkg/centry/runtime_test.go b/pkg/centry/runtime_test.go
index de99f87..50a1494 100644
--- a/pkg/centry/runtime_test.go
+++ b/pkg/centry/runtime_test.go
@@ -181,11 +181,7 @@ func execCentry(source string, quiet bool) *execResult {
 		if quiet {
 			source = fmt.Sprintf("--quiet %s", source)
 		}
-		context := NewContext(CLI, io.InputOutput{
-			Stdin:  nil,
-			Stdout: os.Stdout,
-			Stderr: os.Stderr,
-		})
+		context := NewContext(CLI, io.Headless())
 		runtime := Create(strings.Split(fmt.Sprintf("../../test/data/main_test.yaml %s", source), " "), context)
 		exitCode = runtime.Execute()
 	})
diff --git a/pkg/centry/serve_command.go b/pkg/centry/serve_command.go
index d761ecc..f18faea 100644
--- a/pkg/centry/serve_command.go
+++ b/pkg/centry/serve_command.go
@@ -1,7 +1,6 @@
 package centry
 
 import (
-	"bytes"
 	"encoding/json"
 	"net/http"
 	"strings"
@@ -68,7 +67,6 @@ func executeHandler(manifest *config.Manifest) func(w http.ResponseWriter, r *ht
 		response := api.ExecuteResponse{}
 
 		var body api.ExecuteRequest
-		var buf bytes.Buffer
 
 		decoder := json.NewDecoder(r.Body)
 		err := decoder.Decode(&body)
@@ -81,11 +79,8 @@ func executeHandler(manifest *config.Manifest) func(w http.ResponseWriter, r *ht
 		args = append(args, strings.Fields(body.Args)...)
 
 		// Build
-		context := NewContext(API, io.InputOutput{
-			Stdin:  nil,
-			Stdout: &buf,
-			Stderr: &buf,
-		})
+		io, buf := io.BufferedCombined()
+		context := NewContext(API, io)
 
 		context.commandEnabled = func(cmd config.Command) bool {
 			if cmd.Annotations == nil || cmd.Annotations[config.APIServeAnnotation] != "true" {
diff --git a/pkg/io/io.go b/pkg/io/io.go
index 0832422..7d69994 100644
--- a/pkg/io/io.go
+++ b/pkg/io/io.go
@@ -1,7 +1,9 @@
 package io
 
 import (
+	"bytes"
 	"io"
+	"os"
 )
 
 // InputOutput holds the reader and writers used during execution
@@ -10,3 +12,42 @@ type InputOutput struct {
 	Stdout io.Writer
 	Stderr io.Writer
 }
+
+// Standard creates InputOutput for use from a terminal
+func Standard() InputOutput {
+	return InputOutput{
+		Stdin:  os.Stdin,
+		Stdout: os.Stdout,
+		Stderr: os.Stderr,
+	}
+}
+
+// Headless creates InputOutput for use from a terminal that can't accept input
+func Headless() InputOutput {
+	return InputOutput{
+		Stdin:  nil,
+		Stdout: os.Stdout,
+		Stderr: os.Stderr,
+	}
+}
+
+// Buffered creates a buffered InputOutput object
+func Buffered() (io InputOutput, stdout *bytes.Buffer, stderr *bytes.Buffer) {
+	var bufOut bytes.Buffer
+	var bufErr bytes.Buffer
+	return InputOutput{
+		Stdin:  nil,
+		Stdout: &bufOut,
+		Stderr: &bufErr,
+	}, &bufOut, &bufErr
+}
+
+// BufferedCombined creates a buffered InputOutput object
+func BufferedCombined() (InputOutput, *bytes.Buffer) {
+	var buf bytes.Buffer
+	return InputOutput{
+		Stdin:  nil,
+		Stdout: &buf,
+		Stderr: &buf,
+	}, &buf
+}
diff --git a/pkg/shell/bash.go b/pkg/shell/bash.go
index c836712..66f49a4 100644
--- a/pkg/shell/bash.go
+++ b/pkg/shell/bash.go
@@ -1,7 +1,6 @@
 package shell
 
 import (
-	"bytes"
 	"fmt"
 	"os/exec"
 	"path"
@@ -63,12 +62,7 @@ func (s *BashScript) FullPath() string {
 func (s *BashScript) Functions() ([]string, error) {
 	callArgs := []string{"-c", fmt.Sprintf("source %s; declare -F", s.FullPath())}
 
-	var buf bytes.Buffer
-	io := io.InputOutput{
-		Stdin:  nil,
-		Stdout: &buf,
-		Stderr: &buf,
-	}
+	io, buf := io.BufferedCombined()
 
 	err := NewBash().Run(io, callArgs)
 	if err != nil {