refactor(cli): move cli+logger to own module

This commit is contained in:
Marc 2024-01-23 12:55:06 -05:00
parent c8faae8637
commit a5c7242045
Signed by: marc
GPG key ID: 048E042F22B5DC79
6 changed files with 64 additions and 57 deletions

View file

@ -1,7 +1,8 @@
package main package cli
import ( import (
"strings" "strings"
logger "v/logger"
state "v/state" state "v/state"
) )
@ -69,10 +70,10 @@ func (c CLI) Run(args []string, currentState state.State) error {
// Prints autogenerated help documentation specifying command usage // Prints autogenerated help documentation specifying command usage
// and descriptions based on registered commands (see: AddCommand). // and descriptions based on registered commands (see: AddCommand).
func (c CLI) Help() { func (c CLI) Help() {
InfoLogger.Printf("v: A simple version manager. (v%s)\n---", Version) logger.InfoLogger.Printf("v: A simple version manager. (v%s)\n---", c.Metadata["Version"])
for _, commandLabel := range c.OrderedCommands { for _, commandLabel := range c.OrderedCommands {
command := c.Commands[commandLabel] command := c.Commands[commandLabel]
InfoLogger.Printf("\033[1m%-30s\033[0m%s\n", command.Usage, command.Description) logger.InfoLogger.Printf("\033[1m%-30s\033[0m%s\n", command.Usage, command.Description)
} }
} }

View file

@ -3,6 +3,8 @@ package main
import ( import (
"os" "os"
"slices" "slices"
cli "v/cli"
logger "v/logger"
state "v/state" state "v/state"
) )
@ -30,9 +32,9 @@ func writeShim(shimPath string) error {
// Sets up directories and files used to store downloaded archives, // Sets up directories and files used to store downloaded archives,
// installed runtimes and metadata. // installed runtimes and metadata.
func Initialize(args []string, flags Flags, currentState state.State) error { func Initialize(args []string, flags cli.Flags, currentState state.State) error {
if flags.AddPath { if flags.AddPath {
InfoLogger.Printf("export PATH=%s:$PATH\n", state.GetStatePath("shims")) logger.InfoLogger.Printf("export PATH=%s:$PATH\n", state.GetStatePath("shims"))
return nil return nil
} }
@ -47,19 +49,19 @@ func Initialize(args []string, flags Flags, currentState state.State) error {
return nil return nil
} }
func UninstallPython(args []string, flags Flags, currentState state.State) error { func UninstallPython(args []string, flags cli.Flags, currentState state.State) error {
runtimePath := state.GetStatePath("runtimes", "py-"+args[1]) runtimePath := state.GetStatePath("runtimes", "py-"+args[1])
err := os.RemoveAll(runtimePath) err := os.RemoveAll(runtimePath)
return err return err
} }
func InstallPython(args []string, flags Flags, currentState state.State) error { func InstallPython(args []string, flags cli.Flags, currentState state.State) error {
version := args[1] version := args[1]
return InstallPythonDistribution(version, flags.NoCache, flags.Verbose) return InstallPythonDistribution(version, flags.NoCache, flags.Verbose)
} }
func Use(args []string, flags Flags, currentState state.State) error { func Use(args []string, flags cli.Flags, currentState state.State) error {
version := args[1] version := args[1]
if err := ValidateVersion(version); err != nil { if err := ValidateVersion(version); err != nil {
return err return err
@ -76,16 +78,16 @@ func Use(args []string, flags Flags, currentState state.State) error {
} }
if !found { if !found {
InfoLogger.Println("Version not installed. Installing it first.") logger.InfoLogger.Println("Version not installed. Installing it first.")
InstallPythonDistribution(version, flags.NoCache, flags.Verbose) InstallPythonDistribution(version, flags.NoCache, flags.Verbose)
} }
state.WriteState(version) state.WriteState(version)
InfoLogger.Printf("Now using Python %s\n", version) logger.InfoLogger.Printf("Now using Python %s\n", version)
return nil return nil
} }
func ListVersions(args []string, flags Flags, currentState state.State) error { func ListVersions(args []string, flags cli.Flags, currentState state.State) error {
installedVersions, err := ListInstalledVersions() installedVersions, err := ListInstalledVersions()
if err != nil { if err != nil {
@ -93,19 +95,19 @@ func ListVersions(args []string, flags Flags, currentState state.State) error {
} }
if len(installedVersions) == 0 { if len(installedVersions) == 0 {
InfoLogger.Println("No versions installed!") logger.InfoLogger.Println("No versions installed!")
return nil return nil
} }
for _, d := range installedVersions { for _, d := range installedVersions {
InfoLogger.Println(d) logger.InfoLogger.Println(d)
} }
return nil return nil
} }
// 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.State) error { func Which(args []string, flags cli.Flags, currentState state.State) error {
selectedVersion, _ := DetermineSelectedPythonVersion(currentState) selectedVersion, _ := DetermineSelectedPythonVersion(currentState)
installedVersions, _ := ListInstalledVersions() installedVersions, _ := ListInstalledVersions()
isInstalled := slices.Contains(installedVersions, selectedVersion.Version) isInstalled := slices.Contains(installedVersions, selectedVersion.Version)
@ -119,7 +121,7 @@ func Which(args []string, flags Flags, currentState state.State) error {
tag := VersionStringToStruct(selectedVersion.Version) tag := VersionStringToStruct(selectedVersion.Version)
printedPath = state.GetStatePath("runtimes", "py-"+selectedVersion.Version, "bin", "python"+tag.MajorMinor()) printedPath = state.GetStatePath("runtimes", "py-"+selectedVersion.Version, "bin", "python"+tag.MajorMinor())
} else { } else {
InfoLogger.Printf("The desired version (%s) is not installed.\n", selectedVersion.Version) logger.InfoLogger.Printf("The desired version (%s) is not installed.\n", selectedVersion.Version)
return nil return nil
} }
@ -131,27 +133,27 @@ func Which(args []string, flags Flags, currentState state.State) error {
printedPath = Bold(printedPath) printedPath = Bold(printedPath)
} }
InfoLogger.Printf("%s%s\n", prefix, printedPath) logger.InfoLogger.Printf("%s%s\n", prefix, printedPath)
return nil return nil
} }
// CurrentVersion (called via `v version`) outputs the currently selected version // CurrentVersion (called via `v version`) outputs the currently selected version
// and what configures it. If the version is configured by a file, the file is returned // and what configures it. If the version is configured by a file, the file is returned
// 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.State) error { func CurrentVersion(args []string, flags cli.Flags, currentState state.State) error {
selectedVersion, _ := DetermineSelectedPythonVersion(currentState) selectedVersion, _ := DetermineSelectedPythonVersion(currentState)
installedVersions, _ := ListInstalledVersions() installedVersions, _ := ListInstalledVersions()
isInstalled := slices.Contains(installedVersions, selectedVersion.Version) isInstalled := slices.Contains(installedVersions, selectedVersion.Version)
if !isInstalled { if !isInstalled {
InfoLogger.Println(Bold(Yellow("WARNING: This version is not installed."))) logger.InfoLogger.Println(Bold(Yellow("WARNING: This version is not installed.")))
} }
if flags.RawOutput { if flags.RawOutput {
InfoLogger.Println(selectedVersion.Version) logger.InfoLogger.Println(selectedVersion.Version)
return nil return nil
} }
InfoLogger.Printf("Python version: %s\nSource: %s\n", Bold(selectedVersion.Version), Bold(selectedVersion.Source)) logger.InfoLogger.Printf("Python version: %s\nSource: %s\n", Bold(selectedVersion.Version), Bold(selectedVersion.Source))
return nil return nil
} }

