mirror of
https://github.com/go-task/task.git
synced 2026-06-25 05:35:56 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45dbbcd179 | ||
|
|
83d25bfa00 | ||
|
|
299e27af15 | ||
|
|
ec4cd5ed48 | ||
|
|
59d2733b88 | ||
|
|
cbdd088188 | ||
|
|
2d52485d7b | ||
|
|
d830178ef8 | ||
|
|
049984b4cc | ||
|
|
d261a986ab |
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v3.2.0
|
||||||
|
|
||||||
|
- Fix the `.task` directory being created in the task directory instead of the
|
||||||
|
Taskfile directory
|
||||||
|
([#247](https://github.com/go-task/task/issues/247)).
|
||||||
|
- Fix a bug where dynamic variables (those declared with `sh:`) were not
|
||||||
|
running in the task directory when the task has a custom dir or it was
|
||||||
|
in an included Taskfile
|
||||||
|
([#384](https://github.com/go-task/task/issues/384)).
|
||||||
|
- The watch feature (via the `--watch` flag) got a few different bug fixes and
|
||||||
|
should be more stable now
|
||||||
|
([#423](https://github.com/go-task/task/pull/423), [#365](https://github.com/go-task/task/issues/365)).
|
||||||
|
|
||||||
## v3.1.0
|
## v3.1.0
|
||||||
|
|
||||||
- Fix a bug when the checksum up-to-date resolution is used by a task
|
- Fix a bug when the checksum up-to-date resolution is used by a task
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/args"
|
"github.com/go-task/task/v3/args"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestArgsV3(t *testing.T) {
|
func TestArgsV3(t *testing.T) {
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/go-task/task/v3"
|
"github.com/go-task/task/v3"
|
||||||
"github.com/go-task/task/v3/args"
|
"github.com/go-task/task/v3/args"
|
||||||
"github.com/go-task/task/v3/internal/logger"
|
"github.com/go-task/task/v3/internal/logger"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ import (
|
|||||||
// E.g. variable merger, template processing, etc.
|
// E.g. variable merger, template processing, etc.
|
||||||
type Compiler interface {
|
type Compiler interface {
|
||||||
GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error)
|
GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error)
|
||||||
HandleDynamicVar(v taskfile.Var) (string, error)
|
HandleDynamicVar(v taskfile.Var, dir string) (string, error)
|
||||||
|
ResetCache()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -37,8 +38,20 @@ type CompilerV2 struct {
|
|||||||
// 4. Taskvars file variables
|
// 4. Taskvars file variables
|
||||||
// 5. Environment variables
|
// 5. Environment variables
|
||||||
func (c *CompilerV2) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
func (c *CompilerV2) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
||||||
vr := varResolver{c: c, vars: compiler.GetEnviron()}
|
// NOTE(@andreynering): We're manually joining these paths here because
|
||||||
|
// this is the raw task, not the compiled one.
|
||||||
|
dir := t.Dir
|
||||||
|
if !filepath.IsAbs(dir) {
|
||||||
|
dir = filepath.Join(c.Dir, dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
vr := varResolver{
|
||||||
|
c: c,
|
||||||
|
dir: dir,
|
||||||
|
vars: compiler.GetEnviron(),
|
||||||
|
}
|
||||||
vr.vars.Set("TASK", taskfile.Var{Static: t.Task})
|
vr.vars.Set("TASK", taskfile.Var{Static: t.Task})
|
||||||
|
|
||||||
for _, vars := range []*taskfile.Vars{c.Taskvars, c.TaskfileVars, call.Vars, t.Vars} {
|
for _, vars := range []*taskfile.Vars{c.Taskvars, c.TaskfileVars, call.Vars, t.Vars} {
|
||||||
for i := 0; i < c.Expansions; i++ {
|
for i := 0; i < c.Expansions; i++ {
|
||||||
vr.merge(vars)
|
vr.merge(vars)
|
||||||
@@ -49,6 +62,7 @@ func (c *CompilerV2) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi
|
|||||||
|
|
||||||
type varResolver struct {
|
type varResolver struct {
|
||||||
c *CompilerV2
|
c *CompilerV2
|
||||||
|
dir string
|
||||||
vars *taskfile.Vars
|
vars *taskfile.Vars
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
@@ -63,7 +77,7 @@ func (vr *varResolver) merge(vars *taskfile.Vars) {
|
|||||||
Static: tr.Replace(v.Static),
|
Static: tr.Replace(v.Static),
|
||||||
Sh: tr.Replace(v.Sh),
|
Sh: tr.Replace(v.Sh),
|
||||||
}
|
}
|
||||||
static, err := vr.c.HandleDynamicVar(v)
|
static, err := vr.c.HandleDynamicVar(v, vr.dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vr.err = err
|
vr.err = err
|
||||||
return err
|
return err
|
||||||
@@ -74,7 +88,7 @@ func (vr *varResolver) merge(vars *taskfile.Vars) {
|
|||||||
vr.err = tr.Err()
|
vr.err = tr.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
|
func (c *CompilerV2) HandleDynamicVar(v taskfile.Var, dir string) (string, error) {
|
||||||
if v.Static != "" || v.Sh == "" {
|
if v.Static != "" || v.Sh == "" {
|
||||||
return v.Static, nil
|
return v.Static, nil
|
||||||
}
|
}
|
||||||
@@ -92,7 +106,7 @@ func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
var stdout bytes.Buffer
|
var stdout bytes.Buffer
|
||||||
opts := &execext.RunCommandOptions{
|
opts := &execext.RunCommandOptions{
|
||||||
Command: v.Sh,
|
Command: v.Sh,
|
||||||
Dir: c.Dir,
|
Dir: dir,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
Stderr: c.Logger.Stderr,
|
Stderr: c.Logger.Stderr,
|
||||||
}
|
}
|
||||||
@@ -109,3 +123,11 @@ func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetCache clear the dymanic variables cache
|
||||||
|
func (c *CompilerV2) ResetCache() {
|
||||||
|
c.muDynamicCache.Lock()
|
||||||
|
defer c.muDynamicCache.Unlock()
|
||||||
|
|
||||||
|
c.dynamicCache = nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -31,6 +32,13 @@ func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi
|
|||||||
result := compiler.GetEnviron()
|
result := compiler.GetEnviron()
|
||||||
result.Set("TASK", taskfile.Var{Static: t.Task})
|
result.Set("TASK", taskfile.Var{Static: t.Task})
|
||||||
|
|
||||||
|
// NOTE(@andreynering): We're manually joining these paths here because
|
||||||
|
// this is the raw task, not the compiled one.
|
||||||
|
dir := t.Dir
|
||||||
|
if !filepath.IsAbs(dir) {
|
||||||
|
dir = filepath.Join(c.Dir, dir)
|
||||||
|
}
|
||||||
|
|
||||||
rangeFunc := func(k string, v taskfile.Var) error {
|
rangeFunc := func(k string, v taskfile.Var) error {
|
||||||
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
||||||
v = taskfile.Var{
|
v = taskfile.Var{
|
||||||
@@ -40,7 +48,7 @@ func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi
|
|||||||
if err := tr.Err(); err != nil {
|
if err := tr.Err(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
static, err := c.HandleDynamicVar(v)
|
static, err := c.HandleDynamicVar(v, dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -61,7 +69,7 @@ func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CompilerV3) HandleDynamicVar(v taskfile.Var) (string, error) {
|
func (c *CompilerV3) HandleDynamicVar(v taskfile.Var, dir string) (string, error) {
|
||||||
if v.Static != "" || v.Sh == "" {
|
if v.Static != "" || v.Sh == "" {
|
||||||
return v.Static, nil
|
return v.Static, nil
|
||||||
}
|
}
|
||||||
@@ -79,7 +87,7 @@ func (c *CompilerV3) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
var stdout bytes.Buffer
|
var stdout bytes.Buffer
|
||||||
opts := &execext.RunCommandOptions{
|
opts := &execext.RunCommandOptions{
|
||||||
Command: v.Sh,
|
Command: v.Sh,
|
||||||
Dir: c.Dir,
|
Dir: dir,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
Stderr: c.Logger.Stderr,
|
Stderr: c.Logger.Stderr,
|
||||||
}
|
}
|
||||||
@@ -96,3 +104,11 @@ func (c *CompilerV3) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetCache clear the dymanic variables cache
|
||||||
|
func (c *CompilerV3) ResetCache() {
|
||||||
|
c.muDynamicCache.Lock()
|
||||||
|
defer c.muDynamicCache.Unlock()
|
||||||
|
|
||||||
|
c.dynamicCache = nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/output"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/internal/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInterleaved(t *testing.T) {
|
func TestInterleaved(t *testing.T) {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import (
|
|||||||
// Checksum validades if a task is up to date by calculating its source
|
// Checksum validades if a task is up to date by calculating its source
|
||||||
// files checksum
|
// files checksum
|
||||||
type Checksum struct {
|
type Checksum struct {
|
||||||
Dir string
|
BaseDir string
|
||||||
|
TaskDir string
|
||||||
Task string
|
Task string
|
||||||
Sources []string
|
Sources []string
|
||||||
Generates []string
|
Generates []string
|
||||||
@@ -32,7 +33,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
data, _ := ioutil.ReadFile(checksumFile)
|
data, _ := ioutil.ReadFile(checksumFile)
|
||||||
oldMd5 := strings.TrimSpace(string(data))
|
oldMd5 := strings.TrimSpace(string(data))
|
||||||
|
|
||||||
sources, err := globs(c.Dir, c.Sources)
|
sources, err := globs(c.TaskDir, c.Sources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -43,7 +44,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !c.Dry {
|
if !c.Dry {
|
||||||
_ = os.MkdirAll(filepath.Join(c.Dir, ".task", "checksum"), 0755)
|
_ = os.MkdirAll(filepath.Join(c.BaseDir, ".task", "checksum"), 0755)
|
||||||
if err = ioutil.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
if err = ioutil.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
if len(c.Generates) > 0 {
|
if len(c.Generates) > 0 {
|
||||||
// For each specified 'generates' field, check whether the files actually exist
|
// For each specified 'generates' field, check whether the files actually exist
|
||||||
for _, g := range c.Generates {
|
for _, g := range c.Generates {
|
||||||
generates, err := glob(c.Dir, g)
|
generates, err := glob(c.TaskDir, g)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@@ -107,7 +108,7 @@ func (*Checksum) Kind() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checksum) checksumFilePath() string {
|
func (c *Checksum) checksumFilePath() string {
|
||||||
return filepath.Join(c.Dir, ".task", "checksum", c.normalizeFilename(c.Task))
|
return filepath.Join(c.BaseDir, ".task", "checksum", c.normalizeFilename(c.Task))
|
||||||
}
|
}
|
||||||
|
|
||||||
var checksumFilenameRegexp = regexp.MustCompile("[^A-z0-9]")
|
var checksumFilenameRegexp = regexp.MustCompile("[^A-z0-9]")
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/execext"
|
|
||||||
|
|
||||||
"github.com/mattn/go-zglob"
|
"github.com/mattn/go-zglob"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/internal/execext"
|
||||||
)
|
)
|
||||||
|
|
||||||
func globs(dir string, globs []string) ([]string, error) {
|
func globs(dir string, globs []string) ([]string, error) {
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/logger"
|
"github.com/go-task/task/v3/internal/logger"
|
||||||
"github.com/go-task/task/v3/internal/summary"
|
"github.com/go-task/task/v3/internal/summary"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPrintsDependenciesIfPresent(t *testing.T) {
|
func TestPrintsDependenciesIfPresent(t *testing.T) {
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ func (e *Executor) timestampChecker(t *taskfile.Task) status.Checker {
|
|||||||
|
|
||||||
func (e *Executor) checksumChecker(t *taskfile.Task) status.Checker {
|
func (e *Executor) checksumChecker(t *taskfile.Task) status.Checker {
|
||||||
return &status.Checksum{
|
return &status.Checksum{
|
||||||
Dir: t.Dir,
|
BaseDir: e.Dir,
|
||||||
|
TaskDir: t.Dir,
|
||||||
Task: t.Name(),
|
Task: t.Name(),
|
||||||
Sources: t.Sources,
|
Sources: t.Sources,
|
||||||
Generates: t.Generates,
|
Generates: t.Generates,
|
||||||
|
|||||||
23
task_test.go
23
task_test.go
@@ -11,10 +11,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/go-task/task/v3"
|
"github.com/go-task/task/v3"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// fileContentTest provides a basic reusable test-case for running a Taskfile
|
// fileContentTest provides a basic reusable test-case for running a Taskfile
|
||||||
@@ -303,16 +303,15 @@ func TestPrecondition(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerates(t *testing.T) {
|
func TestGenerates(t *testing.T) {
|
||||||
|
const dir = "testdata/generates"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
srcTask = "sub/src.txt"
|
srcTask = "sub/src.txt"
|
||||||
relTask = "rel.txt"
|
relTask = "rel.txt"
|
||||||
absTask = "abs.txt"
|
absTask = "sub/abs.txt"
|
||||||
fileWithSpaces = "my text file.txt"
|
fileWithSpaces = "my text file.txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This test does not work with a relative dir.
|
|
||||||
dir, err := filepath.Abs("testdata/generates")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
var srcFile = filepath.Join(dir, srcTask)
|
var srcFile = filepath.Join(dir, srcTask)
|
||||||
|
|
||||||
for _, task := range []string{srcTask, relTask, absTask, fileWithSpaces} {
|
for _, task := range []string{srcTask, relTask, absTask, fileWithSpaces} {
|
||||||
@@ -800,6 +799,18 @@ func TestWhenDirAttributeItCreatesMissingAndRunsInThatDir(t *testing.T) {
|
|||||||
_ = os.RemoveAll(toBeCreated)
|
_ = os.RemoveAll(toBeCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDynamicVariablesShouldRunOnTheTaskDir(t *testing.T) {
|
||||||
|
tt := fileContentTest{
|
||||||
|
Dir: "testdata/dir/dynamic_var",
|
||||||
|
Target: "default",
|
||||||
|
TrimSpace: false,
|
||||||
|
Files: map[string]string{
|
||||||
|
"subdirectory/dir.txt": "subdirectory\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tt.Run(t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDisplaysErrorOnUnsupportedVersion(t *testing.T) {
|
func TestDisplaysErrorOnUnsupportedVersion(t *testing.T) {
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: "testdata/version/v1",
|
Dir: "testdata/version/v1",
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package taskfile_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPreconditionParse(t *testing.T) {
|
func TestPreconditionParse(t *testing.T) {
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/templater"
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/internal/templater"
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Taskvars reads a Taskvars for a given directory
|
// Taskvars reads a Taskvars for a given directory
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package taskfile_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCmdParse(t *testing.T) {
|
func TestCmdParse(t *testing.T) {
|
||||||
|
|||||||
1
testdata/dir/dynamic_var/.gitignore
vendored
Normal file
1
testdata/dir/dynamic_var/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
subdirectory/dir.txt
|
||||||
11
testdata/dir/dynamic_var/Taskfile.yml
vendored
Normal file
11
testdata/dir/dynamic_var/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- echo '{{.FOLDER}}' > dir.txt
|
||||||
|
dir: subdirectory
|
||||||
|
vars:
|
||||||
|
FOLDER:
|
||||||
|
sh: basename $(pwd)
|
||||||
|
silent: true
|
||||||
1
testdata/dir/dynamic_var/subdirectory/dir.txt
vendored
Normal file
1
testdata/dir/dynamic_var/subdirectory/dir.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
subdirectory
|
||||||
2
testdata/generates/Taskfile.yml
vendored
2
testdata/generates/Taskfile.yml
vendored
@@ -4,7 +4,7 @@ vars:
|
|||||||
BUILD_DIR: $pwd
|
BUILD_DIR: $pwd
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
abs.txt:
|
sub/abs.txt:
|
||||||
desc: generates dest file based on absolute paths
|
desc: generates dest file based on absolute paths
|
||||||
deps:
|
deps:
|
||||||
- sub/src.txt
|
- sub/src.txt
|
||||||
|
|||||||
0
testdata/generates/sub/.keep
vendored
Normal file
0
testdata/generates/sub/.keep
vendored
Normal file
@@ -60,7 +60,7 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
|||||||
new.Env.Merge(r.ReplaceVars(e.Taskfile.Env))
|
new.Env.Merge(r.ReplaceVars(e.Taskfile.Env))
|
||||||
new.Env.Merge(r.ReplaceVars(origTask.Env))
|
new.Env.Merge(r.ReplaceVars(origTask.Env))
|
||||||
err = new.Env.Range(func(k string, v taskfile.Var) error {
|
err = new.Env.Range(func(k string, v taskfile.Var) error {
|
||||||
static, err := e.Compiler.HandleDynamicVar(v)
|
static, err := e.Compiler.HandleDynamicVar(v, new.Dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
52
watch.go
52
watch.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,10 +15,7 @@ import (
|
|||||||
"github.com/radovskyb/watcher"
|
"github.com/radovskyb/watcher"
|
||||||
)
|
)
|
||||||
|
|
||||||
var watchIgnoredDirs = []string{
|
const watchInterval = 5 * time.Second
|
||||||
".git",
|
|
||||||
"node_modules",
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchTasks start watching the given tasks
|
// watchTasks start watching the given tasks
|
||||||
func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
||||||
@@ -40,9 +38,6 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
w := watcher.New()
|
w := watcher.New()
|
||||||
defer w.Close()
|
defer w.Close()
|
||||||
w.SetMaxEvents(1)
|
w.SetMaxEvents(1)
|
||||||
if err := w.Ignore(watchIgnoredDirs...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
closeOnInterrupt(w)
|
closeOnInterrupt(w)
|
||||||
|
|
||||||
@@ -54,6 +49,9 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
e.Compiler.ResetCache()
|
||||||
|
|
||||||
for _, c := range calls {
|
for _, c := range calls {
|
||||||
c := c
|
c := c
|
||||||
go func() {
|
go func() {
|
||||||
@@ -65,9 +63,6 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
case err := <-w.Error:
|
case err := <-w.Error:
|
||||||
switch err {
|
switch err {
|
||||||
case watcher.ErrWatchedFileDeleted:
|
case watcher.ErrWatchedFileDeleted:
|
||||||
go func() {
|
|
||||||
w.TriggerEvent(watcher.Remove, nil)
|
|
||||||
}()
|
|
||||||
default:
|
default:
|
||||||
e.Logger.Errf(logger.Red, "%v", err)
|
e.Logger.Errf(logger.Red, "%v", err)
|
||||||
}
|
}
|
||||||
@@ -79,16 +74,16 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// re-register each second because we can have new files
|
// re-register every 5 seconds because we can have new files, but this process is expensive to run
|
||||||
for {
|
for {
|
||||||
if err := e.registerWatchedFiles(w, calls...); err != nil {
|
if err := e.registerWatchedFiles(w, calls...); err != nil {
|
||||||
e.Logger.Errf(logger.Red, "%v", err)
|
e.Logger.Errf(logger.Red, "%v", err)
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(watchInterval)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return w.Start(time.Second)
|
return w.Start(watchInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isContextError(err error) bool {
|
func isContextError(err error) bool {
|
||||||
@@ -109,16 +104,7 @@ func closeOnInterrupt(w *watcher.Watcher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Call) error {
|
func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Call) error {
|
||||||
oldWatchedFiles := make(map[string]struct{})
|
watchedFiles := w.WatchedFiles()
|
||||||
for f := range w.WatchedFiles() {
|
|
||||||
oldWatchedFiles[f] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
for f := range oldWatchedFiles {
|
|
||||||
if err := w.Remove(f); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var registerTaskFiles func(taskfile.Call) error
|
var registerTaskFiles func(taskfile.Call) error
|
||||||
registerTaskFiles = func(c taskfile.Call) error {
|
registerTaskFiles = func(c taskfile.Call) error {
|
||||||
@@ -146,12 +132,20 @@ func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Ca
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if _, ok := oldWatchedFiles[f]; ok {
|
absFile, err := filepath.Abs(f)
|
||||||
continue
|
if err != nil {
|
||||||
}
|
|
||||||
if err := w.Add(f); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if shouldIgnoreFile(absFile) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := watchedFiles[absFile]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := w.Add(absFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.Logger.VerboseOutf(logger.Green, "task: watching new file: %v", absFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -164,3 +158,7 @@ func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Ca
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldIgnoreFile(path string) bool {
|
||||||
|
return strings.Contains(path, "/.git") || strings.Contains(path, "/.task") || strings.Contains(path, "/node_modules")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user