Managing dependencies and Continuous Integration ๐Ÿ•

This is how we might use another package in a script:

lib_summary <- function(sizes = FALSE) {
  if (!is.logical(sizes)) {
    stop("'sizes' must be logical (TRUE/FALSE).")
  }
  
  pkgs <- utils::installed.packages()
  pkg_tbl <- table(pkgs[, "LibPath"])
  pkg_df <- as.data.frame(pkg_tbl, stringsAsFactors = FALSE)
  names(pkg_df) <- c("Library", "n_packages")

  if (sizes) {
    library("fs")
    pkg_df$lib_size <- vapply(
      pkg_df$Library,
      function(x) {
        sum(file_size(dir_ls(x, recurse = TRUE)))
      },
      FUN.VALUE = numeric(1)
    )
  }
  pkg_df
}

But this is how we do it in a package:

use_package("fs")

Use fs in our function:

lib_summary <- function(sizes = FALSE) {
  pkgs <- utils::installed.packages()
  pkg_tbl <- table(pkgs[, "LibPath"])
  pkg_df <- as.data.frame(pkg_tbl, stringsAsFactors = FALSE)
  names(pkg_df) <- c("Library", "n_packages")

  if (sizes) {
    pkg_df$lib_size <- vapply(
      pkg_df$Library,
      function(x) {
        sum(fs::file_size(fs::dir_ls(x, recurse = TRUE)))
      },
      FUN.VALUE = numeric(1)
    )
  }
  pkg_df
}
test() # failure for unused argument

Update tests

test_that("lib_summary fails appropriately", {
  expect_error(lib_summary(sizes = "foo"), "not interpretable as logical")
})

test_that("sizes argument works", {
  res <- lib_summary(sizes = TRUE)
  expect_equal(names(res), c("Library", "n_packages", "lib_size"))
  expect_type(res$lib_size, "double")
})
check() # will warn about undocumented parameter

Update documentation

Ctrl+Alt+Shift+R will insert the spot for the sizes param

#' Provides a brief summary of the package libraries on your machine
#'
#' @param sizes Should the sizes of the libraries be calculated?
#'   Logical; default `FALSE`.
#'
#' @return A data.frame containing the count of packages in each of the user's
#'   libraries. A `lib_size` column is included if `sizes = TRUE`.
#' @export
#'
#' @examples
#' lib_summary()
#' lib_summary(sizes = TRUE)
document()

check()

Alternative: use importFrom

use_import_from("purrr", "map_dbl")

Use map_dbl() directly without namespace qualifier:

lib_summary <- function(sizes = FALSE) {
  pkgs <- utils::installed.packages()
  pkg_tbl <- table(pkgs[, "LibPath"])
  pkg_df <- as.data.frame(pkg_tbl, stringsAsFactors = FALSE)
  names(pkg_df) <- c("Library", "n_packages")
  
  if (sizes) {
    pkg_df$lib_size <- map_dbl(
      pkg_df$Library,
      ~ sum(fs::file_size(fs::dir_ls(.x, recurse = TRUE)))
    )
  }
  pkg_df
}

Automated checking with GitHub Actions

use_github_action()
Which action do you want to add? (0 to exit)
(See <https://github.com/r-lib/actions/tree/v2/examples> for other options) 

1: check-standard: Run `R CMD check` on Linux, macOS, and Windows
2: test-coverage: Compute test coverage and report to https://about.codecov.io
3: pr-commands: Add /document and /style commands for pull requests

Selection: 1
โœ” Setting active project to '/Users/andy/dev/libminer'
โœ” Creating '.github/'
โœ” Adding '^\\.github$' to '.Rbuildignore'
โœ” Adding '*.html' to '.github/.gitignore'
โœ” Creating '.github/workflows/'
โœ” Saving 'r-lib/actions/examples/check-standard.yaml@v2' to '.github/workflows/R-CMD-check.yaml'
โ€ข Learn more at <https://github.com/r-lib/actions/blob/v2/examples/README.md>.
โœ” Adding R-CMD-check badge to 'README.Rmd'
โ€ข Re-knit 'README.Rmd' with `devtools::build_readme()`
build_readme()
โ„น Installing libminer in temporary library
โ„น Building /Users/andy/dev/libminer/README.Rmd