Skip to content

Commit d02e53f

Browse files
committed
Move DatabaseItemImpl to separate file
1 parent 4bb4627 commit d02e53f

2 files changed

Lines changed: 252 additions & 236 deletions

File tree

extensions/ql-vscode/src/databases/local-databases.ts

Lines changed: 5 additions & 236 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,24 @@
1-
import { pathExists, stat, remove } from "fs-extra";
1+
import { pathExists, remove } from "fs-extra";
22
import { glob } from "glob";
3-
import { join, basename, resolve, relative, dirname, extname } from "path";
3+
import { join, basename, resolve, dirname, extname } from "path";
44
import * as vscode from "vscode";
55
import * as cli from "../codeql-cli/cli";
66
import { ExtensionContext } from "vscode";
77
import {
88
showAndLogWarningMessage,
99
showAndLogInformationMessage,
10-
isLikelyDatabaseRoot,
1110
showAndLogExceptionWithTelemetry,
1211
isFolderAlreadyInWorkspace,
1312
getFirstWorkspaceFolder,
1413
showNeverAskAgainDialog,
1514
} from "../helpers";
1615
import { 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";
2317
import { DisposableObject } from "../pure/disposable-object";
2418
import { Logger, extLogger } from "../common";
2519
import { asError, getErrorMessage } from "../pure/helpers-pure";
2620
import { QueryRunner } from "../query-server";
27-
import { containsPath, pathsEqual } from "../pure/files";
21+
import { containsPath } from "../pure/files";
2822
import { redactableError } from "../pure/errors";
2923
import {
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

4439
export { 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

Comments
 (0)