Skip to content

Commit

Permalink
Use better vignette workflow
Browse files Browse the repository at this point in the history
This installs the built vignettes to doc/ rather than inst/doc and
builds a vignette index in Meta/vignette.rds. This means that you can
view development vignettes by loading the package with `load_all()` and
calling `browseVignettes(pkgname)` or `vignette(vignName)` and the devel
vignettes are found. The `doc` and `Meta` directories are added to
.Rbuildignore; so they will not be included in the built package.

Fixes #1703
Fixes #1809
  • Loading branch information
jimhester committed Jul 27, 2018
1 parent 6e9ba8c commit 57b6958
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 44 deletions.
3 changes: 2 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
^Meta$
^doc$
^\.github$
^devtools\.Rproj$
^\.Rproj\.user$
Expand All @@ -11,4 +13,3 @@
^codecov\.yml$
^_pkgdown\.yml$
^docs$

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ inst/doc
.httr-oauth
tests/testthat/infrastructure/
script.R
doc
Meta
14 changes: 14 additions & 0 deletions R/usethis.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,17 @@

#' @importFrom withr defer
local_proj <- withr::local_(usethis::proj_set)

usethis_use_directory <- function(pkg, path, ignore = FALSE) {
capture.output({
local_proj(pkg$path)
usethis::use_directory(path, ignore)
})
}

usethis_use_git_ignore <- function(pkg, ignores, ignore = FALSE) {
capture.output({
local_proj(pkg$path)
usethis::use_git_ignore(ignores)
})
}
14 changes: 7 additions & 7 deletions R/vignette-r.r
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,30 @@
copy_vignettes <- function(pkg) {
pkg <- as.package(pkg)

doc_dir <- file.path(pkg$path, "inst", "doc")
if (!file.exists(doc_dir)) {
dir.create(doc_dir, recursive = TRUE, showWarnings = FALSE)
}
usethis_use_directory(pkg, "doc", ignore = TRUE)
usethis_use_git_ignore(pkg, "doc")

doc_dir <- file.path(pkg$path, "doc")

vigns <- tools::pkgVignettes(dir = pkg$path, output = TRUE, source = TRUE)
if (length(vigns$docs) == 0) return(invisible())

out_mv <- c(vigns$outputs, unique(unlist(vigns$sources, use.names = FALSE)))
out_cp <- vigns$docs

message("Moving ", paste(basename(out_mv), collapse = ", "), " to inst/doc/")
message("Moving ", paste(basename(out_mv), collapse = ", "), " to doc/")
file.copy(out_mv, doc_dir, overwrite = TRUE)
file.remove(out_mv)

message("Copying ", paste(basename(out_cp), collapse = ", "), " to inst/doc/")
message("Copying ", paste(basename(out_cp), collapse = ", "), " to doc/")
file.copy(out_cp, doc_dir, overwrite = TRUE)

# Copy extra files, if needed
extra_files <- find_vignette_extras(pkg)
if (length(extra_files) == 0) return(invisible())

message("Copying extra files ", paste(basename(extra_files), collapse = ", "),
" to inst/doc/")
" to doc/")
file.copy(extra_files, doc_dir, recursive = TRUE)

