feat: handling for using versions that are not installed (#14)

* feat: handling for using versions that are not installed

* test: coverage for installed version list

* chore: increment version to 0.0.8
This commit is contained in:
Marc 2023-11-28 20:24:00 -05:00 committed by GitHub
parent 38450e0f72
commit 1bbd6c1050
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 18 deletions

View file

@ -1,10 +1,9 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"strings" "slices"
) )
var DIRECTORIES = []string{ var DIRECTORIES = []string{
@ -54,6 +53,12 @@ func UninstallPython(args []string, flags Flags, currentState State) error {
return err return err
} }
func InstallPython(args []string, flags Flags, currentState State) error {
version := args[1]
return InstallPythonDistribution(version, flags.NoCache, flags.Verbose)
}
func Use(args []string, flags Flags, currentState State) error { func Use(args []string, flags Flags, currentState State) error {
version := args[1] version := args[1]
if err := ValidateVersion(version); err != nil { if err := ValidateVersion(version); err != nil {
@ -71,7 +76,8 @@ func Use(args []string, flags Flags, currentState State) error {
} }
if !found { if !found {
return errors.New("Version not installed.") fmt.Println("Version not installed. Installing it first.")
InstallPythonDistribution(version, flags.NoCache, flags.Verbose)
} }
WriteState(version) WriteState(version)
@ -80,20 +86,19 @@ func Use(args []string, flags Flags, currentState State) error {
return nil return nil
} }
func ListVersions(args []string, flags Flags, currentState State) error { func ListVersions(args []string, flags Flags, currentState State) error {
runtimesDir := GetStatePath("runtimes") installedVersions, err := ListInstalledVersions()
entries, err := os.ReadDir(runtimesDir)
if err != nil { if err != nil {
return err return err
} }
if len(entries) == 0 { if len(installedVersions) == 0 {
fmt.Println("No versions installed!") fmt.Println("No versions installed!")
return nil return nil
} }
for _, d := range entries { for _, d := range installedVersions {
fmt.Println(strings.TrimPrefix(d.Name(), "py-")) fmt.Println(d)
} }
return nil return nil
@ -102,15 +107,20 @@ func ListVersions(args []string, flags Flags, currentState State) error {
// Which prints out the system path to the executable being used by `python`. // Which prints out the system path to the executable being used by `python`.
func Which(args []string, flags Flags, currentState State) error { func Which(args []string, flags Flags, currentState State) error {
selectedVersion, _ := DetermineSelectedPythonVersion(currentState) selectedVersion, _ := DetermineSelectedPythonVersion(currentState)
installedVersions, _ := ListInstalledVersions()
isInstalled := slices.Contains(installedVersions, selectedVersion.Version)
var printedPath string var printedPath string
if selectedVersion.Source == "system" { if selectedVersion.Source == "system" {
_, sysPath := DetermineSystemPython() _, sysPath := DetermineSystemPython()
printedPath = fmt.Sprintf("%s (system)", sysPath) printedPath = fmt.Sprintf("%s (system)", sysPath)
} else { } else if isInstalled {
tag := VersionStringToStruct(selectedVersion.Version) tag := VersionStringToStruct(selectedVersion.Version)
printedPath = GetStatePath("runtimes", fmt.Sprintf("py-%s", selectedVersion.Version), "bin", fmt.Sprintf("python%s", tag.MajorMinor())) printedPath = GetStatePath("runtimes", fmt.Sprintf("py-%s", selectedVersion.Version), "bin", fmt.Sprintf("python%s", tag.MajorMinor()))
} else {
fmt.Printf("The desired version (%s) is not installed.\n", selectedVersion.Version)
return nil
} }
prefix := "Python path: " prefix := "Python path: "
@ -130,6 +140,12 @@ func Which(args []string, flags Flags, currentState State) error {
// under "source", if the system Python is used, "system" is returned as a source. // under "source", if the system Python is used, "system" is returned as a source.
func CurrentVersion(args []string, flags Flags, currentState State) error { func CurrentVersion(args []string, flags Flags, currentState State) error {
selectedVersion, _ := DetermineSelectedPythonVersion(currentState) selectedVersion, _ := DetermineSelectedPythonVersion(currentState)
installedVersions, _ := ListInstalledVersions()
isInstalled := slices.Contains(installedVersions, selectedVersion.Version)
if !isInstalled {
fmt.Println(Bold(Yellow("WARNING: This version is not installed.")))
}
if flags.RawOutput { if flags.RawOutput {
fmt.Println(selectedVersion.Version) fmt.Println(selectedVersion.Version)

View file

@ -30,15 +30,12 @@ func (t VersionTag) MajorMinor() string {
return fmt.Sprintf("%s.%s", t.Major, t.Minor) return fmt.Sprintf("%s.%s", t.Major, t.Minor)
} }
func InstallPython(args []string, flags Flags, currentState State) error { func InstallPythonDistribution(version string, noCache bool, verbose bool) error {
verbose := flags.Verbose
version := args[1]
if err := ValidateVersion(version); err != nil { if err := ValidateVersion(version); err != nil {
return err return err
} }
packageMetadata, dlerr := downloadSource(version, flags.NoCache) packageMetadata, dlerr := downloadSource(version, noCache)
if dlerr != nil { if dlerr != nil {
return dlerr return dlerr

View file

@ -12,6 +12,23 @@ type SelectedVersion struct {
Source string Source string
} }
func ListInstalledVersions() ([]string, error) {
runtimesDir := GetStatePath("runtimes")
entries, err := os.ReadDir(runtimesDir)
if err != nil {
return []string{}, err
}
installedVersions := []string{}
for _, d := range entries {
installedVersions = append(installedVersions, strings.TrimPrefix(d.Name(), "py-"))
}
return installedVersions, nil
}
// SearchForPythonVersionFile crawls up to the system root to find any // SearchForPythonVersionFile crawls up to the system root to find any
// .python-version file that could set the current version. // .python-version file that could set the current version.
func SearchForPythonVersionFile() (SelectedVersion, bool) { func SearchForPythonVersionFile() (SelectedVersion, bool) {

View file

@ -6,6 +6,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
"slices"
"testing" "testing"
) )
@ -131,5 +132,47 @@ func TestSearchForPythonVersionFileReturnsOnRootIfNoneFound(t *testing.T) {
if versionFound.Version != "" || found { if versionFound.Version != "" || found {
t.Errorf("Did not expect any result, found %s.", versionFound.Version) t.Errorf("Did not expect any result, found %s.", versionFound.Version)
} }
}
func TestListInstalledVersion(t *testing.T) {
defer SetupAndCleanupEnvironment(t)()
versions := []string{"1.2.3", "4.5.6", "7.8.9"}
os.Mkdir(GetStatePath("runtimes"), 0750)
for _, version := range versions {
os.Mkdir(GetStatePath("runtimes", "py-"+version), 0750)
}
installedVersions, _ := ListInstalledVersions()
if !slices.Equal(installedVersions, versions) {
t.Errorf("Expected %s, got %s.", versions, installedVersions)
}
}
func TestListInstalledVersionNoVersionsInstalled(t *testing.T) {
defer SetupAndCleanupEnvironment(t)()
os.Mkdir(GetStatePath("runtimes"), 0750)
installedVersions, _ := ListInstalledVersions()
if len(installedVersions) != 0 {
t.Errorf("Expected 0 elements, got %d (%s).", len(installedVersions), installedVersions)
}
}
func TestListInstalledVersionNoRuntimesDir(t *testing.T) {
defer SetupAndCleanupEnvironment(t)()
installedVersions, err := ListInstalledVersions()
if len(installedVersions) != 0 {
t.Errorf("Expected 0 elements, got %d (%s).", len(installedVersions), installedVersions)
}
if err == nil {
t.Errorf("Expected error to be returned, got nil.")
}
} }

View file

@ -3,10 +3,15 @@ package main
import "fmt" import "fmt"
const ( const (
RESET = "\033[0m" RESET = "\033[0m"
BOLD = "\033[1m" BOLD = "\033[1m"
YELLOW = "\033[33m"
) )
func Yellow(text string) string {
return fmt.Sprintf("%s%s%s", YELLOW, text, RESET)
}
func Bold(text string) string { func Bold(text string) string {
return fmt.Sprintf("%s%s%s", BOLD, text, RESET) return fmt.Sprintf("%s%s%s", BOLD, text, RESET)
} }

2
v.go
View file

@ -5,7 +5,7 @@ import (
) )
const ( const (
Version = "0.0.7" Version = "0.0.8"
Author = "Marc Cataford <hello@karnov.club>" Author = "Marc Cataford <hello@karnov.club>"
Homepage = "https://github.com/mcataford/v" Homepage = "https://github.com/mcataford/v"
) )