mirror of
https://github.com/go-task/task.git
synced 2026-06-25 21:56:16 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b2e25735b | ||
|
|
e09e75b0ba | ||
|
|
6630113fef | ||
|
|
b2f08c9c20 | ||
|
|
6a4315b7e7 | ||
|
|
8b3e62ff6d | ||
|
|
f1d3f6740d | ||
|
|
9ccd1d920c | ||
|
|
9674d75ff6 | ||
|
|
22fd74846d | ||
|
|
777645888a | ||
|
|
ac8e344173 | ||
|
|
16fad60833 | ||
|
|
f5eb80759b | ||
|
|
bf88bd5da5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@ tags
|
|||||||
|
|
||||||
/bin
|
/bin
|
||||||
/testdata/vars/v1
|
/testdata/vars/v1
|
||||||
|
/tmp
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ build:
|
|||||||
goarch:
|
goarch:
|
||||||
- 386
|
- 386
|
||||||
- amd64
|
- amd64
|
||||||
|
- arm
|
||||||
|
- arm64
|
||||||
|
goarm:
|
||||||
|
- 6
|
||||||
ignore:
|
ignore:
|
||||||
- goos: darwin
|
- goos: darwin
|
||||||
goarch: 386
|
goarch: 386
|
||||||
|
|||||||
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,7 +1,26 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v3.1.0
|
||||||
|
|
||||||
|
- Fix a bug when the checksum up-to-date resolution is used by a task
|
||||||
|
with a custom `label:` attribute
|
||||||
|
([#412](https://github.com/go-task/task/issues/412)).
|
||||||
|
- Starting from this release, we're releasing official ARMv6 and ARM64 binaries
|
||||||
|
for Linux
|
||||||
|
([#375](https://github.com/go-task/task/issues/375), [#418](https://github.com/go-task/task/issues/418)).
|
||||||
|
- Task now respects the order of declaration of included Taskfiles when
|
||||||
|
evaluating variables declaring by them
|
||||||
|
([#393](https://github.com/go-task/task/issues/393)).
|
||||||
|
- `set -e` is now automatically set on every command. This was done to fix an
|
||||||
|
issue where multiline string commands wouldn't really fail unless the
|
||||||
|
sentence was in the last line
|
||||||
|
([#403](https://github.com/go-task/task/issues/403)).
|
||||||
|
|
||||||
## v3.0.1
|
## v3.0.1
|
||||||
|
|
||||||
|
- Allow use as a library by moving the required packages out of the `internal`
|
||||||
|
directory
|
||||||
|
([#358](https://github.com/go-task/task/pull/358)).
|
||||||
- Do not error if a specified dotenv file does not exist
|
- Do not error if a specified dotenv file does not exist
|
||||||
([#378](https://github.com/go-task/task/issues/378), [#385](https://github.com/go-task/task/pull/385)).
|
([#378](https://github.com/go-task/task/issues/378), [#385](https://github.com/go-task/task/pull/385)).
|
||||||
- Fix panic when you have empty tasks in your Taskfile
|
- Fix panic when you have empty tasks in your Taskfile
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -1,10 +1,15 @@
|
|||||||

|
<div align="center">
|
||||||

|
<a href="https://taskfile.dev">
|
||||||

|
<img src="docs/Logo.png" width="200px" height="200px" />
|
||||||
|
</a>
|
||||||
|
|
||||||
# Task
|
<h1>Task</h1>
|
||||||
|
|
||||||
Task is a task runner / build tool that aims to be simpler and easier to use
|
<p>
|
||||||
than, for example, [GNU Make](https://www.gnu.org/software/make/).
|
Task is a task runner / build tool that aims to be simpler and easier to use than, for example, <a href="https://www.gnu.org/software/make/">GNU Make<a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
See [taskfile.dev](https://taskfile.dev) for the documentation.
|
<p>
|
||||||
|
See <a href="https://taskfile.dev">taskfile.dev</a> for the documentation.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|||||||
BIN
docs/Logo.png
Normal file
BIN
docs/Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -1,5 +1,9 @@
|
|||||||
# Task
|
# Task
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img id="logo" src="/Logo.png" height="250px" width="250px" />
|
||||||
|
</div>
|
||||||
|
|
||||||
Task is a task runner / build tool that aims to be simpler and easier to use
|
Task is a task runner / build tool that aims to be simpler and easier to use
|
||||||
than, for example, [GNU Make][make].
|
than, for example, [GNU Make][make].
|
||||||
|
|
||||||
|
|||||||
@@ -10,3 +10,8 @@ tasks:
|
|||||||
desc: Serves the documentation site locally
|
desc: Serves the documentation site locally
|
||||||
cmds:
|
cmds:
|
||||||
- docsify serve .
|
- docsify serve .
|
||||||
|
|
||||||
|
ico:
|
||||||
|
desc: Generate favicon.ico from Logo.png
|
||||||
|
cmds:
|
||||||
|
- convert -background transparent "Logo.png" -define icon:auto-resize=16,24,32,48,64,72,96,128,256 "favicon.ico"
|
||||||
|
|||||||
BIN
docs/favicon.ico
BIN
docs/favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 170 KiB |
@@ -8,6 +8,19 @@
|
|||||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-themeable/dist/css/theme-simple.css">
|
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-themeable/dist/css/theme-simple.css">
|
||||||
<meta name="google-site-verification" content="VGAYkbdmuaciIDGkBe-eAg9yfZg0C6ostgonbGxxOa0" />
|
<meta name="google-site-verification" content="VGAYkbdmuaciIDGkBe-eAg9yfZg0C6ostgonbGxxOa0" />
|
||||||
|
<style>
|
||||||
|
#logo {
|
||||||
|
transition: all 0.7s ease;
|
||||||
|
}
|
||||||
|
#logo:hover {
|
||||||
|
-webkit-transform: rotateZ(360deg);
|
||||||
|
-ms-transform: rotateZ(360deg);
|
||||||
|
transform: rotateZ(360deg);
|
||||||
|
}
|
||||||
|
.app-name-link img {
|
||||||
|
width: 125px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
@@ -15,7 +28,8 @@
|
|||||||
window.$docsify = {
|
window.$docsify = {
|
||||||
name: 'Task',
|
name: 'Task',
|
||||||
repo: 'go-task/task',
|
repo: 'go-task/task',
|
||||||
themeColor: '#00add8',
|
logo: 'Logo.png',
|
||||||
|
themeColor: '#29beb0',
|
||||||
loadSidebar: true,
|
loadSidebar: true,
|
||||||
auto2top: true,
|
auto2top: true,
|
||||||
maxLevel: 3,
|
maxLevel: 3,
|
||||||
|
|||||||
@@ -269,16 +269,16 @@ attribute:
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
main-task:
|
greet:
|
||||||
|
vars:
|
||||||
|
RECIPIENT: '{{default "World" .RECIPIENT}}'
|
||||||
cmds:
|
cmds:
|
||||||
- task: write-file
|
- echo "Hello, {{.RECIPIENT}}!"
|
||||||
vars: {FILE: "hello.txt", CONTENT: "Hello!"}
|
|
||||||
- task: write-file
|
|
||||||
vars: {FILE: "world.txt", CONTENT: "World!"}
|
|
||||||
|
|
||||||
write-file:
|
greet-pessimistically:
|
||||||
cmds:
|
cmds:
|
||||||
- echo "{{.CONTENT}}" > {{.FILE}}
|
- task: greet
|
||||||
|
vars: {RECIPIENT: "Cruel World"}
|
||||||
```
|
```
|
||||||
|
|
||||||
The above syntax is also supported in `deps`.
|
The above syntax is also supported in `deps`.
|
||||||
@@ -865,7 +865,7 @@ $ task default
|
|||||||
## Short task syntax
|
## Short task syntax
|
||||||
|
|
||||||
Starting on Task v3, you can now write tasks with a shorter syntax if they
|
Starting on Task v3, you can now write tasks with a shorter syntax if they
|
||||||
have the default settings (e.g. no custom `env:`, `vars:`, `silent:` , etc):
|
have the default settings (e.g. no custom `env:`, `vars:`, `desc:`, `silent:` , etc):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: '3'
|
version: '3'
|
||||||
@@ -873,7 +873,7 @@ version: '3'
|
|||||||
tasks:
|
tasks:
|
||||||
build: go build -v -o ./app{{exeExt}} .
|
build: go build -v -o ./app{{exeExt}} .
|
||||||
|
|
||||||
build:
|
run:
|
||||||
- task: build
|
- task: build
|
||||||
- ./app{{exeExt}} -h localhost -p 8080
|
- ./app{{exeExt}} -h localhost -p 8080
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -46,16 +46,10 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r, err := interp.New(
|
r, err := interp.New(
|
||||||
|
interp.Params("-e"),
|
||||||
interp.Dir(opts.Dir),
|
interp.Dir(opts.Dir),
|
||||||
interp.Env(expand.ListEnviron(environ...)),
|
interp.Env(expand.ListEnviron(environ...)),
|
||||||
|
interp.OpenHandler(openHandler),
|
||||||
interp.OpenHandler(func(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
|
||||||
if path == "/dev/null" {
|
|
||||||
return devNull{}, nil
|
|
||||||
}
|
|
||||||
return interp.DefaultOpenHandler()(ctx, path, flag, perm)
|
|
||||||
}),
|
|
||||||
|
|
||||||
interp.StdIO(opts.Stdin, opts.Stdout, opts.Stderr),
|
interp.StdIO(opts.Stdin, opts.Stdout, opts.Stderr),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -86,3 +80,10 @@ func Expand(s string) (string, error) {
|
|||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func openHandler(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
||||||
|
if path == "/dev/null" {
|
||||||
|
return devNull{}, nil
|
||||||
|
}
|
||||||
|
return interp.DefaultOpenHandler()(ctx, path, flag, perm)
|
||||||
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ 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,
|
Dir: t.Dir,
|
||||||
Task: t.Task,
|
Task: t.Name(),
|
||||||
Sources: t.Sources,
|
Sources: t.Sources,
|
||||||
Generates: t.Generates,
|
Generates: t.Generates,
|
||||||
Dry: e.Dry,
|
Dry: e.Dry,
|
||||||
|
|||||||
8
task.go
8
task.go
@@ -176,7 +176,7 @@ func (e *Executor) Setup() error {
|
|||||||
if v < 2.1 && e.Taskfile.Output != "" {
|
if v < 2.1 && e.Taskfile.Output != "" {
|
||||||
return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
|
return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
|
||||||
}
|
}
|
||||||
if v < 2.2 && len(e.Taskfile.Includes) > 0 {
|
if v < 2.2 && e.Taskfile.Includes.Len() > 0 {
|
||||||
return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
|
return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
|
||||||
}
|
}
|
||||||
if v >= 3.0 && e.Taskfile.Expansions > 2 {
|
if v >= 3.0 && e.Taskfile.Expansions > 2 {
|
||||||
@@ -229,10 +229,14 @@ func (e *Executor) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if v < 3 {
|
if v < 3 {
|
||||||
for _, taskfile := range e.Taskfile.Includes {
|
err := e.Taskfile.Includes.Range(func(_ string, taskfile taskfile.IncludedTaskfile) error {
|
||||||
if taskfile.AdvancedImport {
|
if taskfile.AdvancedImport {
|
||||||
return errors.New(`task: Import with additional parameters is only available starting on Taskfile version v3`)
|
return errors.New(`task: Import with additional parameters is only available starting on Taskfile version v3`)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
task_test.go
16
task_test.go
@@ -868,3 +868,19 @@ func TestDotenvShouldAllowMissingEnv(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tt.Run(t)
|
tt.Run(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExitImmediately(t *testing.T) {
|
||||||
|
const dir = "testdata/exit_immediately"
|
||||||
|
|
||||||
|
var buff bytes.Buffer
|
||||||
|
e := task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &buff,
|
||||||
|
Stderr: &buff,
|
||||||
|
Silent: true,
|
||||||
|
}
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
|
||||||
|
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
||||||
|
assert.Contains(t, buff.String(), `"this_should_fail": executable file not found in $PATH`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package taskfile
|
package taskfile
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrCantUnmarshalIncludedTaskfile is returned for invalid var YAML.
|
// ErrCantUnmarshalIncludedTaskfile is returned for invalid var YAML.
|
||||||
@@ -15,7 +19,72 @@ type IncludedTaskfile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IncludedTaskfiles represents information about included tasksfiles
|
// IncludedTaskfiles represents information about included tasksfiles
|
||||||
type IncludedTaskfiles = map[string]IncludedTaskfile
|
type IncludedTaskfiles struct {
|
||||||
|
Keys []string
|
||||||
|
Mapping map[string]IncludedTaskfile
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||||
|
func (tfs *IncludedTaskfiles) UnmarshalYAML(node *yaml.Node) error {
|
||||||
|
if node.Kind != yaml.MappingNode {
|
||||||
|
return errors.New("task: includes is not a map")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(@andreynering): on this style of custom unmarsheling,
|
||||||
|
// even number contains the keys, while odd numbers contains
|
||||||
|
// the values.
|
||||||
|
for i := 0; i < len(node.Content); i += 2 {
|
||||||
|
keyNode := node.Content[i]
|
||||||
|
valueNode := node.Content[i+1]
|
||||||
|
|
||||||
|
var v IncludedTaskfile
|
||||||
|
if err := valueNode.Decode(&v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tfs.Set(keyNode.Value, v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the length of the map
|
||||||
|
func (tfs *IncludedTaskfiles) Len() int {
|
||||||
|
if tfs == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return len(tfs.Keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges the given IncludedTaskfiles into the caller one
|
||||||
|
func (tfs *IncludedTaskfiles) Merge(other *IncludedTaskfiles) {
|
||||||
|
other.Range(func(key string, value IncludedTaskfile) error {
|
||||||
|
tfs.Set(key, value)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets a value to a given key
|
||||||
|
func (tfs *IncludedTaskfiles) Set(key string, includedTaskfile IncludedTaskfile) {
|
||||||
|
if tfs.Mapping == nil {
|
||||||
|
tfs.Mapping = make(map[string]IncludedTaskfile, 1)
|
||||||
|
}
|
||||||
|
if !stringSliceContains(tfs.Keys, key) {
|
||||||
|
tfs.Keys = append(tfs.Keys, key)
|
||||||
|
}
|
||||||
|
tfs.Mapping[key] = includedTaskfile
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range allows you to loop into the included taskfiles in its right order
|
||||||
|
func (tfs *IncludedTaskfiles) Range(yield func(key string, includedTaskfile IncludedTaskfile) error) error {
|
||||||
|
if tfs == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, k := range tfs.Keys {
|
||||||
|
if err := yield(k, tfs.Mapping[k]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalYAML implements yaml.Unmarshaler interface
|
// UnmarshalYAML implements yaml.Unmarshaler interface
|
||||||
func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
|||||||
@@ -22,11 +22,9 @@ func Merge(t1, t2 *Taskfile, namespaces ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if t1.Includes == nil {
|
if t1.Includes == nil {
|
||||||
t1.Includes = make(IncludedTaskfiles)
|
t1.Includes = &IncludedTaskfiles{}
|
||||||
}
|
|
||||||
for k, v := range t2.Includes {
|
|
||||||
t1.Includes[k] = v
|
|
||||||
}
|
}
|
||||||
|
t1.Includes.Merge(t2.Includes)
|
||||||
|
|
||||||
if t1.Vars == nil {
|
if t1.Vars == nil {
|
||||||
t1.Vars = &Vars{}
|
t1.Vars = &Vars{}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for namespace, includedTask := range t.Includes {
|
err = t.Includes.Range(func(namespace string, includedTask taskfile.IncludedTaskfile) error {
|
||||||
if v >= 3.0 {
|
if v >= 3.0 {
|
||||||
tr := templater.Templater{Vars: &taskfile.Vars{}, RemoveNoValue: true}
|
tr := templater.Templater{Vars: &taskfile.Vars{}, RemoveNoValue: true}
|
||||||
includedTask = taskfile.IncludedTaskfile{
|
includedTask = taskfile.IncludedTaskfile{
|
||||||
@@ -67,7 +67,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
AdvancedImport: includedTask.AdvancedImport,
|
AdvancedImport: includedTask.AdvancedImport,
|
||||||
}
|
}
|
||||||
if err := tr.Err(); err != nil {
|
if err := tr.Err(); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,21 +79,21 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
|
|
||||||
info, err := os.Stat(path)
|
info, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
path = filepath.Join(path, "Taskfile.yml")
|
path = filepath.Join(path, "Taskfile.yml")
|
||||||
}
|
}
|
||||||
includedTaskfile, err := readTaskfile(path)
|
includedTaskfile, err := readTaskfile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if len(includedTaskfile.Includes) > 0 {
|
if includedTaskfile.Includes.Len() > 0 {
|
||||||
return nil, ErrIncludedTaskfilesCantHaveIncludes
|
return ErrIncludedTaskfilesCantHaveIncludes
|
||||||
}
|
}
|
||||||
|
|
||||||
if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 {
|
if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 {
|
||||||
return nil, ErrIncludedTaskfilesCantHaveDotenvs
|
return ErrIncludedTaskfilesCantHaveDotenvs
|
||||||
}
|
}
|
||||||
|
|
||||||
if includedTask.AdvancedImport {
|
if includedTask.AdvancedImport {
|
||||||
@@ -105,8 +105,12 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = taskfile.Merge(t, includedTaskfile, namespace); err != nil {
|
if err = taskfile.Merge(t, includedTaskfile, namespace); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if v < 3.0 {
|
if v < 3.0 {
|
||||||
|
|||||||
10
taskfile/slice.go
Normal file
10
taskfile/slice.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package taskfile
|
||||||
|
|
||||||
|
func stringSliceContains(s []string, str string) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if v == str {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ type Taskfile struct {
|
|||||||
Expansions int
|
Expansions int
|
||||||
Output string
|
Output string
|
||||||
Method string
|
Method string
|
||||||
Includes IncludedTaskfiles
|
Includes *IncludedTaskfiles
|
||||||
Vars *Vars
|
Vars *Vars
|
||||||
Env *Vars
|
Env *Vars
|
||||||
Tasks Tasks
|
Tasks Tasks
|
||||||
@@ -26,7 +26,7 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||||||
Expansions int
|
Expansions int
|
||||||
Output string
|
Output string
|
||||||
Method string
|
Method string
|
||||||
Includes IncludedTaskfiles
|
Includes *IncludedTaskfiles
|
||||||
Vars *Vars
|
Vars *Vars
|
||||||
Env *Vars
|
Env *Vars
|
||||||
Tasks Tasks
|
Tasks Tasks
|
||||||
|
|||||||
@@ -53,21 +53,12 @@ func (vs *Vars) Set(key string, value Var) {
|
|||||||
if vs.Mapping == nil {
|
if vs.Mapping == nil {
|
||||||
vs.Mapping = make(map[string]Var, 1)
|
vs.Mapping = make(map[string]Var, 1)
|
||||||
}
|
}
|
||||||
if !strSliceContains(vs.Keys, key) {
|
if !stringSliceContains(vs.Keys, key) {
|
||||||
vs.Keys = append(vs.Keys, key)
|
vs.Keys = append(vs.Keys, key)
|
||||||
}
|
}
|
||||||
vs.Mapping[key] = value
|
vs.Mapping[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
func strSliceContains(s []string, str string) bool {
|
|
||||||
for _, v := range s {
|
|
||||||
if v == str {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Range allows you to loop into the vars in its right order
|
// Range allows you to loop into the vars in its right order
|
||||||
func (vs *Vars) Range(yield func(key string, value Var) error) error {
|
func (vs *Vars) Range(yield func(key string, value Var) error) error {
|
||||||
if vs == nil {
|
if vs == nil {
|
||||||
|
|||||||
6
testdata/exit_immediately/Taskfile.yml
vendored
Normal file
6
testdata/exit_immediately/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default: |
|
||||||
|
this_should_fail
|
||||||
|
echo "This shoudn't be print"
|
||||||
Reference in New Issue
Block a user