github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/platform/runtime/setup/implementations/camel/apy_install_lin_win.go (about)

     1  //go:build !darwin
     2  // +build !darwin
     3  
     4  package camel
     5  
     6  import (
     7  	"os/exec"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/ActiveState/cli/internal/constants"
    12  	"github.com/ActiveState/cli/internal/errs"
    13  	"github.com/ActiveState/cli/internal/fileutils"
    14  	"github.com/ActiveState/cli/internal/locale"
    15  	"github.com/ActiveState/cli/internal/logging"
    16  	"github.com/ActiveState/cli/internal/multilog"
    17  	"github.com/ActiveState/cli/internal/rollbar"
    18  )
    19  
    20  // InstallFromArchive will unpack the installer archive, locate the install script, and then use the installer
    21  // script to install an ActivePython runtime to the configured runtime dir. Any failures
    22  // during this process will result in a failed installation and the install-dir being removed.
    23  func (m *MetaData) pythonRelocationDir(installRoot string) (string, error) {
    24  	python, err := locatePythonExecutable(installRoot)
    25  	if err != nil {
    26  		return "", err
    27  	}
    28  
    29  	prefix, err := extractPythonRelocationPrefix(installRoot, python)
    30  	if err != nil {
    31  		return "", err
    32  	}
    33  
    34  	// relocate python
    35  	return prefix, nil
    36  }
    37  
    38  // locatePythonExecutable will locate the path to the python binary in the runtime dir.
    39  func locatePythonExecutable(installDir string) (string, error) {
    40  	binPath := filepath.Join(installDir, "bin")
    41  	python2 := filepath.Join(installDir, "bin", constants.ActivePython2Executable)
    42  	python3 := filepath.Join(installDir, "bin", constants.ActivePython3Executable)
    43  
    44  	var executable string
    45  	var executablePath string
    46  	if fileutils.FileExists(python3) {
    47  		executable = constants.ActivePython3Executable
    48  		executablePath = python3
    49  	} else if fileutils.FileExists(python2) {
    50  		executable = constants.ActivePython2Executable
    51  		executablePath = python2
    52  	} else {
    53  		return "", locale.NewError("installer_err_runtime_no_executable", "", binPath, constants.ActivePython2Executable, constants.ActivePython3Executable)
    54  	}
    55  
    56  	if !fileutils.IsExecutable(executablePath) {
    57  		return "", &ErrNotExecutable{locale.NewError("installer_err_runtime_executable_not_exec", "", binPath, executable)}
    58  	}
    59  	return executablePath, nil
    60  }
    61  
    62  // extractRelocationPrefix will extract the prefix that needs to be replaced for this installation.
    63  func extractPythonRelocationPrefix(installDir string, python string) (string, error) {
    64  	prefixBytes, err := exec.Command(python, "-c", "import activestate; print('\\n'.join(activestate.prefixes))").Output()
    65  	logging.Debug("bin: %s", python)
    66  	logging.Debug("OUTPUT: %s", string(prefixBytes))
    67  	if err != nil {
    68  		if _, isExitError := err.(*exec.ExitError); isExitError {
    69  			multilog.Log(logging.ErrorNoStacktrace, rollbar.Error)("obtaining relocation prefixes: %v : %s", err, string(prefixBytes))
    70  			return "", &ErrNoPrefixes{locale.NewError("installer_err_fail_obtain_prefixes", "", installDir)}
    71  		}
    72  		return "", errs.Wrap(err, "python import prefixes failed")
    73  	}
    74  	if strings.TrimSpace(string(prefixBytes)) == "" {
    75  		return "", &ErrNoPrefixes{locale.NewError("installer_err_fail_obtain_prefixes", "", installDir)}
    76  	}
    77  	return strings.Split(string(prefixBytes), "\n")[0], nil
    78  }