mirror of
https://github.com/open-webui/desktop
synced 2025-06-26 18:15:59 +00:00
refac: python tar
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -91,5 +91,5 @@ typings/
|
|||||||
# Electron-Forge
|
# Electron-Forge
|
||||||
out/
|
out/
|
||||||
|
|
||||||
|
resources/python
|
||||||
resources/python.tar.gz
|
resources/python.tar.gz
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
"package": "electron-forge package",
|
"package": "electron-forge package",
|
||||||
"make": "electron-forge make",
|
"make": "electron-forge make",
|
||||||
"publish": "electron-forge publish",
|
"publish": "electron-forge publish",
|
||||||
"lint": "eslint --ext .ts,.tsx ."
|
"lint": "eslint --ext .ts,.tsx .",
|
||||||
|
"create:conda-lock": "cd resources && rimraf conda-lock.yml && conda-lock -f environment.yml && cd -",
|
||||||
|
"create:python-tar": "rimraf ./resources/python.tar.gz && conda-lock install --prefix ./resources/python ./resources/conda-lock.yml && conda pack -p ./resources/python -o ./resources/python.tar.gz"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-forge/cli": "^7.6.0",
|
"@electron-forge/cli": "^7.6.0",
|
||||||
|
|||||||
1125
resources/conda-lock.yml
Normal file
1125
resources/conda-lock.yml
Normal file
File diff suppressed because it is too large
Load Diff
12
resources/environment.yml
Normal file
12
resources/environment.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# environment.yml
|
||||||
|
channels:
|
||||||
|
- conda-forge
|
||||||
|
dependencies:
|
||||||
|
- python=3.11
|
||||||
|
platforms:
|
||||||
|
- linux-64
|
||||||
|
- linux-aarch64 # aka arm64, use for Docker on Apple Silicon
|
||||||
|
- osx-64
|
||||||
|
- osx-arm64 # For Apple Silicon, e.g. M1/M2
|
||||||
|
- win-64
|
||||||
|
# TODO: Add win-arm64 when available
|
||||||
@@ -45,6 +45,9 @@ if (!gotTheLock) {
|
|||||||
|
|
||||||
const onReady = () => {
|
const onReady = () => {
|
||||||
console.log(process.resourcesPath);
|
console.log(process.resourcesPath);
|
||||||
|
console.log(app.getName());
|
||||||
|
console.log(app.getPath("userData"));
|
||||||
|
console.log(app.getPath("appData"));
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600,
|
height: 600,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { app } from "electron";
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
export function getAppDir(): string {
|
export function getAppPath(): string {
|
||||||
let appDir = app.getAppPath();
|
let appDir = app.getAppPath();
|
||||||
if (!app.isPackaged) {
|
if (!app.isPackaged) {
|
||||||
appDir = path.dirname(appDir);
|
appDir = path.dirname(appDir);
|
||||||
@@ -28,11 +28,11 @@ export function getAppDir(): string {
|
|||||||
return appDir;
|
return appDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserHomeDir(): string {
|
export function getUserHomePath(): string {
|
||||||
return app.getPath("home");
|
return app.getPath("home");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserDataDir(): string {
|
export function getUserDataPath(): string {
|
||||||
const userDataDir = app.getPath("userData");
|
const userDataDir = app.getPath("userData");
|
||||||
|
|
||||||
if (!fs.existsSync(userDataDir)) {
|
if (!fs.existsSync(userDataDir)) {
|
||||||
@@ -52,16 +52,13 @@ export function getUserDataDir(): string {
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
export function getPackagedPythonTarPath(): string {
|
export function getBundledPythonTarPath(): string {
|
||||||
const appDir = getAppDir();
|
const appPath = getAppPath();
|
||||||
return path.join(appDir, "resources", "python.tar.gz");
|
return path.join(appPath, "resources", "python.tar.gz");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBundledPythonEnvDir(): string {
|
export function getBundledPythonInstallPath(): string {
|
||||||
const installDir =
|
const installDir = path.join(app.getPath("userData"), "python");
|
||||||
process.platform === "darwin"
|
|
||||||
? path.normalize(path.join(app.getPath("home"), "Library", app.getName()))
|
|
||||||
: app.getPath("userData");
|
|
||||||
|
|
||||||
if (!fs.existsSync(installDir)) {
|
if (!fs.existsSync(installDir)) {
|
||||||
try {
|
try {
|
||||||
@@ -73,12 +70,6 @@ export function getBundledPythonEnvDir(): string {
|
|||||||
return installDir;
|
return installDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBundledPythonEnvPath(): string {
|
|
||||||
const userDataDir = getBundledPythonEnvDir();
|
|
||||||
|
|
||||||
return path.join(userDataDir, "python");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCondaEnv(envPath: string): boolean {
|
export function isCondaEnv(envPath: string): boolean {
|
||||||
return fs.existsSync(path.join(envPath, "conda-meta"));
|
return fs.existsSync(path.join(envPath, "conda-meta"));
|
||||||
}
|
}
|
||||||
@@ -92,3 +83,82 @@ export function getPythonPath(envPath: string, isConda?: boolean) {
|
|||||||
return path.join(envPath, "bin", "python");
|
return path.join(envPath, "bin", "python");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getBundledPythonPath() {
|
||||||
|
return getPythonPath(getBundledPythonInstallPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBundledPythonInstalled() {
|
||||||
|
return fs.existsSync(getBundledPythonPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Fixes code-signing issues in macOS by applying ad-hoc signatures to extracted environment files.
|
||||||
|
//
|
||||||
|
// Unpacking a Conda environment on macOS may break the signatures of binaries, causing macOS
|
||||||
|
// Gatekeeper to block them. This script assigns an ad-hoc signature (`-s -`), making the binaries
|
||||||
|
// executable while bypassing macOS's strict validation without requiring trusted certificates.
|
||||||
|
//
|
||||||
|
// It reads an architecture-specific file (`sign-osx-arm64.txt` or `sign-osx-64.txt`), which lists
|
||||||
|
// files requiring re-signing, and generates a `codesign` command to fix them all within the `envPath`.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
export function createAdHocSignCommand(envPath: string): string {
|
||||||
|
const appPath = getAppPath();
|
||||||
|
|
||||||
|
const signListFile = path.join(
|
||||||
|
appPath,
|
||||||
|
"resources",
|
||||||
|
`sign-osx-${process.arch === "arm64" ? "arm64" : "64"}.txt`
|
||||||
|
);
|
||||||
|
const fileContents = fs.readFileSync(signListFile, "utf-8");
|
||||||
|
const signList: string[] = [];
|
||||||
|
|
||||||
|
fileContents.split(/\r?\n/).forEach((line) => {
|
||||||
|
if (line) {
|
||||||
|
signList.push(`"${line}"`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// sign all binaries with ad-hoc signature
|
||||||
|
return `cd ${envPath} && codesign -s - -o 0x2 -f ${signList.join(
|
||||||
|
" "
|
||||||
|
)} && cd -`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function installBundledPython(installPath?: string) {
|
||||||
|
const platform = process.platform;
|
||||||
|
const isWin = platform === "win32";
|
||||||
|
installPath = installPath || getBundledPythonInstallPath();
|
||||||
|
|
||||||
|
const pythonTarPath = getBundledPythonTarPath();
|
||||||
|
if (!fs.existsSync(pythonTarPath)) {
|
||||||
|
log.error("Python tarball not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(installPath, { recursive: true });
|
||||||
|
await tar.x({
|
||||||
|
cwd: installPath,
|
||||||
|
file: pythonTarPath,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
log.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let unpackCommand = isWin
|
||||||
|
? `${installPath}\\Scripts\\activate.bat && conda-unpack`
|
||||||
|
: `source "${installPath}/bin/activate" && conda-unpack`;
|
||||||
|
|
||||||
|
// only unsign when installing from bundled installer
|
||||||
|
if (platform === "darwin") {
|
||||||
|
unpackCommand = `${createAdHocSignCommand(installPath)}\n${unpackCommand}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const commandProcess = exec(unpackCommand, {
|
||||||
|
shell: isWin ? "cmd.exe" : "/bin/bash",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user