This is a non-breaking change. This fixes an issue when Clients are created and called concurrently.
Clients called SetClient on each of the Getters. When no getters were provided, it modified the clients of the default getters defined in the Getters map.
Since the map was mutated from multiple goroutines, it creates a race condition 'concurrent map writes'. The issue is mitigated by creating a new copy of Getters using DefaultGetters() function for every new client created. SetClient now modifies its own copy of the Getter, not the default Getters.
To reproduce the issue:
mkdir hello
touch hello/world
// main.go
package main
import "github.com/hashicorp/go-getter"
import "context"
import "os"
import "sync"
import "path/filepath"
func main() {
var wg sync.WaitGroup
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
keys := []string{"a", "b", "c"}
for _, key := range keys {
wg.Add(1)
go func(key string) {
get := &getter.Client{
Ctx: context.Background(),
Src: "./hello",
Dst: filepath.Join("dest", key),
Pwd: cwd,
Dir: true,
}
err := get.Get()
if err != nil {
panic(err)
}
wg.Done()
}(key)
}
wg.Wait()
}
This is a non-breaking change. This fixes an issue when Clients are created and called concurrently. Clients called
SetClient
on each of theGetter
s. When no getters were provided, it modified the clients of the default getters defined in theGetters
map. Since the map was mutated from multiple goroutines, it creates a race condition 'concurrent map writes'. The issue is mitigated by creating a new copy ofGetters
usingDefaultGetters()
function for every new client created.SetClient
now modifies its own copy of theGetter
, not the defaultGetters
.To reproduce the issue: