File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -25,7 +25,7 @@ import {
2525 showAndLogErrorMessage ,
2626 showAndLogWarningMessage ,
2727} from "../common/logging" ;
28- import { unzipToDirectory } from "../common/unzip" ;
28+ import { unzipToDirectoryConcurrently } from "../common/unzip-concurrently " ;
2929
3030/**
3131 * distribution.ts
@@ -420,7 +420,10 @@ class ExtensionSpecificDistributionManager {
420420 void extLogger . log (
421421 `Extracting CodeQL CLI to ${ this . getDistributionStoragePath ( ) } ` ,
422422 ) ;
423- await unzipToDirectory ( archivePath , this . getDistributionStoragePath ( ) ) ;
423+ await unzipToDirectoryConcurrently (
424+ archivePath ,
425+ this . getDistributionStoragePath ( ) ,
426+ ) ;
424427 } finally {
425428 await remove ( tmpDirectory ) ;
426429 }
Original file line number Diff line number Diff line change 1+ import { availableParallelism } from "os" ;
2+ import { dirname , join } from "path" ;
3+ import { createWriteStream , ensureDir } from "fs-extra" ;
4+ import {
5+ copyStream ,
6+ openZip ,
7+ openZipReadStream ,
8+ readZipEntries ,
9+ } from "./unzip" ;
10+ import PQueue from "p-queue" ;
11+
12+ export async function unzipToDirectoryConcurrently (
13+ archivePath : string ,
14+ destinationPath : string ,
15+ ) : Promise < void > {
16+ const zipFile = await openZip ( archivePath , {
17+ autoClose : false ,
18+ strictFileNames : true ,
19+ lazyEntries : true ,
20+ } ) ;
21+
22+ try {
23+ const entries = await readZipEntries ( zipFile ) ;
24+
25+ const queue = new PQueue ( {
26+ concurrency : availableParallelism ( ) ,
27+ } ) ;
28+
29+ await queue . addAll (
30+ entries . map ( ( entry ) => async ( ) => {
31+ const path = join ( destinationPath , entry . fileName ) ;
32+
33+ if ( / \/ $ / . test ( entry . fileName ) ) {
34+ // Directory file names end with '/'
35+
36+ await ensureDir ( path ) ;
37+ } else {
38+ // Ensure the directory exists
39+ await ensureDir ( dirname ( path ) ) ;
40+
41+ const readable = await openZipReadStream ( zipFile , entry ) ;
42+
43+ let mode : number | undefined = entry . externalFileAttributes >>> 16 ;
44+ if ( mode <= 0 ) {
45+ mode = undefined ;
46+ }
47+
48+ const writeStream = createWriteStream ( path , {
49+ autoClose : true ,
50+ mode,
51+ } ) ;
52+
53+ await copyStream ( readable , writeStream ) ;
54+ }
55+ } ) ,
56+ ) ;
57+ } finally {
58+ zipFile . close ( ) ;
59+ }
60+ }
Original file line number Diff line number Diff line change @@ -51,7 +51,7 @@ export function readZipEntries(zipFile: ZipFile): Promise<ZipEntry[]> {
5151 } ) ;
5252}
5353
54- function openZipReadStream (
54+ export function openZipReadStream (
5555 zipFile : ZipFile ,
5656 entry : ZipEntry ,
5757) : Promise < Readable > {
@@ -86,7 +86,7 @@ export async function openZipBuffer(
8686 } ) ;
8787}
8888
89- async function copyStream (
89+ export async function copyStream (
9090 readable : Readable ,
9191 writeStream : WriteStream ,
9292) : Promise < void > {
@@ -102,6 +102,14 @@ async function copyStream(
102102 } ) ;
103103}
104104
105+ /**
106+ * Sequentially unzips all files from a zip archive. Please use
107+ * `unzipToDirectoryConcurrently` if you can. This function is only
108+ * provided because Jest cannot import `p-queue`.
109+ *
110+ * @param archivePath
111+ * @param destinationPath
112+ */
105113export async function unzipToDirectory (
106114 archivePath : string ,
107115 destinationPath : string ,
Original file line number Diff line number Diff line change @@ -16,7 +16,7 @@ import {
1616} from "./shared/variant-analysis" ;
1717import { DisposableObject , DisposeHandler } from "../common/disposable-object" ;
1818import { EventEmitter } from "vscode" ;
19- import { unzipToDirectory } from "../common/unzip" ;
19+ import { unzipToDirectoryConcurrently } from "../common/unzip-concurrently " ;
2020import { readRepoTask , writeRepoTask } from "./repo-tasks-store" ;
2121
2222type CacheKey = `${number } /${string } `;
@@ -106,7 +106,7 @@ export class VariantAnalysisResultsManager extends DisposableObject {
106106 VariantAnalysisResultsManager . RESULTS_DIRECTORY ,
107107 ) ;
108108
109- await unzipToDirectory ( zipFilePath , unzippedFilesDirectory ) ;
109+ await unzipToDirectoryConcurrently ( zipFilePath , unzippedFilesDirectory ) ;
110110
111111 this . _onResultDownloaded . fire ( {
112112 variantAnalysisId,
You can’t perform that action at this time.
0 commit comments