@@ -34,6 +34,7 @@ import { QueryLanguage } from "../common/query-language";
3434import { LINE_ENDINGS , splitStreamAtSeparators } from "../common/split-stream" ;
3535import type { Position } from "../query-server/messages" ;
3636import { LOGGING_FLAGS } from "./cli-command" ;
37+ import type { CliFeatures , VersionAndFeatures } from "./cli-version" ;
3738
3839/**
3940 * The version of the SARIF format that we are using.
@@ -203,7 +204,9 @@ type OnLineCallback = (
203204 line : string ,
204205) => Promise < string | undefined > | string | undefined ;
205206
206- type VersionChangedListener = ( newVersion : SemVer | undefined ) => void ;
207+ type VersionChangedListener = (
208+ newVersionAndFeatures : VersionAndFeatures | undefined ,
209+ ) => void ;
207210
208211/**
209212 * This class manages a cli server started by `codeql execute cli-server` to
@@ -221,8 +224,8 @@ export class CodeQLCliServer implements Disposable {
221224 /** A buffer with a single null byte. */
222225 nullBuffer : Buffer ;
223226
224- /** Version of current cli, lazily computed by the `getVersion()` method */
225- private _version : SemVer | undefined ;
227+ /** Version of current cli and its supported features , lazily computed by the `getVersion()` method */
228+ private _versionAndFeatures : VersionAndFeatures | undefined ;
226229
227230 private _versionChangedListeners : VersionChangedListener [ ] = [ ] ;
228231
@@ -298,7 +301,7 @@ export class CodeQLCliServer implements Disposable {
298301 const callback = ( ) : void => {
299302 try {
300303 this . killProcessIfRunning ( ) ;
301- this . _version = undefined ;
304+ this . _versionAndFeatures = undefined ;
302305 this . _supportedLanguages = undefined ;
303306 } finally {
304307 this . runNext ( ) ;
@@ -1427,16 +1430,28 @@ export class CodeQLCliServer implements Disposable {
14271430 ) ;
14281431 }
14291432
1433+ /**
1434+ * Compile a CodeQL pack and bundle it into a single file.
1435+ *
1436+ * @param sourcePackDir The directory of the input CodeQL pack.
1437+ * @param workspaceFolders The workspace folders to search for additional packs.
1438+ * @param outputBundleFile The path to the output bundle file.
1439+ * @param outputPackDir The directory to contain the unbundled output pack.
1440+ * @param moreOptions Additional options to be passed to `codeql pack bundle`.
1441+ */
14301442 async packBundle (
1431- dir : string ,
1443+ sourcePackDir : string ,
14321444 workspaceFolders : string [ ] ,
1433- outputPath : string ,
1445+ outputBundleFile : string ,
1446+ outputPackDir : string ,
14341447 moreOptions : string [ ] ,
14351448 ) : Promise < void > {
14361449 const args = [
14371450 "-o" ,
1438- outputPath ,
1439- dir ,
1451+ outputBundleFile ,
1452+ sourcePackDir ,
1453+ "--pack-path" ,
1454+ outputPackDir ,
14401455 ...moreOptions ,
14411456 ...this . getAdditionalPacksArg ( workspaceFolders ) ,
14421457 ] ;
@@ -1491,27 +1506,35 @@ export class CodeQLCliServer implements Disposable {
14911506 ) ;
14921507 }
14931508
1494- public async getVersion ( ) {
1495- if ( ! this . _version ) {
1509+ public async getVersion ( ) : Promise < SemVer > {
1510+ return ( await this . getVersionAndFeatures ( ) ) . version ;
1511+ }
1512+
1513+ public async getFeatures ( ) : Promise < CliFeatures > {
1514+ return ( await this . getVersionAndFeatures ( ) ) . features ;
1515+ }
1516+
1517+ private async getVersionAndFeatures ( ) : Promise < VersionAndFeatures > {
1518+ if ( ! this . _versionAndFeatures ) {
14961519 try {
1497- const newVersion = await this . refreshVersion ( ) ;
1498- this . _version = newVersion ;
1520+ const newVersionAndFeatures = await this . refreshVersion ( ) ;
1521+ this . _versionAndFeatures = newVersionAndFeatures ;
14991522 this . _versionChangedListeners . forEach ( ( listener ) =>
1500- listener ( newVersion ) ,
1523+ listener ( newVersionAndFeatures ) ,
15011524 ) ;
15021525
15031526 // this._version is only undefined upon config change, so we reset CLI-based context key only when necessary.
15041527 await this . app . commands . execute (
15051528 "setContext" ,
15061529 "codeql.supportsQuickEvalCount" ,
1507- newVersion . compare (
1530+ newVersionAndFeatures . version . compare (
15081531 CliVersionConstraint . CLI_VERSION_WITH_QUICK_EVAL_COUNT ,
15091532 ) >= 0 ,
15101533 ) ;
15111534 await this . app . commands . execute (
15121535 "setContext" ,
15131536 "codeql.supportsTrimCache" ,
1514- newVersion . compare (
1537+ newVersionAndFeatures . version . compare (
15151538 CliVersionConstraint . CLI_VERSION_WITH_TRIM_CACHE ,
15161539 ) >= 0 ,
15171540 ) ;
@@ -1522,23 +1545,23 @@ export class CodeQLCliServer implements Disposable {
15221545 throw e ;
15231546 }
15241547 }
1525- return this . _version ;
1548+ return this . _versionAndFeatures ;
15261549 }
15271550
15281551 public addVersionChangedListener ( listener : VersionChangedListener ) {
1529- if ( this . _version ) {
1530- listener ( this . _version ) ;
1552+ if ( this . _versionAndFeatures ) {
1553+ listener ( this . _versionAndFeatures ) ;
15311554 }
15321555 this . _versionChangedListeners . push ( listener ) ;
15331556 }
15341557
1535- private async refreshVersion ( ) {
1558+ private async refreshVersion ( ) : Promise < VersionAndFeatures > {
15361559 const distribution = await this . distributionProvider . getDistribution ( ) ;
15371560 switch ( distribution . kind ) {
15381561 case FindDistributionResultKind . CompatibleDistribution :
15391562 // eslint-disable-next-line no-fallthrough -- Intentional fallthrough
15401563 case FindDistributionResultKind . IncompatibleDistribution :
1541- return distribution . version ;
1564+ return distribution . versionAndFeatures ;
15421565
15431566 default :
15441567 // We should not get here because if no distributions are available, then
@@ -1755,4 +1778,8 @@ export class CliVersionConstraint {
17551778 CliVersionConstraint . CLI_VERSION_WITH_EXTENSIBLE_PREDICATE_METADATA ,
17561779 ) ;
17571780 }
1781+
1782+ async supportsMrvaPackCreate ( ) : Promise < boolean > {
1783+ return ( await this . cli . getFeatures ( ) ) . mrvaPackCreate === true ;
1784+ }
17581785}
0 commit comments