Skip to content

Commit

Permalink
Merge pull request #5 from MTVersionManager/usecmd
Browse files Browse the repository at this point in the history
Implement the use command
  • Loading branch information
leomick authored Nov 23, 2024
2 parents 962a4c4 + 1ba6db6 commit ee9ddb3
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 129 deletions.
122 changes: 30 additions & 92 deletions cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,108 +2,38 @@ package cmd

import (
"fmt"
"github.com/MTVersionManager/goplugin"
"github.com/MTVersionManager/mtvm/components/install"
"github.com/MTVersionManager/mtvm/shared"
"github.com/MTVersionManager/mtvmplugin"
"github.com/charmbracelet/bubbles/progress"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/spf13/cobra"
"log"
"os"
"path"
)

type installModel struct {
progressChannel chan float64
plugin mtvmplugin.Plugin
installing bool
progress float64
progressBar progress.Model
version string
spinner spinner.Model
pluginName string
installer install.Model
}

type progressMsg float64
type downloadedMsg bool
type installedMsg bool

func installInitialModel(plugin mtvmplugin.Plugin, pluginName string, version string) installModel {
progressChannel := make(chan float64)
progressBar := progress.New(progress.WithDefaultGradient())
spinnerModel := spinner.New()
spinnerModel.Spinner = spinner.Dot
downloadModel := install.New(plugin, pluginName, version)
return installModel{
progressChannel: progressChannel,
progressBar: progressBar,
version: version,
plugin: plugin,
installing: true,
spinner: spinnerModel,
pluginName: pluginName,
installer: downloadModel,
}
}

func (m installModel) Init() tea.Cmd {
return tea.Batch(download(m.plugin, m.version, m.progressChannel), waitForProgress(m.progressChannel), m.spinner.Tick)
return m.installer.Init()
}

func (m installModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case error:
log.Fatal(msg)
case downloadedMsg:
m.progress = 1
m.installing = false
return m, install(m.plugin, shared.Configuration.InstallDir, m.pluginName, m.version)
case installedMsg:
return m, tea.Quit
case progressMsg:
m.progress = float64(msg)
cmds = append(cmds, waitForProgress(m.progressChannel))
}
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...)
m.installer, cmd = m.installer.Update(msg)
return m, cmd
}

func (m installModel) View() string {
if m.installing {
return m.progressBar.ViewAs(m.progress)
}
return m.spinner.View() + " Installing..."
}

func download(plugin mtvmplugin.Plugin, version string, progressChannel chan float64) tea.Cmd {
return func() tea.Msg {
err := plugin.Download(version, progressChannel)
if err != nil {
return err
}
return nil
}
}

func install(plugin mtvmplugin.Plugin, installDir string, pluginName string, version string) tea.Cmd {
return func() tea.Msg {
err := plugin.Install(path.Join(installDir, pluginName, version))
if err != nil {
return err
}
return installedMsg(true)
}
}
func waitForProgress(progressChannel chan float64) tea.Cmd {
return func() tea.Msg {
downloadProgress := <-progressChannel
if downloadProgress == 1 {
return downloadedMsg(true)
}
return progressMsg(downloadProgress)
}
return m.installer.View()
}

// installCmd represents the install command
Expand All @@ -115,12 +45,13 @@ For example:
If you run "mtvm install go latest" it will install the latest version of go`,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
var plugin mtvmplugin.Plugin
if args[0] == "go" {
plugin = &goplugin.Plugin{}
} else {
// log.Fatal bc we aren't loading plugins for now
log.Fatal("Unknown plugin")
err := createInstallDir()
if err != nil {
log.Fatal(err)
}
plugin, err := shared.LoadPlugin(args[0])
if err != nil {
log.Fatal(err)
}
version := args[1]
if version == "latest" {
Expand All @@ -130,23 +61,30 @@ If you run "mtvm install go latest" it will install the latest version of go`,
log.Fatal(err)
}
}
_, err := os.Stat(path.Join(shared.Configuration.InstallDir, args[0], version))
installed, err := shared.IsVersionInstalled(args[0], version)
if err != nil {
if os.IsNotExist(err) {
p := tea.NewProgram(installInitialModel(plugin, args[0], version))
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
}
} else {
log.Fatal(err)
}
if !installed {
p := tea.NewProgram(installInitialModel(plugin, args[0], version))
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
} else {
fmt.Println("That version is already installed")
os.Exit(1)
}
},
}

func createInstallDir() error {
err := os.MkdirAll(shared.Configuration.InstallDir, 0755)
if err != nil && !os.IsExist(err) {
return err
}
return nil
}

