From b845a62149d5f4990462ac6c9167c5cfaa0e66cb Mon Sep 17 00:00:00 2001
From: Rafe Colton <rafael.colton@gmail.com>
Date: Mon, 29 Sep 2014 23:16:27 -0700
Subject: [PATCH] Move Go() promise-like func from utils to pkg/promise

This is the first of two steps to break the archive package's dependence
on utils so that archive may be moved into pkg.  Also, the `Go()`
function is small, concise, and not specific to the docker internals, so
it is a good candidate for pkg.

Signed-off-by: Rafe Colton <rafael.colton@gmail.com>
---
 api/client/commands.go |  7 ++++---
 api/client/hijack.go   |  6 +++---
 builder/internals.go   |  3 ++-
 daemon/attach.go       |  3 ++-
 daemon/container.go    |  3 ++-
 daemon/exec.go         |  3 ++-
 pkg/promise/promise.go | 11 +++++++++++
 utils/utils.go         | 10 ----------
 8 files changed, 26 insertions(+), 20 deletions(-)
 create mode 100644 pkg/promise/promise.go

diff --git a/api/client/commands.go b/api/client/commands.go
index a6e7defc79..901e992a8c 100644
--- a/api/client/commands.go
+++ b/api/client/commands.go
@@ -33,6 +33,7 @@ import (
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers/filters"
+	"github.com/docker/docker/pkg/promise"
 	"github.com/docker/docker/pkg/signal"
 	"github.com/docker/docker/pkg/term"
 	"github.com/docker/docker/pkg/timeutils"
@@ -648,7 +649,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
 		v.Set("stdout", "1")
 		v.Set("stderr", "1")
 
-		cErr = utils.Go(func() error {
+		cErr = promise.Go(func() error {
 			return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, nil, nil)
 		})
 	}
@@ -2220,7 +2221,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
 			}
 		}
 
-		errCh = utils.Go(func() error {
+		errCh = promise.Go(func() error {
 			return cli.hijack("POST", "/containers/"+runResult.Get("Id")+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked, nil)
 		})
 	} else {
@@ -2477,7 +2478,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
 			stderr = cli.err
 		}
 	}
