1 import { execSync } from "child_process";
2 import Logger from "../logger.mjs";
3 import { mkdir } from "fs";
4 import { rimrafSync } from "rimraf";
5 import { dirname, join } from "path";
7 // eslint-disable-next-line @typescript-eslint/no-unused-vars
8 function ensureDir(dirPath: string): Promise<void> {
9 return new Promise(resolve => {
10 mkdir(dirPath, { recursive: true }, () => {
16 function removeDir(dirPath: string): Promise<void> {
17 return new Promise(resolve => {
24 * This class is responsible for extracting the Python framework from the macOS installer pkg.
26 * Currently only support Apple Silicon (arm64) architecture.
28 export default class MacOSPythonPkgExtractor {
29 private _logger: Logger;
30 private pkgFilePath: string;
31 private targetDirectory: string;
33 constructor(pkgFilePath: string, targetDirectory: string) {
34 this._logger = new Logger("MacOSPythonPkgExtractor");
35 this.pkgFilePath = pkgFilePath;
36 this.targetDirectory = targetDirectory;
39 public async extractPkg(): Promise<boolean> {
40 // Create a temporary directory for extraction
41 const tempDir = join(dirname(this.pkgFilePath), "temp-extract");
42 // required by pkgutil to not already exist in fs
43 //await ensureDir(tempDir);
45 let exceptionOccurred = false;
47 // Step 1: Extract the pkg file using pkgutil
48 const extractCmd = `pkgutil --expand "${this.pkgFilePath}" "${tempDir}"`;
49 this.runCommand(extractCmd);
51 // Step 2: Extract the payload using tar
52 const payloadPath = join(tempDir, "Python_Framework.pkg", "Payload");
53 const tarCmd = `tar -xvf "${payloadPath}" -C "${this.targetDirectory}"`;
54 this.runCommand(tarCmd);
56 exceptionOccurred = true;
58 // Clean up: Remove the temporary directory
59 await removeDir(tempDir);
62 if (exceptionOccurred) {
63 this._logger.error("Failed to extract the Python framework");
71 private runCommand(command: string): void {
75 const mesage = error instanceof Error ? error.message : (error as string);
77 `Error executing command: ${command} Error: ${mesage}`