From 6e6f07c58b948d6e43f3ccec90d55f96bc6e465d Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 19 Dec 2014 03:32:13 -0800 Subject: [PATCH] Add simple ExecPipe() to be used with filesystem format work --- pkgs/utils/execpipe.go | 46 +++++++++++++++++++++++++++++++++++++ pkgs/utils/execpipe_test.go | 34 +++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 pkgs/utils/execpipe.go create mode 100644 pkgs/utils/execpipe_test.go diff --git a/pkgs/utils/execpipe.go b/pkgs/utils/execpipe.go new file mode 100644 index 000000000..4f1ba6b59 --- /dev/null +++ b/pkgs/utils/execpipe.go @@ -0,0 +1,46 @@ +package utils + +import ( + "bytes" + "errors" + "os/exec" +) + +// A simple ExecPipe() pipes exec.Cmd together - somewhat similar to how bash pipes "|" behave. +// Each command's standard output is connected to the standard input of the next command +// and the output of the final command is returned + +func ExecPipe(cmds ...*exec.Cmd) (pipeLineOutput []byte, pipeLineError error) { + // Require at least one command + if len(cmds) < 1 { + return nil, errors.New("Invalid argument") + } + + // Collect the output from the command(s) + var output bytes.Buffer + + lastIndex := len(cmds) - 1 + for i, cmd := range cmds[:lastIndex] { + cmds[i+1].Stdin, _ = cmd.StdoutPipe() + } + + // Final ---> output buffer + cmds[lastIndex].Stdout = &output + + // Start each command + for _, cmd := range cmds { + if err := cmd.Start(); err != nil { + return output.Bytes(), err + } + } + + // We should Wait() for each command to complete + for _, cmd := range cmds { + if err := cmd.Wait(); err != nil { + return output.Bytes(), err + } + } + + // Return the output + return output.Bytes(), nil +} diff --git a/pkgs/utils/execpipe_test.go b/pkgs/utils/execpipe_test.go new file mode 100644 index 000000000..f5fce2415 --- /dev/null +++ b/pkgs/utils/execpipe_test.go @@ -0,0 +1,34 @@ +// !build linux,amd64 + +package utils + +import ( + . "gopkg.in/check.v1" + "os/exec" + "testing" +) + +type MySuite struct{} + +var _ = Suite(&MySuite{}) + +func Test(t *testing.T) { TestingT(t) } + +func (s *MySuite) TestPiping(c *C) { + // Collect directories from the command-line + dirs := []string{"."} + + // Run the command on each directory + for _, dir := range dirs { + // find $DIR -type f # Find all files + ls := exec.Command("ls", dir, "-l") + + // | sort -t. -k2 # Sort by file extension + sort := exec.Command("sort", "-t.", "-k2") + + // Run + output, err := ExecPipe(ls, sort) + c.Assert(err, IsNil) + c.Assert(len(output), Not(Equals), 0) + } +}