library(testthat)
# Load already included functions if relevant pkgload::load_all(export_all = FALSE)
#' dependencies_file_text #' #' Create the text of create_dependencies_file() #' #' @param ll a vector of all packages #' @param remotes_orig a vector of remotes #' @param install_only_if_missing Logical Modify the installation instructions to check, beforehand, if the packages are missing . (default FALSE) #' @importFrom glue glue #' @return a list #' #' @noRd dependencies_file_text <- function(ll, remotes_orig, install_only_if_missing = FALSE){ if (length(remotes_orig) != 0) { remotes_orig_pkg <- gsub("^.*/|^local::|.git$", "", remotes_orig) remotes_without_orig <- gsub("^.*::/{0,1}", "", remotes_orig) # Remove remotes from ll ll <- ll[!ll %in% remotes_orig_pkg] # Install script inst_remotes <- remotes_orig # _If no (), then bioc w.bioc <- grepl("bioc::", remotes_orig) inst_remotes[w.bioc] <- glue("remotes::install_bioc('{remotes_without_orig[w.bioc]}')") # _If no (), then local w.local <- grepl("local::", remotes_orig) inst_remotes[w.local] <- glue("remotes::install_local('{remotes_without_orig[w.local]}')") # _If no (), then git w.git <- grepl("git::", remotes_orig) inst_remotes[w.git] <- glue("remotes::install_git('{remotes_without_orig[w.git]}')") # _If no (), then git w.gitlab <- grepl("gitlab::", remotes_orig) inst_remotes[w.gitlab] <- glue("remotes::install_gitlab('{remotes_without_orig[w.gitlab]}')") # _If no (), then github w.github <- !grepl("\\(", remotes_orig) & !grepl("remotes::", inst_remotes) inst_remotes[w.github] <- glue("remotes::install_github('{remotes_without_orig[w.github]}')") # Install only if missing if (isTRUE(install_only_if_missing)) { inst_remotes <- paste0( "if(isFALSE(requireNamespace('", remotes_orig_pkg, "', quietly = TRUE))) {","message('installation of " ,remotes_orig_pkg,"');", inst_remotes, "}" ) install_pkg_remote <- "if(isFALSE(requireNamespace('remotes', quietly = TRUE))) {install.packages(\"remotes\")}" } else { install_pkg_remote <- "install.packages(\"remotes\")" } # _Others (WIP...) inst_remotes[!(w.github | w.local | w.bioc | w.git | w.gitlab)] <- remotes_orig[!(w.github | w.local | w.bioc | w.git | w.gitlab)] # Store content remotes_content <- paste("# Remotes ----", install_pkg_remote, paste(inst_remotes, collapse = "\n"), sep = "\n") } else { remotes_content <- "# No Remotes ----" } if (length(ll) != 0) { attachment_content <- glue::glue( ' # Attachments ---- to_install <- c("*{glue::glue_collapse(as.character(ll), sep="\\", \\"")}*") for (i in to_install) { message(paste("looking for ", i)) if (!requireNamespace(i, quietly = TRUE)) { message(paste(" installing", i)) install.packages(i) } }\n\n', .open = "*{", .close = "}*") } else { attachment_content <- glue::glue( ' # No attachments ---- \n\n', .open = "*{", .close = "}*") } content <- list("remotes_content" = remotes_content, "attachment_content" = attachment_content) return(content) }
test_that("dependencies_file_text works", { expect_true(inherits(dependencies_file_text, "function")) remo <- c("ThinkR-open/attachment", "local::/path/fakelocal", "gitlab::statnmap/fakepkg", "bioc::3.3/fakepkgbioc", "git::https://github.com/fakepkggit.git", "git::https://MyForge.com/fakepkggit2r", "ThinkR-open/fusen") ll <- c("knitr", "magrittr", "rmarkdown", "testthat") thetext <- dependencies_file_text(ll, remo, FALSE) expect_equal(class(thetext), "list") expect_length(thetext, 2) expect_equal(names(thetext), c("remotes_content","attachment_content")) expect_equal(thetext[1], list(remotes_content = "# Remotes ----\ninstall.packages(\"remotes\")\nremotes::install_github('ThinkR-open/attachment')\nremotes::install_local('path/fakelocal')\nremotes::install_gitlab('statnmap/fakepkg')\nremotes::install_bioc('3.3/fakepkgbioc')\nremotes::install_git('https://github.com/fakepkggit.git')\nremotes::install_git('https://MyForge.com/fakepkggit2r')\nremotes::install_github('ThinkR-open/fusen')")) expect_equal(thetext[2], list(attachment_content = structure("# Attachments ----\nto_install <- c(\"knitr\", \"magrittr\", \"rmarkdown\", \"testthat\")\n for (i in to_install) {\n message(paste(\"looking for \", i))\n if (!requireNamespace(i, quietly = TRUE)) {\n message(paste(\" installing\", i))\n install.packages(i)\n }\n }\n", class = c("glue", "character")))) remo <- NULL ll <- NULL thetext2 <- dependencies_file_text(ll, remo, FALSE) expect_equal(class(thetext2), "list") expect_length(thetext2, 2) expect_equal(names(thetext2), c("remotes_content", "attachment_content")) expect_equal(thetext2[1],list(remotes_content = "# No Remotes ----")) expect_equal(thetext2[2], list(attachment_content = structure("# No attachments ----\n \n", class = c("glue", "character")))) })
create_dependencies_file()
creates "inst/dependencies.R" file with the instructions to install all dependencies listed in your "DESCRIPTION".
This accounts for the "Remotes" field and write instructions accordingly.
Use create_dependencies_file(to = NULL)
to only retrieve the output as a list of character and not save a "inst/dependencies.R" file in your project.
This can be used in a Readme.Rmd
file for instance, to get the full list of each dependency to install and how, from any "DESCRIPTION" file.
#' Create the list of instructions to install dependencies from a DESCRIPTION file #' #' Outputs the list of instructions and a "dependencies.R" file with instructions in the "inst/" directory #' #' @param path path to the DESCRIPTION file #' @param field DESCRIPTION field to parse, "Import" and "Depends" by default. Can add "Suggests" #' @param to path where to save the dependencies file. Set to "inst/dependencies.R" by default. Set to `NULL` if you do not want the file, but only the instructions as a list of character. #' @param open_file Logical. Open the file created in an editor #' @param ignore_base Logical. Whether to ignore package coming with base, as they cannot be installed (default TRUE) #' @param install_only_if_missing Logical Modify the installation instructions to check, beforehand, if the packages are missing . (default FALSE) #' @export #' @return List of R instructions to install all dependencies from a DESCRIPTION file. Side effect: creates a R file containing these instructions. #' @importFrom glue glue glue_collapse #' @importFrom desc description #' @importFrom utils packageDescription #' #' @examples create_dependencies_file <- function(path = "DESCRIPTION", field = c("Depends", "Imports"), to = "inst/dependencies.R", open_file = TRUE, ignore_base = TRUE, install_only_if_missing = FALSE) { # get all packages ll <- att_from_description(path = path, field = field) # get pkg in remotes if (isTRUE(ignore_base)) { to_remove <- which(lapply(ll , packageDescription, field = "Priority") == "base") if (length(to_remove) > 0) { ll <- ll[-to_remove] } } desc <- description$new(path) # Get previous dependencies in Description in case version is set remotes_orig <- desc$get_remotes() content <- dependencies_file_text(ll = ll, remotes_orig = remotes_orig, install_only_if_missing = install_only_if_missing) if (!is.null(to)) { if (!dir.exists(dirname(to))) { dir.create(dirname(to), recursive = TRUE, showWarnings = FALSE) dir_to <- normalizePath(dirname(to)) } else { dir_to <- normalizePath(dirname(to)) } the_file <- file.path(dir_to, basename(to)) # file.create(the_file) cat(unlist(content), sep = "\n", file = the_file) if (interactive() && open_file) { utils::file.edit(file, editor = "internal") } return(invisible(content)) } else { return(content) } }
# Create a fake package tmpdir <- tempfile(pattern = "depsfile") dir.create(tmpdir) file.copy(system.file("dummypackage",package = "attachment"), tmpdir, recursive = TRUE) dummypackage <- file.path(tmpdir, "dummypackage") # Create the dependencies commands but no file create_dependencies_file( path = file.path(dummypackage,"DESCRIPTION"), to = NULL, open_file = FALSE) # Create the dependencies files in the package create_dependencies_file( path = file.path(dummypackage,"DESCRIPTION"), to = file.path(dummypackage, "inst/dependencies.R"), open_file = FALSE) list.files(file.path(dummypackage, "inst")) # browseURL(dummypackage) # Clean temp files after this example unlink(tmpdir, recursive = TRUE)
# Copy package in a temporary directory tmpdir <- tempfile(pattern = "pkgdeps") dir.create(tmpdir) file.copy(system.file("dummypackage",package = "attachment"), tmpdir, recursive = TRUE) dummypackage <- file.path(tmpdir, "dummypackage") # browseURL(dummypackage) # Create the dependencies commands but no file test_that("create_dependencies_file does not create file with NULL", { out_list <- create_dependencies_file( path = file.path(dummypackage, "DESCRIPTION"), to = NULL, field = c("Depends", "Imports", "Suggests"), open_file = FALSE) expect_false(file.exists( file.path(dummypackage, "inst", "dependencies.R"))) }) create_dependencies_file( path = file.path(dummypackage, "DESCRIPTION"), to = file.path(dummypackage, "inst", "dependencies.R"), field = c("Depends", "Imports", "Suggests"), open_file = FALSE) expect_true(file.exists( file.path(dummypackage, "inst", "dependencies.R"))) dep_file_without_remotes <- readLines(file.path(dummypackage, "inst", "dependencies.R")) test_that("create-dependencies-file works without remotes", { expect_equal(dep_file_without_remotes[1], "# No Remotes ----") expect_equal(dep_file_without_remotes[3], "to_install <- c(\"glue\", \"knitr\", \"magrittr\", \"rmarkdown\", \"stringr\", \"testthat\")") }) # Add remotes in DESCRIPTION # Test internal_remotes_to_desc ---- tmpdir <- tempfile(pattern = "pkgwithremotes") dir.create(tmpdir) file.copy(system.file("dummypackage",package = "attachment"), tmpdir, recursive = TRUE) dummypackage <- file.path(tmpdir, "dummypackage") path.d <- file.path(dummypackage, "DESCRIPTION") cat(c("Remotes:\n ThinkR-open/attachment,\n local::/path/fakelocal,\n gitlab::statnmap/fakepkg,\n bioc::3.3/fakepkgbioc,\n git::https://github.com/fakepkggit.git,\n git::https://MyForge.com/fakepkggit2r,\n ThinkR-open/fusen\n"), append = TRUE, file = path.d) new_desc <- readLines(path.d) create_dependencies_file(path = file.path(dummypackage,"DESCRIPTION"), to = file.path(dummypackage, "inst/dependencies.R"), field = c("Depends", "Imports", "Suggests"), open_file = FALSE) dep_file_with_remotes <- readLines(file.path(tmpdir, "dummypackage", "inst/dependencies.R")) test_that("create-dependencies-file works with remotes", { expect_equal(dep_file_with_remotes[1], "# Remotes ----") expect_equal(dep_file_with_remotes[3], "remotes::install_github('ThinkR-open/attachment')") expect_equal(dep_file_with_remotes[4], "remotes::install_local('path/fakelocal')") expect_equal(dep_file_with_remotes[5], "remotes::install_gitlab('statnmap/fakepkg')") expect_equal(dep_file_with_remotes[6], "remotes::install_bioc('3.3/fakepkgbioc')") expect_equal(dep_file_with_remotes[7], "remotes::install_git('https://github.com/fakepkggit.git')") expect_equal(dep_file_with_remotes[8], "remotes::install_git('https://MyForge.com/fakepkggit2r')") expect_equal(dep_file_with_remotes[9], "remotes::install_github('ThinkR-open/fusen')") expect_equal(dep_file_with_remotes[11], "to_install <- c(\"glue\", \"knitr\", \"magrittr\", \"rmarkdown\", \"stringr\", \"testthat\")") }) create_dependencies_file(path = file.path(dummypackage,"DESCRIPTION"), to = file.path(dummypackage, "inst/dependencies.R"), field = c("Depends", "Imports", "Suggests"), open_file = FALSE, install_only_if_missing = TRUE) dep_file_with_remotes_install_only_if_missing <- readLines(file.path(tmpdir, "dummypackage", "inst/dependencies.R")) test_that("create-dependencies-file works with remotes install_only_if_missing", { expect_equal(dep_file_with_remotes_install_only_if_missing[1], "# Remotes ----") expect_equal(dep_file_with_remotes_install_only_if_missing[3], "if(isFALSE(requireNamespace('attachment', quietly = TRUE))) {message('installation of attachment');remotes::install_github('ThinkR-open/attachment')}") expect_equal(dep_file_with_remotes_install_only_if_missing[4], "if(isFALSE(requireNamespace('fakelocal', quietly = TRUE))) {message('installation of fakelocal');remotes::install_local('path/fakelocal')}") expect_equal(dep_file_with_remotes_install_only_if_missing[5], "if(isFALSE(requireNamespace('fakepkg', quietly = TRUE))) {message('installation of fakepkg');remotes::install_gitlab('statnmap/fakepkg')}") expect_equal(dep_file_with_remotes_install_only_if_missing[6], "if(isFALSE(requireNamespace('fakepkgbioc', quietly = TRUE))) {message('installation of fakepkgbioc');remotes::install_bioc('3.3/fakepkgbioc')}") expect_equal(dep_file_with_remotes_install_only_if_missing[7], "if(isFALSE(requireNamespace('fakepkggit', quietly = TRUE))) {message('installation of fakepkggit');remotes::install_git('https://github.com/fakepkggit.git')}") expect_equal(dep_file_with_remotes_install_only_if_missing[8], "if(isFALSE(requireNamespace('fakepkggit2r', quietly = TRUE))) {message('installation of fakepkggit2r');remotes::install_git('https://MyForge.com/fakepkggit2r')}") expect_equal(dep_file_with_remotes_install_only_if_missing[9], "if(isFALSE(requireNamespace('fusen', quietly = TRUE))) {message('installation of fusen');remotes::install_github('ThinkR-open/fusen')}") expect_equal(dep_file_with_remotes_install_only_if_missing[11], "to_install <- c(\"glue\", \"knitr\", \"magrittr\", \"rmarkdown\", \"stringr\", \"testthat\")") }) # Clean temp files after this example unlink(tmpdir, recursive = TRUE)
# Run but keep eval=FALSE to avoid infinite loop # Execute in the console directly fusen::inflate(flat_file = "dev/flat_create_dependencies_file.Rmd", vignette_name = "Create dependencies file", check = FALSE, open_vignette = FALSE, overwrite = TRUE, document = TRUE)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.