-
Notifications
You must be signed in to change notification settings - Fork 239
Expand file tree
/
Copy pathstandard-queries.ts
More file actions
82 lines (74 loc) · 2.99 KB
/
Copy pathstandard-queries.ts
File metadata and controls
82 lines (74 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import type { CodeQLCliServer } from "../codeql-cli/cli";
import { QLPACK_FILENAMES, QLPACK_LOCK_FILENAMES } from "../common/ql";
import { basename, dirname, resolve } from "path";
import { extLogger } from "../common/logging/vscode";
import { pathExists, promises } from "fs-extra";
import type { BaseLogger } from "../common/logging";
type LockFileForStandardQueryResult = {
cleanup?: () => Promise<void>;
};
/**
* Create a temporary query suite for a given query living within the standard library packs.
*
* This will create a lock file so the CLI can run the query without having the ql submodule.
*/
export async function createLockFileForStandardQuery(
cli: CodeQLCliServer,
queryPath: string,
logger: BaseLogger = extLogger,
): Promise<LockFileForStandardQueryResult> {
// These queries live within the standard library packs.
// This simplifies distribution (you don't need the standard query pack to use the AST viewer),
// but if the library pack doesn't have a lockfile, we won't be able to find
// other pack dependencies of the library pack.
// Work out the enclosing pack.
const packContents = await cli.packPacklist(queryPath, false);
const packFilePath = packContents.find((p) =>
QLPACK_FILENAMES.includes(basename(p)),
);
if (packFilePath === undefined) {
// Should not happen; we already resolved this query.
throw new Error(
`Could not find a CodeQL pack file for the pack enclosing the contextual query ${queryPath}`,
);
}
const packPath = dirname(packFilePath);
let lockFilePath: string | undefined;
for (const lockFileName of QLPACK_LOCK_FILENAMES) {
const candidateLockFilePath = resolve(packPath, lockFileName);
if (await pathExists(candidateLockFilePath)) {
lockFilePath = candidateLockFilePath;
break;
}
}
let cleanup: (() => Promise<void>) | undefined = undefined;
if (!lockFilePath) {
// No lock file, likely because this library pack is in the package cache.
// Create a lock file so that we can resolve dependencies and library path
// for the contextual query.
void logger.log(
`Library pack ${packPath} is missing a lock file; creating a temporary lock file`,
);
await cli.packResolveDependencies(packPath);
cleanup = async () => {
const tempLockFilePath = resolve(packPath, "codeql-pack.lock.yml");
void logger.log(
`Deleting temporary package lock file at ${tempLockFilePath}`,
);
// It's fine if the file doesn't exist.
await promises.rm(resolve(packPath, "codeql-pack.lock.yml"), {
force: true,
});
};
// Clear CLI server pack cache before installing dependencies,
// so that it picks up the new lock file, not the previously cached pack.
void logger.log("Clearing the CodeQL CLI server's pack cache");
await cli.clearCache();
// Install dependencies.
void logger.log(
`Installing package dependencies for library pack ${packPath}`,
);
await cli.packInstall(packPath);
}
return { cleanup };
}