Skip to content

Failures in a file included with @includeRmd will nuke the NAMESPACE #1254

@DavisVaughan

Description

@DavisVaughan

If you include a file with @includeRmd that fails during roxygenise(), then your NAMESPACE will be (mostly) nuked, which often puts you in a state where you can't even roxygenise() again to fix it. You end up having to revert the changes made to the NAMESPACE manually, fix the Rmd (or whatever made it fail), and then redocument. (This has bitten the tidymodels team, and me in vctrs quite a few times)

I have a somewhat minimal example here, where this commit changed an Rmd to make it fail, I redocumented, and now the exported function fn() is no longer part of NAMESPACE
DavisVaughan/testfailingroxygen2@ad6f49f

The way this occurs is:

  • roclet_preprocess() has a namespace method that inserts partial information into the NAMESPACE file. It seems to insert information about imports only.
  • roclet_process() will then run, and the Rd method for that is where the Rmd is rendered and subsequently fails.
  • roclet_output() never gets to run, which is where the NAMESPACE is finalized, so we end up with the broken partial NAMESPACE that roclet_preprocess() wrote.

I see two potential solutions:

  • roxy_tag_rd.roxy_tag_includeRmd() could tryCatch() the rmarkdown::render() call? Or maybe pass something to render() to make it not fail.
  • More generally, I'm not entirely sure why roclet_preprocess.roclet_namespace() exists. It seems like the process and output methods for roclet_namespace will basically do the same thing, just with import_only = FALSE. If the preprocess method wasn't run, it seems like we wouldn't get into that problematic state from above because we would never write a partial NAMESPACE to disk. I'm probably missing something though

    roxygen2/R/namespace.R

    Lines 34 to 63 in 6c1e42f

    roclet_preprocess.roclet_namespace <- function(x, blocks, base_path) {
    lines <- blocks_to_ns(blocks, emptyenv(), import_only = TRUE)
    NAMESPACE <- file.path(base_path, "NAMESPACE")
    if (length(lines) == 0 && !made_by_roxygen(NAMESPACE)) {
    return(x)
    }
    results <- c(made_by("#"), lines)
    write_if_different(NAMESPACE, results, check = TRUE)
    invisible(x)
    }
    #' @export
    roclet_process.roclet_namespace <- function(x, blocks, env, base_path) {
    blocks_to_ns(blocks, env)
    }
    #' @export
    roclet_output.roclet_namespace <- function(x, results, base_path, ...) {
    NAMESPACE <- file.path(base_path, "NAMESPACE")
    results <- c(made_by("#"), results)
    # Always check for roxygen2 header before overwriting NAMESPACE (#436),
    # even when running for the first time
    write_if_different(NAMESPACE, results, check = TRUE)
    NAMESPACE
    }
    .

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions