From a407b0a8eb56760ee225cc66dcf61002308f2de7 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Sun, 22 Apr 2018 15:41:53 -0300 Subject: [PATCH] First step implementing "prefixed" output option Ref #104 --- internal/output/group.go | 2 +- internal/output/interleaved.go | 2 +- internal/output/output.go | 2 +- internal/output/prefixed.go | 65 ++++++++++++++++++++++++++++++++++ internal/taskfile/task.go | 1 + task.go | 6 ++-- variables.go | 4 +++ 7 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 internal/output/prefixed.go diff --git a/internal/output/group.go b/internal/output/group.go index 1e5a434a..62259f34 100644 --- a/internal/output/group.go +++ b/internal/output/group.go @@ -7,7 +7,7 @@ import ( type Group struct{} -func (Group) WrapWriter(w io.Writer) io.WriteCloser { +func (Group) WrapWriter(w io.Writer, _ string) io.WriteCloser { return &groupWriter{writer: w} } diff --git a/internal/output/interleaved.go b/internal/output/interleaved.go index 9d37f485..305338d2 100644 --- a/internal/output/interleaved.go +++ b/internal/output/interleaved.go @@ -6,7 +6,7 @@ import ( type Interleaved struct{} -func (Interleaved) WrapWriter(w io.Writer) io.WriteCloser { +func (Interleaved) WrapWriter(w io.Writer, _ string) io.WriteCloser { return nopWriterCloser{w: w} } diff --git a/internal/output/output.go b/internal/output/output.go index fd19bb4a..f63b83a7 100644 --- a/internal/output/output.go +++ b/internal/output/output.go @@ -5,5 +5,5 @@ import ( ) type Output interface { - WrapWriter(io.Writer) io.WriteCloser + WrapWriter(w io.Writer, prefix string) io.WriteCloser } diff --git a/internal/output/prefixed.go b/internal/output/prefixed.go new file mode 100644 index 00000000..f9ea8578 --- /dev/null +++ b/internal/output/prefixed.go @@ -0,0 +1,65 @@ +package output + +import ( + "bytes" + "fmt" + "io" + "strings" +) + +type Prefixed struct{} + +func (Prefixed) WrapWriter(w io.Writer, prefix string) io.WriteCloser { + return &prefixWriter{writer: w, prefix: prefix} +} + +type prefixWriter struct { + writer io.Writer + prefix string + buff bytes.Buffer +} + +func (pw *prefixWriter) Write(p []byte) (int, error) { + n, err := pw.buff.Write(p) + if err != nil { + return n, err + } + + return n, pw.writeOutputLines(false) +} + +func (pw *prefixWriter) Close() error { + return pw.writeOutputLines(true) +} + +func (pw *prefixWriter) writeOutputLines(force bool) error { + for { + line, err := pw.buff.ReadString('\n') + if err == nil { + if err = pw.writeLine(line); err != nil { + return err + } + } else if err == io.EOF { + // if this line was not a complete line, re-add to the buffer + if !force && !strings.HasSuffix(line, "\n") { + _, err = pw.buff.WriteString(line) + return err + } + + return pw.writeLine(line) + } else { + return err + } + } +} + +func (pw *prefixWriter) writeLine(line string) error { + if line == "" { + return nil + } + if !strings.HasSuffix(line, "\n") { + line += "\n" + } + _, err := fmt.Fprintf(pw.writer, "[%s] %s", pw.prefix, line) + return err +} diff --git a/internal/taskfile/task.go b/internal/taskfile/task.go index 6a2b4708..cf15ea8a 100644 --- a/internal/taskfile/task.go +++ b/internal/taskfile/task.go @@ -17,4 +17,5 @@ type Task struct { Env Vars Silent bool Method string + Prefix string } diff --git a/task.go b/task.go index 96f51bf6..e2de4c62 100644 --- a/task.go +++ b/task.go @@ -130,6 +130,8 @@ func (e *Executor) Setup() error { e.Output = output.Interleaved{} case "group": e.Output = output.Group{} + case "prefixed": + e.Output = output.Prefixed{} default: return fmt.Errorf(`task: output option "%s" not recognized`, e.Taskfile.Output) } @@ -204,8 +206,8 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi e.Logger.Errf(cmd.Cmd) } - stdOut := e.Output.WrapWriter(e.Stdout) - stdErr := e.Output.WrapWriter(e.Stderr) + stdOut := e.Output.WrapWriter(e.Stdout, t.Prefix) + stdErr := e.Output.WrapWriter(e.Stderr, t.Prefix) defer stdOut.Close() defer stdErr.Close() diff --git a/variables.go b/variables.go index ca0722bb..e5d8b411 100644 --- a/variables.go +++ b/variables.go @@ -39,6 +39,7 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) { Env: r.ReplaceVars(origTask.Env), Silent: origTask.Silent, Method: r.Replace(origTask.Method), + Prefix: r.Replace(origTask.Prefix), } new.Dir, err = homedir.Expand(new.Dir) if err != nil { @@ -47,6 +48,9 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) { if e.Dir != "" && !filepath.IsAbs(new.Dir) { new.Dir = filepath.Join(e.Dir, new.Dir) } + if new.Prefix == "" { + new.Prefix = new.Task + } for k, v := range new.Env { static, err := e.Compiler.HandleDynamicVar(v) if err != nil {