Skip to content

Commit

Permalink
Use js which as fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
jneira committed Dec 8, 2021
1 parent 70f6883 commit a424a6b
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 87 deletions.
22 changes: 16 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@
"@types/node": "^14.0.3",
"@types/request-promise-native": "^1.0.17",
"@types/vscode": "^1.52.0",
"@types/which": "^2.0.1",
"@types/yauzl": "^2.9.1",
"@vscode/test-electron": "^1.6.2",
"glob": "^7.1.4",
Expand Down Expand Up @@ -425,6 +426,7 @@
"request": "^2.88.2",
"request-promise-native": "^1.0.8",
"vscode-languageclient": "^7.0.0",
"which": "^2.0.1",
"yauzl": "^2.10.0"
}
}
162 changes: 81 additions & 81 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as url from 'url';
import { promisify } from 'util';
import { OutputChannel, ProgressLocation, window, WorkspaceFolder } from 'vscode';
import { Logger } from 'vscode-languageclient';
import * as which from 'which';
import * as yazul from 'yauzl';
import { createGunzip } from 'zlib';

Expand All @@ -18,7 +19,7 @@ enum LogLevel {
Error,
Warn,
Info,
Debug
Debug,
}
export class ExtensionLogger implements Logger {
public readonly name: string;
Expand Down Expand Up @@ -52,7 +53,7 @@ export class ExtensionLogger implements Logger {
let now = new Date();
// Ugly hack to make js date iso format similar to hls one
const offset = now.getTimezoneOffset();
now = new Date(now.getTime() - (offset * 60 * 1000));
now = new Date(now.getTime() - offset * 60 * 1000);
const timedMsg = `${new Date().toISOString().replace('T', ' ').replace('Z', '0000')} ${msg}`;
this.channel.appendLine(timedMsg);
if (this.logFile) {
Expand Down Expand Up @@ -161,87 +162,90 @@ export async function downloadFile(titleMsg: string, src: string, dest: string):
fs.unlinkSync(downloadDest);
}

const downloadTask = window.withProgress(
{
location: ProgressLocation.Notification,
title: titleMsg,
cancellable: false,
},
async (progress) => {
const p = new Promise<void>((resolve, reject) => {
const srcUrl = url.parse(src);
const opts: https.RequestOptions = {
host: srcUrl.host,
path: srcUrl.path,
protocol: srcUrl.protocol,
port: srcUrl.port,
headers: userAgentHeader,
};
getWithRedirects(opts, (res) => {
const totalSize = parseInt(res.headers['content-length'] || '1', 10);
const fileStream = fs.createWriteStream(downloadDest, { mode: 0o744 });
let curSize = 0;
const downloadTask = window
.withProgress(
{
location: ProgressLocation.Notification,
title: titleMsg,
cancellable: false,
},
async (progress) => {
const p = new Promise<void>((resolve, reject) => {
const srcUrl = url.parse(src);
const opts: https.RequestOptions = {
host: srcUrl.host,
path: srcUrl.path,
protocol: srcUrl.protocol,
port: srcUrl.port,
headers: userAgentHeader,
};
getWithRedirects(opts, (res) => {
const totalSize = parseInt(res.headers['content-length'] || '1', 10);
const fileStream = fs.createWriteStream(downloadDest, { mode: 0o744 });
let curSize = 0;

// Decompress it if it's a gzip or zip
const needsGunzip =
res.headers['content-type'] === 'application/gzip' || extname(srcUrl.path ?? '') === '.gz';
const needsUnzip = res.headers['content-type'] === 'application/zip' || extname(srcUrl.path ?? '') === '.zip';
if (needsGunzip) {
const gunzip = createGunzip();
gunzip.on('error', reject);
res.pipe(gunzip).pipe(fileStream);
} else if (needsUnzip) {
const zipDest = downloadDest + '.zip';
const zipFs = fs.createWriteStream(zipDest);
zipFs.on('error', reject);
zipFs.on('close', () => {
yazul.open(zipDest, (err, zipfile) => {
if (err) {
throw err;
}
if (!zipfile) {
throw Error("Couldn't decompress zip");
}
// Decompress it if it's a gzip or zip
const needsGunzip =
res.headers['content-type'] === 'application/gzip' || extname(srcUrl.path ?? '') === '.gz';
const needsUnzip =
res.headers['content-type'] === 'application/zip' || extname(srcUrl.path ?? '') === '.zip';
if (needsGunzip) {
const gunzip = createGunzip();
gunzip.on('error', reject);
res.pipe(gunzip).pipe(fileStream);
} else if (needsUnzip) {
const zipDest = downloadDest + '.zip';
const zipFs = fs.createWriteStream(zipDest);
zipFs.on('error', reject);
zipFs.on('close', () => {
yazul.open(zipDest, (err, zipfile) => {
if (err) {
throw err;
}
if (!zipfile) {
throw Error("Couldn't decompress zip");
}

// We only expect *one* file inside each zip
zipfile.on('entry', (entry: yazul.Entry) => {
zipfile.openReadStream(entry, (err2, readStream) => {
if (err2) {
throw err2;
}
readStream?.pipe(fileStream);
// We only expect *one* file inside each zip
zipfile.on('entry', (entry: yazul.Entry) => {
zipfile.openReadStream(entry, (err2, readStream) => {
if (err2) {
throw err2;
}
readStream?.pipe(fileStream);
});
});
});
});
});
res.pipe(zipFs);
} else {
res.pipe(fileStream);
}
res.pipe(zipFs);
} else {
res.pipe(fileStream);
}

function toMB(bytes: number) {
return bytes / (1024 * 1024);
}
function toMB(bytes: number) {
return bytes / (1024 * 1024);
}

res.on('data', (chunk: Buffer) => {
curSize += chunk.byteLength;
const msg = `${toMB(curSize).toFixed(1)}MB / ${toMB(totalSize).toFixed(1)}MB`;
progress.report({ message: msg, increment: (chunk.length / totalSize) * 100 });
});
res.on('error', reject);
fileStream.on('close', resolve);
}).on('error', reject);
});
try {
await p;
// Finally rename it to the actual dest
fs.renameSync(downloadDest, dest);
} finally {
// And remember to remove it from the list of current downloads
inFlightDownloads.get(src)?.delete(dest);
res.on('data', (chunk: Buffer) => {
curSize += chunk.byteLength;
const msg = `${toMB(curSize).toFixed(1)}MB / ${toMB(totalSize).toFixed(1)}MB`;
progress.report({ message: msg, increment: (chunk.length / totalSize) * 100 });
});
res.on('error', reject);
fileStream.on('close', resolve);
}).on('error', reject);
});
try {
await p;
// Finally rename it to the actual dest
fs.renameSync(downloadDest, dest);
} finally {
// And remember to remove it from the list of current downloads
inFlightDownloads.get(src)?.delete(dest);
}
}
}
).then(_ => true);
)
.then((_) => true);

try {
if (inFlightDownloads.has(src)) {
Expand All @@ -250,7 +254,7 @@ export async function downloadFile(titleMsg: string, src: string, dest: string):
inFlightDownloads.set(src, new Map([[dest, downloadTask]]));
}
return await downloadTask;
} catch (e: any) {
} catch (e) {
await promisify(fs.unlink)(downloadDest).catch(ignoreFileNotExists);
throw new Error(`Failed to download ${src}:\n${e.message}`);
}
Expand All @@ -277,17 +281,13 @@ export function executableExists(exe: string): boolean {
const isWindows = process.platform === 'win32';
const cmd: string = isWindows ? 'where' : 'which';
const out = child_process.spawnSync(cmd, [exe]);
return out.status === 0 || (isWindows && fileExists(exe));
return out.status === 0 || (!isWindows && (which.sync(exe, { nothrow: true }) ?? '') !== '');
}

export function directoryExists(path: string): boolean {
return fs.existsSync(path) && fs.lstatSync(path).isDirectory();
}

function fileExists(path: string): boolean {
return fs.existsSync(path) && fs.lstatSync(path).isFile();
}

export function resolvePathPlaceHolders(path: string, folder?: WorkspaceFolder) {
path = path.replace('${HOME}', os.homedir).replace('${home}', os.homedir).replace(/^~/, os.homedir);
if (folder) {
Expand Down

0 comments on commit a424a6b

Please sign in to comment.