Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions pkg/cmd/plugin/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"syscall"

goversion "github.com/hashicorp/go-version"
log "github.com/sirupsen/logrus"
"github.com/spf13/afero"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -65,55 +66,69 @@ func parseInstallArg(arg string) (string, string) {
return plugin, version
}

func (ic *InstallCmd) installPluginByName(cmd *cobra.Command, arg string) (version string, err error) {
Comment thread
vcheung-stripe marked this conversation as resolved.
pluginName, version := parseInstallArg(arg)
func (ic *InstallCmd) runInstallCmd(cmd *cobra.Command, args []string) error {
if err := stripe.ValidateAPIBaseURL(ic.apiBaseURL); err != nil {
return err
}

plugin, err := plugins.LookUpPlugin(cmd.Context(), ic.cfg, ic.fs, pluginName)
color := ansi.Color(os.Stdout)

// Refresh the plugin before proceeding
if err := plugins.RefreshPluginManifest(cmd.Context(), ic.cfg, ic.fs, ic.apiBaseURL); err != nil {
return err
}

pluginName, version := parseInstallArg(args[0])

plugin, err := plugins.LookUpPlugin(cmd.Context(), ic.cfg, ic.fs, pluginName)
if err != nil {
return version, err
return err
}

if len(version) == 0 {
isLatest := len(version) == 0
if isLatest {
version = plugin.LookUpLatestVersion()
}

if plugin.IsVersionInstalled(ic.cfg, ic.fs, version) {
if isLatest {
fmt.Println(color.Green(fmt.Sprintf("✔ v%s is already installed (latest).", version)))
} else {
fmt.Println(color.Green(fmt.Sprintf("✔ v%s is already installed.", version)))
}
return nil
}

prevVersion := plugin.InstalledVersion(ic.cfg, ic.fs)

ctx := withSIGTERMCancel(cmd.Context(), func() {
log.WithFields(log.Fields{
"prefix": "cmd.installCmd.runInstallCmd",
}).Debug("Ctrl+C received, cleaning up...")
})

err = plugin.Install(ctx, ic.cfg, ic.fs, version, ic.apiBaseURL)

return version, err
}

func (ic *InstallCmd) runInstallCmd(cmd *cobra.Command, args []string) error {
if err := stripe.ValidateAPIBaseURL(ic.apiBaseURL); err != nil {
if err := plugin.Install(ctx, ic.cfg, ic.fs, version, ic.apiBaseURL); err != nil {
return err
}

var err error
var version string
color := ansi.Color(os.Stdout)

// Refresh the plugin before proceeding
err = plugins.RefreshPluginManifest(cmd.Context(), ic.cfg, ic.fs, ic.apiBaseURL)
if err != nil {
return err
if prevVersion != "" {
fmt.Println(color.Green(fmt.Sprintf("✔ %s from v%s to v%s.", versionChangeVerb(prevVersion, version), prevVersion, version)))
} else {
fmt.Println(color.Green(fmt.Sprintf("✔ installation of v%s complete.", version)))
}

version, err = ic.installPluginByName(cmd, args[0])
if err != nil {
return err
}

fmt.Println(color.Green(fmt.Sprintf("✔ installation of v%s complete.", version)))

return nil
}

func versionChangeVerb(from, to string) string {
prev, prevErr := goversion.NewVersion(from)
next, nextErr := goversion.NewVersion(to)
if prevErr == nil && nextErr == nil && prev.GreaterThan(next) {
return "downgraded"
}
return "upgraded"
}

func withSIGTERMCancel(ctx context.Context, onCancel func()) context.Context {
// Create a context that will be canceled when Ctrl+C is pressed
ctx, cancel := context.WithCancel(ctx)
Expand Down
23 changes: 17 additions & 6 deletions pkg/cmd/plugin/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,24 @@ func (uc *UpgradeCmd) runUpgradeCmd(cmd *cobra.Command, args []string) error {

version := plugin.LookUpLatestVersion()

err = plugin.Install(ctx, uc.cfg, uc.fs, version, uc.apiBaseURL)
color := ansi.Color(os.Stdout)

if err == nil {
color := ansi.Color(os.Stdout)
successMsg := fmt.Sprintf("✔ upgrade to v%s complete.", version)
fmt.Println(color.Green(successMsg))
if plugin.IsVersionInstalled(uc.cfg, uc.fs, version) {
fmt.Println(color.Green(fmt.Sprintf("✔ v%s is already installed (latest).", version)))
return nil
}

return err
prevVersion := plugin.InstalledVersion(uc.cfg, uc.fs)

if err := plugin.Install(ctx, uc.cfg, uc.fs, version, uc.apiBaseURL); err != nil {
return err
}

if prevVersion != "" {
fmt.Println(color.Green(fmt.Sprintf("✔ %s from v%s to v%s.", versionChangeVerb(prevVersion, version), prevVersion, version)))
} else {
fmt.Println(color.Green(fmt.Sprintf("✔ upgrade to v%s complete.", version)))
}

return nil
}
27 changes: 27 additions & 0 deletions pkg/plugins/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,33 @@ func (p *Plugin) getReleaseForVersion(version string) *Release {
return nil
}

// IsVersionInstalled returns true if the given version of the plugin is already installed on disk.
Comment thread
vcheung-stripe marked this conversation as resolved.
func (p *Plugin) IsVersionInstalled(config config.IConfig, fs afero.Fs, version string) bool {
pluginDir := p.getPluginInstallPath(config, version)
pluginBinaryPath := filepath.Join(pluginDir, p.Binary) + GetBinaryExtension()
_, err := fs.Stat(pluginBinaryPath)
return err == nil
}

// InstalledVersion returns the currently installed version of the plugin, or empty string if none.
func (p *Plugin) InstalledVersion(config config.IConfig, fs afero.Fs) string {
pluginsDir := getPluginsDir(config)
pluginDir := filepath.Join(pluginsDir, p.Shortname)

entries, err := afero.ReadDir(fs, pluginDir)
if err != nil {
return ""
}

for _, entry := range entries {
if entry.IsDir() {
return entry.Name()
}
}

return ""
}

// Install installs the plugin of the given version
func (p *Plugin) Install(ctx context.Context, cfg config.IConfig, fs afero.Fs, version string, baseURL string) error {
spinner := ansi.StartNewSpinner(ansi.Faint(fmt.Sprintf("installing '%s' v%s...", p.Shortname, version)), os.Stdout)
Expand Down
Loading