1- import { pathExists , stat , remove } from "fs-extra" ;
1+ import { pathExists , remove } from "fs-extra" ;
22import { glob } from "glob" ;
3- import { join , basename , resolve , relative , dirname , extname } from "path" ;
3+ import { join , basename , resolve , dirname , extname } from "path" ;
44import * as vscode from "vscode" ;
55import * as cli from "../codeql-cli/cli" ;
66import { ExtensionContext } from "vscode" ;
77import {
88 showAndLogWarningMessage ,
99 showAndLogInformationMessage ,
10- isLikelyDatabaseRoot ,
1110 showAndLogExceptionWithTelemetry ,
1211 isFolderAlreadyInWorkspace ,
1312 getFirstWorkspaceFolder ,
1413 showNeverAskAgainDialog ,
1514} from "../helpers" ;
1615import { ProgressCallback , withProgress } from "../common/vscode/progress" ;
17- import {
18- zipArchiveScheme ,
19- encodeArchiveBasePath ,
20- decodeSourceArchiveUri ,
21- encodeSourceArchiveUri ,
22- } from "../common/vscode/archive-filesystem-provider" ;
16+ import { encodeArchiveBasePath } from "../common/vscode/archive-filesystem-provider" ;
2317import { DisposableObject } from "../pure/disposable-object" ;
2418import { Logger , extLogger } from "../common" ;
2519import { asError , getErrorMessage } from "../pure/helpers-pure" ;
2620import { QueryRunner } from "../query-server" ;
27- import { containsPath , pathsEqual } from "../pure/files" ;
21+ import { containsPath } from "../pure/files" ;
2822import { redactableError } from "../pure/errors" ;
2923import {
3024 getAutogenerateQlPacks ,
@@ -40,6 +34,7 @@ import {
4034 DatabaseItem ,
4135 PersistedDatabaseItem ,
4236} from "./local-databases/database-item" ;
37+ import { DatabaseItemImpl } from "./local-databases/database-item-impl" ;
4338
4439export { DatabaseItem } from "./local-databases/database-item" ;
4540
@@ -242,232 +237,6 @@ export interface DatabaseChangedEvent {
242237 item : DatabaseItem | undefined ;
243238}
244239
245- // Exported for testing
246- export class DatabaseItemImpl implements DatabaseItem {
247- private _error : Error | undefined = undefined ;
248- private _contents : DatabaseContents | undefined ;
249- /** A cache of database info */
250- private _dbinfo : cli . DbInfo | undefined ;
251-
252- public constructor (
253- public readonly databaseUri : vscode . Uri ,
254- contents : DatabaseContents | undefined ,
255- private options : FullDatabaseOptions ,
256- private readonly onChanged : ( event : DatabaseChangedEvent ) => void ,
257- ) {
258- this . _contents = contents ;
259- }
260-
261- public get name ( ) : string {
262- if ( this . options . displayName ) {
263- return this . options . displayName ;
264- } else if ( this . _contents ) {
265- return this . _contents . name ;
266- } else {
267- return basename ( this . databaseUri . fsPath ) ;
268- }
269- }
270-
271- public set name ( newName : string ) {
272- this . options . displayName = newName ;
273- }
274-
275- public get sourceArchive ( ) : vscode . Uri | undefined {
276- if ( this . options . ignoreSourceArchive || this . _contents === undefined ) {
277- return undefined ;
278- } else {
279- return this . _contents . sourceArchiveUri ;
280- }
281- }
282-
283- public get contents ( ) : DatabaseContents | undefined {
284- return this . _contents ;
285- }
286-
287- public get dateAdded ( ) : number | undefined {
288- return this . options . dateAdded ;
289- }
290-
291- public get error ( ) : Error | undefined {
292- return this . _error ;
293- }
294-
295- public async refresh ( ) : Promise < void > {
296- try {
297- try {
298- this . _contents = await DatabaseResolver . resolveDatabaseContents (
299- this . databaseUri ,
300- ) ;
301- this . _error = undefined ;
302- } catch ( e ) {
303- this . _contents = undefined ;
304- this . _error = asError ( e ) ;
305- throw e ;
306- }
307- } finally {
308- this . onChanged ( {
309- kind : DatabaseEventKind . Refresh ,
310- item : this ,
311- } ) ;
312- }
313- }
314-
315- public resolveSourceFile ( uriStr : string | undefined ) : vscode . Uri {
316- const sourceArchive = this . sourceArchive ;
317- const uri = uriStr ? vscode . Uri . parse ( uriStr , true ) : undefined ;
318- if ( uri && uri . scheme !== "file" ) {
319- throw new Error (
320- `Invalid uri scheme in ${ uriStr } . Only 'file' is allowed.` ,
321- ) ;
322- }
323- if ( ! sourceArchive ) {
324- if ( uri ) {
325- return uri ;
326- } else {
327- return this . databaseUri ;
328- }
329- }
330-
331- if ( uri ) {
332- const relativeFilePath = decodeURI ( uri . path )
333- . replace ( ":" , "_" )
334- . replace ( / ^ \/ * / , "" ) ;
335- if ( sourceArchive . scheme === zipArchiveScheme ) {
336- const zipRef = decodeSourceArchiveUri ( sourceArchive ) ;
337- const pathWithinSourceArchive =
338- zipRef . pathWithinSourceArchive === "/"
339- ? relativeFilePath
340- : `${ zipRef . pathWithinSourceArchive } /${ relativeFilePath } ` ;
341- return encodeSourceArchiveUri ( {
342- pathWithinSourceArchive,
343- sourceArchiveZipPath : zipRef . sourceArchiveZipPath ,
344- } ) ;
345- } else {
346- let newPath = sourceArchive . path ;
347- if ( ! newPath . endsWith ( "/" ) ) {
348- // Ensure a trailing slash.
349- newPath += "/" ;
350- }
351- newPath += relativeFilePath ;
352-
353- return sourceArchive . with ( { path : newPath } ) ;
354- }
355- } else {
356- return sourceArchive ;
357- }
358- }
359-
360- /**
361- * Gets the state of this database, to be persisted in the workspace state.
362- */
363- public getPersistedState ( ) : PersistedDatabaseItem {
364- return {
365- uri : this . databaseUri . toString ( true ) ,
366- options : this . options ,
367- } ;
368- }
369-
370- /**
371- * Holds if the database item refers to an exported snapshot
372- */
373- public async hasMetadataFile ( ) : Promise < boolean > {
374- return await isLikelyDatabaseRoot ( this . databaseUri . fsPath ) ;
375- }
376-
377- /**
378- * Returns information about a database.
379- */
380- private async getDbInfo ( server : cli . CodeQLCliServer ) : Promise < cli . DbInfo > {
381- if ( this . _dbinfo === undefined ) {
382- this . _dbinfo = await server . resolveDatabase ( this . databaseUri . fsPath ) ;
383- }
384- return this . _dbinfo ;
385- }
386-
387- /**
388- * Returns `sourceLocationPrefix` of database. Requires that the database
389- * has a `.dbinfo` file, which is the source of the prefix.
390- */
391- public async getSourceLocationPrefix (
392- server : cli . CodeQLCliServer ,
393- ) : Promise < string > {
394- const dbInfo = await this . getDbInfo ( server ) ;
395- return dbInfo . sourceLocationPrefix ;
396- }
397-
398- /**
399- * Returns path to dataset folder of database.
400- */
401- public async getDatasetFolder ( server : cli . CodeQLCliServer ) : Promise < string > {
402- const dbInfo = await this . getDbInfo ( server ) ;
403- return dbInfo . datasetFolder ;
404- }
405-
406- public get language ( ) {
407- return this . options . language || "" ;
408- }
409-
410- /**
411- * Returns the root uri of the virtual filesystem for this database's source archive.
412- */
413- public getSourceArchiveExplorerUri ( ) : vscode . Uri {
414- const sourceArchive = this . sourceArchive ;
415- if ( sourceArchive === undefined || ! sourceArchive . fsPath . endsWith ( ".zip" ) ) {
416- throw new Error ( this . verifyZippedSources ( ) ) ;
417- }
418- return encodeArchiveBasePath ( sourceArchive . fsPath ) ;
419- }
420-
421- public verifyZippedSources ( ) : string | undefined {
422- const sourceArchive = this . sourceArchive ;
423- if ( sourceArchive === undefined ) {
424- return `${ this . name } has no source archive.` ;
425- }
426-
427- if ( ! sourceArchive . fsPath . endsWith ( ".zip" ) ) {
428- return `${ this . name } has a source folder that is unzipped.` ;
429- }
430- return ;
431- }
432-
433- /**
434- * Holds if `uri` belongs to this database's source archive.
435- */
436- public belongsToSourceArchiveExplorerUri ( uri : vscode . Uri ) : boolean {
437- if ( this . sourceArchive === undefined ) return false ;
438- return (
439- uri . scheme === zipArchiveScheme &&
440- decodeSourceArchiveUri ( uri ) . sourceArchiveZipPath ===
441- this . sourceArchive . fsPath
442- ) ;
443- }
444-
445- public async isAffectedByTest ( testPath : string ) : Promise < boolean > {
446- const databasePath = this . databaseUri . fsPath ;
447- if ( ! databasePath . endsWith ( ".testproj" ) ) {
448- return false ;
449- }
450- try {
451- const stats = await stat ( testPath ) ;
452- if ( stats . isDirectory ( ) ) {
453- return ! relative ( testPath , databasePath ) . startsWith ( ".." ) ;
454- } else {
455- // database for /one/two/three/test.ql is at /one/two/three/three.testproj
456- const testdir = dirname ( testPath ) ;
457- const testdirbase = basename ( testdir ) ;
458- return pathsEqual (
459- databasePath ,
460- join ( testdir , `${ testdirbase } .testproj` ) ,
461- process . platform ,
462- ) ;
463- }
464- } catch {
465- // No information available for test path - assume database is unaffected.
466- return false ;
467- }
468- }
469- }
470-
471240/**
472241 * A promise that resolves to an event's result value when the event
473242 * `event` fires. If waiting for the event takes too long (by default
0 commit comments