taskfile.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package ast
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/Masterminds/semver/v3"
  6. "gopkg.in/yaml.v3"
  7. "github.com/go-task/task/v3/errors"
  8. )
  9. // NamespaceSeparator contains the character that separates namespaces
  10. const NamespaceSeparator = ":"
  11. var V3 = semver.MustParse("3")
  12. // ErrIncludedTaskfilesCantHaveDotenvs is returned when a included Taskfile contains dotenvs
  13. var ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles can't have dotenv declarations. Please, move the dotenv declaration to the main Taskfile")
  14. // Taskfile is the abstract syntax tree for a Taskfile
  15. type Taskfile struct {
  16. Location string
  17. Version *semver.Version
  18. Output Output
  19. Method string
  20. Includes *Includes
  21. Set []string
  22. Shopt []string
  23. Vars *Vars
  24. Env *Vars
  25. Tasks Tasks
  26. Silent bool
  27. Dotenv []string
  28. Run string
  29. Interval time.Duration
  30. }
  31. // Merge merges the second Taskfile into the first
  32. func (t1 *Taskfile) Merge(t2 *Taskfile, include *Include) error {
  33. if !t1.Version.Equal(t2.Version) {
  34. return fmt.Errorf(`task: Taskfiles versions should match. First is "%s" but second is "%s"`, t1.Version, t2.Version)
  35. }
  36. if len(t2.Dotenv) > 0 {
  37. return ErrIncludedTaskfilesCantHaveDotenvs
  38. }
  39. if t2.Output.IsSet() {
  40. t1.Output = t2.Output
  41. }
  42. if t1.Vars == nil {
  43. t1.Vars = &Vars{}
  44. }
  45. if t1.Env == nil {
  46. t1.Env = &Vars{}
  47. }
  48. t1.Vars.Merge(t2.Vars, include)
  49. t1.Env.Merge(t2.Env, include)
  50. return t1.Tasks.Merge(t2.Tasks, include, t1.Vars)
  51. }
  52. func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error {
  53. switch node.Kind {
  54. case yaml.MappingNode:
  55. var taskfile struct {
  56. Version *semver.Version
  57. Output Output
  58. Method string
  59. Includes *Includes
  60. Set []string
  61. Shopt []string
  62. Vars *Vars
  63. Env *Vars
  64. Tasks Tasks
  65. Silent bool
  66. Dotenv []string
  67. Run string
  68. Interval time.Duration
  69. }
  70. if err := node.Decode(&taskfile); err != nil {
  71. return errors.NewTaskfileDecodeError(err, node)
  72. }
  73. tf.Version = taskfile.Version
  74. tf.Output = taskfile.Output
  75. tf.Method = taskfile.Method
  76. tf.Includes = taskfile.Includes
  77. tf.Set = taskfile.Set
  78. tf.Shopt = taskfile.Shopt
  79. tf.Vars = taskfile.Vars
  80. tf.Env = taskfile.Env
  81. tf.Tasks = taskfile.Tasks
  82. tf.Silent = taskfile.Silent
  83. tf.Dotenv = taskfile.Dotenv
  84. tf.Run = taskfile.Run
  85. tf.Interval = taskfile.Interval
  86. if tf.Vars == nil {
  87. tf.Vars = &Vars{}
  88. }
  89. if tf.Env == nil {
  90. tf.Env = &Vars{}
  91. }
  92. return nil
  93. }
  94. return errors.NewTaskfileDecodeError(nil, node).WithTypeMessage("taskfile")
  95. }