func init() {
rootCmd.AddCommand(installCmd)

Expand Down
47 changes: 44 additions & 3 deletions cmd/use.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package cmd

import (
"fmt"
"github.com/MTVersionManager/mtvm/shared"
tea "github.com/charmbracelet/bubbletea"
"log"
"os"
"path/filepath"

"github.com/spf13/cobra"
)
Expand All @@ -22,12 +25,42 @@ So if you run go version it will print the version number 1.23.3`,
if err != nil {
log.Fatal(err)
}
plugin, err := shared.LoadPlugin(args[0])
if err != nil {
log.Fatal(err)
}
switch {
case len(args) == 2:
if installFlagUsed {
fmt.Println("I would be installing the version you specified")
version := args[1]
if version == "latest" {
var err error
version, err = plugin.GetLatestVersion()
if err != nil {
log.Fatal(err)
}
}
versionInstalled, err := shared.IsVersionInstalled(args[0], version)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Setting version of %v to %v\n", args[0], args[1])
if installFlagUsed && !versionInstalled {
p := tea.NewProgram(installInitialModel(plugin, args[0], version))
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
} else if !versionInstalled {
fmt.Println("That version is not installed.")
os.Exit(1)
}
err = createPathDir()
if err != nil {
log.Fatal(err)
}
err = plugin.Use(filepath.Join(shared.Configuration.InstallDir, args[0], version), shared.Configuration.PathDir)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Set version of %v to %v\n", args[0], version)
case installFlagUsed:
fmt.Println("You need to specify a version to install.")
err = cmd.Usage()
Expand All @@ -41,6 +74,14 @@ So if you run go version it will print the version number 1.23.3`,
},
}

func createPathDir() error {
err := os.MkdirAll(shared.Configuration.PathDir, 0755)
if err != nil && !os.IsExist(err) {
return err
}
return nil
}

func init() {
rootCmd.AddCommand(useCmd)

Expand Down
56 changes: 56 additions & 0 deletions components/downloadProgress/downloadProgress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package downloadProgress

import (
"github.com/charmbracelet/bubbles/progress"
tea "github.com/charmbracelet/bubbletea"
)

type ProgressMsg float64
type DownloadedMsg bool

type Model struct {
Title string
progress float64
progressBar progress.Model
progressChannel chan float64
}

func New(progressChannel chan float64) Model {
progressBar := progress.New(progress.WithDefaultGradient())
return Model{
progress: 0,
progressBar: progressBar,
progressChannel: progressChannel,
}
}

func WaitForProgress(progressChannel chan float64) tea.Cmd {
return func() tea.Msg {
downloadProgress := <-progressChannel
if downloadProgress == 1 {
return DownloadedMsg(true)
}
return ProgressMsg(downloadProgress)
}
}

func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case ProgressMsg:
m.progress = float64(msg)
cmd = WaitForProgress(m.progressChannel)
case DownloadedMsg:
m.progress = 1
}
return m, cmd
}

func (m Model) View() string {
var s string
if m.Title != "" {
s += m.Title + "\n"
}
s += m.progressBar.ViewAs(m.progress)
return s
}
90 changes: 90 additions & 0 deletions components/install/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package install

import (
"github.com/MTVersionManager/mtvm/components/downloadProgress"
"github.com/MTVersionManager/mtvm/shared"
"github.com/MTVersionManager/mtvmplugin"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"log"
"path/filepath"
)

type Model struct {
progressChannel chan float64
plugin mtvmplugin.Plugin
installing bool
version string
spinner spinner.Model
pluginName string
downloader downloadProgress.Model
}

type InstalledMsg bool

func New(plugin mtvmplugin.Plugin, pluginName string, version string) Model {
progressChannel := make(chan float64)
downloader := downloadProgress.New(progressChannel)
downloader.Title = "Downloading..."
spinnerModel := spinner.New()
spinnerModel.Spinner = spinner.Dot
return Model{
progressChannel: progressChannel,
version: version,
plugin: plugin,
downloader: downloader,
installing: true,
spinner: spinnerModel,
pluginName: pluginName,
}
}

func (m Model) Init() tea.Cmd {
return tea.Batch(downloadProgress.WaitForProgress(m.progressChannel), Download(m.plugin, m.version, m.progressChannel), m.spinner.Tick)
}

func Download(plugin mtvmplugin.Plugin, version string, progressChannel chan float64) tea.Cmd {
return func() tea.Msg {
err := plugin.Download(version, progressChannel)
if err != nil {
return err
}
return nil
}
}

func Install(plugin mtvmplugin.Plugin, installDir string, pluginName string, version string) tea.Cmd {
return func() tea.Msg {
err := plugin.Install(filepath.Join(installDir, pluginName, version))
if err != nil {
return err
}
return InstalledMsg(true)
}
}

func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case error:
log.Fatal(msg)
case downloadProgress.DownloadedMsg:
m.installing = false
cmds = append(cmds, Install(m.plugin, shared.Configuration.InstallDir, m.pluginName, m.version))
case InstalledMsg:
return m, tea.Quit
}
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
cmds = append(cmds, cmd)
m.downloader, cmd = m.downloader.Update(msg)
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...)
}

func (m Model) View() string {
if m.installing {
return m.downloader.View()
}
return m.spinner.View() + " Installing..."
}
Loading

0 comments on commit ee9ddb3

Please sign in to comment.