From 8200c30cd68f3fa8bebbad622df6f0c52cc2f2cd Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Wed, 2 Oct 2024 17:00:06 -0500 Subject: [PATCH] fix #804: use xfun::file_rename() because file.rename() would fail to rename files across different disk volumes --- DESCRIPTION | 5 +++-- NAMESPACE | 1 + NEWS.md | 2 ++ R/bookdown-package.R | 2 +- R/ebook.R | 2 +- R/html.R | 2 +- R/latex.R | 4 ++-- R/render.R | 6 +++--- R/skeleton.R | 2 +- R/utils.R | 13 ------------- inst/scripts/render_one.R | 2 +- tests/testit/test-utils.R | 24 ------------------------ 12 files changed, 16 insertions(+), 49 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 67b98aff1..c97c278a9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: bookdown Type: Package Title: Authoring Books and Technical Documents with R Markdown -Version: 0.40.1 +Version: 0.40.2 Authors@R: c( person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666")), person("Christophe", "Dervieux", , "cderv@posit.co", role = c("ctb"), @@ -65,7 +65,7 @@ Imports: knitr (>= 1.38), rmarkdown (>= 2.14), jquerylib, - xfun (>= 0.39), + xfun (>= 0.47.12), tinytex (>= 0.12), yaml (>= 2.1.19) Suggests: @@ -94,3 +94,4 @@ Config/Needs/book: remotes, webshot, svglite Config/Needs/website: pkgdown, tidyverse/tidytemplate, rstudio/quillt Config/testthat/edition: 3 VignetteBuilder: knitr +Remotes: yihui/xfun diff --git a/NAMESPACE b/NAMESPACE index 7b2d0b8ce..c77a3ad88 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -43,6 +43,7 @@ import(utils) importFrom(xfun,dir_create) importFrom(xfun,dir_exists) importFrom(xfun,existing_files) +importFrom(xfun,file_rename) importFrom(xfun,in_dir) importFrom(xfun,read_utf8) importFrom(xfun,same_path) diff --git a/NEWS.md b/NEWS.md index 438a005a2..fc4463125 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,8 @@ - If set to `TeX-AMS-MML_HTMLorMML` renders equations in HTML + CSS (which may look nicer for some equations). - If set to `TeX-MML-AM_SVG` renders equations in SVG. +- Fixed the bug that `render_book()` fails due to `file.rename()` being unable to rename files across different disk volumes (thanks, @Giqles @katrinabrock, #804). + # CHANGES IN bookdown VERSION 0.40 - Footnotes are not rendered correctly when `katex` is used to render LaTeX math expressions (thanks, @pbreheny, #1470). diff --git a/R/bookdown-package.R b/R/bookdown-package.R index 295cf139e..2e37d79da 100644 --- a/R/bookdown-package.R +++ b/R/bookdown-package.R @@ -6,6 +6,6 @@ "_PACKAGE" ## usethis namespace: start -#' @importFrom xfun dir_create dir_exists +#' @importFrom xfun dir_create dir_exists file_rename ## usethis namespace: end NULL diff --git a/R/ebook.R b/R/ebook.R index 2cd0be6ab..ef429e81c 100644 --- a/R/ebook.R +++ b/R/ebook.R @@ -76,7 +76,7 @@ epub_book = function( move_output = function(output) { if (is.null(opts$get('output_dir'))) return(output) output2 = output_path(output) - file.rename(output, output2) + file_rename(output, output2) output2 } diff --git a/R/html.R b/R/html.R index 493ab83bf..c0a854ebd 100644 --- a/R/html.R +++ b/R/html.R @@ -534,7 +534,7 @@ clean_html_tags = function(x) { move_to_output_dir = function(files) { files2 = output_path(files) i = file.exists(files) & (files != files2) - file.rename(files[i], files2[i]) + file_rename(files[i], files2[i]) files2 } diff --git a/R/latex.R b/R/latex.R index e46d11013..6d2c6e095 100644 --- a/R/latex.R +++ b/R/latex.R @@ -75,8 +75,8 @@ pdf_book = function( if (is.null(o)) return(output) output2 = file.path(o, output) - file.rename(output, output2) - if (keep_tex) file.rename(f, file.path(o, f)) + file_rename(output, output2) + if (keep_tex) file_rename(f, file.path(o, f)) output2 } # always enable tables (use packages booktabs, longtable, ...) diff --git a/R/render.R b/R/render.R index f38b68468..6533d8aed 100644 --- a/R/render.R +++ b/R/render.R @@ -121,12 +121,12 @@ render_book = function( aux_diro = '_bookdown_files' # move _files and _cache from _bookdown_files to ./, then from ./ to _bookdown_files aux_dirs = files_cache_dirs(aux_diro) - move_dirs(aux_dirs, basename(aux_dirs)) + file_rename(aux_dirs, basename(aux_dirs)) on.exit({ aux_dirs = files_cache_dirs('.') if (length(aux_dirs)) { dir_create(aux_diro) - move_dirs(aux_dirs, file.path(aux_diro, basename(aux_dirs))) + file_rename(aux_dirs, file.path(aux_diro, basename(aux_dirs))) } }, add = TRUE) @@ -215,7 +215,7 @@ render_new_session = function(files, main, config, output_format, clean, envir, meta = clean_meta(render_meta, files) move = !(unlist(meta) %in% files) # do not move input files to output dir - on.exit(file.rename(unlist(meta)[move], files_md[move]), add = TRUE) + on.exit(file_rename(unlist(meta)[move], files_md[move]), add = TRUE) merge_chapters(unlist(meta), main, orig = files) diff --git a/R/skeleton.R b/R/skeleton.R index b4772119c..0237c04ea 100644 --- a/R/skeleton.R +++ b/R/skeleton.R @@ -20,7 +20,7 @@ bookdown_skeleton = function(path, output_format = skeleton_formats()) { skeleton_build_index(path, output_format) skeleton_build_output_yml(path, output_format) skeleton_build_bookdown_yml(path, output_format) - move_dir(file.path(path, output_format), path) # move left format files + file_rename(file.path(path, output_format), path) # move left format files skeleton_remove_blocks(path, output_format) # Get missing assets diff --git a/R/utils.R b/R/utils.R index 60ba53f57..a54a89bfd 100644 --- a/R/utils.R +++ b/R/utils.R @@ -457,19 +457,6 @@ files_cache_dirs = function(dir = '.') { out } -# file.rename() does not work if target directory is not empty, so we just copy -# everything from `from` to `to`, and delete `from` -move_dir = function(from, to) { - if (!dir_exists(to)) return(file.rename(from, to)) - to_copy = list.files(from, full.names = TRUE) - if (length(to_copy) == 0 || - any(file.copy(list.files(from, full.names = TRUE), to, recursive = TRUE)) - ) unlink(from, recursive = TRUE) - invisible(TRUE) -} - -move_dirs = function(from, to) mapply(move_dir, from, to) - #' @importFrom xfun existing_files existing_r = function(base) { x = apply(expand.grid(base, c('R', 'r')), 1, paste, collapse = '.') diff --git a/inst/scripts/render_one.R b/inst/scripts/render_one.R index 64f565e0f..22512c24f 100644 --- a/inst/scripts/render_one.R +++ b/inst/scripts/render_one.R @@ -14,7 +14,7 @@ local({ out_expected = xfun::with_ext(args[1], '.md') if (out != out_expected) { - file.rename(out, out_expected) + file_rename(out, out_expected) attributes(out_expected) = attributes(out) out = out_expected } diff --git a/tests/testit/test-utils.R b/tests/testit/test-utils.R index de32ba206..0967144ce 100644 --- a/tests/testit/test-utils.R +++ b/tests/testit/test-utils.R @@ -165,27 +165,3 @@ assert('fence_theorems() converts the knitr engine syntax to fenced Divs', { res = fence_theorems(text = old) (unclass(res) %==% old) }) - -assert("move_dir works", { - # work in temp dir - dir.create(tmp_dir <- tempfile()) - owd = setwd(tmp_dir) - - # empty dir is not moved but deleted - dir.create("dest") - dir.create("empty") - move_dir("empty", "dest") - (dir.exists("empty") %==% FALSE) - - # files are moved correctly - dir.create("filled") - dummy_files = c("dummy1", "dummy2") - file.create(file.path("filled", dummy_files)) - move_dir("filled", "dest") - (dir.exists("filled") %==% FALSE) - (list.files("dest") %==% dummy_files) - - # remove temp dir - setwd(owd) - unlink(tmp_dir, recursive = TRUE) -})