diff --git a/cli/cli.go b/cli/cli.go index 2a661c1..e64f290 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -1,6 +1,7 @@ package cli import ( + "os" "slices" "strings" logger "v/logger" @@ -47,6 +48,12 @@ func (c *CLI) ListNamespaces() []string { // Executes one of the registered commands if any match the provided // user arguments. func (c CLI) Run(args []string, currentState state.State) error { + flags := collectFlags(args) + + if flags.Verbose { + logger.DebugLogger.SetOutput(os.Stdout) + } + if len(args) == 0 { c.Help() return nil @@ -59,8 +66,6 @@ func (c CLI) Run(args []string, currentState state.State) error { return nil } - flags := collectFlags(args) - namespace, isNamespace := c.Namespaces[action] if isNamespace { diff --git a/exec/util.go b/exec/util.go index 8ea239e..f9eb35c 100644 --- a/exec/util.go +++ b/exec/util.go @@ -1,15 +1,16 @@ package exec import ( - "os" + "io" "os/exec" "strings" + logger "v/logger" ) // RunCommand is a thin wrapper around running command-line calls // programmatically. It abstracts common configuration like routing // output and handling the directory the calls are made from. -func RunCommand(command []string, cwd string, quiet bool) (string, error) { +func RunCommand(command []string, cwd string) (string, error) { cmd := exec.Command(command[0], command[1:]...) cmd.Dir = cwd @@ -17,13 +18,11 @@ func RunCommand(command []string, cwd string, quiet bool) (string, error) { var out strings.Builder var errOut strings.Builder - if !quiet { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } else { - cmd.Stdout = &out - cmd.Stderr = &errOut - } + stdOutMultiWriter := io.MultiWriter(&out, logger.DebugLogger.Writer()) + stdErrMultiWriter := io.MultiWriter(&errOut, logger.DebugLogger.Writer()) + + cmd.Stdout = stdOutMultiWriter + cmd.Stderr = stdErrMultiWriter if err := cmd.Run(); err != nil { return errOut.String(), err diff --git a/logger/logger.go b/logger/logger.go index 42d0a20..97d0ca6 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,10 +1,12 @@ package logger import ( + "io/ioutil" "log" "os" ) var ( - InfoLogger = log.New(os.Stdout, "", 0) + InfoLogger = log.New(os.Stdout, "", 0) + DebugLogger = log.New(ioutil.Discard, "", 0) ) diff --git a/python/commands.go b/python/commands.go index d490538..330ed38 100644 --- a/python/commands.go +++ b/python/commands.go @@ -17,7 +17,7 @@ func uninstallPython(args []string, flags cli.Flags, currentState state.State) e func installPython(args []string, flags cli.Flags, currentState state.State) error { version := args[1] - return InstallPythonDistribution(version, flags.NoCache, flags.Verbose) + return InstallPythonDistribution(version, flags.NoCache) } func use(args []string, flags cli.Flags, currentState state.State) error { @@ -38,7 +38,7 @@ func use(args []string, flags cli.Flags, currentState state.State) error { if !found { logger.InfoLogger.Println("Version not installed. Installing it first.") - InstallPythonDistribution(version, flags.NoCache, flags.Verbose) + InstallPythonDistribution(version, flags.NoCache) } state.WriteState(version) diff --git a/python/install.go b/python/install.go index ded5b79..a4a279b 100644 --- a/python/install.go +++ b/python/install.go @@ -32,7 +32,7 @@ func (t VersionTag) MajorMinor() string { return t.Major + "." + t.Minor } -func InstallPythonDistribution(version string, noCache bool, verbose bool) error { +func InstallPythonDistribution(version string, noCache bool) error { if err := ValidateVersion(version); err != nil { return err } @@ -42,9 +42,8 @@ func InstallPythonDistribution(version string, noCache bool, verbose bool) error if dlerr != nil { return dlerr } - _, err := buildFromSource(packageMetadata, verbose) - if err != nil { + if _, err := buildFromSource(packageMetadata); err != nil { return err } @@ -64,9 +63,8 @@ func downloadSource(version string, skipCache bool) (PackageMetadata, error) { defer logger.InfoLogger.SetPrefix("") start := time.Now() - _, err := os.Stat(archivePath) - if errors.Is(err, os.ErrNotExist) || skipCache { + if _, err := os.Stat(archivePath); errors.Is(err, os.ErrNotExist) || skipCache { logger.InfoLogger.Println("Fetching from " + sourceUrl) resp, err := client.Get(sourceUrl) @@ -88,7 +86,7 @@ func downloadSource(version string, skipCache bool) (PackageMetadata, error) { return PackageMetadata{ArchivePath: archivePath, Version: version}, nil } -func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, error) { +func buildFromSource(pkgMeta PackageMetadata) (PackageMetadata, error) { logger.InfoLogger.Println(logger.Bold("Building from source")) logger.InfoLogger.SetPrefix(" ") defer logger.InfoLogger.SetPrefix("") @@ -97,9 +95,7 @@ func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, er logger.InfoLogger.Println("Unpacking source for " + pkgMeta.ArchivePath) - _, untarErr := exec.RunCommand([]string{"tar", "zxvf", pkgMeta.ArchivePath}, state.GetStatePath("cache"), !verbose) - - if untarErr != nil { + if _, untarErr := exec.RunCommand([]string{"tar", "zxvf", pkgMeta.ArchivePath}, state.GetStatePath("cache")); untarErr != nil { return pkgMeta, untarErr } @@ -113,16 +109,13 @@ func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, er targetDirectory := state.GetStatePath("runtimes", "python", pkgMeta.Version) - _, configureErr := exec.RunCommand([]string{"./configure", "--prefix=" + targetDirectory, "--enable-optimizations"}, unzippedRoot, !verbose) - - if configureErr != nil { + if _, configureErr := exec.RunCommand([]string{"./configure", "--prefix=" + targetDirectory, "--enable-optimizations"}, unzippedRoot); configureErr != nil { return pkgMeta, configureErr } logger.InfoLogger.Println("Building") - _, buildErr := exec.RunCommand([]string{"make", "altinstall", "-j4"}, unzippedRoot, !verbose) - if buildErr != nil { + if _, buildErr := exec.RunCommand([]string{"make", "altinstall", "-j4"}, unzippedRoot); buildErr != nil { return pkgMeta, buildErr } @@ -132,7 +125,6 @@ func buildFromSource(pkgMeta PackageMetadata, verbose bool) (PackageMetadata, er pkgMeta.InstallPath = targetDirectory - logger.InfoLogger.Printf("Installed Python %s at %s\n", pkgMeta.Version, pkgMeta.InstallPath) - logger.InfoLogger.Printf("✅ Done (%s)\n", time.Since(start)) + logger.InfoLogger.Printf("✅ Installed Python %s at %s (%s)\n", pkgMeta.Version, pkgMeta.InstallPath, time.Since(start)) return pkgMeta, nil } diff --git a/python/version.go b/python/version.go index 28981fc..04a94c3 100644 --- a/python/version.go +++ b/python/version.go @@ -100,7 +100,7 @@ func DetermineSelectedPythonVersion(currentState state.State) (SelectedVersion, // DetermineSystemPython returns the unshimmed Python version and path. // It assumes that /bin/python is where system Python lives. func DetermineSystemPython() (string, string) { - versionOut, _ := exec.RunCommand([]string{"/bin/python", "--version"}, state.GetStatePath(), true) + versionOut, _ := exec.RunCommand([]string{"/bin/python", "--version"}, state.GetStatePath()) detectedVersion, _ := strings.CutPrefix(versionOut, "Python") return strings.TrimSpace(detectedVersion), "/bin/python" }