Skip to content

Commit 29c29f9

Browse files
committed
Save query history across restarts
Successfully completed queries will be stored on disk and available across restarts. - The query results are contained in global storage. - Metadata and a summary about a query are stored in workspace storage. - There is a job that runs every 2 hours to determine if any queries are old enough to be deleted.
1 parent b7dafc3 commit 29c29f9

14 files changed

Lines changed: 535 additions & 93 deletions

File tree

extensions/ql-vscode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Fix a bug where invoking _View AST_ from the file explorer would not view the selected file. Instead it would view the active editor. Also, prevent the _View AST_ from appearing if the current selection includes a directory or multiple files. [#1113](https://github.com/github/vscode-codeql/pull/1113)
66
- Add query history items as soon as a query is run, including new icons for each history item. [#1094](https://github.com/github/vscode-codeql/pull/1094)
7+
- Save query history items across restarts. Items will be saved for 30 days and can be overwritten by setting the `codeQL.queryHistory.ttl` configuration setting. [???]
78

89
## 1.5.10 - 25 January 2022
910

extensions/ql-vscode/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@
224224
"default": "%q on %d - %s, %r result count [%t]",
225225
"markdownDescription": "Default string for how to label query history items.\n* %t is the time of the query\n* %q is the human-readable query name\n* %f is the query file name\n* %d is the database name\n* %r is the number of results\n* %s is a status string"
226226
},
227+
"codeQL.queryHistory.ttl": {
228+
"type": "number",
229+
"default": 30,
230+
"description": "Number of days to retain queries in the query history before being automatically deleted.",
231+
"scope": "machine"
232+
},
227233
"codeQL.runningTests.additionalTestArguments": {
228234
"scope": "window",
229235
"type": "array",

extensions/ql-vscode/src/config.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { workspace, Event, EventEmitter, ConfigurationChangeEvent, Configuration
33
import { DistributionManager } from './distribution';
44
import { logger } from './logging';
55

6+
const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;
7+
68
/** Helper class to look up a labelled (and possibly nested) setting. */
79
export class Setting {
810
name: string;
@@ -54,8 +56,11 @@ const DISTRIBUTION_SETTING = new Setting('cli', ROOT_SETTING);
5456
export const CUSTOM_CODEQL_PATH_SETTING = new Setting('executablePath', DISTRIBUTION_SETTING);
5557
const INCLUDE_PRERELEASE_SETTING = new Setting('includePrerelease', DISTRIBUTION_SETTING);
5658
const PERSONAL_ACCESS_TOKEN_SETTING = new Setting('personalAccessToken', DISTRIBUTION_SETTING);
59+
60+
// Query History configuration
5761
const QUERY_HISTORY_SETTING = new Setting('queryHistory', ROOT_SETTING);
5862
const QUERY_HISTORY_FORMAT_SETTING = new Setting('format', QUERY_HISTORY_SETTING);
63+
const QUERY_HISTORY_TTL = new Setting('format', QUERY_HISTORY_SETTING);
5964

6065
/** When these settings change, the distribution should be updated. */
6166
const DISTRIBUTION_CHANGE_SETTINGS = [CUSTOM_CODEQL_PATH_SETTING, INCLUDE_PRERELEASE_SETTING, PERSONAL_ACCESS_TOKEN_SETTING];
@@ -71,7 +76,6 @@ export interface DistributionConfig {
7176
}
7277

7378
// Query server configuration
74-
7579
const RUNNING_QUERIES_SETTING = new Setting('runningQueries', ROOT_SETTING);
7680
const NUMBER_OF_THREADS_SETTING = new Setting('numberOfThreads', RUNNING_QUERIES_SETTING);
7781
const SAVE_CACHE_SETTING = new Setting('saveCache', RUNNING_QUERIES_SETTING);
@@ -106,10 +110,11 @@ export interface QueryServerConfig {
106110
}
107111

108112
/** When these settings change, the query history should be refreshed. */
109-
const QUERY_HISTORY_SETTINGS = [QUERY_HISTORY_FORMAT_SETTING];
113+
const QUERY_HISTORY_SETTINGS = [QUERY_HISTORY_FORMAT_SETTING, QUERY_HISTORY_TTL];
110114

111115
export interface QueryHistoryConfig {
112116
format: string;
117+
ttlInMillis: number;
113118
onDidChangeConfiguration: Event<void>;
114119
}
115120

@@ -251,6 +256,13 @@ export class QueryHistoryConfigListener extends ConfigListener implements QueryH
251256
public get format(): string {
252257
return QUERY_HISTORY_FORMAT_SETTING.getValue<string>();
253258
}
259+
260+
/**
261+
* The configuration value is in days, but return the value in milliseconds.
262+
*/
263+
public get ttlInMillis(): number {
264+
return (QUERY_HISTORY_TTL.getValue<number>() || 30) * ONE_DAY_IN_MS;
265+
}
254266
}
255267

256268
export class CliConfigListener extends ConfigListener implements CliConfig {

extensions/ql-vscode/src/contextual/locationFinder.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export async function getLocationsForUriString(
3838
dbm: DatabaseManager,
3939
uriString: string,
4040
keyType: KeyType,
41+
queryStorageLocation: string,
4142
progress: ProgressCallback,
4243
token: CancellationToken,
4344
filter: (src: string, dest: string) => boolean
@@ -69,6 +70,7 @@ export async function getLocationsForUriString(
6970
qs,
7071
db,
7172
initialInfo,
73+
queryStorageLocation,
7274
progress,
7375
token,
7476
templates

extensions/ql-vscode/src/contextual/templateProvider.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export class TemplateQueryDefinitionProvider implements DefinitionProvider {
4242
private cli: CodeQLCliServer,
4343
private qs: QueryServerClient,
4444
private dbm: DatabaseManager,
45+
private queryStorageLocation: string,
4546
) {
4647
this.cache = new CachedOperation<LocationLink[]>(this.getDefinitions.bind(this));
4748
}
@@ -69,6 +70,7 @@ export class TemplateQueryDefinitionProvider implements DefinitionProvider {
6970
this.dbm,
7071
uriString,
7172
KeyType.DefinitionQuery,
73+
this.queryStorageLocation,
7274
progress,
7375
token,
7476
(src, _dest) => src === uriString
@@ -84,6 +86,7 @@ export class TemplateQueryReferenceProvider implements ReferenceProvider {
8486
private cli: CodeQLCliServer,
8587
private qs: QueryServerClient,
8688
private dbm: DatabaseManager,
89+
private queryStorageLocation: string,
8790
) {
8891
this.cache = new CachedOperation<FullLocationLink[]>(this.getReferences.bind(this));
8992
}
@@ -116,6 +119,7 @@ export class TemplateQueryReferenceProvider implements ReferenceProvider {
116119
this.dbm,
117120
uriString,
118121
KeyType.DefinitionQuery,
122+
this.queryStorageLocation,
119123
progress,
120124
token,
121125
(src, _dest) => src === uriString
@@ -136,6 +140,7 @@ export class TemplatePrintAstProvider {
136140
private cli: CodeQLCliServer,
137141
private qs: QueryServerClient,
138142
private dbm: DatabaseManager,
143+
private queryStorageLocation: string,
139144
) {
140145
this.cache = new CachedOperation<QueryWithDb>(this.getAst.bind(this));
141146
}
@@ -216,6 +221,7 @@ export class TemplatePrintAstProvider {
216221
this.qs,
217222
db,
218223
initialInfo,
224+
this.queryStorageLocation,
219225
progress,
220226
token,
221227
templates

extensions/ql-vscode/src/extension.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from 'vscode';
2020
import { LanguageClient } from 'vscode-languageclient';
2121
import * as os from 'os';
22+
import * as fs from 'fs-extra';
2223
import * as path from 'path';
2324
import * as tmp from 'tmp-promise';
2425
import { testExplorerExtensionId, TestHub } from 'vscode-test-adapter-api';
@@ -435,16 +436,21 @@ async function activateWithInstalledDistribution(
435436
ctx.subscriptions.push(queryHistoryConfigurationListener);
436437
const showResults = async (item: FullCompletedQueryInfo) =>
437438
showResultsForCompletedQuery(item, WebviewReveal.Forced);
439+
const queryStorageLocation = path.join(ctx.globalStorageUri.fsPath, 'queries');
440+
await fs.ensureDir(queryStorageLocation);
438441

439442
const qhm = new QueryHistoryManager(
440443
qs,
441444
dbm,
442-
ctx.extensionPath,
445+
queryStorageLocation,
446+
ctx,
443447
queryHistoryConfigurationListener,
444448
showResults,
445449
async (from: FullCompletedQueryInfo, to: FullCompletedQueryInfo) =>
446450
showResultsForComparison(from, to),
447451
);
452+
await qhm.readQueryHistory();
453+
448454
ctx.subscriptions.push(qhm);
449455
void logger.log('Initializing results panel interface.');
450456
const intm = new InterfaceManager(ctx, dbm, cliServer, queryServerLogger);
@@ -513,10 +519,12 @@ async function activateWithInstalledDistribution(
513519
qs,
514520
databaseItem,
515521
initialInfo,
522+
queryStorageLocation,
516523
progress,
517524
source.token,
518525
);
519526
item.completeThisQuery(completedQueryInfo);
527+
await qhm.writeQueryHistory();
520528
await showResultsForCompletedQuery(item as FullCompletedQueryInfo, WebviewReveal.NotForced);
521529
// Note we must update the query history view after showing results as the
522530
// display and sorting might depend on the number of results
@@ -988,16 +996,16 @@ async function activateWithInstalledDistribution(
988996
void logger.log('Registering jump-to-definition handlers.');
989997
languages.registerDefinitionProvider(
990998
{ scheme: archiveFilesystemProvider.zipArchiveScheme },
991-
new TemplateQueryDefinitionProvider(cliServer, qs, dbm)
999+
new TemplateQueryDefinitionProvider(cliServer, qs, dbm, queryStorageLocation)
9921000
);
9931001

9941002
languages.registerReferenceProvider(
9951003
{ scheme: archiveFilesystemProvider.zipArchiveScheme },
996-
new TemplateQueryReferenceProvider(cliServer, qs, dbm)
1004+
new TemplateQueryReferenceProvider(cliServer, qs, dbm, queryStorageLocation)
9971005
);
9981006

9991007
const astViewer = new AstViewer();
1000-
const templateProvider = new TemplatePrintAstProvider(cliServer, qs, dbm);
1008+
const templateProvider = new TemplatePrintAstProvider(cliServer, qs, dbm, queryStorageLocation);
10011009

10021010
ctx.subscriptions.push(astViewer);
10031011
ctx.subscriptions.push(commandRunnerWithProgress('codeQL.viewAst', async (
@@ -1036,7 +1044,7 @@ async function activateWithInstalledDistribution(
10361044
}
10371045

10381046
function getContextStoragePath(ctx: ExtensionContext) {
1039-
return ctx.storagePath || ctx.globalStoragePath;
1047+
return ctx.storageUri?.fsPath || ctx.globalStorageUri.fsPath;
10401048
}
10411049

10421050
async function initializeLogging(ctx: ExtensionContext): Promise<void> {

0 commit comments

Comments
 (0)