mirror of
https://github.com/go-task/task.git
synced 2026-06-29 15:44:30 +00:00
Add support for multi-level includes and cyclic include detection
This commit is contained in:
@@ -15,29 +15,35 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrIncludedTaskfilesCantHaveIncludes is returned when a included Taskfile contains includes
|
||||
ErrIncludedTaskfilesCantHaveIncludes = errors.New("task: Included Taskfiles can't have includes. Please, move the include to the main Taskfile")
|
||||
// ErrIncludedTaskfilesCantHaveDotenvs is returned when a included Taskfile contains dotenvs
|
||||
ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles can't have dotenv declarations. Please, move the dotenv declaration to the main Taskfile")
|
||||
|
||||
defaultTaskfiles = []string{"Taskfile.yml", "Taskfile.yaml"}
|
||||
)
|
||||
|
||||
type ReaderNode struct {
|
||||
Dir string
|
||||
Entrypoint string
|
||||
Optional bool
|
||||
Parent *ReaderNode
|
||||
}
|
||||
|
||||
// Taskfile reads a Taskfile for a given directory
|
||||
// Uses current dir when dir is left empty. Uses Taskfile.yml
|
||||
// or Taskfile.yaml when entrypoint is left empty
|
||||
func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||
if dir == "" {
|
||||
func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) {
|
||||
if readerNode.Dir == "" {
|
||||
d, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dir = d
|
||||
readerNode.Dir = d
|
||||
}
|
||||
path, err := exists(filepath.Join(dir, entrypoint))
|
||||
path, err := exists(filepath.Join(readerNode.Dir, readerNode.Entrypoint))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
readerNode.Entrypoint = filepath.Base(path)
|
||||
|
||||
t, err := readTaskfile(path)
|
||||
if err != nil {
|
||||
@@ -68,10 +74,32 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||
return err
|
||||
}
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Join(dir, path)
|
||||
path = filepath.Join(readerNode.Dir, path)
|
||||
}
|
||||
|
||||
path, err = exists(path)
|
||||
// check for cyclic include references by walking up
|
||||
// node tree of parents and comparing paths
|
||||
var curNode = readerNode
|
||||
for curNode.Parent != nil {
|
||||
curNode = curNode.Parent
|
||||
curPath := filepath.Join(curNode.Dir, curNode.Entrypoint)
|
||||
if curPath == path {
|
||||
return fmt.Errorf("include cycle detected between %s <--> %s",
|
||||
curPath,
|
||||
filepath.Join(readerNode.Dir, readerNode.Entrypoint),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// if we made it here then there is no cyclic include
|
||||
readOpts := &ReaderNode{
|
||||
Dir: filepath.Dir(path),
|
||||
Entrypoint: filepath.Base(path),
|
||||
Parent: readerNode,
|
||||
Optional: includedTask.Optional,
|
||||
}
|
||||
|
||||
includedTaskfile, err := Taskfile(readOpts)
|
||||
if err != nil {
|
||||
if includedTask.Optional {
|
||||
return nil
|
||||
@@ -79,14 +107,6 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||
return err
|
||||
}
|
||||
|
||||
includedTaskfile, err := readTaskfile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if includedTaskfile.Includes.Len() > 0 {
|
||||
return ErrIncludedTaskfilesCantHaveIncludes
|
||||
}
|
||||
|
||||
if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 {
|
||||
return ErrIncludedTaskfilesCantHaveDotenvs
|
||||
}
|
||||
@@ -94,12 +114,12 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||
if includedTask.AdvancedImport {
|
||||
for k, v := range includedTaskfile.Vars.Mapping {
|
||||
o := v
|
||||
o.Dir = filepath.Join(dir, includedTask.Dir)
|
||||
o.Dir = filepath.Join(readerNode.Dir, includedTask.Dir)
|
||||
includedTaskfile.Vars.Mapping[k] = o
|
||||
}
|
||||
for k, v := range includedTaskfile.Env.Mapping {
|
||||
o := v
|
||||
o.Dir = filepath.Join(dir, includedTask.Dir)
|
||||
o.Dir = filepath.Join(readerNode.Dir, includedTask.Dir)
|
||||
includedTaskfile.Env.Mapping[k] = o
|
||||
}
|
||||
|
||||
@@ -120,7 +140,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||
}
|
||||
|
||||
if v < 3.0 {
|
||||
path = filepath.Join(dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS))
|
||||
path = filepath.Join(readerNode.Dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS))
|
||||
if _, err = os.Stat(path); err == nil {
|
||||
osTaskfile, err := readTaskfile(path)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user