-	errCh = utils.Go(func() error {
+	errCh = promise.Go(func() error {
 		return cli.hijack("POST", "/exec/"+execID+"/start", execConfig.Tty, in, out, stderr, hijacked, execConfig)
 	})
 
diff --git a/api/client/hijack.go b/api/client/hijack.go
index 7a934fde15..00170a4a37 100644
--- a/api/client/hijack.go
+++ b/api/client/hijack.go
@@ -14,9 +14,9 @@ import (
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/pkg/log"
+	"github.com/docker/docker/pkg/promise"
 	"github.com/docker/docker/pkg/stdcopy"
 	"github.com/docker/docker/pkg/term"
-	"github.com/docker/docker/utils"
 )
 
 func (cli *DockerCli) dial() (net.Conn, error) {
@@ -78,7 +78,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
 	}
 
 	if stdout != nil || stderr != nil {
-		receiveStdout = utils.Go(func() (err error) {
+		receiveStdout = promise.Go(func() (err error) {
 			defer func() {
 				if in != nil {
 					if setRawTerminal && cli.isTerminalIn {
@@ -104,7 +104,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
 		})
 	}
 
-	sendStdin := utils.Go(func() error {
+	sendStdin := promise.Go(func() error {
 		if in != nil {
 			io.Copy(rwc, in)
 			log.Debugf("[hijack] End of stdin")
diff --git a/builder/internals.go b/builder/internals.go
index 3e30127b48..1d05b60ee6 100644
--- a/builder/internals.go
+++ b/builder/internals.go
@@ -23,6 +23,7 @@ import (
 	imagepkg "github.com/docker/docker/image"
 	"github.com/docker/docker/pkg/log"
 	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/pkg/promise"
 	"github.com/docker/docker/pkg/symlink"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/tarsum"
@@ -516,7 +517,7 @@ func (b *Builder) create() (*daemon.Container, error) {
 func (b *Builder) run(c *daemon.Container) error {
 	var errCh chan error
 	if b.Verbose {
-		errCh = utils.Go(func() error {
+		errCh = promise.Go(func() error {
 			// FIXME: call the 'attach' job so that daemon.Attach can be made private
 			//
 			// FIXME (LK4D4): Also, maybe makes sense to call "logs" job, it is like attach
diff --git a/daemon/attach.go b/daemon/attach.go
index 6ad1cbad48..c5d2e7298a 100644
--- a/daemon/attach.go
+++ b/daemon/attach.go
@@ -10,6 +10,7 @@ import (
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/jsonlog"
 	"github.com/docker/docker/pkg/log"
+	"github.com/docker/docker/pkg/promise"
 	"github.com/docker/docker/utils"
 )
 
@@ -246,7 +247,7 @@ func (daemon *Daemon) Attach(streamConfig *StreamConfig, openStdin, stdinOnce, t
 		}()
 	}
 
-	return utils.Go(func() error {
+	return promise.Go(func() error {
 		defer func() {
 			if cStdout != nil {
 				cStdout.Close()
diff --git a/daemon/container.go b/daemon/container.go
index 5ea2df2af5..c39428c266 100644
--- a/daemon/container.go
+++ b/daemon/container.go
@@ -27,6 +27,7 @@ import (
 	"github.com/docker/docker/pkg/log"
 	"github.com/docker/docker/pkg/networkfs/etchosts"
 	"github.com/docker/docker/pkg/networkfs/resolvconf"
+	"github.com/docker/docker/pkg/promise"
 	"github.com/docker/docker/pkg/symlink"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/utils"
@@ -1117,7 +1118,7 @@ func (container *Container) waitForStart() error {
 	// process or until the process is running in the container
 	select {
 	case <-container.monitor.startSignal:
-	case err := <-utils.Go(container.monitor.Start):
+	case err := <-promise.Go(container.monitor.Start):
 		return err
 	}
 
diff --git a/daemon/exec.go b/daemon/exec.go
index 6ce5b91ddc..272d1e3f1d 100644
--- a/daemon/exec.go
+++ b/daemon/exec.go
@@ -15,6 +15,7 @@ import (
 	"github.com/docker/docker/pkg/broadcastwriter"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/log"
+	"github.com/docker/docker/pkg/promise"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/utils"
 )
@@ -254,7 +255,7 @@ func (container *Container) Exec(execConfig *execConfig) error {
 
 	// We use a callback here instead of a goroutine and an chan for
 	// syncronization purposes
-	cErr := utils.Go(func() error { return container.monitorExec(execConfig, callback) })
+	cErr := promise.Go(func() error { return container.monitorExec(execConfig, callback) })
 
 	// Exec should not return until the process is actually running
 	select {
diff --git a/pkg/promise/promise.go b/pkg/promise/promise.go
new file mode 100644
index 0000000000..dd52b9082f
--- /dev/null
+++ b/pkg/promise/promise.go
@@ -0,0 +1,11 @@
+package promise
+
+// Go is a basic promise implementation: it wraps calls a function in a goroutine,
+// and returns a channel which will later return the function's return value.
+func Go(f func() error) chan error {
+	ch := make(chan error, 1)
+	go func() {
+		ch <- f()
+	}()
+	return ch
+}
diff --git a/utils/utils.go b/utils/utils.go
index d2fd1ae701..3a14c41699 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -30,16 +30,6 @@ type KeyValuePair struct {
 	Value string
 }
 
-// Go is a basic promise implementation: it wraps calls a function in a goroutine,
-// and returns a channel which will later return the function's return value.
-func Go(f func() error) chan error {
-	ch := make(chan error, 1)
-	go func() {
-		ch <- f()
-	}()
-	return ch
-}
-
 // Request a given URL and return an io.Reader
 func Download(url string) (resp *http.Response, err error) {
 	if resp, err = http.Get(url); err != nil {