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
import (
"errors"
"fmt"
"os"
"strings"
"slices"
)
var DIRECTORIES = []string{
@ -54,6 +53,12 @@ func UninstallPython(args []string, flags Flags, currentState State) error {
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 {
version := args[1]
if err := ValidateVersion(version); err != nil {
@ -71,7 +76,8 @@ func Use(args []string, flags Flags, currentState State) error {
}
if !found {
return errors.New("Version not installed.")
fmt.Println("Version not installed. Installing it first.")
InstallPythonDistribution(version, flags.NoCache, flags.Verbose)
}
WriteState(version)
@ -80,20 +86,19 @@ func Use(args []string, flags Flags, currentState State) error {
return nil
}
func ListVersions(args []string, flags Flags, currentState State) error {
runtimesDir := GetStatePath("runtimes")
entries, err := os.ReadDir(runtimesDir)
installedVersions, err := ListInstalledVersions()
if err != nil {
return err
}
if len(entries) == 0 {
if len(installedVersions) == 0 {
fmt.Println("No versions installed!")
return nil
}
for _, d := range entries {
fmt.Println(strings.TrimPrefix(d.Name(), "py-"))
for _, d := range installedVersions {
fmt.Println(d)
}
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`.
func Which(args []string, flags Flags, currentState State) error {
selectedVersion, _ := DetermineSelectedPythonVersion(currentState)
installedVersions, _ := ListInstalledVersions()
isInstalled := slices.Contains(installedVersions, selectedVersion.Version)
var printedPath string
if selectedVersion.Source == "system" {
_, sysPath := DetermineSystemPython()
printedPath = fmt.Sprintf("%s (system)", sysPath)
} else {
} else if isInstalled {
tag := VersionStringToStruct(selectedVersion.Version)
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: "
@ -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.
func CurrentVersion(args []string, flags Flags, currentState State) error {
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 {
fmt.Println(selectedVersion.Version)

View file

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

View file

@ -12,6 +12,23 @@ type SelectedVersion struct {
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
// .python-version file that could set the current version.
func SearchForPythonVersionFile() (SelectedVersion, bool) {

View file

@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"path"
"slices"
"testing"
)
@ -131,5 +132,47 @@ func TestSearchForPythonVersionFileReturnsOnRootIfNoneFound(t *testing.T) {
if versionFound.Version != "" || found {
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"
const (
RESET = "\033[0m"
BOLD = "\033[1m"
RESET = "\033[0m"
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 {
return fmt.Sprintf("%s%s%s", BOLD, text, RESET)
}

2
v.go
View file

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