2023-11-05 01:28:11 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
var DIRECTORIES = []string{
|
|
|
|
"cache",
|
|
|
|
"runtimes",
|
|
|
|
"shims",
|
|
|
|
}
|
|
|
|
|
|
|
|
var SHIMS = []string{
|
|
|
|
"python",
|
|
|
|
"python3",
|
|
|
|
}
|
|
|
|
|
|
|
|
const DEFAULT_PERMISSION = 0775
|
|
|
|
|
|
|
|
func writeShim(shimPath string) error {
|
2023-11-27 23:46:19 +00:00
|
|
|
shimContent := []byte("#!/bin/bash\n$(v where --raw) $@")
|
2023-11-05 01:28:11 +00:00
|
|
|
if err := os.WriteFile(shimPath, shimContent, DEFAULT_PERMISSION); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sets up directories and files used to store downloaded archives,
|
|
|
|
// installed runtimes and metadata.
|
|
|
|
func Initialize(args []string, flags Flags, currentState State) error {
|
2023-11-05 15:41:43 +00:00
|
|
|
if flags.AddPath {
|
|
|
|
fmt.Printf("export PATH=%s:$PATH\n", GetStatePath("shims"))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-11-05 15:19:53 +00:00
|
|
|
os.Mkdir(GetStatePath(), DEFAULT_PERMISSION)
|
2023-11-05 01:28:11 +00:00
|
|
|
for _, dir := range DIRECTORIES {
|
2023-11-05 15:19:53 +00:00
|
|
|
os.Mkdir(GetStatePath(dir), DEFAULT_PERMISSION)
|
2023-11-05 01:28:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, shim := range SHIMS {
|
2023-11-05 15:19:53 +00:00
|
|
|
writeShim(GetStatePath("shims", shim))
|
2023-11-05 01:28:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func UninstallPython(args []string, flags Flags, currentState State) error {
|
2023-11-05 15:19:53 +00:00
|
|
|
runtimePath := GetStatePath("runtimes", fmt.Sprintf("py-%s", args[1]))
|
2023-11-05 01:28:11 +00:00
|
|
|
err := os.RemoveAll(runtimePath)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func Use(args []string, flags Flags, currentState State) error {
|
|
|
|
version := args[1]
|
|
|
|
if err := ValidateVersion(version); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
availableVersions := GetAvailableVersions()
|
|
|
|
|
|
|
|
found := false
|
|
|
|
for _, v := range availableVersions {
|
|
|
|
if v == version {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
return errors.New("Version not installed.")
|
|
|
|
}
|
|
|
|
|
|
|
|
WriteState(version)
|
|
|
|
fmt.Printf("Now using Python %s\n", version)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func ListVersions(args []string, flags Flags, currentState State) error {
|
2023-11-05 15:19:53 +00:00
|
|
|
runtimesDir := GetStatePath("runtimes")
|
2023-11-05 01:28:11 +00:00
|
|
|
entries, err := os.ReadDir(runtimesDir)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(entries) == 0 {
|
|
|
|
fmt.Println("No versions installed!")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, d := range entries {
|
|
|
|
fmt.Println(strings.TrimPrefix(d.Name(), "py-"))
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-11-27 23:16:57 +00:00
|
|
|
// Where prints out the system path to the executable being used by `python`.
|
2023-11-05 01:28:11 +00:00
|
|
|
func Where(args []string, flags Flags, currentState State) error {
|
2023-11-27 23:16:57 +00:00
|
|
|
selectedVersion, _ := DetermineSelectedPythonVersion(currentState)
|
|
|
|
|
2023-11-27 23:46:19 +00:00
|
|
|
var printedPath string
|
2023-11-28 03:31:14 +00:00
|
|
|
|
2023-11-27 23:16:57 +00:00
|
|
|
if selectedVersion == "SYSTEM" {
|
2023-11-28 03:31:14 +00:00
|
|
|
_, sysPath := DetermineSystemPython()
|
|
|
|
printedPath = fmt.Sprintf("%s (system)", sysPath)
|
2023-11-27 23:46:19 +00:00
|
|
|
} else {
|
|
|
|
tag := VersionStringToStruct(selectedVersion)
|
|
|
|
printedPath = GetStatePath("runtimes", fmt.Sprintf("py-%s", selectedVersion), "bin", fmt.Sprintf("python%s", tag.MajorMinor()))
|
|
|
|
}
|
|
|
|
|
|
|
|
prefix := "Python path: "
|
|
|
|
|
|
|
|
if flags.RawOutput {
|
|
|
|
prefix = ""
|
|
|
|
} else {
|
|
|
|
printedPath = Bold(printedPath)
|
2023-11-27 23:16:57 +00:00
|
|
|
}
|
|
|
|
|
2023-11-27 23:46:19 +00:00
|
|
|
fmt.Printf("%s%s\n", prefix, printedPath)
|
2023-11-05 01:28:11 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-11-27 23:16:57 +00:00
|
|
|
// Which prints out the Python version that will be used by shims. It can be invoked
|
|
|
|
// directly by the `v which` command.
|
|
|
|
//
|
|
|
|
// If no version is set (i.e. none is installed, the specified version is not installed),
|
|
|
|
// the system version is used and 'SYSTEM' is printed by Which.
|
2023-11-05 01:28:11 +00:00
|
|
|
func Which(args []string, flags Flags, currentState State) error {
|
2023-11-27 23:16:57 +00:00
|
|
|
selectedVersion, _ := DetermineSelectedPythonVersion(currentState)
|
2023-11-27 23:46:19 +00:00
|
|
|
printedVersion := selectedVersion
|
2023-11-27 23:16:57 +00:00
|
|
|
|
|
|
|
if selectedVersion == "SYSTEM" {
|
|
|
|
sysVersion, _ := DetermineSystemPython()
|
2023-11-27 23:46:19 +00:00
|
|
|
printedVersion = fmt.Sprintf("%s (system)", sysVersion)
|
|
|
|
}
|
|
|
|
|
|
|
|
prefix := "Python version: "
|
|
|
|
|
|
|
|
if flags.RawOutput {
|
|
|
|
prefix = ""
|
|
|
|
} else {
|
|
|
|
printedVersion = Bold(printedVersion)
|
2023-11-27 23:16:57 +00:00
|
|
|
}
|
|
|
|
|
2023-11-27 23:46:19 +00:00
|
|
|
fmt.Printf("%s%s\n", prefix, printedVersion)
|
2023-11-05 01:28:11 +00:00
|
|
|
return nil
|
|
|
|
}
|