mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-05-19 16:31:36 +00:00
refactor: use class to organize install
This commit is contained in:
parent
c4f4de6c2e
commit
bd875d1aeb
1 changed files with 135 additions and 105 deletions
|
|
@ -4,6 +4,7 @@ import log from 'electron-log'
|
|||
import { getMainWindow } from './init'
|
||||
import fs from 'node:fs'
|
||||
import { getBackendPath, getBinaryPath, getCachePath, isBinaryExists, runInstallScript } from './utils/process'
|
||||
import { spawn } from 'child_process'
|
||||
|
||||
const userData = app.getPath('userData');
|
||||
const versionFile = path.join(userData, 'version.txt');
|
||||
|
|
@ -76,7 +77,7 @@ export async function checkAndInstallDepsOnUpdate(win:BrowserWindow): Promise<bo
|
|||
*/
|
||||
export async function installCommandTool() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const ensureInstalled = async (toolName: 'uv' | 'bun', scriptName: string): Promise<boolean> => {
|
||||
const ensureInstalled = async (toolName: 'uv' | 'bun', scriptName: string): Promise<PromiseReturnType> => {
|
||||
if (await isBinaryExists(toolName)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -115,120 +116,149 @@ export async function installCommandTool() {
|
|||
})
|
||||
}
|
||||
|
||||
export async function installDependencies() {
|
||||
const { spawn } = await import('child_process');
|
||||
return new Promise<boolean>(async (resolve, reject) => {
|
||||
console.log('start install dependencies')
|
||||
let uv_path:string;
|
||||
const mainWindow = getMainWindow();
|
||||
const backendPath = getBackendPath();
|
||||
const installingLockPath = path.join(backendPath, 'uv_installing.lock')
|
||||
const installedLockPath = path.join(backendPath, 'uv_installed.lock')
|
||||
// const proxyArgs = ['--default-index', 'https://pypi.tuna.tsinghua.edu.cn/simple']
|
||||
const proxyArgs = ['--default-index', 'https://mirrors.aliyun.com/pypi/simple/']
|
||||
|
||||
const mainWindow = getMainWindow();
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-start');
|
||||
class InstallLogs {
|
||||
private node_process;
|
||||
|
||||
constructor(extraArgs:string[]) {
|
||||
console.log('start install dependencies', extraArgs)
|
||||
this.node_process = spawn(uv_path, [
|
||||
'sync',
|
||||
'--no-dev',
|
||||
'--cache-dir', getCachePath('uv_cache'),
|
||||
...extraArgs], {
|
||||
cwd: backendPath,
|
||||
env: {
|
||||
...process.env,
|
||||
UV_TOOL_DIR: getCachePath('uv_tool'),
|
||||
UV_PYTHON_INSTALL_DIR: getCachePath('uv_python'),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**Handle stdout data */
|
||||
onStdout() {
|
||||
this.node_process.stdout.on('data', (data:any) => {
|
||||
log.info(`Script output: ${data}`)
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-log', { type: 'stdout', data: data.toString() });
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const isInstalCommandTool = await installCommandTool()
|
||||
if (!isInstalCommandTool) {
|
||||
resolve(false)
|
||||
return
|
||||
/**Handle stderr data */
|
||||
onStderr() {
|
||||
this.node_process.stderr.on('data', (data:any) => {
|
||||
log.error(`Script error: ${data}`)
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-log', { type: 'stderr', data: data.toString() });
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const uv_path = await getBinaryPath('uv')
|
||||
const backendPath = getBackendPath()
|
||||
|
||||
if (!fs.existsSync(backendPath)) {
|
||||
fs.mkdirSync(backendPath, { recursive: true })
|
||||
/**Handle process close event */
|
||||
onClose(resolveInner:(code: number | null) => void) {
|
||||
this.node_process.on('close', resolveInner);
|
||||
}
|
||||
|
||||
const installingLockPath = path.join(backendPath, 'uv_installing.lock')
|
||||
fs.writeFileSync(installingLockPath, '')
|
||||
|
||||
const installedLockPath = path.join(backendPath, 'uv_installed.lock')
|
||||
// const proxyArgs = ['--default-index', 'https://pypi.tuna.tsinghua.edu.cn/simple']
|
||||
const proxyArgs = ['--default-index', 'https://mirrors.aliyun.com/pypi/simple/']
|
||||
const runInstall = (extraArgs: string[]) => {
|
||||
return new Promise<boolean>((resolveInner, rejectInner) => {
|
||||
try {
|
||||
const node_process = spawn(uv_path, [
|
||||
'sync',
|
||||
'--no-dev',
|
||||
'--cache-dir', getCachePath('uv_cache'),
|
||||
...extraArgs], {
|
||||
cwd: backendPath,
|
||||
env: {
|
||||
...process.env,
|
||||
UV_TOOL_DIR: getCachePath('uv_tool'),
|
||||
UV_PYTHON_INSTALL_DIR: getCachePath('uv_python'),
|
||||
}
|
||||
})
|
||||
console.log('start install dependencies', extraArgs)
|
||||
node_process.stdout.on('data', (data) => {
|
||||
|
||||
log.info(`Script output: ${data}`)
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-log', { type: 'stdout', data: data.toString() });
|
||||
}
|
||||
})
|
||||
|
||||
node_process.stderr.on('data', (data) => {
|
||||
log.error(`Script error: ${data}`)
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-log', { type: 'stderr', data: data.toString() });
|
||||
}
|
||||
})
|
||||
|
||||
node_process.on('close', (code) => {
|
||||
console.log('install dependencies end', code === 0)
|
||||
resolveInner(code === 0)
|
||||
})
|
||||
}catch(err) {
|
||||
log.error('run install failed', err)
|
||||
// Clean up uv_installing.lock file if installation fails
|
||||
if (fs.existsSync(installingLockPath)) {
|
||||
fs.unlinkSync(installingLockPath);
|
||||
}
|
||||
rejectInner(err)
|
||||
}
|
||||
|
||||
})
|
||||
/**
|
||||
* Set installing Lock Path
|
||||
* Creates uv_installing.lock file to indicate installation in progress
|
||||
* Creates backend directory if not exists
|
||||
*/
|
||||
static setLockPath() {
|
||||
if (!fs.existsSync(backendPath)) {
|
||||
fs.mkdirSync(backendPath, { recursive: true })
|
||||
}
|
||||
fs.writeFileSync(installingLockPath, '')
|
||||
}
|
||||
|
||||
// try default install
|
||||
const installSuccess = await runInstall([])
|
||||
|
||||
if (installSuccess) {
|
||||
fs.unlinkSync(installingLockPath)
|
||||
fs.writeFileSync(installedLockPath, '')
|
||||
log.info('Script completed successfully')
|
||||
console.log('end install dependencies')
|
||||
spawn(uv_path, ['run', 'task', 'babel'], { cwd: backendPath })
|
||||
resolve(true)
|
||||
return
|
||||
/**Clean installing Lock Path */
|
||||
static cleanLockPath() {
|
||||
if (fs.existsSync(installingLockPath)) {
|
||||
fs.unlinkSync(installingLockPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try mirror install
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
let mirrorInstallSuccess = false
|
||||
|
||||
if (timezone === 'Asia/Shanghai') {
|
||||
mirrorInstallSuccess = await runInstall(proxyArgs)
|
||||
} else {
|
||||
mirrorInstallSuccess = await runInstall([])
|
||||
}
|
||||
|
||||
|
||||
fs.existsSync(installingLockPath) && fs.unlinkSync(installingLockPath)
|
||||
|
||||
if (mirrorInstallSuccess) {
|
||||
fs.writeFileSync(installedLockPath, '')
|
||||
log.info('Mirror script completed successfully')
|
||||
console.log('end install dependencies (mirror)')
|
||||
spawn(uv_path, ['run', 'task', 'babel'], { cwd: backendPath })
|
||||
resolve(true)
|
||||
} else {
|
||||
log.error('Both default and mirror install failed')
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-complete', { success: false, error: 'Both default and mirror install failed' });
|
||||
}
|
||||
resolve(false)
|
||||
}
|
||||
const runInstall = (extraArgs: string[]) => {
|
||||
const installLogs = new InstallLogs(extraArgs);
|
||||
return new Promise<PromiseReturnType>((resolveInner, rejectInner) => {
|
||||
try {
|
||||
installLogs.onStdout();
|
||||
installLogs.onStderr();
|
||||
installLogs.onClose((code) => {
|
||||
console.log('install dependencies end', code === 0)
|
||||
InstallLogs.cleanLockPath()
|
||||
resolveInner(code === 0)
|
||||
})
|
||||
} catch (err) {
|
||||
log.error('run install failed', err)
|
||||
// Clean up uv_installing.lock file if installation fails
|
||||
InstallLogs.cleanLockPath();
|
||||
rejectInner(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function installDependencies() {
|
||||
uv_path = await getBinaryPath('uv');
|
||||
const handleCompletion = {
|
||||
spawnBabel: (type:"mirror"|"main"="main") => {
|
||||
fs.writeFileSync(installedLockPath, '')
|
||||
log.info('Script completed successfully')
|
||||
console.log(`Install Dependencies completed ${type}`)
|
||||
spawn(uv_path, ['run', 'task', 'babel'], { cwd: backendPath })
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise<PromiseReturnType>(async (resolve, reject) => {
|
||||
console.log('start install dependencies')
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-start');
|
||||
} else {
|
||||
resolve(false)
|
||||
return
|
||||
}
|
||||
|
||||
const isInstalCommandTool = await installCommandTool()
|
||||
if (!isInstalCommandTool) {
|
||||
resolve(false)
|
||||
return
|
||||
}
|
||||
|
||||
// Set Installing Lock Files
|
||||
InstallLogs.setLockPath();
|
||||
|
||||
// try default install
|
||||
const installSuccess = await runInstall([])
|
||||
if (installSuccess) {
|
||||
handleCompletion.spawnBabel()
|
||||
resolve(true)
|
||||
return
|
||||
}
|
||||
|
||||
// try mirror install
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
let mirrorInstallSuccess = false
|
||||
mirrorInstallSuccess = (timezone === 'Asia/Shanghai')? await runInstall(proxyArgs) :await runInstall([])
|
||||
|
||||
if (mirrorInstallSuccess) {
|
||||
handleCompletion.spawnBabel("mirror")
|
||||
resolve(true)
|
||||
} else {
|
||||
log.error('Both default and mirror install failed')
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('install-dependencies-complete', { success: false, error: 'Both default and mirror install failed' });
|
||||
}
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue