diff --git a/api/internal/git/cloner.go b/api/internal/git/cloner.go index 2098cdd31e..1d1bef2ea1 100644 --- a/api/internal/git/cloner.go +++ b/api/internal/git/cloner.go @@ -4,21 +4,39 @@ package git import ( + "sync" + "sigs.k8s.io/kustomize/kyaml/filesys" ) // Cloner is a function that can clone a git repo. type Cloner func(repoSpec *RepoSpec) error +var ( + clones = make(map[string]filesys.ConfirmedDir) + cloneCount = make(map[filesys.ConfirmedDir]uint16) + cloneMutex sync.Mutex +) + // ClonerUsingGitExec uses a local git install, as opposed // to say, some remote API, to obtain a local clone of // a remote repo. func ClonerUsingGitExec(repoSpec *RepoSpec) error { + if dir, found := clones[repoSpec.Raw()]; found { + repoSpec.Dir = dir + cloneCount[dir] += 1 + return nil + } + + cloneMutex.Lock() + defer cloneMutex.Unlock() + r, err := newCmdRunner(repoSpec.Timeout) if err != nil { return err } repoSpec.Dir = r.dir + cloneCount[r.dir] = 1 if err = r.run("init"); err != nil { return err } @@ -41,6 +59,10 @@ func ClonerUsingGitExec(repoSpec *RepoSpec) error { if repoSpec.Submodules { return r.run("submodule", "update", "--init", "--recursive") } + + // save the location of the clone for later reuse + clones[repoSpec.Raw()] = r.dir + return nil } @@ -54,3 +76,16 @@ func DoNothingCloner(dir filesys.ConfirmedDir) Cloner { return nil } } + +// DecrementCloneCount decrements the count of repoSpecs using a directory clone. +func DecrementCloneCount(dir filesys.ConfirmedDir) uint16 { + cloneMutex.Lock() + defer cloneMutex.Unlock() + + if count, exists := cloneCount[dir]; exists && count > 0 { + cloneCount[dir] -= 1 + return cloneCount[dir] + } + + return 0 +} diff --git a/api/internal/git/repospec.go b/api/internal/git/repospec.go index ba6156cc5b..91d4a0438c 100644 --- a/api/internal/git/repospec.go +++ b/api/internal/git/repospec.go @@ -72,7 +72,12 @@ func (x *RepoSpec) AbsPath() string { } func (x *RepoSpec) Cleaner(fSys filesys.FileSystem) func() error { - return func() error { return fSys.RemoveAll(x.Dir.String()) } + return func() error { + if DecrementCloneCount(x.Dir) == 0 { + return fSys.RemoveAll(x.Dir.String()) + } + return nil + } } const (