1
0
mirror of https://github.com/go-task/task.git synced 2025-03-17 21:08:01 +02:00

Merge branch 'pull-6-variables'

This commit is contained in:
Andrey Nering 2017-03-05 15:48:51 -03:00
commit 4127ea5afe
3 changed files with 164 additions and 8 deletions

View File

@ -42,6 +42,55 @@ task assets build
If Bash is available (Linux and Windows while on Git Bash), the commands will
run in Bash, otherwise will fallback to `cmd` (on Windows).
### Variables
```yml
build:
deps: [setvar]
cmds:
- echo "{{prefix}} {{THEVAR}}"
variables:
prefix: "Path:"
setvar:
cmds:
- echo "{{PATH}}"
set: THEVAR
```
The above sample saves the path into a new variable which is then again echoed.
You can use environment variables, task level variables and a file called `Variables` as source of variables.
They are evaluated in the following order:
Task local variables are overwritten by variables found in `Variables`. Variables found in `Variables` are overwritten with variables from the environment. The output of the last command is stored in the environment. So you can do something like this:
```yml
build:
deps: [setvar]
cmds:
- echo "{{prefix}} '{{THEVAR}}'"
variables:
prefix: "Result: "
setvar:
cmds:
- echo -n "a"
- echo -n "{{THEVAR}}b"
- echo -n "{{THEVAR}}c"
set: THEVAR
```
The result of a run of build would be:
```
a
ab
abc
Result: 'abc'
```
### Running task in another dir
By default, tasks will be executed in the directory where the Taskfile is

41
task.go
View File

@ -2,6 +2,7 @@ package task
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
@ -45,6 +46,8 @@ type Task struct {
Sources []string
Generates []string
Dir string
Variables map[string]string
Set string
}
// Run runs Task
@ -81,8 +84,13 @@ func RunTask(name string) error {
return &taskNotFoundError{name}
}
vars, err := t.handleVariables()
if err != nil {
return &taskRunError{name, err}
}
for _, d := range t.Deps {
if err := RunTask(d); err != nil {
if err := RunTask(ReplaceVariables(d, vars)); err != nil {
return err
}
}
@ -93,9 +101,23 @@ func RunTask(name string) error {
}
for _, c := range t.Cmds {
if err := runCommand(c, t.Dir); err != nil {
// read in a each time, as a command could change a variable or it has been changed by a dependency
vars, err = t.handleVariables()
if err != nil {
return &taskRunError{name, err}
}
var (
output string
err error
)
if output, err = runCommand(ReplaceVariables(c, vars), ReplaceVariables(t.Dir, vars)); err != nil {
return &taskRunError{name, err}
}
if t.Set != "" {
os.Setenv(t.Set, output)
} else {
fmt.Println(output)
}
}
return nil
}
@ -118,8 +140,12 @@ func isTaskUpToDate(t *Task) bool {
return generatesMinTime.After(sourcesMaxTime)
}
func runCommand(c, path string) error {
var cmd *exec.Cmd
func runCommand(c, path string) (string, error) {
var (
cmd *exec.Cmd
b []byte
err error
)
if ShExists {
cmd = exec.Command(ShPath, "-c", c)
} else {
@ -128,12 +154,11 @@ func runCommand(c, path string) error {
if path != "" {
cmd.Dir = path
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return err
if b, err = cmd.Output(); err != nil {
return "", err
}
return nil
return string(b), nil
}
func readTaskfile() (tasks map[string]*Task, err error) {

82
variable_handling.go Normal file
View File

@ -0,0 +1,82 @@
package task
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/BurntSushi/toml"
"gopkg.in/yaml.v2"
)
var (
// VariableFilePath file containing additional variables
VariableFilePath = "Taskvars"
)
func (t Task) handleVariables() (map[string]string, error) {
localVariables := make(map[string]string)
for key, value := range t.Variables {
localVariables[key] = value
}
if fileVariables, err := readVariablefile(); err == nil {
for key, value := range fileVariables {
localVariables[key] = value
}
} else {
return nil, err
}
for key, value := range getEnvironmentVariables() {
localVariables[key] = value
}
return localVariables, nil
}
// ReplaceVariables writes variables into initial string
func ReplaceVariables(initial string, variables map[string]string) string {
replaced := initial
for name, val := range variables {
replaced = strings.Replace(replaced, fmt.Sprintf("{{%s}}", name), val, -1)
}
return replaced
}
// GetEnvironmentVariables returns environment variables as map
func getEnvironmentVariables() map[string]string {
getenvironment := func(data []string, getkeyval func(item string) (key, val string)) map[string]string {
items := make(map[string]string)
for _, item := range data {
key, val := getkeyval(item)
items[key] = val
}
return items
}
return getenvironment(os.Environ(), func(item string) (key, val string) {
splits := strings.Split(item, "=")
key = splits[0]
val = splits[1]
return
})
}
func readVariablefile() (map[string]string, error) {
var variables map[string]string
if b, err := ioutil.ReadFile(VariableFilePath + ".yml"); err == nil {
if err := yaml.Unmarshal(b, &variables); err != nil {
return nil, err
}
}
if b, err := ioutil.ReadFile(VariableFilePath + ".json"); err == nil {
if err := json.Unmarshal(b, &variables); err != nil {
return nil, err
}
}
if b, err := ioutil.ReadFile(VariableFilePath + ".toml"); err == nil {
if err := toml.Unmarshal(b, &variables); err != nil {
return nil, err
}
}
return variables, nil
}