2023-12-29 22:32:03 +02:00
package ast
2018-02-17 18:22:18 +02:00
2020-05-17 20:42:27 +02:00
import (
2024-01-04 13:58:46 +02:00
"errors"
2020-05-17 20:42:27 +02:00
"fmt"
2022-12-31 18:48:49 +02:00
"time"
2022-12-19 03:11:31 +02:00
2023-02-08 12:21:43 +02:00
"github.com/Masterminds/semver/v3"
2022-12-19 03:11:31 +02:00
"gopkg.in/yaml.v3"
2020-05-17 20:42:27 +02:00
)
2024-01-09 20:48:20 +02:00
// NamespaceSeparator contains the character that separates namespaces
const NamespaceSeparator = ":"
2023-12-29 22:26:02 +02:00
var V3 = semver . MustParse ( "3" )
2023-02-08 12:21:43 +02:00
2024-01-04 13:58:46 +02:00
// ErrIncludedTaskfilesCantHaveDotenvs is returned when a included Taskfile contains dotenvs
var ErrIncludedTaskfilesCantHaveDotenvs = errors . New ( "task: Included Taskfiles can't have dotenv declarations. Please, move the dotenv declaration to the main Taskfile" )
2023-12-29 22:32:03 +02:00
// Taskfile is the abstract syntax tree for a Taskfile
2018-02-17 18:22:18 +02:00
type Taskfile struct {
2023-12-29 22:26:02 +02:00
Location string
Version * semver . Version
Output Output
Method string
2024-01-04 02:04:53 +02:00
Includes * Includes
2023-12-29 22:26:02 +02:00
Set [ ] string
Shopt [ ] string
Vars * Vars
Env * Vars
Tasks Tasks
Silent bool
Dotenv [ ] string
Run string
Interval time . Duration
2018-02-17 18:22:18 +02:00
}
2024-01-09 20:48:20 +02:00
// Merge merges the second Taskfile into the first
func ( t1 * Taskfile ) Merge ( t2 * Taskfile , include * Include ) error {
if ! t1 . Version . Equal ( t2 . Version ) {
return fmt . Errorf ( ` task: Taskfiles versions should match. First is "%s" but second is "%s" ` , t1 . Version , t2 . Version )
}
2024-01-04 13:58:46 +02:00
if len ( t2 . Dotenv ) > 0 {
return ErrIncludedTaskfilesCantHaveDotenvs
}
2024-01-09 20:48:20 +02:00
if t2 . Output . IsSet ( ) {
t1 . Output = t2 . Output
}
if t1 . Vars == nil {
t1 . Vars = & Vars { }
}
if t1 . Env == nil {
t1 . Env = & Vars { }
}
t1 . Vars . Merge ( t2 . Vars )
t1 . Env . Merge ( t2 . Env )
2024-01-22 00:06:54 +02:00
t1 . Tasks . Merge ( t2 . Tasks , include )
2024-01-09 20:48:20 +02:00
return nil
}
2022-12-19 03:11:31 +02:00
func ( tf * Taskfile ) UnmarshalYAML ( node * yaml . Node ) error {
switch node . Kind {
case yaml . MappingNode :
var taskfile struct {
2023-12-29 22:26:02 +02:00
Version * semver . Version
Output Output
Method string
2024-01-04 02:04:53 +02:00
Includes * Includes
2023-12-29 22:26:02 +02:00
Set [ ] string
Shopt [ ] string
Vars * Vars
Env * Vars
Tasks Tasks
Silent bool
Dotenv [ ] string
Run string
Interval time . Duration
2022-12-19 03:11:31 +02:00
}
if err := node . Decode ( & taskfile ) ; err != nil {
return err
}
tf . Version = taskfile . Version
tf . Output = taskfile . Output
tf . Method = taskfile . Method
tf . Includes = taskfile . Includes
2023-01-14 21:41:56 +02:00
tf . Set = taskfile . Set
tf . Shopt = taskfile . Shopt
2022-12-19 03:11:31 +02:00
tf . Vars = taskfile . Vars
tf . Env = taskfile . Env
tf . Tasks = taskfile . Tasks
tf . Silent = taskfile . Silent
tf . Dotenv = taskfile . Dotenv
tf . Run = taskfile . Run
tf . Interval = taskfile . Interval
if tf . Vars == nil {
tf . Vars = & Vars { }
}
if tf . Env == nil {
tf . Env = & Vars { }
}
return nil
2018-02-17 18:22:18 +02:00
}
2022-09-08 19:22:44 +02:00
2022-12-19 03:11:31 +02:00
return fmt . Errorf ( "yaml: line %d: cannot unmarshal %s into taskfile" , node . Line , node . ShortTag ( ) )
2018-02-17 18:22:18 +02:00
}