mirror of
https://github.com/go-task/task.git
synced 2025-03-17 21:08:01 +02:00
fix: deep copy included tasks
This commit is contained in:
parent
bb79fa1dc3
commit
d33906b6e4
23
taskfile/copy.go
Normal file
23
taskfile/copy.go
Normal file
@ -0,0 +1,23 @@
|
||||
package taskfile
|
||||
|
||||
import "golang.org/x/exp/constraints"
|
||||
|
||||
func deepCopySlice[T any](orig []T) []T {
|
||||
if orig == nil {
|
||||
return nil
|
||||
}
|
||||
c := make([]T, len(orig))
|
||||
copy(c, orig)
|
||||
return c
|
||||
}
|
||||
|
||||
func deepCopyMap[K constraints.Ordered, V any](orig map[K]V) map[K]V {
|
||||
if orig == nil {
|
||||
return nil
|
||||
}
|
||||
c := make(map[K]V, len(orig))
|
||||
for k, v := range orig {
|
||||
c[k] = v
|
||||
}
|
||||
return c
|
||||
}
|
@ -120,6 +120,23 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopy creates a new instance of IncludedTaskfile and copies
|
||||
// data by value from the source struct.
|
||||
func (it *IncludedTaskfile) DeepCopy() *IncludedTaskfile {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
return &IncludedTaskfile{
|
||||
Taskfile: it.Taskfile,
|
||||
Dir: it.Dir,
|
||||
Optional: it.Optional,
|
||||
Internal: it.Internal,
|
||||
AdvancedImport: it.AdvancedImport,
|
||||
Vars: it.Vars.DeepCopy(),
|
||||
BaseDir: it.BaseDir,
|
||||
}
|
||||
}
|
||||
|
||||
// FullTaskfilePath returns the fully qualified path to the included taskfile
|
||||
func (it *IncludedTaskfile) FullTaskfilePath() (string, error) {
|
||||
return it.resolvePath(it.Taskfile)
|
||||
|
@ -39,19 +39,14 @@ func Merge(t1, t2 *Taskfile, includedTaskfile *IncludedTaskfile, namespaces ...s
|
||||
t1.Tasks = make(Tasks)
|
||||
}
|
||||
for k, v := range t2.Tasks {
|
||||
// FIXME(@andreynering): Refactor this block, otherwise we can
|
||||
// have serious side-effects in the future, since we're editing
|
||||
// the original references instead of deep copying them.
|
||||
task := v
|
||||
// We do a deep copy of the task struct here to ensure that no data can
|
||||
// be changed elsewhere once the taskfile is merged.
|
||||
task := v.DeepCopy()
|
||||
|
||||
// Set the task to internal if EITHER the included task or the included
|
||||
// taskfile are marked as internal
|
||||
task.Internal = task.Internal || includedTaskfile.Internal
|
||||
|
||||
// Deep copy the aliases so we can use them later
|
||||
origAliases := make([]string, len(task.Aliases))
|
||||
copy(origAliases, task.Aliases)
|
||||
|
||||
// Add namespaces to dependencies, commands and aliases
|
||||
for _, dep := range task.Deps {
|
||||
dep.Task = taskNameWithNamespace(dep.Task, namespaces...)
|
||||
@ -67,8 +62,8 @@ func Merge(t1, t2 *Taskfile, includedTaskfile *IncludedTaskfile, namespaces ...s
|
||||
// Add namespace aliases
|
||||
if includedTaskfile != nil {
|
||||
for _, namespaceAlias := range includedTaskfile.Aliases {
|
||||
for _, alias := range origAliases {
|
||||
task.Aliases = append(v.Aliases, taskNameWithNamespace(alias, namespaceAlias))
|
||||
for _, alias := range v.Aliases {
|
||||
task.Aliases = append(task.Aliases, taskNameWithNamespace(alias, namespaceAlias))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,3 +98,35 @@ func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
t.Run = task.Run
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopy creates a new instance of Task and copies
|
||||
// data by value from the source struct.
|
||||
func (t *Task) DeepCopy() *Task {
|
||||
c := &Task{
|
||||
Task: t.Task,
|
||||
Cmds: deepCopySlice(t.Cmds),
|
||||
Deps: deepCopySlice(t.Deps),
|
||||
Label: t.Label,
|
||||
Desc: t.Desc,
|
||||
Summary: t.Summary,
|
||||
Aliases: deepCopySlice(t.Aliases),
|
||||
Sources: deepCopySlice(t.Sources),
|
||||
Generates: deepCopySlice(t.Generates),
|
||||
Status: deepCopySlice(t.Status),
|
||||
Preconditions: deepCopySlice(t.Preconditions),
|
||||
Dir: t.Dir,
|
||||
Vars: t.Vars.DeepCopy(),
|
||||
Env: t.Env.DeepCopy(),
|
||||
Silent: t.Silent,
|
||||
Interactive: t.Interactive,
|
||||
Internal: t.Internal,
|
||||
Method: t.Method,
|
||||
Prefix: t.Prefix,
|
||||
IgnoreError: t.IgnoreError,
|
||||
Run: t.Run,
|
||||
IncludeVars: t.IncludeVars.DeepCopy(),
|
||||
IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(),
|
||||
IncludedTaskfile: t.IncludedTaskfile.DeepCopy(),
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
@ -34,6 +34,18 @@ func (vs *Vars) UnmarshalYAML(node *yaml.Node) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopy creates a new instance of Vars and copies
|
||||
// data by value from the source struct.
|
||||
func (vs *Vars) DeepCopy() *Vars {
|
||||
if vs == nil {
|
||||
return nil
|
||||
}
|
||||
return &Vars{
|
||||
Keys: deepCopySlice(vs.Keys),
|
||||
Mapping: deepCopyMap(vs.Mapping),
|
||||
}
|
||||
}
|
||||
|
||||
// Merge merges the given Vars into the caller one
|
||||
func (vs *Vars) Merge(other *Vars) {
|
||||
_ = other.Range(func(key string, value Var) error {
|
||||
|
Loading…
x
Reference in New Issue
Block a user