diff --git a/cmd/task/task.go b/cmd/task/task.go index 4abafb0f..48e95efe 100644 --- a/cmd/task/task.go +++ b/cmd/task/task.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "os" "github.com/go-task/task" @@ -52,7 +53,11 @@ hello: } if init { - if err := task.InitTaskfile(); err != nil { + wd, err := os.Getwd() + if err != nil { + log.Fatal(err) + } + if err := task.InitTaskfile(wd); err != nil { log.Fatal(err) } return @@ -61,6 +66,10 @@ hello: e := task.Executor{ Force: force, Watch: watch, + + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, } if err := e.ReadTaskfile(); err != nil { log.Fatal(err) diff --git a/help.go b/help.go index 2673c294..d8053818 100644 --- a/help.go +++ b/help.go @@ -2,7 +2,6 @@ package task import ( "fmt" - "os" "sort" "text/tabwriter" ) @@ -12,10 +11,10 @@ func (e *Executor) printExistingTasksHelp() { if len(tasks) == 0 { return } - fmt.Println("Available tasks for this project:") + e.println("Available tasks for this project:") // Format in tab-separated columns with a tab stop of 8. - w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) + w := tabwriter.NewWriter(e.Stdout, 0, 8, 0, '\t', 0) for _, task := range tasks { fmt.Fprintln(w, fmt.Sprintf("- %s:\t%s", task, e.Tasks[task].Desc)) } diff --git a/init.go b/init.go index 21675b99..0b66479f 100644 --- a/init.go +++ b/init.go @@ -4,6 +4,7 @@ import ( "io/ioutil" "log" "os" + "path/filepath" ) const defaultTaskfile = `# github.com/go-task/task @@ -14,14 +15,16 @@ default: ` // InitTaskfile Taskfile creates a new Taskfile -func InitTaskfile() error { +func InitTaskfile(path string) error { for _, f := range []string{"Taskfile.yml", "Taskfile.toml", "Taskfile.json"} { + f = filepath.Join(path, f) if _, err := os.Stat(f); err == nil { return ErrTaskfileAlreadyExists } } - if err := ioutil.WriteFile("Taskfile.yml", []byte(defaultTaskfile), 0666); err != nil { + f := filepath.Join(path, "Taskfile.yml") + if err := ioutil.WriteFile(f, []byte(defaultTaskfile), 0666); err != nil { return err } log.Printf("Taskfile.yml created in the current directory") diff --git a/log.go b/log.go new file mode 100644 index 00000000..e5ee75b8 --- /dev/null +++ b/log.go @@ -0,0 +1,13 @@ +package task + +import ( + "fmt" +) + +func (e *Executor) println(args ...interface{}) { + fmt.Fprintln(e.Stdout, args...) +} + +func (e *Executor) printfln(format string, args ...interface{}) { + fmt.Fprintf(e.Stdout, format+"\n", args...) +} diff --git a/task.go b/task.go index 599d5968..cc69bdfe 100644 --- a/task.go +++ b/task.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "fmt" - "log" + "io" "os" "path/filepath" "strings" @@ -26,6 +26,10 @@ type Executor struct { Force bool Watch bool + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer + watchingFiles map[string]struct{} } @@ -52,6 +56,16 @@ func (e *Executor) Run(args ...string) error { return ErrCyclicDependencyDetected } + if e.Stdin == nil { + e.Stdin = os.Stdin + } + if e.Stdout == nil { + e.Stdout = os.Stdout + } + if e.Stderr == nil { + e.Stderr = os.Stderr + } + // check if given tasks exist for _, a := range args { if _, ok := e.Tasks[a]; !ok { @@ -93,7 +107,7 @@ func (e *Executor) RunTask(ctx context.Context, name string) error { return err } if upToDate { - log.Printf(`task: Task "%s" is up to date`, name) + e.printfln(`task: Task "%s" is up to date`, name) return nil } } @@ -231,13 +245,13 @@ func (e *Executor) runCommand(ctx context.Context, task string, i int) error { Command: c, Dir: dir, Env: envs, - Stdin: os.Stdin, - Stderr: os.Stderr, + Stdin: e.Stdin, + Stderr: e.Stderr, } if t.Set == "" { - log.Println(c) - opts.Stdout = os.Stdout + e.println(c) + opts.Stdout = e.Stdout if err = execext.RunCommand(opts); err != nil { return err } diff --git a/task_test.go b/task_test.go index e4dae54b..d38e7446 100644 --- a/task_test.go +++ b/task_test.go @@ -4,7 +4,6 @@ import ( "bytes" "io/ioutil" "os" - "os/exec" "path/filepath" "strings" "testing" @@ -37,7 +36,9 @@ func TestDeps(t *testing.T) { } e := &task.Executor{ - Dir: dir, + Dir: dir, + Stdout: ioutil.Discard, + Stderr: ioutil.Discard, } assert.NoError(t, e.ReadTaskfile()) assert.NoError(t, e.Run("default")) @@ -69,7 +70,9 @@ func TestVars(t *testing.T) { } e := &task.Executor{ - Dir: dir, + Dir: dir, + Stdout: ioutil.Discard, + Stderr: ioutil.Discard, } assert.NoError(t, e.ReadTaskfile()) assert.NoError(t, e.Run("default")) @@ -101,7 +104,9 @@ func TestTaskCall(t *testing.T) { } e := &task.Executor{ - Dir: dir, + Dir: dir, + Stdout: ioutil.Discard, + Stderr: ioutil.Discard, } assert.NoError(t, e.ReadTaskfile()) assert.NoError(t, e.Run("default")) @@ -122,23 +127,23 @@ func TestStatus(t *testing.T) { if _, err := os.Stat(file); err == nil { t.Errorf("File should not exists: %v", err) } - c := exec.Command("task", "gen-foo") - c.Dir = dir - if err := c.Run(); err != nil { - t.Error(err) + + e := &task.Executor{ + Dir: dir, + Stdout: ioutil.Discard, + Stderr: ioutil.Discard, } + assert.NoError(t, e.ReadTaskfile()) + assert.NoError(t, e.Run("gen-foo")) + if _, err := os.Stat(file); err != nil { t.Errorf("File should exists: %v", err) } buff := bytes.NewBuffer(nil) - c = exec.Command("task", "gen-foo") - c.Dir = dir - c.Stderr = buff - c.Stdout = buff - if err := c.Run(); err != nil { - t.Error(err) - } + e.Stdout, e.Stderr = buff, buff + assert.NoError(t, e.Run("gen-foo")) + if buff.String() != `task: Task "gen-foo" is up to date`+"\n" { t.Errorf("Wrong output message: %s", buff.String()) } @@ -153,11 +158,10 @@ func TestInit(t *testing.T) { t.Errorf("Taskfile.yml should not exists") } - c := exec.Command("task", "--init") - c.Dir = dir - if err := c.Run(); err != nil { + if err := task.InitTaskfile(dir); err != nil { t.Error(err) } + if _, err := os.Stat(file); err != nil { t.Errorf("Taskfile.yml should exists") } diff --git a/variable_handling.go b/variable_handling.go index 26db4002..08cd7685 100644 --- a/variable_handling.go +++ b/variable_handling.go @@ -36,7 +36,7 @@ func (e *Executor) handleDynamicVariableContent(value string) (string, error) { Command: strings.TrimPrefix(value, "$"), Dir: e.Dir, Stdout: buff, - Stderr: os.Stderr, + Stderr: e.Stderr, } if err := execext.RunCommand(opts); err != nil { return "", err diff --git a/vendor/github.com/mvdan/sh/interp/test.go b/vendor/github.com/mvdan/sh/interp/test.go index 0383c2ca..7780c3de 100644 --- a/vendor/github.com/mvdan/sh/interp/test.go +++ b/vendor/github.com/mvdan/sh/interp/test.go @@ -58,19 +58,19 @@ func (r *Runner) binTest(op syntax.BinTestOperator, x, y string) bool { } return re.MatchString(x) case syntax.TsNewer: - i1, i2 := stat(x), stat(y) + i1, i2 := stat(r.Dir, x), stat(r.Dir, y) if i1 == nil || i2 == nil { return false } return i1.ModTime().After(i2.ModTime()) case syntax.TsOlder: - i1, i2 := stat(x), stat(y) + i1, i2 := stat(r.Dir, x), stat(r.Dir, y) if i1 == nil || i2 == nil { return false } return i1.ModTime().Before(i2.ModTime()) case syntax.TsDevIno: - i1, i2 := stat(x), stat(y) + i1, i2 := stat(r.Dir, x), stat(r.Dir, y) return os.SameFile(i1, i2) case syntax.TsEql: return atoi(x) == atoi(y) @@ -95,40 +95,40 @@ func (r *Runner) binTest(op syntax.BinTestOperator, x, y string) bool { } } -func stat(name string) os.FileInfo { - info, _ := os.Stat(name) +func stat(dir, name string) os.FileInfo { + info, _ := os.Stat(filepath.Join(dir, name)) return info } -func statMode(name string, mode os.FileMode) bool { - info := stat(name) +func statMode(dir, name string, mode os.FileMode) bool { + info := stat(dir, name) return info != nil && info.Mode()&mode != 0 } func (r *Runner) unTest(op syntax.UnTestOperator, x string) bool { switch op { case syntax.TsExists: - return stat(x) != nil + return stat(r.Dir, x) != nil case syntax.TsRegFile: - info := stat(x) + info := stat(r.Dir, x) return info != nil && info.Mode().IsRegular() case syntax.TsDirect: - return statMode(x, os.ModeDir) + return statMode(r.Dir, x, os.ModeDir) //case syntax.TsCharSp: //case syntax.TsBlckSp: case syntax.TsNmPipe: - return statMode(x, os.ModeNamedPipe) + return statMode(r.Dir, x, os.ModeNamedPipe) case syntax.TsSocket: - return statMode(x, os.ModeSocket) + return statMode(r.Dir, x, os.ModeSocket) case syntax.TsSmbLink: info, _ := os.Lstat(x) return info != nil && info.Mode()&os.ModeSymlink != 0 case syntax.TsSticky: - return statMode(x, os.ModeSticky) + return statMode(r.Dir, x, os.ModeSticky) case syntax.TsUIDSet: - return statMode(x, os.ModeSetuid) + return statMode(r.Dir, x, os.ModeSetuid) case syntax.TsGIDSet: - return statMode(x, os.ModeSetgid) + return statMode(r.Dir, x, os.ModeSetgid) //case syntax.TsGrpOwn: //case syntax.TsUsrOwn: //case syntax.TsModif: @@ -149,7 +149,7 @@ func (r *Runner) unTest(op syntax.UnTestOperator, x string) bool { _, err := exec.LookPath(filepath.Join(r.Dir, x)) return err == nil case syntax.TsNoEmpty: - info := stat(x) + info := stat(r.Dir, x) return info != nil && info.Size() > 0 //case syntax.TsFdTerm: case syntax.TsEmpStr: diff --git a/watch.go b/watch.go index 49f2127a..d203fe34 100644 --- a/watch.go +++ b/watch.go @@ -2,8 +2,6 @@ package task import ( "context" - "fmt" - "log" "strings" "time" @@ -13,12 +11,12 @@ import ( // watchTasks start watching the given tasks func (e *Executor) watchTasks(args ...string) error { - log.Printf("task: Started watching for tasks: %s", strings.Join(args, ", ")) + e.printfln("task: Started watching for tasks: %s", strings.Join(args, ", ")) // run tasks on init for _, a := range args { if err := e.RunTask(context.Background(), a); err != nil { - fmt.Println(err) + e.println(err) break } } @@ -32,7 +30,7 @@ func (e *Executor) watchTasks(args ...string) error { go func() { for { if err := e.registerWatchedFiles(watcher, args); err != nil { - log.Printf("Error watching files: %v", err) + e.printfln("Error watching files: %v", err) } time.Sleep(time.Second * 2) } @@ -44,12 +42,12 @@ loop: case <-watcher.Events: for _, a := range args { if err := e.RunTask(context.Background(), a); err != nil { - fmt.Println(err) + e.println(err) continue loop } } case err := <-watcher.Errors: - fmt.Println(err) + e.println(err) continue loop } }