diff --git a/pkg/state/storage.go b/pkg/state/storage.go index 68b7e217..3a471c98 100644 --- a/pkg/state/storage.go +++ b/pkg/state/storage.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" "path/filepath" + "runtime" "sort" "strings" @@ -135,11 +136,18 @@ func (st *Storage) normalizePath(path string) string { if u != nil && (u.Scheme != "" || filepath.IsAbs(path)) { return path } else { - return st.JoinBase(path) + return st.JoinBase(path, runtime.GOOS) } } // JoinBase returns an absolute path in the form basePath/relative -func (st *Storage) JoinBase(relPath string) string { - return filepath.Join(st.basePath, relPath) +// Helm's setFiles command does not support unescaped filepath separators (\) on Windows. +// Instead, it requires double backslashes (\\) as filepath separators. +// See https://github.com/helm/helm/issues/9537 +func (st *Storage) JoinBase(relPath, GOOS string) string { + path := filepath.Join(st.basePath, relPath) + if GOOS == "windows" { + return strings.ReplaceAll(path, "\\", "\\\\") + } + return path } diff --git a/pkg/state/storage_test.go b/pkg/state/storage_test.go index 5cc349b3..6bf66ad0 100644 --- a/pkg/state/storage_test.go +++ b/pkg/state/storage_test.go @@ -176,27 +176,37 @@ func TestJoinBase(t *testing.T) { tests := []struct { name string base string + goos string path string want string }{ { name: "joinBase with non-root base", base: "/root", + goos: "linux", path: "local/timespan-application.yml", want: "/local/timespan-application.yml", }, { name: "joinBase with root path", base: "/", + goos: "linux", path: "data/timespan-application.yml", want: "/data/timespan-application.yml", }, + { + name: "windows joinBase", + base: "", + goos: "windows", + path: "data\\timespan-application.yml", + want: "data\\\\timespan-application.yml", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { storageIns := NewStorage(tt.base, helmexec.NewLogger(io.Discard, "debug"), filesystem.DefaultFileSystem()) - if got := storageIns.JoinBase(tt.path); got != tt.want { + if got := storageIns.JoinBase(tt.path, tt.goos); got != tt.want { t.Errorf("JoinBase() = %v, want %v", got, tt.want) } })