Skip to content

Commit caa8cc1

Browse files
committed
do not use Deno.env.set indiscriminately to avoid races
1 parent d4125e4 commit caa8cc1

File tree

5 files changed

+66
-53
lines changed

5 files changed

+66
-53
lines changed

src/quarto.ts

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,10 @@ const checkReconfiguration = async () => {
7777
}
7878
};
7979

80-
const passThroughPandoc = async (
81-
args: string[],
82-
env?: Record<string, string>,
83-
) => {
80+
const passThroughPandoc = async (args: string[]) => {
8481
const result = await execProcess(
8582
{
8683
cmd: [pandocBinaryPath(), ...args.slice(1)],
87-
env,
8884
},
8985
undefined,
9086
undefined,
@@ -94,10 +90,7 @@ const passThroughPandoc = async (
9490
Deno.exit(result.code);
9591
};
9692

97-
const passThroughTypst = async (
98-
args: string[],
99-
env?: Record<string, string>,
100-
) => {
93+
const passThroughTypst = async (args: string[]) => {
10194
if (args[1] === "update") {
10295
error(
10396
"The 'typst update' command is not supported.\n" +
@@ -107,28 +100,26 @@ const passThroughTypst = async (
107100
}
108101
const result = await execProcess({
109102
cmd: [typstBinaryPath(), ...args.slice(1)],
110-
env,
111103
});
112104
Deno.exit(result.code);
113105
};
114106

115107
export async function quarto(
116108
args: string[],
117109
cmdHandler?: (command: Command) => Command,
118-
env?: Record<string, string>,
119110
) {
120111
await checkReconfiguration();
121112
checkVersionRequirement();
122113
if (args[0] === "pandoc" && args[1] !== "help") {
123-
await passThroughPandoc(args, env);
114+
await passThroughPandoc(args);
124115
}
125116
if (args[0] === "typst") {
126-
await passThroughTypst(args, env);
117+
await passThroughTypst(args);
127118
}
128119

129120
// passthrough to run handlers
130121
if (args[0] === "run" && args[1] !== "help" && args[1] !== "--help") {
131-
const result = await runScript(args.slice(1), env);
122+
const result = await runScript(args.slice(1));
132123
Deno.exit(result.code);
133124
}
134125

@@ -153,13 +144,6 @@ export async function quarto(
153144

154145
debug("Quarto version: " + quartoConfig.version());
155146

156-
const oldEnv: Record<string, string | undefined> = {};
157-
for (const [key, value] of Object.entries(env || {})) {
158-
const oldV = Deno.env.get(key);
159-
oldEnv[key] = oldV;
160-
Deno.env.set(key, value);
161-
}
162-
163147
const quartoCommand = new Command()
164148
.name("quarto")
165149
.help({ colors: false })
@@ -189,13 +173,6 @@ export async function quarto(
189173

190174
try {
191175
await promise;
192-
for (const [key, value] of Object.entries(oldEnv)) {
193-
if (value === undefined) {
194-
Deno.env.delete(key);
195-
} else {
196-
Deno.env.set(key, value);
197-
}
198-
}
199176
if (commandFailed()) {
200177
exitWithCleanup(1);
201178
}

tests/smoke/env/install.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ testQuartoCmd(
1313
[
1414
noErrorsOrWarnings,
1515
printsMessage({level: "INFO", regex: /tinytex\s+/}),
16+
// FIXME WE SHOULD BE ABLE TO TURN THIS BACK ON
1617
// printsMessage({level: "INFO", regex: /chromium\s+/}),
1718
// temporarily disabled until we get puppeteer back
1819
],

tests/smoke/extensions/extension-render-journals.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ for (const journalRepo of journalRepos) {
4242
// Sets up the test
4343
setup: async () => {
4444
console.log(`using quarto-journals/${journalRepo.repo}`);
45+
46+
// FIXME THIS DOESN'T WORK
47+
// WE CANNOT GUARANTEE THAT CHDIR WILL BE CONSTANT
48+
// THROUGHOUT THE ASYNC CALL
4549
const wd = Deno.cwd();
4650
Deno.chdir(workingDir);
4751
await quarto([

tests/smoke/project/project-prepost.test.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { docs } from "../../utils.ts";
88

99
import { join } from "../../../src/deno_ral/path.ts";
1010
import { existsSync } from "../../../src/deno_ral/fs.ts";
11-
import { testQuartoCmd } from "../../test.ts";
11+
import { testQuartoCmd, testQuartoCmdWithEnv } from "../../test.ts";
1212
import { fileExists, noErrors, printsMessage, verifyNoPath, verifyPath } from "../../verify.ts";
1313
import { normalizePath, safeRemoveIfExists } from "../../../src/core/path.ts";
1414

@@ -78,22 +78,22 @@ testQuartoCmd(
7878
}
7979
});
8080

81-
testQuartoCmd(
82-
"render",
83-
[docs("project/prepost/issue-10828")],
84-
[],
85-
{
86-
env: {
87-
"QUARTO_USE_FILE_FOR_PROJECT_INPUT_FILES": normalizePath(docs("project/prepost/issue-10828/input-files.txt")),
88-
"QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES": normalizePath(docs("project/prepost/issue-10828/output-files.txt"))
89-
},
90-
teardown: async () => {
91-
const inputPath = normalizePath(docs("project/prepost/issue-10828/input-files.txt"));
92-
const outputPath = normalizePath(docs("project/prepost/issue-10828/output-files.txt"));
93-
verifyPath(inputPath);
94-
safeRemoveIfExists(inputPath);
95-
verifyPath(outputPath);
96-
safeRemoveIfExists(outputPath);
97-
}
81+
testQuartoCmdWithEnv(
82+
"render",
83+
[docs("project/prepost/issue-10828")],
84+
[],
85+
{
86+
"QUARTO_USE_FILE_FOR_PROJECT_INPUT_FILES": normalizePath(docs("project/prepost/issue-10828/input-files.txt")),
87+
"QUARTO_USE_FILE_FOR_PROJECT_OUTPUT_FILES": normalizePath(docs("project/prepost/issue-10828/output-files.txt"))
88+
},
89+
{
90+
teardown: async () => {
91+
const inputPath = normalizePath(docs("project/prepost/issue-10828/input-files.txt"));
92+
const outputPath = normalizePath(docs("project/prepost/issue-10828/output-files.txt"));
93+
verifyPath(inputPath);
94+
safeRemoveIfExists(inputPath);
95+
verifyPath(outputPath);
96+
safeRemoveIfExists(outputPath);
9897
}
99-
)
98+
}
99+
)

tests/test.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { runningInCI } from "../src/core/ci-info.ts";
1717
import { relative, fromFileUrl } from "../src/deno_ral/path.ts";
1818
import { quartoConfig } from "../src/core/quarto.ts";
1919
import { isWindows } from "../src/deno_ral/platform.ts";
20+
import { execProcess } from "../src/core/process.ts";
2021

2122
export interface TestDescriptor {
2223
// The name of the test
@@ -55,9 +56,6 @@ export interface TestContext {
5556

5657
// control if test is ran or skipped
5758
ignore?: boolean;
58-
59-
// environment to pass to downstream processes
60-
env?: Record<string, string>;
6159
}
6260

6361
// Allow to merge test contexts in Tests helpers
@@ -95,11 +93,44 @@ export function mergeTestContexts(baseContext: TestContext, additionalContext?:
9593
},
9694
// override ignore if provided
9795
ignore: additionalContext.ignore ?? baseContext.ignore,
98-
// merge env with additional context taking precedence
99-
env: { ...baseContext.env, ...additionalContext.env },
10096
};
10197
}
10298

99+
// for Quarto tests that new to change the environment,
100+
// we use a subprocess call to run the command, or else we risk
101+
// race conditions with environment variables overwriting
102+
// each other
103+
export function testQuartoCmdWithEnv(
104+
cmd: string,
105+
args: string[],
106+
verify: Verify[],
107+
env: Record<string, string>,
108+
context?: TestContext,
109+
name?: string
110+
) {
111+
if (name === undefined) {
112+
name = `quarto ${cmd} ${args.join(" ")}`;
113+
}
114+
test({
115+
name,
116+
execute: async () => {
117+
const timeout = new Promise((_resolve, reject) => {
118+
setTimeout(reject, 600000, "timed out after 10 minutes");
119+
});
120+
await Promise.race([
121+
execProcess({
122+
cmd: [quartoConfig.binPath(), cmd, ...args],
123+
env
124+
}),
125+
timeout,
126+
]);
127+
},
128+
verify,
129+
context: context || {},
130+
type: "smoke",
131+
});
132+
}
133+
103134
export function testQuartoCmd(
104135
cmd: string,
105136
args: string[],
@@ -117,7 +148,7 @@ export function testQuartoCmd(
117148
setTimeout(reject, 600000, "timed out after 10 minutes");
118149
});
119150
await Promise.race([
120-
quarto([cmd, ...args], undefined, context?.env),
151+
quarto([cmd, ...args]),
121152
timeout,
122153
]);
123154
},

0 commit comments

Comments
 (0)