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

     1  //go:build darwin
     2  // +build darwin
     3  
     4  package camel
     5  
     6  import (
     7  	"os"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  
    12  	"github.com/ActiveState/cli/internal/constants"
    13  	"github.com/ActiveState/cli/internal/errs"
    14  	"github.com/ActiveState/cli/internal/fileutils"
    15  	"github.com/ActiveState/cli/internal/logging"
    16  )
    17  
    18  // Prepare ensures Metadata can handle Python runtimes on MacOS.
    19  // These runtimes do not include metadata files as they should
    20  // be runnable from where they are unarchived
    21  func (m *MetaData) Prepare(installRoot string) error {
    22  	frameWorkDir := "Library/Frameworks/Python.framework/Versions/"
    23  	m.BinaryLocations = []MetaDataBinary{
    24  		{
    25  			Path:     filepath.Join(frameWorkDir, "Current", "bin"),
    26  			Relative: true,
    27  		},
    28  	}
    29  
    30  	if !m.hasBinaryFile(installRoot, constants.ActivePython3Executable) && !m.hasBinaryFile(installRoot, constants.ActivePython2Executable) {
    31  		logging.Debug("No language detected for %s", installRoot)
    32  		return nil
    33  	}
    34  
    35  	m.setPythonEnv()
    36  
    37  	libDir := filepath.Join(installRoot, frameWorkDir, "Current", "lib")
    38  	dirRe := regexp.MustCompile(`python\d+.\d+`)
    39  
    40  	files, err := os.ReadDir(libDir)
    41  	if err != nil {
    42  		return errs.Wrap(err, "OS failure")
    43  	}
    44  
    45  	var sitePackages string
    46  	for _, f := range files {
    47  		if !f.IsDir() {
    48  			continue
    49  		}
    50  		if dirRe.MatchString(f.Name()) {
    51  			sitePackages = filepath.Join(libDir, f.Name(), "site-packages")
    52  			break
    53  		}
    54  	}
    55  
    56  	if pythonpath, ok := os.LookupEnv("PYTHONPATH"); ok {
    57  		m.PathListEnv["PYTHONPATH"] = pythonpath
    58  	} else if fileutils.DirExists(sitePackages) {
    59  		if strings.HasPrefix(sitePackages, installRoot) {
    60  			sitePackages = strings.Replace(sitePackages, installRoot, "${INSTALLDIR}", 1)
    61  		}
    62  		m.PathListEnv["PYTHONPATH"] = sitePackages
    63  	}
    64  
    65  	if m.TargetedRelocations == nil {
    66  		// the binaries are actually in a versioned directory
    67  		// this version is likely the same as the found above, but it doesn't hurt to get explicitly
    68  		dirRe = regexp.MustCompile(`\d+(?:\.\d+)+`)
    69  		files, err = os.ReadDir(filepath.Join(installRoot, frameWorkDir))
    70  		if err != nil {
    71  			return errs.Wrap(err, "OS failure")
    72  		}
    73  
    74  		var relVersionedFrameWorkDir string
    75  		for _, f := range files {
    76  			if !f.IsDir() {
    77  				continue
    78  			}
    79  			if dirRe.MatchString(f.Name()) {
    80  				relVersionedFrameWorkDir = filepath.Join(frameWorkDir, f.Name())
    81  				break
    82  			}
    83  		}
    84  
    85  		if relVersionedFrameWorkDir == "" {
    86  			return errs.New("could not find path %s/x.x in build artifact", frameWorkDir)
    87  		}
    88  
    89  		m.TargetedRelocations = []TargetedRelocation{TargetedRelocation{
    90  			InDir:        filepath.Join(frameWorkDir, "Current", "bin"),
    91  			SearchString: "#!" + filepath.Join("/", relVersionedFrameWorkDir),
    92  			Replacement:  "#!" + filepath.Join("${INSTALLDIR}", relVersionedFrameWorkDir),
    93  		}}
    94  	}
    95  
    96  	return nil
    97  }