diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index a045f7ff..3d8e6bd0 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -72,6 +72,8 @@ jobs: needs: check - uses: r-lib/actions/check-r-package@v2 + env: + QUARTO_R_QUIET: FALSE with: upload-snapshots: true build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' diff --git a/NEWS.md b/NEWS.md index 57661bb4..e8a3ed1e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -29,6 +29,8 @@ - `QUARTO_R_QUIET` environment variable can be used to set `quarto.quiet` option, which overrides any `quiet = TRUE` argument passed to `quarto_*` functions. This can be useful to debug Quarto rendering inside other packages, like **pkgdown**. Overrides will also now happens for [GHA debug logging](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/enabling-debug-logging). +- `.libPaths()` from the calling R session will now be passed by default to all call to quarto as a subprocess. This should solve issue with **pkgdown** or when building vignettes + - Correctly report Quarto CLI error when background process call to `quarto` fails (thanks, @salim-b, [#235](https://github.com/quarto-dev/quarto-r/issues/235)) # quarto 1.4.4 diff --git a/R/quarto.R b/R/quarto.R index 71f3fa60..6240d81d 100644 --- a/R/quarto.R +++ b/R/quarto.R @@ -124,16 +124,37 @@ quarto_run <- function( args = character(), quarto_bin = find_quarto(), echo = FALSE, + libpaths = .libPaths(), echo_cmd = getOption("quarto.echo_cmd", FALSE), ..., .call = rlang::caller_env() ) { + # To store any environment variables to pass to the process + custom_env <- NULL + + # handle session .libpaths() for background session + # It needs to be passed if .libPaths() was modified in the current R session + # (e.g. to install dev package in a temporary library) + opt_in_libpath <- getOption("quarto.use_libpaths", TRUE) + if (isTRUE(opt_in_libpath) && !is.null(libpaths)) { + custom_env <- c( + custom_env, + R_LIBS = paste(libpaths, collapse = .Platform$path.sep) + ) + } + # This is required due to a bug in QUARTO CLI, fixed only in 1.8+ # https://github.com/quarto-dev/quarto-cli/pull/12887 - custom_env <- NULL if (!quarto_available(min = "1.8.13")) { - custom_env <- c("current", QUARTO_R = R.home("bin")) + custom_env <- c(custom_env, QUARTO_R = R.home("bin")) + } + + # This is required because `"current"` only is not supported by processx + # FIXME: https://github.com/r-lib/processx/issues/399 + if (!is.null(custom_env)) { + custom_env <- c("current", custom_env) } + res <- tryCatch( { processx::run( diff --git a/R/render.R b/R/render.R index 2cb0c8cb..09909903 100644 --- a/R/render.R +++ b/R/render.R @@ -52,6 +52,10 @@ #' advanced usage and useful for CLI arguments which are not yet mirrored in a #' dedicated parameter of this \R function. See `quarto render --help` for options. #' @param pandoc_args Additional command line arguments to pass on to Pandoc. +#' @param libpaths A character vector of library paths to use for the R session run by Quarto. +#' If `NULL`, no library paths will be pass to quarto subprocess and defaults R one will be used. +#' Setting `options(quarto.use_libpaths = FALSE)` will disable this behavior and +#' never pass library paths to quarto subprocess. #' @param as_job Render as an RStudio background job. Default is `"auto"`, #' which will render individual documents normally and projects as #' background jobs. Use the `quarto.render_as_job` \R option to control @@ -93,6 +97,7 @@ quarto_render <- function( profile = NULL, quarto_args = NULL, pandoc_args = NULL, + libpaths = .libPaths(), as_job = getOption("quarto.render_as_job", "auto") ) { # get quarto binary @@ -203,7 +208,7 @@ quarto_render <- function( } # run quarto - quarto_run(args, echo = TRUE, quarto_bin = quarto_bin) + quarto_run(args, echo = TRUE, quarto_bin = quarto_bin, libpaths = libpaths) # no return value invisible(NULL) diff --git a/man/quarto_render.Rd b/man/quarto_render.Rd index e626dd4f..de485216 100644 --- a/man/quarto_render.Rd +++ b/man/quarto_render.Rd @@ -24,6 +24,7 @@ quarto_render( profile = NULL, quarto_args = NULL, pandoc_args = NULL, + libpaths = .libPaths(), as_job = getOption("quarto.render_as_job", "auto") ) } @@ -94,6 +95,11 @@ dedicated parameter of this \R function. See \verb{quarto render --help} for opt \item{pandoc_args}{Additional command line arguments to pass on to Pandoc.} +\item{libpaths}{A character vector of library paths to use for the R session run by Quarto. +If \code{NULL}, no library paths will be pass to quarto subprocess and defaults R one will be used. +Setting \code{options(quarto.use_libpaths = FALSE)} will disable this behavior and +never pass library paths to quarto subprocess.} + \item{as_job}{Render as an RStudio background job. Default is \code{"auto"}, which will render individual documents normally and projects as background jobs. Use the \code{quarto.render_as_job} \R option to control diff --git a/tests/testthat/test-quarto-args.R b/tests/testthat/test-quarto-args.R index f0f4845e..089a1224 100644 --- a/tests/testthat/test-quarto-args.R +++ b/tests/testthat/test-quarto-args.R @@ -24,6 +24,7 @@ test_that("create quiete arg", { }) test_that("quarto.quiet options takes over", { + withr::local_envvar(list(QUARTO_R_QUIET = NA)) expect_identical(is_quiet(TRUE), TRUE) expect_identical(is_quiet(FALSE), FALSE) expect_identical(is_quiet(NA), FALSE) @@ -63,6 +64,7 @@ test_that("QUARTO_R_QUIET options takes over", { }) test_that("quarto.quiet options takes over QUARTO_R_QUIET", { + withr::local_envvar(list(QUARTO_R_QUIET = NA)) withr::with_options(list(quarto.quiet = TRUE), { withr::with_envvar(list(QUARTO_R_QUIET = FALSE), { expect_identical(is_quiet(TRUE), TRUE) diff --git a/tests/testthat/test-quarto.R b/tests/testthat/test-quarto.R index d6e276ee..0847b61c 100644 --- a/tests/testthat/test-quarto.R +++ b/tests/testthat/test-quarto.R @@ -123,6 +123,28 @@ test_that("quarto.quiet options controls echo and overwrite function argument", }) }) +test_that("quarto sees same libpaths as main process", { + skip_if_no_quarto() + skip_on_cran() + qmd <- local_qmd_file(c("```{r}", "#| echo: false", ".libPaths()", "```")) + tmp_lib <- withr::local_tempdir("tmp_libpath") + withr::local_libpaths(tmp_lib, action = "prefix") + withr::local_dir(dirname(qmd)) + out <- "out.md" + # .libPaths() is known in Quarto render + out <- .render_and_read(qmd, output_format = "gfm") + expect_match(out, basename(tmp_lib), all = FALSE, fixed = TRUE) + # Opting-out globally + withr::with_options( + list(quarto.use_libpaths = FALSE), + out <- .render_and_read(qmd, output_format = "gfm") + ) + expect_no_match(out, basename(tmp_lib), fixed = TRUE) + # Opting-out at command + out <- .render_and_read(qmd, output_format = "gfm", libpaths = NULL) + expect_no_match(out, basename(tmp_lib), fixed = TRUE) +}) + test_that("quarto_available()", { expect_error( quarto_available("1.5", "1.4"), diff --git a/tests/testthat/test-render.R b/tests/testthat/test-render.R index eedc0fdf..68fa782a 100644 --- a/tests/testthat/test-render.R +++ b/tests/testthat/test-render.R @@ -54,6 +54,7 @@ test_that("metadata-file and metadata are merged in quarto_render", { test_that("quarto_args in quarto_render", { skip_if_no_quarto() + withr::local_envvar(list(QUARTO_R_QUIET = NA)) qmd <- local_qmd_file(c("content")) local_quarto_run_echo_cmd() withr::local_dir(dirname(qmd))