Use version ranges instead of version constraint for simplicity
This commit is contained in:
Родитель
577ce95cb1
Коммит
7b9e540332
|
@ -36,14 +36,11 @@ const DEFAULT_DISTRIBUTION_OWNER_NAME = "github";
|
|||
const DEFAULT_DISTRIBUTION_REPOSITORY_NAME = "codeql-cli-binaries";
|
||||
|
||||
/**
|
||||
* Version constraint for the CLI.
|
||||
* Range of versions of the CLI that are compatible with the extension.
|
||||
*
|
||||
* This applies to both extension-managed and CLI distributions.
|
||||
*/
|
||||
export const DEFAULT_DISTRIBUTION_VERSION_CONSTRAINT: VersionConstraint = {
|
||||
description: "2.*.*",
|
||||
isVersionCompatible: (v: semver.SemVer) => semver.satisfies(v, "2.x")
|
||||
};
|
||||
export const DEFAULT_DISTRIBUTION_VERSION_RANGE: semver.Range = new semver.Range("2.x");
|
||||
|
||||
export interface DistributionProvider {
|
||||
getCodeQlPathWithoutVersionCheck(): Promise<string | undefined>;
|
||||
|
@ -51,16 +48,16 @@ export interface DistributionProvider {
|
|||
}
|
||||
|
||||
export class DistributionManager implements DistributionProvider {
|
||||
constructor(extensionContext: ExtensionContext, config: DistributionConfig, versionConstraint: VersionConstraint) {
|
||||
constructor(extensionContext: ExtensionContext, config: DistributionConfig, versionRange: semver.Range) {
|
||||
this._config = config;
|
||||
this._extensionSpecificDistributionManager = new ExtensionSpecificDistributionManager(extensionContext, config, versionConstraint);
|
||||
this._extensionSpecificDistributionManager = new ExtensionSpecificDistributionManager(extensionContext, config, versionRange);
|
||||
this._onDidChangeDistribution = config.onDidChangeDistributionConfiguration;
|
||||
this._updateCheckRateLimiter = new InvocationRateLimiter(
|
||||
extensionContext,
|
||||
"extensionSpecificDistributionUpdateCheck",
|
||||
() => this._extensionSpecificDistributionManager.checkForUpdatesToDistribution()
|
||||
);
|
||||
this._versionConstraint = versionConstraint;
|
||||
this._versionRange = versionRange;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,19 +71,19 @@ export class DistributionManager implements DistributionProvider {
|
|||
};
|
||||
}
|
||||
const version = await getCodeQlCliVersion(codeQlPath, logger);
|
||||
if (version !== undefined && !this._versionConstraint.isVersionCompatible(version)) {
|
||||
return {
|
||||
codeQlPath,
|
||||
kind: FindDistributionResultKind.IncompatibleDistribution,
|
||||
version,
|
||||
};
|
||||
}
|
||||
if (version === undefined) {
|
||||
return {
|
||||
codeQlPath,
|
||||
kind: FindDistributionResultKind.UnknownCompatibilityDistribution,
|
||||
};
|
||||
}
|
||||
if (!semver.satisfies(version, this._versionRange)) {
|
||||
return {
|
||||
codeQlPath,
|
||||
kind: FindDistributionResultKind.IncompatibleDistribution,
|
||||
version,
|
||||
};
|
||||
}
|
||||
return {
|
||||
codeQlPath,
|
||||
kind: FindDistributionResultKind.CompatibleDistribution,
|
||||
|
@ -197,14 +194,14 @@ export class DistributionManager implements DistributionProvider {
|
|||
private readonly _extensionSpecificDistributionManager: ExtensionSpecificDistributionManager;
|
||||
private readonly _updateCheckRateLimiter: InvocationRateLimiter<DistributionUpdateCheckResult>;
|
||||
private readonly _onDidChangeDistribution: Event<void> | undefined;
|
||||
private readonly _versionConstraint: VersionConstraint;
|
||||
private readonly _versionRange: semver.Range;
|
||||
}
|
||||
|
||||
class ExtensionSpecificDistributionManager {
|
||||
constructor(extensionContext: ExtensionContext, config: DistributionConfig, versionConstraint: VersionConstraint) {
|
||||
constructor(extensionContext: ExtensionContext, config: DistributionConfig, versionRange: semver.Range) {
|
||||
this._extensionContext = extensionContext;
|
||||
this._config = config;
|
||||
this._versionConstraint = versionConstraint;
|
||||
this._versionRange = versionRange;
|
||||
}
|
||||
|
||||
public async getCodeQlPathWithoutVersionCheck(): Promise<string | undefined> {
|
||||
|
@ -325,7 +322,7 @@ class ExtensionSpecificDistributionManager {
|
|||
}
|
||||
|
||||
private async getLatestRelease(): Promise<Release> {
|
||||
const release = await this.createReleasesApiConsumer().getLatestRelease(this._versionConstraint, this._config.includePrerelease);
|
||||
const release = await this.createReleasesApiConsumer().getLatestRelease(this._versionRange, this._config.includePrerelease);
|
||||
// FIXME: Look for platform-specific codeql distribution if available
|
||||
release.assets = release.assets.filter(asset => asset.name === 'codeql.zip');
|
||||
if (release.assets.length === 0) {
|
||||
|
@ -373,7 +370,7 @@ class ExtensionSpecificDistributionManager {
|
|||
|
||||
private readonly _config: DistributionConfig;
|
||||
private readonly _extensionContext: ExtensionContext;
|
||||
private readonly _versionConstraint: VersionConstraint;
|
||||
private readonly _versionRange: semver.Range;
|
||||
|
||||
private static readonly _currentDistributionFolderBaseName = "distribution";
|
||||
private static readonly _currentDistributionFolderIndexStateKey = "distributionFolderIndex";
|
||||
|
@ -394,7 +391,7 @@ export class ReleasesApiConsumer {
|
|||
this._repoName = repoName;
|
||||
}
|
||||
|
||||
public async getLatestRelease(versionConstraint: VersionConstraint, includePrerelease = false): Promise<Release> {
|
||||
public async getLatestRelease(versionRange: semver.Range, includePrerelease = false): Promise<Release> {
|
||||
const apiPath = `/repos/${this._ownerName}/${this._repoName}/releases`;
|
||||
const allReleases: GithubRelease[] = await (await this.makeApiCall(apiPath)).json();
|
||||
const compatibleReleases = allReleases.filter(release => {
|
||||
|
@ -403,7 +400,7 @@ export class ReleasesApiConsumer {
|
|||
}
|
||||
|
||||
const version = semver.parse(release.tag_name);
|
||||
return version !== null && versionConstraint.isVersionCompatible(version);
|
||||
return version !== null && semver.satisfies(version, versionRange);
|
||||
});
|
||||
// Tag names must all be parsable to semvers due to the previous filtering step.
|
||||
const latestRelease = compatibleReleases.sort((a, b) => {
|
||||
|
@ -739,11 +736,6 @@ export interface GithubReleaseAsset {
|
|||
size: number;
|
||||
}
|
||||
|
||||
interface VersionConstraint {
|
||||
description: string;
|
||||
isVersionCompatible(version: semver.SemVer): boolean;
|
||||
}
|
||||
|
||||
export class GithubApiError extends Error {
|
||||
constructor(public status: number, public body: string) {
|
||||
super(`API call failed with status code ${status}, body: ${body}`);
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as languageSupport from './languageSupport';
|
|||
import { DatabaseManager } from './databases';
|
||||
import { DatabaseUI } from './databases-ui';
|
||||
import { TemplateQueryDefinitionProvider, TemplateQueryReferenceProvider } from './definitions';
|
||||
import { DEFAULT_DISTRIBUTION_VERSION_CONSTRAINT, DistributionManager, DistributionUpdateCheckResultKind, FindDistributionResult, FindDistributionResultKind, GithubApiError, GithubRateLimitedError } from './distribution';
|
||||
import { DEFAULT_DISTRIBUTION_VERSION_RANGE, DistributionManager, DistributionUpdateCheckResultKind, FindDistributionResult, FindDistributionResultKind, GithubApiError, GithubRateLimitedError } from './distribution';
|
||||
import * as helpers from './helpers';
|
||||
import { assertNever } from './helpers-pure';
|
||||
import { spawnIdeServer } from './ide-server';
|
||||
|
@ -83,7 +83,7 @@ export async function activate(ctx: ExtensionContext): Promise<void> {
|
|||
|
||||
const distributionConfigListener = new DistributionConfigListener();
|
||||
ctx.subscriptions.push(distributionConfigListener);
|
||||
const distributionManager = new DistributionManager(ctx, distributionConfigListener, DEFAULT_DISTRIBUTION_VERSION_CONSTRAINT);
|
||||
const distributionManager = new DistributionManager(ctx, distributionConfigListener, DEFAULT_DISTRIBUTION_VERSION_RANGE);
|
||||
|
||||
const shouldUpdateOnNextActivationKey = "shouldUpdateOnNextActivation";
|
||||
|
||||
|
|
|
@ -51,10 +51,7 @@ describe("Releases API consumer", () => {
|
|||
"tag_name": "v3.1.2-pre"
|
||||
},
|
||||
];
|
||||
const unconstrainedVersionConstraint = {
|
||||
description: "*",
|
||||
isVersionCompatible: () => true
|
||||
};
|
||||
const unconstrainedVersionRange = new semver.Range("*");
|
||||
|
||||
it("picking latest release: is based on version", async () => {
|
||||
class MockReleasesApiConsumer extends ReleasesApiConsumer {
|
||||
|
@ -68,11 +65,11 @@ describe("Releases API consumer", () => {
|
|||
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const latestRelease = await consumer.getLatestRelease(unconstrainedVersionConstraint);
|
||||
const latestRelease = await consumer.getLatestRelease(unconstrainedVersionRange);
|
||||
expect(latestRelease.id).to.equal(2);
|
||||
});
|
||||
|
||||
it("picking latest release: obeys version constraints", async () => {
|
||||
it("picking latest release: version satisfies version range", async () => {
|
||||
class MockReleasesApiConsumer extends ReleasesApiConsumer {
|
||||
protected async makeApiCall(apiPath: string): Promise<fetch.Response> {
|
||||
if (apiPath === `/repos/${owner}/${repo}/releases`) {
|
||||
|
@ -84,10 +81,7 @@ describe("Releases API consumer", () => {
|
|||
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const latestRelease = await consumer.getLatestRelease({
|
||||
description: "2.*.*",
|
||||
isVersionCompatible: version => semver.satisfies(version, "2.x")
|
||||
});
|
||||
const latestRelease = await consumer.getLatestRelease(new semver.Range("2.*.*"));
|
||||
expect(latestRelease.id).to.equal(1);
|
||||
});
|
||||
|
||||
|
@ -103,7 +97,7 @@ describe("Releases API consumer", () => {
|
|||
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const latestRelease = await consumer.getLatestRelease(unconstrainedVersionConstraint, true);
|
||||
const latestRelease = await consumer.getLatestRelease(unconstrainedVersionRange, true);
|
||||
expect(latestRelease.id).to.equal(4);
|
||||
});
|
||||
|
||||
|
@ -141,7 +135,7 @@ describe("Releases API consumer", () => {
|
|||
|
||||
const consumer = new MockReleasesApiConsumer(owner, repo);
|
||||
|
||||
const assets = (await consumer.getLatestRelease(unconstrainedVersionConstraint)).assets;
|
||||
const assets = (await consumer.getLatestRelease(unconstrainedVersionRange)).assets;
|
||||
|
||||
expect(assets.length).to.equal(expectedAssets.length);
|
||||
expectedAssets.map((expectedAsset, index) => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче