Fix: Windows decompression and installation paths.

This commit is contained in:
2026-01-11 14:03:10 +01:00
parent b20a066030
commit 4ee62009bb
3 changed files with 42 additions and 16 deletions

View File

@@ -94,17 +94,21 @@ Options:
if (values['install-path']) {
installDir = path.resolve(values['install-path']);
} else {
const isRoot = process.getuid && process.getuid() === 0;
if (isRoot) {
installDir = '/usr/local/bin';
if (process.platform === 'win32') {
const localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
installDir = path.join(localAppData, 'bin');
} else {
const homeBin = path.join(os.homedir(), 'bin');
if (fs.existsSync(homeBin)) {
installDir = homeBin;
} else {
// Fallback or error? Let's use a local bin if possible or /usr/local/bin (might fail)
const isRoot = process.getuid && process.getuid() === 0;
if (isRoot) {
installDir = '/usr/local/bin';
} else {
const homeBin = path.join(os.homedir(), 'bin');
if (fs.existsSync(homeBin)) {
installDir = homeBin;
} else {
installDir = '/usr/local/bin';
}
}
}
}
@@ -117,7 +121,17 @@ Options:
const destPath = path.join(installDir, finalName);
console.log(`Installing ${finalName} to ${destPath}...`);
fs.copyFileSync(binaryPath, destPath);
try {
fs.copyFileSync(binaryPath, destPath);
} catch (err: any) {
if (err.code === 'EBUSY') {
throw new Error(`The file ${destPath} is currently in use. Please close any running instances and try again.`);
}
if (err.code === 'EACCES' || err.code === 'EPERM') {
throw new Error(`Permission denied while installing to ${destPath}. Try running with sudo or as administrator, or use -p to specify a custom path.`);
}
throw err;
}
if (process.platform !== 'win32') {
fs.chmodSync(destPath, '755');

View File

@@ -18,11 +18,23 @@ export async function extractAsset(filePath: string, destDir: string): Promise<v
}
} else if (name.endsWith('.zip')) {
if (process.platform === 'win32') {
const command = `Expand-Archive -Path "${filePath}" -DestinationPath "${destDir}" -Force`;
const result = spawnSync('powershell', ['-Command', command]);
if (result.status !== 0) {
throw new Error(`powershell Expand-Archive failed with status ${result.status}: ${result.stderr.toString()}`);
// Modern Windows 10/11 has tar that handles zip
const tarResult = spawnSync('tar', ['-xf', filePath, '-C', destDir]);
if (tarResult.status === 0) return;
// Fallback: Use .NET ZipFile class to bypass PowerShell module trust issues (Microsoft.PowerShell.Archive)
// We escape single quotes for PowerShell.
const escapedFilePath = filePath.replace(/'/g, "''");
const escapedDestDir = destDir.replace(/'/g, "''");
const dotNetCommand = `Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFilePath}', '${escapedDestDir}')`;
// Try pwsh (PowerShell 7) then powershell (Windows PowerShell)
for (const shell of ['pwsh', 'powershell']) {
const result = spawnSync(shell, ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', dotNetCommand]);
if (result.status === 0) return;
}
throw new Error(`Extraction failed: Both tar and PowerShell fallback failed. Make sure your system can extract ZIP files.`);
} else {
const result = spawnSync('unzip', ['-q', filePath, '-d', destDir]);
if (result.status !== 0) {