Add version info to cli
And also only add the `--kind=DIL` to `generateDil` if version is >= 2.3.0.
This commit is contained in:
@@ -4,15 +4,16 @@ import * as child_process from 'child_process';
|
|||||||
import * as fs from 'fs-extra';
|
import * as fs from 'fs-extra';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as sarif from 'sarif';
|
import * as sarif from 'sarif';
|
||||||
|
import { SemVer } from 'semver';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import { StringDecoder } from 'string_decoder';
|
import { StringDecoder } from 'string_decoder';
|
||||||
import * as tk from 'tree-kill';
|
import * as tk from 'tree-kill';
|
||||||
import * as util from 'util';
|
import { promisify } from 'util';
|
||||||
import { CancellationToken, Disposable } from 'vscode';
|
import { CancellationToken, Disposable } from 'vscode';
|
||||||
|
|
||||||
import { BQRSInfo, DecodedBqrsChunk } from './bqrs-cli-types';
|
import { BQRSInfo, DecodedBqrsChunk } from './bqrs-cli-types';
|
||||||
import { CliConfig } from './config';
|
import { CliConfig } from './config';
|
||||||
import { DistributionProvider } from './distribution';
|
import { DistributionProvider, FindDistributionResultKind } from './distribution';
|
||||||
import { assertNever } from './helpers-pure';
|
import { assertNever } from './helpers-pure';
|
||||||
import { QueryMetadata, SortDirection } from './interface-types';
|
import { QueryMetadata, SortDirection } from './interface-types';
|
||||||
import { Logger, ProgressReporter } from './logging';
|
import { Logger, ProgressReporter } from './logging';
|
||||||
@@ -115,6 +116,11 @@ interface BqrsDecodeOptions {
|
|||||||
*/
|
*/
|
||||||
export class CodeQLCliServer implements Disposable {
|
export class CodeQLCliServer implements Disposable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CLI version where --kind=DIL was introduced
|
||||||
|
*/
|
||||||
|
private static CLI_VERSION_WITH_DECOMPILE_KIND_DIL = new SemVer('2.3.0');
|
||||||
|
|
||||||
/** The process for the cli server, or undefined if one doesn't exist yet */
|
/** The process for the cli server, or undefined if one doesn't exist yet */
|
||||||
process?: child_process.ChildProcessWithoutNullStreams;
|
process?: child_process.ChildProcessWithoutNullStreams;
|
||||||
/** Queue of future commands*/
|
/** Queue of future commands*/
|
||||||
@@ -124,6 +130,12 @@ export class CodeQLCliServer implements Disposable {
|
|||||||
/** A buffer with a single null byte. */
|
/** A buffer with a single null byte. */
|
||||||
nullBuffer: Buffer;
|
nullBuffer: Buffer;
|
||||||
|
|
||||||
|
/** Version of current cli, lazily computed by the `getVersion()` method */
|
||||||
|
_version: SemVer | undefined;
|
||||||
|
|
||||||
|
/** Path to current codeQL executable, or undefined if not running yet. */
|
||||||
|
codeQlPath: string | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private distributionProvider: DistributionProvider,
|
private distributionProvider: DistributionProvider,
|
||||||
private cliConfig: CliConfig,
|
private cliConfig: CliConfig,
|
||||||
@@ -140,11 +152,11 @@ export class CodeQLCliServer implements Disposable {
|
|||||||
if (this.cliConfig.onDidChangeConfiguration) {
|
if (this.cliConfig.onDidChangeConfiguration) {
|
||||||
this.cliConfig.onDidChangeConfiguration(() => {
|
this.cliConfig.onDidChangeConfiguration(() => {
|
||||||
this.restartCliServer();
|
this.restartCliServer();
|
||||||
|
this._version = undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
this.killProcessIfRunning();
|
this.killProcessIfRunning();
|
||||||
}
|
}
|
||||||
@@ -210,9 +222,9 @@ export class CodeQLCliServer implements Disposable {
|
|||||||
* Launch the cli server
|
* Launch the cli server
|
||||||
*/
|
*/
|
||||||
private async launchProcess(): Promise<child_process.ChildProcessWithoutNullStreams> {
|
private async launchProcess(): Promise<child_process.ChildProcessWithoutNullStreams> {
|
||||||
const config = await this.getCodeQlPath();
|
const codeQlPath = await this.getCodeQlPath();
|
||||||
return spawnServer(
|
return await spawnServer(
|
||||||
config,
|
codeQlPath,
|
||||||
'CodeQL CLI Server',
|
'CodeQL CLI Server',
|
||||||
['execute', 'cli-server'],
|
['execute', 'cli-server'],
|
||||||
[],
|
[],
|
||||||
@@ -671,12 +683,37 @@ export class CodeQLCliServer implements Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generateDil(qloFile: string, outFile: string): Promise<void> {
|
async generateDil(qloFile: string, outFile: string): Promise<void> {
|
||||||
|
const extraArgs = (await this.getVersion()).compare(CodeQLCliServer.CLI_VERSION_WITH_DECOMPILE_KIND_DIL) >= 0
|
||||||
|
? ['--kind', 'dil', '-o', outFile, qloFile]
|
||||||
|
: ['-o', outFile, qloFile];
|
||||||
await this.runCodeQlCliCommand(
|
await this.runCodeQlCliCommand(
|
||||||
['query', 'decompile'],
|
['query', 'decompile'],
|
||||||
['-o', outFile, qloFile],
|
extraArgs,
|
||||||
'Generating DIL',
|
'Generating DIL',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async getVersion() {
|
||||||
|
if (!this._version) {
|
||||||
|
this._version = await this.refreshVersion();
|
||||||
|
}
|
||||||
|
return this._version;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async refreshVersion() {
|
||||||
|
const distribution = await this.distributionProvider.getDistribution();
|
||||||
|
switch(distribution.kind) {
|
||||||
|
case FindDistributionResultKind.CompatibleDistribution:
|
||||||
|
// eslint-disable-next-line no-fallthrough
|
||||||
|
case FindDistributionResultKind.IncompatibleDistribution:
|
||||||
|
return distribution.version;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// We should not get here because if no distributions are available, then
|
||||||
|
// the cli class is never instantiated.
|
||||||
|
throw new Error('No distribution found');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -734,7 +771,7 @@ export function spawnServer(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a CodeQL CLI command without invoking the CLI server, returning the output as a string.
|
* Runs a CodeQL CLI command without invoking the CLI server, returning the output as a string.
|
||||||
* @param config The configuration containing the path to the CLI.
|
* @param codeQlPath The path to the CLI.
|
||||||
* @param command The `codeql` command to be run, provided as an array of command/subcommand names.
|
* @param command The `codeql` command to be run, provided as an array of command/subcommand names.
|
||||||
* @param commandArgs The arguments to pass to the `codeql` command.
|
* @param commandArgs The arguments to pass to the `codeql` command.
|
||||||
* @param description Description of the action being run, to be shown in log and error messages.
|
* @param description Description of the action being run, to be shown in log and error messages.
|
||||||
@@ -742,7 +779,14 @@ export function spawnServer(
|
|||||||
* @param progressReporter Used to output progress messages, e.g. to the status bar.
|
* @param progressReporter Used to output progress messages, e.g. to the status bar.
|
||||||
* @returns The contents of the command's stdout, if the command succeeded.
|
* @returns The contents of the command's stdout, if the command succeeded.
|
||||||
*/
|
*/
|
||||||
export async function runCodeQlCliCommand(codeQlPath: string, command: string[], commandArgs: string[], description: string, logger: Logger, progressReporter?: ProgressReporter): Promise<string> {
|
export async function runCodeQlCliCommand(
|
||||||
|
codeQlPath: string,
|
||||||
|
command: string[],
|
||||||
|
commandArgs: string[],
|
||||||
|
description: string,
|
||||||
|
logger: Logger,
|
||||||
|
progressReporter?: ProgressReporter
|
||||||
|
): Promise<string> {
|
||||||
// Add logging arguments first, in case commandArgs contains positional parameters.
|
// Add logging arguments first, in case commandArgs contains positional parameters.
|
||||||
const args = command.concat(LOGGING_FLAGS).concat(commandArgs);
|
const args = command.concat(LOGGING_FLAGS).concat(commandArgs);
|
||||||
const argsString = args.join(' ');
|
const argsString = args.join(' ');
|
||||||
@@ -751,7 +795,7 @@ export async function runCodeQlCliCommand(codeQlPath: string, command: string[],
|
|||||||
progressReporter.report({ message: description });
|
progressReporter.report({ message: description });
|
||||||
}
|
}
|
||||||
logger.log(`${description} using CodeQL CLI: ${codeQlPath} ${argsString}...`);
|
logger.log(`${description} using CodeQL CLI: ${codeQlPath} ${argsString}...`);
|
||||||
const result = await util.promisify(child_process.execFile)(codeQlPath, args);
|
const result = await promisify(child_process.execFile)(codeQlPath, args);
|
||||||
logger.log(result.stderr);
|
logger.log(result.stderr);
|
||||||
logger.log('CLI command succeeded.');
|
logger.log('CLI command succeeded.');
|
||||||
return result.stdout;
|
return result.stdout;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export const DEFAULT_DISTRIBUTION_VERSION_RANGE: semver.Range = new semver.Range
|
|||||||
export interface DistributionProvider {
|
export interface DistributionProvider {
|
||||||
getCodeQlPathWithoutVersionCheck(): Promise<string | undefined>;
|
getCodeQlPathWithoutVersionCheck(): Promise<string | undefined>;
|
||||||
onDidChangeDistribution?: Event<void>;
|
onDidChangeDistribution?: Event<void>;
|
||||||
|
getDistribution(): Promise<FindDistributionResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DistributionManager implements DistributionProvider {
|
export class DistributionManager implements DistributionProvider {
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ import * as path from 'path';
|
|||||||
import * as tmp from 'tmp';
|
import * as tmp from 'tmp';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import { CancellationTokenSource } from 'vscode-jsonrpc';
|
import { CancellationTokenSource } from 'vscode-jsonrpc';
|
||||||
import * as messages from '../../src/messages';
|
import * as messages from '../../messages';
|
||||||
import * as qsClient from '../../src/queryserver-client';
|
import * as qsClient from '../../queryserver-client';
|
||||||
import * as cli from '../../src/cli';
|
import * as cli from '../../cli';
|
||||||
import { ProgressReporter, Logger } from '../../src/logging';
|
import { ProgressReporter, Logger } from '../../logging';
|
||||||
import { ColumnValue } from '../../src/bqrs-cli-types';
|
import { ColumnValue } from '../../bqrs-cli-types';
|
||||||
|
import { FindDistributionResultKind } from '../../distribution';
|
||||||
|
|
||||||
|
|
||||||
declare module 'url' {
|
declare module 'url' {
|
||||||
@@ -114,6 +115,11 @@ describe('using the query server', function() {
|
|||||||
async getCodeQlPathWithoutVersionCheck(): Promise<string | undefined> {
|
async getCodeQlPathWithoutVersionCheck(): Promise<string | undefined> {
|
||||||
return codeQlPath;
|
return codeQlPath;
|
||||||
},
|
},
|
||||||
|
getDistribution: async () => {
|
||||||
|
return {
|
||||||
|
kind: FindDistributionResultKind.NoDistribution
|
||||||
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
numberTestThreads: 2
|
numberTestThreads: 2
|
||||||
Reference in New Issue
Block a user