View file

@ -5,6 +5,8 @@ import (
"os" "os"
"strings" "strings"
"testing" "testing"
cli "v/cli"
logger "v/logger"
state "v/state" state "v/state"
) )
@ -14,10 +16,10 @@ func TestListVersionOutputsNoticeIfNoVersionsInstalled(t *testing.T) {
os.Mkdir(state.GetStatePath("runtimes"), 0750) os.Mkdir(state.GetStatePath("runtimes"), 0750)
var out bytes.Buffer var out bytes.Buffer
InfoLogger.SetOutput(&out) logger.InfoLogger.SetOutput(&out)
defer InfoLogger.SetOutput(os.Stdout) defer logger.InfoLogger.SetOutput(os.Stdout)
ListVersions([]string{}, Flags{}, state.State{}) ListVersions([]string{}, cli.Flags{}, state.State{})
captured := out.String() captured := out.String()
if captured != "No versions installed!\n" { if captured != "No versions installed!\n" {
@ -31,10 +33,10 @@ func TestListVersionOutputsVersionsInstalled(t *testing.T) {
os.MkdirAll(state.GetStatePath("runtimes", "py-1.2.3"), 0750) os.MkdirAll(state.GetStatePath("runtimes", "py-1.2.3"), 0750)
var out bytes.Buffer var out bytes.Buffer
InfoLogger.SetOutput(&out) logger.InfoLogger.SetOutput(&out)
defer InfoLogger.SetOutput(os.Stdout) defer logger.InfoLogger.SetOutput(os.Stdout)
ListVersions([]string{}, Flags{}, state.State{}) ListVersions([]string{}, cli.Flags{}, state.State{})
captured := out.String() captured := out.String()
if captured != "1.2.3\n" { if captured != "1.2.3\n" {
@ -47,10 +49,10 @@ func TestListVersionReturnsErrorOnFailure(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
InfoLogger.SetOutput(&out) logger.InfoLogger.SetOutput(&out)
defer InfoLogger.SetOutput(os.Stdout) defer logger.InfoLogger.SetOutput(os.Stdout)
err := ListVersions([]string{}, Flags{}, state.State{}) err := ListVersions([]string{}, cli.Flags{}, state.State{})
captured := out.String() captured := out.String()
if captured != "" { if captured != "" {
@ -67,10 +69,10 @@ func TestListVersionOutputsVersionSelectedAndWarnsNotInstalled(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
InfoLogger.SetOutput(&out) logger.InfoLogger.SetOutput(&out)
defer InfoLogger.SetOutput(os.Stdout) defer logger.InfoLogger.SetOutput(os.Stdout)
Which([]string{}, Flags{}, state.State{GlobalVersion: "1.2.3"}) Which([]string{}, cli.Flags{}, state.State{GlobalVersion: "1.2.3"})
captured := out.String() captured := out.String()
if captured != "The desired version (1.2.3) is not installed.\n" { if captured != "The desired version (1.2.3) is not installed.\n" {
@ -83,11 +85,11 @@ func TestWhichOutputsVersionSelectedIfInstalled(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
InfoLogger.SetOutput(&out) logger.InfoLogger.SetOutput(&out)
defer InfoLogger.SetOutput(os.Stdout) defer logger.InfoLogger.SetOutput(os.Stdout)
os.MkdirAll(state.GetStatePath("runtimes", "py-1.2.3"), 0750) os.MkdirAll(state.GetStatePath("runtimes", "py-1.2.3"), 0750)
Which([]string{}, Flags{}, state.State{GlobalVersion: "1.2.3"}) Which([]string{}, cli.Flags{}, state.State{GlobalVersion: "1.2.3"})
captured := strings.TrimSpace(out.String()) captured := strings.TrimSpace(out.String())
expected := state.GetStatePath("runtimes", "py-1.2.3", "bin", "python1.2") expected := state.GetStatePath("runtimes", "py-1.2.3", "bin", "python1.2")
@ -101,10 +103,10 @@ func TestWhichOutputsSystemVersionIfNoneSelected(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
InfoLogger.SetOutput(&out) logger.InfoLogger.SetOutput(&out)
defer InfoLogger.SetOutput(os.Stdout) defer logger.InfoLogger.SetOutput(os.Stdout)
Which([]string{}, Flags{RawOutput: true}, state.State{}) Which([]string{}, cli.Flags{RawOutput: true}, state.State{})
captured := strings.TrimSpace(out.String()) captured := strings.TrimSpace(out.String())
@ -118,11 +120,11 @@ func TestWhichOutputsVersionWithoutPrefixesIfRawOutput(t *testing.T) {
var out bytes.Buffer var out bytes.Buffer
InfoLogger.SetOutput(&out) logger.InfoLogger.SetOutput(&out)
defer InfoLogger.SetOutput(os.Stdout) defer logger.InfoLogger.SetOutput(os.Stdout)
os.MkdirAll(state.GetStatePath("runtimes", "py-1.2.3"), 0750) os.MkdirAll(state.GetStatePath("runtimes", "py-1.2.3"), 0750)
Which([]string{}, Flags{RawOutput: true}, state.State{GlobalVersion: "1.2.3"}) Which([]string{}, cli.Flags{RawOutput: true}, state.State{GlobalVersion: "1.2.3"})
captured := strings.TrimSpace(out.String()) captured := strings.TrimSpace(out.String())
expected := state.GetStatePath("runtimes", "py-1.2.3", "bin", "python1.2") expected := state.GetStatePath("runtimes", "py-1.2.3", "bin", "python1.2")

View file

@ -9,6 +9,7 @@ import (
"path" "path"
"strings" "strings"
"time" "time"
logger "v/logger"
state "v/state" state "v/state"
) )
@ -57,15 +58,15 @@ func downloadSource(version string, skipCache bool) (PackageMetadata, error) {
client := http.Client{} client := http.Client{}
InfoLogger.Println(Bold("Downloading source for Python " + version)) logger.InfoLogger.Println(Bold("Downloading source for Python " + version))
InfoLogger.SetPrefix(" ") logger.InfoLogger.SetPrefix(" ")
defer InfoLogger.SetPrefix("") defer logger.InfoLogger.SetPrefix("")
start := time.Now() start := time.Now()
_, err := os.Stat(archivePath) _, err := os.Stat(archivePath)
if errors.Is(err, os.ErrNotExist) || skipCache { if errors.Is(err, os.ErrNotExist) || skipCache {
InfoLogger.Println("Fetching from " + sourceUrl) logger.InfoLogger.Println("Fetching from " + sourceUrl)
resp, err := client.Get(sourceUrl) resp, err := client.Get(sourceUrl)
@ -79,21 +80,21 @@ func downloadSource(version string, skipCache bool) (PackageMetadata, error) {
defer file.Close() defer file.Close()
} else { } else {
InfoLogger.Println("Found in cache: " + archivePath) logger.InfoLogger.Println("Found in cache: " + archivePath)
} }
InfoLogger.Printf("✅ Done (%s)\n", time.Since(start)) logger.InfoLogger.Printf("✅ Done (%s)\n", time.Since(start))
return PackageMetadata{ArchivePath: archivePath, Version: version}, nil return PackageMetadata{ArchivePath: archivePath, Version: version}, nil
} }
func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, error) { func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, error) {
InfoLogger.Println(Bold("Building from source")) logger.InfoLogger.Println(Bold("Building from source"))
InfoLogger.SetPrefix(" ") logger.InfoLogger.SetPrefix(" ")
defer InfoLogger.SetPrefix("") defer logger.InfoLogger.SetPrefix("")
start := time.Now() start := time.Now()
InfoLogger.Println("Unpacking source for " + pkgMeta.ArchivePath) logger.InfoLogger.Println("Unpacking source for " + pkgMeta.ArchivePath)
_, untarErr := RunCommand([]string{"tar", "zxvf", pkgMeta.ArchivePath}, state.GetStatePath("cache"), !verbose) _, untarErr := RunCommand([]string{"tar", "zxvf", pkgMeta.ArchivePath}, state.GetStatePath("cache"), !verbose)
@ -103,7 +104,7 @@ func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, er
unzippedRoot := strings.TrimSuffix(pkgMeta.ArchivePath, path.Ext(pkgMeta.ArchivePath)) unzippedRoot := strings.TrimSuffix(pkgMeta.ArchivePath, path.Ext(pkgMeta.ArchivePath))
InfoLogger.Println("Configuring installer") logger.InfoLogger.Println("Configuring installer")
targetDirectory := state.GetStatePath("runtimes", "py-"+pkgMeta.Version) targetDirectory := state.GetStatePath("runtimes", "py-"+pkgMeta.Version)
@ -113,7 +114,7 @@ func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, er
return pkgMeta, configureErr return pkgMeta, configureErr
} }
InfoLogger.Println("Building") logger.InfoLogger.Println("Building")
_, buildErr := RunCommand([]string{"make", "altinstall", "-j4"}, unzippedRoot, !verbose) _, buildErr := RunCommand([]string{"make", "altinstall", "-j4"}, unzippedRoot, !verbose)
if buildErr != nil { if buildErr != nil {
@ -126,7 +127,7 @@ func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, er
pkgMeta.InstallPath = targetDirectory pkgMeta.InstallPath = targetDirectory
InfoLogger.Printf("Installed Python %s at %s\n", pkgMeta.Version, pkgMeta.InstallPath) logger.InfoLogger.Printf("Installed Python %s at %s\n", pkgMeta.Version, pkgMeta.InstallPath)
InfoLogger.Printf("✅ Done (%s)\n", time.Since(start)) logger.InfoLogger.Printf("✅ Done (%s)\n", time.Since(start))
return pkgMeta, nil return pkgMeta, nil
} }

View file

@ -1,4 +1,4 @@
package main package logger
import ( import (
"log" "log"

3
v.go
View file

@ -2,6 +2,7 @@ package main
import ( import (
"os" "os"
cli "v/cli"
state "v/state" state "v/state"
) )
@ -16,7 +17,7 @@ func main() {
args := os.Args[1:] args := os.Args[1:]
currentState := state.ReadState() currentState := state.ReadState()
cli := CLI{ cli := cli.CLI{
Metadata: map[string]string{ Metadata: map[string]string{
"Version": Version, "Version": Version,
}, },