@@ -24,13 +24,18 @@ mutable struct File
2424 options = _parsed_options (options)
2525 _, _, file_frontmatter = raw_text_chunks (path)
2626 merged_options = _extract_relevant_options (file_frontmatter, options)
27- exeflags, env = _exeflags_and_env (merged_options)
27+ exeflags, env, quarto_env = _exeflags_and_env (merged_options)
2828 timeout = _extract_timeout (merged_options)
2929
30-
3130 exe, _exeflags = _julia_exe (exeflags)
32- worker =
33- cd (() -> Malt. Worker (; exe, exeflags = _exeflags, env), dirname (path))
31+ worker = cd (
32+ () -> Malt. Worker (;
33+ exe,
34+ exeflags = _exeflags,
35+ env = vcat (env, quarto_env),
36+ ),
37+ dirname (path),
38+ )
3439 file = new (
3540 worker,
3641 path,
@@ -104,7 +109,7 @@ function _julia_exe(exeflags)
104109end
105110
106111function _extract_timeout (merged_options)
107- daemon = merged_options[" format" ][" execute" ][" daemon" ]
112+ daemon = something ( merged_options[" format" ][" execute" ][" daemon" ], true )
108113 if daemon === true
109114 300.0 # match quarto's default timeout of 300 seconds
110115 elseif daemon === false
@@ -149,6 +154,13 @@ function _exeflags_and_env(options)
149154 # if exeflags already contains '--color=no', the 'no' will prevail
150155 pushfirst! (exeflags, " --color=yes" )
151156
157+ # Several QUARTO_* environment variables are passed to the worker process
158+ # via the `env` field rather than via real environment variables. Capture
159+ # these and pass them to the worker process separate from `env` since that
160+ # is used by the worker status printout and we don't want these extra ones
161+ # that the user has not set themselves to show up there.
162+ quarto_env = Base. byteenv (options[" env" ])
163+
152164 # Ensure that coverage settings are passed to the worker so that worker
153165 # code is tracked correctly during tests.
154166 # Based on https://github.com/JuliaLang/julia/blob/eed18bdf706b7aab15b12f3ba0588e8fafcd4930/base/util.jl#L216-L229.
@@ -171,7 +183,7 @@ function _exeflags_and_env(options)
171183 end
172184 end
173185
174- return exeflags, env
186+ return exeflags, env, quarto_env
175187end
176188
177189struct Server
@@ -205,22 +217,40 @@ function init!(file::File, options::Dict)
205217end
206218
207219function refresh! (file:: File , options:: Dict )
208- exeflags, env = _exeflags_and_env (options)
220+ exeflags, env, quarto_env = _exeflags_and_env (options)
209221 if exeflags != file. exeflags || env != file. env || ! Malt. isrunning (file. worker) # the worker might have been killed on another task
210222 Malt. stop (file. worker)
211223 exe, _exeflags = _julia_exe (exeflags)
212- file. worker =
213- cd (() -> Malt. Worker (; exe, exeflags = _exeflags, env), dirname (file. path))
224+ file. worker = cd (
225+ () -> Malt. Worker (; exe, exeflags = _exeflags, env = vcat (env, quarto_env)),
226+ dirname (file. path),
227+ )
214228 file. exe = exe
215229 file. exeflags = exeflags
216230 file. env = env
217231 file. source_code_hash = hash (VERSION )
218232 file. output_chunks = []
219233 init! (file, options)
220234 end
235+ refresh_quarto_env_vars! (file, quarto_env)
221236 remote_eval_fetch_channeled (file. worker, :(refresh! ($ (options)); revise_hook ()))
222237end
223238
239+ # Environment variables provided by Quarto may change between `quarto render`
240+ # calls. To update them correctly in the worker process, we need to refresh
241+ # them before each run.
242+ function refresh_quarto_env_vars! (file:: File , quarto_env)
243+ if ! isempty (quarto_env)
244+ remote_eval_fetch_channeled (file. worker, quote
245+ for each in $ quarto_env
246+ k, v = Base. splitenv (each)
247+ ENV [k] = v
248+ end
249+ end )
250+ end
251+ return nothing
252+ end
253+
224254function _cache_file (f:: File , source_code_hash)
225255 path = joinpath (dirname (f. path), " .cache" )
226256 hs = string (hash (f. worker. manifest_file, source_code_hash); base = 62 )
@@ -441,9 +471,11 @@ function _extract_relevant_options(file_frontmatter::Dict, options::Dict)
441471 daemon = daemon_default,
442472 params = params_default,
443473 cache = cache_default,
474+ env = Dict {String,Any} (),
444475 )
445476 else
446477 format = get (D, options, " format" )
478+ env = get (D, options, " env" )
447479 execute = get (D, format, " execute" )
448480 fig_width = get (execute, " fig-width" , fig_width_default)
449481 fig_height = get (execute, " fig-height" , fig_height_default)
@@ -481,6 +513,7 @@ function _extract_relevant_options(file_frontmatter::Dict, options::Dict)
481513 daemon,
482514 params = params_merged,
483515 cache,
516+ env,
484517 )
485518 end
486519end
@@ -497,6 +530,7 @@ function _options_template(;
497530 daemon,
498531 params,
499532 cache,
533+ env,
500534)
501535 D = Dict{String,Any}
502536 return D (
@@ -515,6 +549,7 @@ function _options_template(;
515549 " metadata" => D (" julia" => julia),
516550 ),
517551 " params" => D (params),
552+ " env" => env,
518553 )
519554end
520555
@@ -1466,7 +1501,7 @@ function run!(
14661501 chunk_callback = (i, n, c) -> nothing ,
14671502)
14681503 try
1469- borrow_file! (server, path; optionally_create = true ) do file
1504+ borrow_file! (server, path; options, optionally_create = true ) do file
14701505 if file. timeout_timer != = nothing
14711506 close (file. timeout_timer)
14721507 file. timeout_timer = nothing
@@ -1606,7 +1641,7 @@ function borrow_file!(
16061641 get (server. workers, apath, nothing )
16071642 end
16081643 if file != = current_file
1609- return borrow_file! (f, server, apath; optionally_create)
1644+ return borrow_file! (f, server, apath; options, optionally_create)
16101645 else
16111646 return f (file)
16121647 end
0 commit comments