Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions configuration
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
# but it also used when packaging (e.g. run configure.sh, then prepare-dist.sh, then package.sh)
# deno_dom should match release at https://github.com/b-fuze/deno-dom/releases

# NB: When these are updated, you must also update the versions
# in src/command/check/check.ts

# Binary dependencies
export DENO=v1.46.3
# TODO figure out where 0.1.41 apple silicon libs are available
Expand Down
1 change: 1 addition & 0 deletions news/changelog-1.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ All changes included in 1.7:

## `quarto check`

- ([#10047](https://github.com/quarto-dev/quarto-cli/issues/10047)): `quarto check` will now check binary dependency versions strictly by default. Use `quarto check --no-strict` to revert to old behavior.
- ([#11608](https://github.com/quarto-dev/quarto-cli/pull/11608)): Do not issue error message when calling `quarto check info`.

## `quarto convert`
Expand Down
75 changes: 51 additions & 24 deletions src/command/check/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ export const enforceTargetType = makeStringEnumTypeEnforcer(...kTargets);

const kIndent = " ";

export async function check(target: Target): Promise<void> {
export async function check(target: Target, strict?: boolean): Promise<void> {
const services = renderServices(notebookContext());
try {
info(`Quarto ${quartoConfig.version()}`);
if (target === "info" || target === "all") {
await checkInfo(services);
}
if (target === "versions" || target === "all") {
await checkVersions(services);
await checkVersions(services, strict);
}
if (target === "install" || target === "all") {
await checkInstall(services);
Expand All @@ -96,8 +96,8 @@ async function checkInfo(_services: RenderServices) {
info(kIndent + "Quarto cache location: " + cacheDir);
}

async function checkVersions(_services: RenderServices) {
const checkVersion = async (
async function checkVersions(_services: RenderServices, strict?: boolean) {
const checkVersion = (
version: string | undefined,
constraint: string,
name: string,
Expand All @@ -116,6 +116,20 @@ async function checkVersions(_services: RenderServices) {
}
};

const strictCheckVersion = (
version: string,
constraint: string,
name: string,
) => {
if (version !== constraint) {
info(
` NOTE: ${name} version ${version} does not strictly match ${constraint} and strict checking is enabled. Please use ${constraint}.`,
);
} else {
info(` ${name} version ${version}: OK`);
}
};

completeMessage("Checking versions of quarto binary dependencies...");

let pandocVersion = lines(
Expand All @@ -124,6 +138,15 @@ async function checkVersions(_services: RenderServices) {
stdout: "piped",
})).stdout!,
)[0]?.split(" ")[1];
const sassVersion = (await dartCommand(["--version"]))?.trim();
const denoVersion = Deno.version.deno;
const typstVersion = lines(
(await execProcess({
cmd: [typstBinaryPath(), "--version"],
stdout: "piped",
})).stdout!,
)[0].split(" ")[1];

// We hack around pandocVersion to build a sem-verish string
// that satisfies the semver package
// if pandoc reports more than three version numbers, pick the first three
Expand All @@ -138,29 +161,33 @@ async function checkVersions(_services: RenderServices) {
).join(".");
}
}
checkVersion(pandocVersion, ">=2.19.2", "Pandoc");

const sassVersion = (await dartCommand(["--version"]))?.trim();
checkVersion(sassVersion, ">=1.32.8", "Dart Sass");

// manually check Deno version without shelling out
// because we're actually running in Deno right now
if (!satisfies(Deno.version.deno, ">=1.33.1")) {
info(
` NOTE: Deno version ${Deno.version.deno} is too old. Please upgrade to 1.33.1 or later.`,
);
} else {
info(` Deno version ${Deno.version.deno}: OK`);
// FIXME: all of these strict checks should be done by
// loading the configuration file directly, but that
// file is in an awkward format and it is not packaged
// with our installers
const checkData: [string | undefined, string, string][] = strict
? [
[pandocVersion, "3.6.3", "Pandoc"],
[sassVersion, "1.85.1", "Dart Sass"],
[denoVersion, "1.46.3", "Deno"],
[typstVersion, "0.13.0", "Typst"],
]
: [
[pandocVersion, ">=2.19.2", "Pandoc"],
[sassVersion, ">=1.32.8", "Dart Sass"],
[denoVersion, ">=1.33.1", "Deno"],
[typstVersion, ">=0.10.0", "Typst"],
];
const fun = strict ? strictCheckVersion : checkVersion;
for (const [version, constraint, name] of checkData) {
if (version === undefined) {
info(` ${name} version: (not detected)`);
} else {
fun(version, constraint, name);
}
}

let typstVersion = lines(
(await execProcess({
cmd: [typstBinaryPath(), "--version"],
stdout: "piped",
})).stdout!,
)[0].split(" ")[1];
checkVersion(typstVersion, ">=0.10.0", "Typst");

completeMessage("Checking versions of quarto dependencies......OK");
}

Expand Down
9 changes: 7 additions & 2 deletions src/command/check/cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { check, enforceTargetType } from "./check.ts";

export const checkCommand = new Command()
.name("check")
.option(
"--no-strict",
"When set, will not fail if dependency versions don't match precisely",
)
.arguments("[target:string]")
.description(
"Verify correct functioning of Quarto installation.\n\n" +
Expand All @@ -18,7 +22,8 @@ export const checkCommand = new Command()
.example("Check Jupyter engine", "quarto check jupyter")
.example("Check Knitr engine", "quarto check knitr")
.example("Check installation and all engines", "quarto check all")
.action(async (_options: unknown, targetStr?: string) => {
// deno-lint-ignore no-explicit-any
.action(async (options: any, targetStr?: string) => {
targetStr = targetStr || "all";
await check(enforceTargetType(targetStr));
await check(enforceTargetType(targetStr), options.strict);
});
Loading