diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index 96162499f..a28bb82a1 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -22,6 +22,7 @@ import ( "io" "io/ioutil" "os" + "path/filepath" "time" "github.com/gofrs/flock" @@ -78,6 +79,12 @@ func newRepoAddCmd(out io.Writer) *cobra.Command { } func (o *repoAddOptions) run(out io.Writer) error { + //Ensure the file directory exists as it is required for file locking + err := os.MkdirAll(filepath.Dir(o.repoFile), os.ModePerm) + if err != nil && !os.IsExist(err) { + return err + } + // Lock the repository file for concurrent goroutines or processes synchronization fileLock := flock.New(o.repoFile) lockCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) diff --git a/cmd/helm/repo_add_test.go b/cmd/helm/repo_add_test.go index c53f3bd65..1ac61fba8 100644 --- a/cmd/helm/repo_add_test.go +++ b/cmd/helm/repo_add_test.go @@ -92,15 +92,23 @@ func TestRepoAdd(t *testing.T) { func TestRepoAddConcurrentGoRoutines(t *testing.T) { const testName = "test-name" + repoFile := filepath.Join(ensure.TempDir(t), "repositories.yaml") + repoAddConcurrent(t, testName, repoFile) +} + +func TestRepoAddConcurrentDirNotExist(t *testing.T) { + const testName = "test-name-2" + repoFile := filepath.Join(ensure.TempDir(t), "foo", "repositories.yaml") + repoAddConcurrent(t, testName, repoFile) +} +func repoAddConcurrent(t *testing.T, testName, repoFile string) { ts, err := repotest.NewTempServer("testdata/testserver/*.*") if err != nil { t.Fatal(err) } defer ts.Stop() - repoFile := filepath.Join(ensure.TempDir(t), "repositories.yaml") - var wg sync.WaitGroup wg.Add(3) for i := 0; i < 3; i++ {