From 74537689dcac260db4b8da6fe1fa9bfa2c3d1996 Mon Sep 17 00:00:00 2001 From: Marco Molteni Date: Tue, 4 Jun 2019 08:08:25 +0200 Subject: [PATCH 1/6] Fix spelling --- task_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/task_test.go b/task_test.go index e2278dc5..0006b674 100644 --- a/task_test.go +++ b/task_test.go @@ -236,7 +236,7 @@ func TestDeps(t *testing.T) { for _, f := range files { f = filepath.Join(dir, f) if _, err := os.Stat(f); err != nil { - t.Errorf("File %s should exists", f) + t.Errorf("File %s should exist", f) } } } @@ -248,7 +248,7 @@ func TestStatus(t *testing.T) { _ = os.Remove(file) if _, err := os.Stat(file); err == nil { - t.Errorf("File should not exists: %v", err) + t.Errorf("File should not exist: %v", err) } var buff bytes.Buffer @@ -262,7 +262,7 @@ func TestStatus(t *testing.T) { assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "gen-foo"})) if _, err := os.Stat(file); err != nil { - t.Errorf("File should exists: %v", err) + t.Errorf("File should exist: %v", err) } e.Silent = false @@ -290,7 +290,7 @@ func TestGenerates(t *testing.T) { path := filepath.Join(dir, task) _ = os.Remove(path) if _, err := os.Stat(path); err == nil { - t.Errorf("File should not exists: %v", err) + t.Errorf("File should not exist: %v", err) } } @@ -311,10 +311,10 @@ func TestGenerates(t *testing.T) { assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: theTask})) if _, err := os.Stat(srcFile); err != nil { - t.Errorf("File should exists: %v", err) + t.Errorf("File should exist: %v", err) } if _, err := os.Stat(destFile); err != nil { - t.Errorf("File should exists: %v", err) + t.Errorf("File should exist: %v", err) } // Ensure task was not incorrectly found to be up-to-date on first run. if buff.String() == upToDate { @@ -371,7 +371,7 @@ func TestInit(t *testing.T) { _ = os.Remove(file) if _, err := os.Stat(file); err == nil { - t.Errorf("Taskfile.yml should not exists") + t.Errorf("Taskfile.yml should not exist") } if err := task.InitTaskfile(ioutil.Discard, dir); err != nil { @@ -379,7 +379,7 @@ func TestInit(t *testing.T) { } if _, err := os.Stat(file); err != nil { - t.Errorf("Taskfile.yml should exists") + t.Errorf("Taskfile.yml should exist") } } From 81baf808c9a7bd8bb68ecbec9742c37615acb43c Mon Sep 17 00:00:00 2001 From: Marco Molteni Date: Tue, 4 Jun 2019 09:45:11 +0200 Subject: [PATCH 2/6] Task directory: test default case (no "dir:" attribute) --- task_test.go | 19 +++++++++++++++++++ testdata/dir/Taskfile.yml | 7 +++++++ 2 files changed, 26 insertions(+) create mode 100644 testdata/dir/Taskfile.yml diff --git a/task_test.go b/task_test.go index 0006b674..3e98802c 100644 --- a/task_test.go +++ b/task_test.go @@ -575,3 +575,22 @@ func readTestFixture(t *testing.T, dir string, file string) string { assert.NoError(t, err, "error reading text fixture") return string(b) } + +func TestWhenNoDirAttributeItRunsInSameDirAsTaskfile(t *testing.T) { + const expected = "dir" + const dir = "testdata/" + expected + var out bytes.Buffer + e := &task.Executor{ + Dir: dir, + Stdout: &out, + Stderr: &out, + } + + assert.NoError(t, e.Setup()) + assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "whereami"})) + + // got should be the "dir" part of "testdata/dir" + got := strings.TrimSuffix(filepath.Base(out.String()), "\n") + assert.Equal(t, expected, got, "Mismatch in the working directory") +} + diff --git a/testdata/dir/Taskfile.yml b/testdata/dir/Taskfile.yml new file mode 100644 index 00000000..f17dd9fe --- /dev/null +++ b/testdata/dir/Taskfile.yml @@ -0,0 +1,7 @@ +version: '2' + +tasks: + whereami: + cmds: + - pwd + silent: true From 1e93c3830706f06ed28fd1133fa681997d968ff6 Mon Sep 17 00:00:00 2001 From: Marco Molteni Date: Tue, 4 Jun 2019 18:36:35 +0200 Subject: [PATCH 3/6] Task directory: test when "dir:" attribute points to an existing dir --- task_test.go | 17 +++++++++++++++++ testdata/dir/explicit_exists/Taskfile.yml | 8 ++++++++ testdata/dir/explicit_exists/exists/.keepme | 0 3 files changed, 25 insertions(+) create mode 100644 testdata/dir/explicit_exists/Taskfile.yml create mode 100644 testdata/dir/explicit_exists/exists/.keepme diff --git a/task_test.go b/task_test.go index 3e98802c..85887265 100644 --- a/task_test.go +++ b/task_test.go @@ -594,3 +594,20 @@ func TestWhenNoDirAttributeItRunsInSameDirAsTaskfile(t *testing.T) { assert.Equal(t, expected, got, "Mismatch in the working directory") } +func TestWhenDirAttributeAndDirExistsItRunsInThatDir(t *testing.T) { + const expected = "exists" + const dir = "testdata/dir/explicit_exists" + var out bytes.Buffer + e := &task.Executor{ + Dir: dir, + Stdout: &out, + Stderr: &out, + } + + assert.NoError(t, e.Setup()) + assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "whereami"})) + + got := strings.TrimSuffix(filepath.Base(out.String()), "\n") + assert.Equal(t, expected, got, "Mismatch in the working directory") +} + diff --git a/testdata/dir/explicit_exists/Taskfile.yml b/testdata/dir/explicit_exists/Taskfile.yml new file mode 100644 index 00000000..0ab53b26 --- /dev/null +++ b/testdata/dir/explicit_exists/Taskfile.yml @@ -0,0 +1,8 @@ +version: '2' + +tasks: + whereami: + dir: exists + cmds: + - pwd + silent: true diff --git a/testdata/dir/explicit_exists/exists/.keepme b/testdata/dir/explicit_exists/exists/.keepme new file mode 100644 index 00000000..e69de29b From c663c5c5071060069a5c29fae36c1cff72ef523e Mon Sep 17 00:00:00 2001 From: Marco Molteni Date: Tue, 4 Jun 2019 18:58:22 +0200 Subject: [PATCH 4/6] When "dir:" attribute points to a non-existing dir, create it Closes #209 --- task.go | 9 +++++++ task_test.go | 26 +++++++++++++++++++ .../dir/explicit_doesnt_exist/Taskfile.yml | 8 ++++++ 3 files changed, 43 insertions(+) create mode 100644 testdata/dir/explicit_doesnt_exist/Taskfile.yml diff --git a/task.go b/task.go index 2df08c2c..1e5f430e 100644 --- a/task.go +++ b/task.go @@ -200,6 +200,15 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error { } } + // When using the dir: attribute it can happen that the directory doesn't exist. + // If so, we create it. + if _, err := os.Stat(t.Dir); os.IsNotExist(err) { + if err := os.MkdirAll(t.Dir, 0755); err != nil { + e.Logger.Errf("cannot make directory %v: %v", t.Dir, err) + return err + } + } + for i := range t.Cmds { if err := e.runCommand(ctx, t, call, i); err != nil { if err2 := e.statusOnError(t); err2 != nil { diff --git a/task_test.go b/task_test.go index 85887265..bb73b56a 100644 --- a/task_test.go +++ b/task_test.go @@ -611,3 +611,29 @@ func TestWhenDirAttributeAndDirExistsItRunsInThatDir(t *testing.T) { assert.Equal(t, expected, got, "Mismatch in the working directory") } +func TestWhenDirAttributeItCreatesMissingAndRunsInThatDir(t *testing.T) { + const expected = "createme" + const dir = "testdata/dir/explicit_doesnt_exist/" + const toBeCreated = dir + expected + const target = "whereami" + var out bytes.Buffer + e := &task.Executor{ + Dir: dir, + Stdout: &out, + Stderr: &out, + } + + // Ensure that the directory to be created doesn't actually exist. + _ = os.Remove(toBeCreated) + if _, err := os.Stat(toBeCreated); err == nil { + t.Errorf("Directory should not exist: %v", err) + } + assert.NoError(t, e.Setup()) + assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: target})) + + got := strings.TrimSuffix(filepath.Base(out.String()), "\n") + assert.Equal(t, expected, got, "Mismatch in the working directory") + + // Clean-up after ourselves only if no error. + _ = os.Remove(toBeCreated) +} diff --git a/testdata/dir/explicit_doesnt_exist/Taskfile.yml b/testdata/dir/explicit_doesnt_exist/Taskfile.yml new file mode 100644 index 00000000..1b6fb7d1 --- /dev/null +++ b/testdata/dir/explicit_doesnt_exist/Taskfile.yml @@ -0,0 +1,8 @@ +version: '2' + +tasks: + whereami: + dir: createme + cmds: + - pwd + silent: true From 9c475c36e7f39bca76414c46f783fcb427f905d3 Mon Sep 17 00:00:00 2001 From: Marco Molteni Date: Thu, 6 Jun 2019 18:16:09 +0200 Subject: [PATCH 5/6] Handle the common case when the task directory is not specified Closes #209 --- task.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/task.go b/task.go index 1e5f430e..9789cf35 100644 --- a/task.go +++ b/task.go @@ -200,12 +200,14 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error { } } - // When using the dir: attribute it can happen that the directory doesn't exist. + // When using the "dir:" attribute it can happen that the directory doesn't exist. // If so, we create it. - if _, err := os.Stat(t.Dir); os.IsNotExist(err) { - if err := os.MkdirAll(t.Dir, 0755); err != nil { - e.Logger.Errf("cannot make directory %v: %v", t.Dir, err) - return err + if t.Dir != "" { + if _, err := os.Stat(t.Dir); os.IsNotExist(err) { + if err := os.MkdirAll(t.Dir, 0755); err != nil { + e.Logger.Errf("task: cannot make directory %q: %v", t.Dir, err) + return err + } } } From 733c563194b013e7ea93153237b7ff2226d4ada7 Mon Sep 17 00:00:00 2001 From: Marco Molteni Date: Mon, 10 Jun 2019 17:40:20 +0200 Subject: [PATCH 6/6] Protect creation of "dir:" with a mutex --- internal/taskfile/task.go | 23 +++++++++++++++++++++++ task.go | 9 ++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/internal/taskfile/task.go b/internal/taskfile/task.go index 1afcbfa3..a686f04b 100644 --- a/internal/taskfile/task.go +++ b/internal/taskfile/task.go @@ -1,5 +1,8 @@ package taskfile +import "os" +import "sync" + // Tasks represents a group of tasks type Tasks map[string]*Task @@ -14,6 +17,7 @@ type Task struct { Generates []string Status []string Dir string + mkdirMutex sync.Mutex Vars Vars Env Vars Silent bool @@ -21,3 +25,22 @@ type Task struct { Prefix string IgnoreError bool `yaml:"ignore_error"` } + +// Mkdir creates the directory Task.Dir. +// Safe to be called concurrently. +func (t *Task) Mkdir() error { + if t.Dir == "" { + // No "dir:" attribute, so we do nothing. + return nil + } + + t.mkdirMutex.Lock() + defer t.mkdirMutex.Unlock() + + if _, err := os.Stat(t.Dir); os.IsNotExist(err) { + if err := os.MkdirAll(t.Dir, 0755); err != nil { + return err + } + } + return nil +} diff --git a/task.go b/task.go index 9789cf35..bca22c4d 100644 --- a/task.go +++ b/task.go @@ -202,13 +202,8 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error { // When using the "dir:" attribute it can happen that the directory doesn't exist. // If so, we create it. - if t.Dir != "" { - if _, err := os.Stat(t.Dir); os.IsNotExist(err) { - if err := os.MkdirAll(t.Dir, 0755); err != nil { - e.Logger.Errf("task: cannot make directory %q: %v", t.Dir, err) - return err - } - } + if err := t.Mkdir(); err != nil { + e.Logger.Errf("task: cannot make directory %q: %v", t.Dir, err) } for i := range t.Cmds {