Merge remote-tracking branch 'origin/main' into koesie10/yauzl-unzip-tests
This commit is contained in:
@@ -15,7 +15,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
codeQlLauncherName,
|
codeQlLauncherName,
|
||||||
deprecatedCodeQlLauncherName,
|
deprecatedCodeQlLauncherName,
|
||||||
extractZipArchive,
|
|
||||||
getRequiredAssetName,
|
getRequiredAssetName,
|
||||||
} from "../common/distribution";
|
} from "../common/distribution";
|
||||||
import {
|
import {
|
||||||
@@ -26,6 +25,7 @@ import {
|
|||||||
showAndLogErrorMessage,
|
showAndLogErrorMessage,
|
||||||
showAndLogWarningMessage,
|
showAndLogWarningMessage,
|
||||||
} from "../common/logging";
|
} from "../common/logging";
|
||||||
|
import { unzipToDirectory } from "../common/unzip";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* distribution.ts
|
* distribution.ts
|
||||||
@@ -420,7 +420,7 @@ class ExtensionSpecificDistributionManager {
|
|||||||
void extLogger.log(
|
void extLogger.log(
|
||||||
`Extracting CodeQL CLI to ${this.getDistributionStoragePath()}`,
|
`Extracting CodeQL CLI to ${this.getDistributionStoragePath()}`,
|
||||||
);
|
);
|
||||||
await extractZipArchive(archivePath, this.getDistributionStoragePath());
|
await unzipToDirectory(archivePath, this.getDistributionStoragePath());
|
||||||
} finally {
|
} finally {
|
||||||
await remove(tmpDirectory);
|
await remove(tmpDirectory);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import { platform } from "os";
|
import { platform } from "os";
|
||||||
import { Open } from "unzipper";
|
|
||||||
import { join } from "path";
|
|
||||||
import { pathExists, chmod } from "fs-extra";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the codeql cli installation we prefer to install, based on our current platform.
|
* Get the name of the codeql cli installation we prefer to install, based on our current platform.
|
||||||
@@ -19,31 +16,6 @@ export function getRequiredAssetName(): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function extractZipArchive(
|
|
||||||
archivePath: string,
|
|
||||||
outPath: string,
|
|
||||||
): Promise<void> {
|
|
||||||
const archive = await Open.file(archivePath);
|
|
||||||
await archive.extract({
|
|
||||||
concurrency: 4,
|
|
||||||
path: outPath,
|
|
||||||
});
|
|
||||||
// Set file permissions for extracted files
|
|
||||||
await Promise.all(
|
|
||||||
archive.files.map(async (file) => {
|
|
||||||
// Only change file permissions if within outPath (path.join normalises the path)
|
|
||||||
const extractedPath = join(outPath, file.path);
|
|
||||||
if (
|
|
||||||
extractedPath.indexOf(outPath) !== 0 ||
|
|
||||||
!(await pathExists(extractedPath))
|
|
||||||
) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
return chmod(extractedPath, file.externalFileAttributes >>> 16);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function codeQlLauncherName(): string {
|
export function codeQlLauncherName(): string {
|
||||||
return platform() === "win32" ? "codeql.exe" : "codeql";
|
return platform() === "win32" ? "codeql.exe" : "codeql";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { Entry as ZipEntry, open, Options as ZipOptions, ZipFile } from "yauzl";
|
import { Entry as ZipEntry, open, Options as ZipOptions, ZipFile } from "yauzl";
|
||||||
import { Readable } from "stream";
|
import { Readable } from "stream";
|
||||||
|
import { dirname, join } from "path";
|
||||||
|
import { WriteStream } from "fs";
|
||||||
|
import { createWriteStream, ensureDir } from "fs-extra";
|
||||||
|
|
||||||
// We can't use promisify because it picks up the wrong overload.
|
// We can't use promisify because it picks up the wrong overload.
|
||||||
export function openZip(
|
export function openZip(
|
||||||
@@ -77,3 +80,63 @@ export async function openZipBuffer(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function copyStream(
|
||||||
|
readable: Readable,
|
||||||
|
writeStream: WriteStream,
|
||||||
|
): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
readable.on("error", (err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
readable.on("end", () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
readable.pipe(writeStream);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function unzipToDirectory(
|
||||||
|
archivePath: string,
|
||||||
|
destinationPath: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const zipFile = await openZip(archivePath, {
|
||||||
|
autoClose: false,
|
||||||
|
strictFileNames: true,
|
||||||
|
lazyEntries: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const entries = await readZipEntries(zipFile);
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const path = join(destinationPath, entry.fileName);
|
||||||
|
|
||||||
|
if (/\/$/.test(entry.fileName)) {
|
||||||
|
// Directory file names end with '/'
|
||||||
|
|
||||||
|
await ensureDir(path);
|
||||||
|
} else {
|
||||||
|
// Ensure the directory exists
|
||||||
|
await ensureDir(dirname(path));
|
||||||
|
|
||||||
|
const readable = await openZipReadStream(zipFile, entry);
|
||||||
|
|
||||||
|
let mode: number | undefined = entry.externalFileAttributes >>> 16;
|
||||||
|
if (mode <= 0) {
|
||||||
|
mode = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const writeStream = createWriteStream(path, {
|
||||||
|
autoClose: true,
|
||||||
|
mode,
|
||||||
|
});
|
||||||
|
|
||||||
|
await copyStream(readable, writeStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
zipFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { Open } from "unzipper";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unzips a zip file to a directory.
|
|
||||||
* @param sourcePath The path to the zip file.
|
|
||||||
* @param destinationPath The path to the directory to unzip to.
|
|
||||||
*/
|
|
||||||
export async function unzipFile(sourcePath: string, destinationPath: string) {
|
|
||||||
const file = await Open.file(sourcePath);
|
|
||||||
await file.extract({ path: destinationPath });
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
} from "./shared/variant-analysis";
|
} from "./shared/variant-analysis";
|
||||||
import { DisposableObject, DisposeHandler } from "../common/disposable-object";
|
import { DisposableObject, DisposeHandler } from "../common/disposable-object";
|
||||||
import { EventEmitter } from "vscode";
|
import { EventEmitter } from "vscode";
|
||||||
import { unzipFile } from "../common/zip";
|
import { unzipToDirectory } from "../common/unzip";
|
||||||
import { readRepoTask, writeRepoTask } from "./repo-tasks-store";
|
import { readRepoTask, writeRepoTask } from "./repo-tasks-store";
|
||||||
|
|
||||||
type CacheKey = `${number}/${string}`;
|
type CacheKey = `${number}/${string}`;
|
||||||
@@ -106,7 +106,7 @@ export class VariantAnalysisResultsManager extends DisposableObject {
|
|||||||
VariantAnalysisResultsManager.RESULTS_DIRECTORY,
|
VariantAnalysisResultsManager.RESULTS_DIRECTORY,
|
||||||
);
|
);
|
||||||
|
|
||||||
await unzipFile(zipFilePath, unzippedFilesDirectory);
|
await unzipToDirectory(zipFilePath, unzippedFilesDirectory);
|
||||||
|
|
||||||
this._onResultDownloaded.fire({
|
this._onResultDownloaded.fire({
|
||||||
variantAnalysisId,
|
variantAnalysisId,
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ describe(VariantAnalysisResultsManager.name, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
if (fs.existsSync(variantAnalysisStoragePath)) {
|
if (await fs.pathExists(variantAnalysisStoragePath)) {
|
||||||
fs.rmSync(variantAnalysisStoragePath, { recursive: true });
|
await fs.remove(variantAnalysisStoragePath);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { existsSync, createWriteStream, mkdirpSync } from "fs-extra";
|
|||||||
import { normalize, join } from "path";
|
import { normalize, join } from "path";
|
||||||
import {
|
import {
|
||||||
getRequiredAssetName,
|
getRequiredAssetName,
|
||||||
extractZipArchive,
|
|
||||||
codeQlLauncherName,
|
codeQlLauncherName,
|
||||||
} from "../../src/common/distribution";
|
} from "../../src/common/distribution";
|
||||||
|
import { unzipToDirectory } from "../../src/common/unzip";
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import supportedCliVersions from "../../supported_cli_versions.json";
|
import supportedCliVersions from "../../supported_cli_versions.json";
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ export async function ensureCli(useCli: boolean) {
|
|||||||
|
|
||||||
console.log(`Unzipping into '${unzipDir}'`);
|
console.log(`Unzipping into '${unzipDir}'`);
|
||||||
mkdirpSync(unzipDir);
|
mkdirpSync(unzipDir);
|
||||||
await extractZipArchive(downloadedFilePath, unzipDir);
|
await unzipToDirectory(downloadedFilePath, unzipDir);
|
||||||
console.log("Done.");
|
console.log("Done.");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to download CLI.");
|
console.error("Failed to download CLI.");
|
||||||
|
|||||||
Reference in New Issue
Block a user