invisible()
Expand Down
69 changes: 54 additions & 15 deletions R/vignettes.r
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@
#'
#' Builds package vignettes using the same algorithm that \code{R CMD build}
#' does. This means including non-Sweave vignettes, using makefiles (if
#' present), and copying over extra files. You need to ensure that these
#' files are not included in the built package - ideally they should not
#' be checked into source, or at least excluded with \code{.Rbuildignore}
#' present), and copying over extra files. The files are copied in the 'doc'
#' directory and an vignette index is created in 'Meta/vignette.rds', as they
#' would be in a built package. 'doc' and 'Meta' are added to
#' \code{.Rbuildignore}, so will not be included in the built package. These
#' files can be checked into version control, so they can be viewed with
#' \code{browseVignettes()} and \code{vignette()} if the package has been
#' loaded with \code{load_all()} without needing to re-build them locally.
#'
#' @param pkg package description, can be path or package name. See
#' \code{\link{as.package}} for more information
#' @param quiet If \code{TRUE}, suppresses most output. Set to \code{FALSE}
#' if you need to debug.
#' @param install If \code{TRUE}, install the package before building
#' vignettes.
#' @inheritParams tools::buildVignettes
#' @inheritParams install_deps
#' @keywords programming
#' @seealso \code{\link{clean_vignettes}} to remove the pdfs in
#' \file{inst/doc} created from vignettes
#' \file{doc} created from vignettes
#' @export
#' @seealso \code{\link{clean_vignettes}} to remove build tex/pdf files.
build_vignettes <- function(pkg = ".",
dependencies = "VignetteBuilder",
clean = TRUE,
upgrade = FALSE,
quiet = TRUE
quiet = TRUE,
install = TRUE
) {
pkg <- as.package(pkg)
vigns <- tools::pkgVignettes(dir = pkg$path)
Expand All @@ -31,24 +38,53 @@ build_vignettes <- function(pkg = ".",

message("Building ", pkg$package, " vignettes")

build <- function(pkg_path, clean, quiet) {
withr::with_temp_libpaths(action = "prefix", code = {
devtools::install(pkg_path, upgrade_dependencies = FALSE, reload = FALSE, quiet = quiet)
if (isTRUE(install)) {
build <- function(pkg_path, clean, quiet) {
withr::with_temp_libpaths(action = "prefix", {
devtools::install(pkg_path, upgrade_dependencies = FALSE, reload = FALSE, quiet = quiet)
tools::buildVignettes(dir = pkg_path, clean = clean, tangle = TRUE, quiet = quiet)
})
}
} else {
build <- function(pkg_path, clean, quiet) {
tools::buildVignettes(dir = pkg_path, clean = clean, tangle = TRUE, quiet = quiet)
})
}
}
callr::r(build,

callr::r(
build,
args = list(pkg_path = pkg$path, clean = clean, quiet = quiet),
show = TRUE, spinner = FALSE)
show = TRUE,
spinner = FALSE)

# We need to re-run pkgVignettes now that they are built to get the output
# files as well
vigns <- tools::pkgVignettes(dir = pkg$path, source = TRUE, output = TRUE)

copy_vignettes(pkg)

create_vignette_index(pkg, vigns)

invisible(TRUE)
}

create_vignette_index <- function(pkg, vigns) {

usethis_use_directory(pkg, "Meta", ignore = TRUE)
usethis_use_git_ignore(pkg, "Meta")

message("Building vignette index")

vignette_index <- ("tools" %:::% ".build_vignette_index")(vigns)

vignette_index_path <- file.path(pkg$path, "Meta", "vignette.rds")

saveRDS(vignette_index, vignette_index_path, version = 2L)
}

#' Clean built vignettes.
#'
#' This uses a fairly rudimentary algorithm where any files in \file{inst/doc}
#' This uses a fairly rudimentary algorithm where any files in \file{doc}
#' with a name that exists in \file{vignettes} are removed.
#'
#' @param pkg package description, can be path or package name. See
Expand All @@ -59,17 +95,20 @@ clean_vignettes <- function(pkg = ".") {
vigns <- tools::pkgVignettes(dir = pkg$path)
if (basename(vigns$dir) != "vignettes") return()

message("Cleaning built vignettes from ", pkg$package)
message("Cleaning built vignettes and index from ", pkg$package)

doc_path <- file.path(pkg$path, "inst", "doc")
doc_path <- file.path(pkg$path, "doc")

vig_candidates <- dir(doc_path, full.names = TRUE)
vig_rm <- vig_candidates[file_name(vig_candidates) %in% file_name(vigns$docs)]

extra_candidates <- file.path(doc_path, basename(find_vignette_extras(pkg)))
extra_rm <- extra_candidates[file.exists(extra_candidates)]

to_remove <- c(vig_rm, extra_rm)
vig_index_path <- file.path(pkg$path, "Meta", "vignette.rds")
vig_index_rm <- if (file.exists(vig_index_path)) vig_index_path

to_remove <- c(vig_rm, extra_rm, vig_index_rm)
if (length(to_remove) > 0) {
message("Removing ", paste(basename(to_remove), collapse = ", "))
file.remove(to_remove)
Expand Down
17 changes: 12 additions & 5 deletions man/build_vignettes.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/clean_vignettes.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 15 additions & 15 deletions tests/testthat/test-vignettes.r
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
context("Vignettes")

test_that("Sweave vignettes copied into inst/doc", {
test_that("Sweave vignettes copied into doc", {
if (!pkgbuild::has_latex()) {
skip("pdflatex not available")
}

clean_vignettes("testVignettes")
expect_false("new.pdf" %in% dir("testVignettes/inst/doc"))
expect_false("new.R" %in% dir("testVignettes/inst/doc"))
expect_false("new.Rnw" %in% dir("testVignettes/inst/doc"))
expect_false("new.pdf" %in% dir("testVignettes/doc"))
expect_false("new.R" %in% dir("testVignettes/doc"))
expect_false("new.Rnw" %in% dir("testVignettes/doc"))

build_vignettes("testVignettes")
expect_true("new.pdf" %in% dir("testVignettes/inst/doc"))
expect_true("new.R" %in% dir("testVignettes/inst/doc"))
expect_true("new.Rnw" %in% dir("testVignettes/inst/doc"))
expect_true("new.pdf" %in% dir("testVignettes/doc"))
expect_true("new.R" %in% dir("testVignettes/doc"))
expect_true("new.Rnw" %in% dir("testVignettes/doc"))

clean_vignettes("testVignettes")
expect_false("new.pdf" %in% dir("testVignettes/inst/doc"))
expect_false("new.R" %in% dir("testVignettes/inst/doc"))
expect_false("new.Rnw" %in% dir("testVignettes/inst/doc"))
expect_false("new.pdf" %in% dir("testVignettes/doc"))
expect_false("new.R" %in% dir("testVignettes/doc"))
expect_false("new.Rnw" %in% dir("testVignettes/doc"))
})

test_that("Built files are updated", {
Expand All @@ -30,7 +30,7 @@ test_that("Built files are updated", {
build_vignettes("testVignettes")
on.exit(clean_vignettes("testVignettes"))

output <- dir("testVignettes/inst/doc", "new", full.names = TRUE)
output <- dir("testVignettes/doc", "new", full.names = TRUE)
first <- file.info(output)$mtime

Sys.sleep(1)
Expand All @@ -41,9 +41,9 @@ test_that("Built files are updated", {
})

if (packageVersion("knitr") >= 1.2) {
test_that("Rmarkdown vignettes copied into inst/doc", {
test_that("Rmarkdown vignettes copied into doc", {
pkg <- as.package("testMarkdownVignettes")
doc_path <- file.path(pkg$path, "inst", "doc")
doc_path <- file.path(pkg$path, "doc")

clean_vignettes(pkg)
expect_false("test.html" %in% dir(doc_path))
Expand All @@ -63,7 +63,7 @@ if (packageVersion("knitr") >= 1.2) {

test_that("dependencies argument", {
pkg <- as.package("testMarkdownVignettes")
doc_path <- file.path(pkg$path, "inst", "doc")
doc_path <- file.path(pkg$path, "doc")

clean_vignettes(pkg)
on.exit(clean_vignettes(pkg), add = TRUE)
Expand All @@ -83,7 +83,7 @@ test_that("Extra files copied and removed", {
}

pkg <- as.package("testVignetteExtras")
doc_path <- file.path(pkg$path, "inst", "doc")
doc_path <- file.path(pkg$path, "doc")

extras_path <- file.path("testVignetteExtras", "vignettes",
".install_extras")
Expand Down
2 changes: 2 additions & 0 deletions tests/testthat/testMarkdownVignettes/.Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
^Meta$
^doc$
2 changes: 2 additions & 0 deletions tests/testthat/testVignetteExtras/.Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
^Meta$
^doc$
2 changes: 2 additions & 0 deletions tests/testthat/testVignettes/.Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
^Meta$
^doc$

0 comments on commit 57b6958

Please sign in to comment.