diff --git a/internal/plugin/installer/base.go b/internal/plugin/installer/base.go index c21a245a8..acb4441e4 100644 --- a/internal/plugin/installer/base.go +++ b/internal/plugin/installer/base.go @@ -32,10 +32,25 @@ func newBase(source string) base { settings := cli.New() return base{ Source: source, - PluginsDirectory: settings.PluginsDirectory, + PluginsDirectory: pluginInstallDir(settings.PluginsDirectory), } } +// pluginInstallDir returns the directory to install a new plugin into. +// When HELM_PLUGINS contains multiple colon-separated paths, the first +// path is used as the install destination — consistent with how +// FindPlugins() loads from all paths and matching git conventions. +func pluginInstallDir(helmPlugins string) string { + if helmPlugins == "" { + return helmPlugins + } + dirs := filepath.SplitList(helmPlugins) + if len(dirs) == 0 { + return helmPlugins + } + return dirs[0] +} + // Path is where the plugin will be installed. func (b *base) Path() string { if b.Source == "" { diff --git a/internal/plugin/installer/base_test.go b/internal/plugin/installer/base_test.go index 62b77bde5..5f9851e4a 100644 --- a/internal/plugin/installer/base_test.go +++ b/internal/plugin/installer/base_test.go @@ -44,3 +44,40 @@ func TestPath(t *testing.T) { } } } + +func TestPluginInstallDir(t *testing.T) { + tests := []struct { + name string + helmPlugins string + want string + }{ + { + name: "empty string returns empty string", + helmPlugins: "", + want: "", + }, + { + name: "single path returned as-is", + helmPlugins: "/tmp/plugins", + want: "/tmp/plugins", + }, + { + name: "two paths returns first", + helmPlugins: "/tmp/abc:/tmp/xyz", + want: "/tmp/abc", + }, + { + name: "three paths returns first", + helmPlugins: "/tmp/a:/tmp/b:/tmp/c", + want: "/tmp/a", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := pluginInstallDir(tt.helmPlugins) + if got != tt.want { + t.Errorf("pluginInstallDir(%q) = %q, want %q", tt.helmPlugins, got, tt.want) + } + }) + } +}