The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
The ‘goodpractice’ repository includes a ‘Makefile’. This allows many commands to be run directly from a shell console (rather than within an R session). The default behaviour is to list all options:
#> Usage: make [target]
#> allcon Run 'allcontributors::add_contributors'
#> check Run `rcmdcheck`
#> clean Clean all junk files, including all pkgdown docs
#> doc Update package documentation with `roxygen2`
#> help Show this help
#> init Initialize pkgdown site
#> knith Render README as HTML
#> knitr Render README as markdown
#> open Open main HTML vignette in browser
#> pkgcheck Run `pkgcheck` and print results to screen.
#> pkgdown Build entire pkgdown site
#> pkgdowncheck Run check_pkgdown function
#> test Run test suite
#> vignette Build pkgdown article
Any of those options can then be run as
make <command>. For example, this command checks for
any issues with the pkgdown site:
#> ✔ No problems found
Note that some of the Makefile options depend on
additional packages which may need to be installed. These include:
Checks are defined in groups. Each group is generally defined within
two files: 1. A prep_<group>.R file for collecting
data needed for the check 2. A chk_<group>.R file
defining the output structure of the check.
The R/ directory here consistns almost entirely of
paired files defining each check group:
#> api.R
#> chk_avoided_packages.R
#> chk_code_structure.R
#> chk_covr.R
#> chk_cyclocomp.R
#> chk_description.R
#> chk_generic.R
#> chk_lintr.R
#> chk_namespace.R
#> chk_rcmdcheck.R
#> chk_rd.R
#> chk_revdep.R
#> chk_roxygen2.R
#> chk_spelling.R
#> chk_tidyverse.R
#> chk_urlchecker.R
#> chk_vignette.R
#> customization.R
#> gp.R
#> lists.R
#> package.R
#> prep_covr.R
#> prep_cyclocomp.R
#> prep_description.R
#> prep_lintr.R
#> prep_namespace.R
#> prep_rcmdcheck.R
#> prep_rd.R
#> prep_revdep.R
#> prep_roxygen2.R
#> prep_source.R
#> prep_spelling.R
#> prep_tidyverse.R
#> prep_urlchecker.R
#> prep_utils.R
#> prep_vignette.R
#> print.R
#> rstudio_markers.R
#> treesitter.R
#> utils.R
An example is the cyclocomp check, which is largely a
wrapper around the external cyclocomp
package. The prep_cyclocomp.R file looks like this:
#>
#> #' @include lists.R prep_utils.R
#> #' @importFrom cyclocomp cyclocomp_package_dir
#>
#> PREPS$cyclocomp <- function(state, path = state$path, quiet) {
#> run_prep_step(state, "cyclocomp", function(path) {
#> cyclocomp_package_dir(path)
#> }, path = path, silent = quiet)
#> }
That preparation steps runs the
cyclocomp::cyclocomp_package_dir() function in the source
directory of the package being checked. The corresponding
check_cyclocomp.R file then uses a variable called
state that is accessible to all functions within the
package. The line above PREPS$cyclocomp <- creates an
entry of state$cyclocomp containing the results of the
preparation step that can then be accessed to defined the check output
in R/chk_cyclocomp.R:
#>
#> #' @include lists.R
#>
#> #' @noRd
#> cyclocomp_limit <- function() {
#> getOption("goodpractice.cyclocomp_limit", 15)
#> }
#>
#> CHECKS$cyclocomp <- make_check(
#>
#> description = "Functions are simple",
#> tags = c("info", "code complexity"),
#> preps = "cyclocomp",
#>
#> gp = function(state) {
#> limit <- cyclocomp_limit()
#> cyc <- state$cyclocomp
#> long <- which(cyc$cyclocomp > limit)
#> funcs <- paste0(
#> cyc$name[long],
#> " (", cyc$cyclocomp[long], ")",
#> collapse = ", "
#> )
#> paste0(
#> "write short and simple functions.",
#> " These functions have high",
#> " cyclomatic complexity (>", limit, "): ",
#> funcs, ". ",
#> "You can make them easier to reason about",
#> " by encapsulating distinct steps",
#> " of your function into subfunctions."
#> )
#> },
#>
#> check = function(state) {
#> if (inherits(state$cyclocomp, "try-error")) return(na_result())
#> check_result(all(state$cyclocomp$cyclocomp <= cyclocomp_limit()))
#> }
#> )
All checks following this general pattern of defining
PREPS$<group> <- entries containing data from the
check, then defining CHECKS$<group> entries for
output format, using state$<group> to access the
check data. The best way to learn about check structure is to examine
some of the existing files.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.