Merge pull request #2054 from github/koesie10/codeql-pack-yml
Handle `codeql-pack.yml` files everywhere
This commit is contained in:
@@ -19,6 +19,7 @@ import { CancellationToken, Uri } from "vscode";
|
||||
import { ProgressCallback } from "../commandRunner";
|
||||
import { QueryRunner } from "../queryRunner";
|
||||
import { redactableError } from "../pure/errors";
|
||||
import { QLPACK_FILENAMES } from "../pure/ql";
|
||||
|
||||
export async function qlpackOfDatabase(
|
||||
cli: CodeQLCliServer,
|
||||
@@ -113,7 +114,7 @@ async function resolveContextualQuery(
|
||||
// Work out the enclosing pack.
|
||||
const packContents = await cli.packPacklist(query, false);
|
||||
const packFilePath = packContents.find((p) =>
|
||||
["codeql-pack.yml", "qlpack.yml"].includes(basename(p)),
|
||||
QLPACK_FILENAMES.includes(basename(p)),
|
||||
);
|
||||
if (packFilePath === undefined) {
|
||||
// Should not happen; we already resolved this query.
|
||||
|
||||
@@ -845,6 +845,7 @@ async function activateWithInstalledDistribution(
|
||||
documentSelector: [
|
||||
{ language: "ql", scheme: "file" },
|
||||
{ language: "yaml", scheme: "file", pattern: "**/qlpack.yml" },
|
||||
{ language: "yaml", scheme: "file", pattern: "**/codeql-pack.yml" },
|
||||
],
|
||||
synchronize: {
|
||||
configurationSection: "codeQL",
|
||||
|
||||
@@ -23,6 +23,7 @@ import { extLogger, OutputChannelLogger } from "./common";
|
||||
import { QueryMetadata } from "./pure/interface-types";
|
||||
import { telemetryListener } from "./telemetry";
|
||||
import { RedactableError } from "./pure/errors";
|
||||
import { getQlPackPath } from "./pure/ql";
|
||||
|
||||
// Shared temporary folder for the extension.
|
||||
export const tmpDir = dirSync({
|
||||
@@ -387,17 +388,22 @@ async function findDbschemePack(
|
||||
): Promise<{ name: string; isLibraryPack: boolean }> {
|
||||
for (const { packDir, packName } of packs) {
|
||||
if (packDir !== undefined) {
|
||||
const qlpack = load(
|
||||
await readFile(join(packDir, "qlpack.yml"), "utf8"),
|
||||
) as { dbscheme?: string; library?: boolean };
|
||||
if (
|
||||
qlpack.dbscheme !== undefined &&
|
||||
basename(qlpack.dbscheme) === basename(dbschemePath)
|
||||
) {
|
||||
return {
|
||||
name: packName,
|
||||
isLibraryPack: qlpack.library === true,
|
||||
const qlpackPath = await getQlPackPath(packDir);
|
||||
|
||||
if (qlpackPath !== undefined) {
|
||||
const qlpack = load(await readFile(qlpackPath, "utf8")) as {
|
||||
dbscheme?: string;
|
||||
library?: boolean;
|
||||
};
|
||||
if (
|
||||
qlpack.dbscheme !== undefined &&
|
||||
basename(qlpack.dbscheme) === basename(dbschemePath)
|
||||
) {
|
||||
return {
|
||||
name: packName,
|
||||
isLibraryPack: qlpack.library === true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
extensions/ql-vscode/src/pure/ql.ts
Normal file
19
extensions/ql-vscode/src/pure/ql.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { join } from "path";
|
||||
import { pathExists } from "fs-extra";
|
||||
|
||||
export const QLPACK_FILENAMES = ["qlpack.yml", "codeql-pack.yml"];
|
||||
export const FALLBACK_QLPACK_FILENAME = QLPACK_FILENAMES[0];
|
||||
|
||||
export async function getQlPackPath(
|
||||
packRoot: string,
|
||||
): Promise<string | undefined> {
|
||||
for (const filename of QLPACK_FILENAMES) {
|
||||
const path = join(packRoot, filename);
|
||||
|
||||
if (await pathExists(path)) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from "./helpers";
|
||||
import { ProgressCallback, UserCancellationException } from "./commandRunner";
|
||||
import { getErrorMessage } from "./pure/helpers-pure";
|
||||
import { FALLBACK_QLPACK_FILENAME, getQlPackPath } from "./pure/ql";
|
||||
|
||||
const QUICK_QUERIES_DIR_NAME = "quick-queries";
|
||||
const QUICK_QUERY_QUERY_NAME = "quick-query.ql";
|
||||
@@ -112,7 +113,7 @@ export async function displayQuickQuery(
|
||||
const dbscheme = await getPrimaryDbscheme(datasetFolder);
|
||||
const qlpack = (await getQlPackForDbscheme(cliServer, dbscheme))
|
||||
.dbschemePack;
|
||||
const qlPackFile = join(queriesDir, "qlpack.yml");
|
||||
const qlPackFile = await getQlPackPath(queriesDir);
|
||||
const qlFile = join(queriesDir, QUICK_QUERY_QUERY_NAME);
|
||||
const shouldRewrite = await checkShouldRewrite(qlPackFile, qlpack);
|
||||
|
||||
@@ -126,7 +127,7 @@ export async function displayQuickQuery(
|
||||
},
|
||||
};
|
||||
await writeFile(
|
||||
qlPackFile,
|
||||
qlPackFile ?? join(queriesDir, FALLBACK_QLPACK_FILENAME),
|
||||
QLPACK_FILE_HEADER + dump(quickQueryQlpackYaml),
|
||||
"utf8",
|
||||
);
|
||||
@@ -158,7 +159,13 @@ export async function displayQuickQuery(
|
||||
}
|
||||
}
|
||||
|
||||
async function checkShouldRewrite(qlPackFile: string, newDependency: string) {
|
||||
async function checkShouldRewrite(
|
||||
qlPackFile: string | undefined,
|
||||
newDependency: string,
|
||||
) {
|
||||
if (!qlPackFile) {
|
||||
return true;
|
||||
}
|
||||
if (!(await pathExists(qlPackFile))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CancellationToken, Uri, window } from "vscode";
|
||||
import { relative, join, sep, dirname, parse, basename } from "path";
|
||||
import { dump, load } from "js-yaml";
|
||||
import { pathExists, copy, writeFile, readFile, mkdirp } from "fs-extra";
|
||||
import { copy, writeFile, readFile, mkdirp } from "fs-extra";
|
||||
import { dir, tmpName } from "tmp-promise";
|
||||
import {
|
||||
askForLanguage,
|
||||
@@ -30,6 +30,11 @@ import {
|
||||
} from "./repository-selection";
|
||||
import { Repository } from "./shared/repository";
|
||||
import { DbManager } from "../databases/db-manager";
|
||||
import {
|
||||
getQlPackPath,
|
||||
FALLBACK_QLPACK_FILENAME,
|
||||
QLPACK_FILENAMES,
|
||||
} from "../pure/ql";
|
||||
|
||||
export interface QlPack {
|
||||
name: string;
|
||||
@@ -67,7 +72,7 @@ async function generateQueryPack(
|
||||
const targetQueryFileName = join(queryPackDir, packRelativePath);
|
||||
|
||||
let language: string | undefined;
|
||||
if (await getExistingPackFile(originalPackRoot)) {
|
||||
if (await getQlPackPath(originalPackRoot)) {
|
||||
// don't include ql files. We only want the queryFile to be copied.
|
||||
const toCopy = await cliServer.packPacklist(originalPackRoot, false);
|
||||
|
||||
@@ -120,7 +125,10 @@ async function generateQueryPack(
|
||||
},
|
||||
defaultSuite: generateDefaultSuite(packRelativePath),
|
||||
};
|
||||
await writeFile(join(queryPackDir, "qlpack.yml"), dump(syntheticQueryPack));
|
||||
await writeFile(
|
||||
join(queryPackDir, FALLBACK_QLPACK_FILENAME),
|
||||
dump(syntheticQueryPack),
|
||||
);
|
||||
}
|
||||
if (!language) {
|
||||
throw new UserCancellationException("Could not determine language.");
|
||||
@@ -163,7 +171,7 @@ async function generateQueryPack(
|
||||
async function findPackRoot(queryFile: string): Promise<string> {
|
||||
// recursively find the directory containing qlpack.yml
|
||||
let dir = dirname(queryFile);
|
||||
while (!(await getExistingPackFile(dir))) {
|
||||
while (!(await getQlPackPath(dir))) {
|
||||
dir = dirname(dir);
|
||||
if (isFileSystemRoot(dir)) {
|
||||
// there is no qlpack.yml in this directory or any parent directory.
|
||||
@@ -175,16 +183,6 @@ async function findPackRoot(queryFile: string): Promise<string> {
|
||||
return dir;
|
||||
}
|
||||
|
||||
async function getExistingPackFile(dir: string) {
|
||||
if (await pathExists(join(dir, "qlpack.yml"))) {
|
||||
return join(dir, "qlpack.yml");
|
||||
}
|
||||
if (await pathExists(join(dir, "codeql-pack.yml"))) {
|
||||
return join(dir, "codeql-pack.yml");
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isFileSystemRoot(dir: string): boolean {
|
||||
const pathObj = parse(dir);
|
||||
return pathObj.root === dir && pathObj.base === "";
|
||||
@@ -319,12 +317,14 @@ async function fixPackFile(
|
||||
queryPackDir: string,
|
||||
packRelativePath: string,
|
||||
): Promise<void> {
|
||||
const packPath = await getExistingPackFile(queryPackDir);
|
||||
const packPath = await getQlPackPath(queryPackDir);
|
||||
|
||||
// This should not happen since we create the pack ourselves.
|
||||
if (!packPath) {
|
||||
throw new Error(
|
||||
`Could not find qlpack.yml or codeql-pack.yml file in '${queryPackDir}'`,
|
||||
`Could not find ${QLPACK_FILENAMES.join(
|
||||
" or ",
|
||||
)} file in '${queryPackDir}'`,
|
||||
);
|
||||
}
|
||||
const qlpack = load(await readFile(packPath, "utf8")) as QlPack;
|
||||
|
||||
48
extensions/ql-vscode/test/unit-tests/pure/ql.test.ts
Normal file
48
extensions/ql-vscode/test/unit-tests/pure/ql.test.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { join } from "path";
|
||||
import { dirSync } from "tmp-promise";
|
||||
import { DirResult } from "tmp";
|
||||
import { writeFile } from "fs-extra";
|
||||
import { getQlPackPath } from "../../../src/pure/ql";
|
||||
|
||||
describe("getQlPackPath", () => {
|
||||
let tmpDir: DirResult;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = dirSync({
|
||||
prefix: "queries_",
|
||||
keep: false,
|
||||
unsafeCleanup: true,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tmpDir.removeCallback();
|
||||
});
|
||||
|
||||
it("should find a qlpack.yml when it exists", async () => {
|
||||
await writeFile(join(tmpDir.name, "qlpack.yml"), "name: test");
|
||||
|
||||
const result = await getQlPackPath(tmpDir.name);
|
||||
expect(result).toEqual(join(tmpDir.name, "qlpack.yml"));
|
||||
});
|
||||
|
||||
it("should find a codeql-pack.yml when it exists", async () => {
|
||||
await writeFile(join(tmpDir.name, "codeql-pack.yml"), "name: test");
|
||||
|
||||
const result = await getQlPackPath(tmpDir.name);
|
||||
expect(result).toEqual(join(tmpDir.name, "codeql-pack.yml"));
|
||||
});
|
||||
|
||||
it("should find a qlpack.yml when both exist", async () => {
|
||||
await writeFile(join(tmpDir.name, "qlpack.yml"), "name: test");
|
||||
await writeFile(join(tmpDir.name, "codeql-pack.yml"), "name: test");
|
||||
|
||||
const result = await getQlPackPath(tmpDir.name);
|
||||
expect(result).toEqual(join(tmpDir.name, "qlpack.yml"));
|
||||
});
|
||||
|
||||
it("should find nothing when it doesn't exist", async () => {
|
||||
const result = await getQlPackPath(tmpDir.name);
|
||||
expect(result).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user