From bd4e660ef73ae7e40bb96e308e78ddfc91885730 Mon Sep 17 00:00:00 2001 From: Henrik Bengtsson Date: Thu, 24 Sep 2020 07:44:50 -0700 Subject: [PATCH] CI/REVDEP: Modernizing --- .github/workflows/R-CMD-check.yaml | 45 +++-- CONDUCT.md | 147 +++++++++++------ NEWS | 6 +- README.md | 22 ++- revdep/run.R | 257 +---------------------------- 5 files changed, 139 insertions(+), 338 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index d305d8cd..95c87eca 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -4,31 +4,33 @@ name: R-CMD-check jobs: R-CMD-check: + if: "! contains(github.event.head_commit.message, '[ci skip]')" + runs-on: ${{ matrix.config.os }} + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) - if: "! contains(github.event.head_commit.message, '[ci skip]')" - + strategy: fail-fast: false matrix: config: - - { os: windows-latest, r: '3.5'} - - { os: windows-latest, r: '3.6'} - - { os: windows-latest, r: '4.0'} - - { os: windows-latest, r: 'devel'} - - { os: macOS-latest, r: '3.5'} - - { os: macOS-latest, r: '3.6'} - - { os: macOS-latest, r: '4.0'} - - { os: macOS-latest, r: 'devel'} - - { os: ubuntu-16.04, r: '3.4', cran: "https://demo.rstudiopm.com/all/__linux__/xenial/latest"} - - { os: ubuntu-16.04, r: '3.5', cran: "https://demo.rstudiopm.com/all/__linux__/xenial/latest"} - - { os: ubuntu-16.04, r: '3.6', cran: "https://demo.rstudiopm.com/all/__linux__/xenial/latest"} - - { os: ubuntu-16.04, r: '4.0', cran: "https://demo.rstudiopm.com/all/__linux__/xenial/latest"} + - {os: windows-latest, r: 'devel'} + - {os: windows-latest, r: 'release'} + - {os: windows-latest, r: 'oldrel'} + - {os: macOS-latest, r: 'devel'} + - {os: macOS-latest, r: 'release'} + - {os: macOS-latest, r: 'oldrel'} + - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-20.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-20.04, r: '3.4', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} + - {os: ubuntu-20.04, r: '3.2', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"} env: R_REMOTES_NO_ERRORS_FROM_WARNINGS: true - CRAN: ${{ matrix.config.cran }} - + R_FUTURE_RNG_ONMISUSE: error + RSPM: ${{ matrix.config.rspm }} + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 @@ -51,8 +53,8 @@ jobs: uses: actions/cache@v1 with: path: ${{ env.R_LIBS_USER }} - key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('.github/depends.Rds') }} - restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}- + key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} + restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- - name: Install system dependencies if: runner.os == 'Linux' @@ -75,7 +77,7 @@ jobs: pkgs <- installed.packages()[, "Package"] sessioninfo::session_info(pkgs, include_base = TRUE) shell: Rscript {0} - + - name: Check env: _R_CHECK_CRAN_INCOMING_: false @@ -88,8 +90,3 @@ jobs: with: name: ${{ runner.os }}-r${{ matrix.config.r }}-results path: check - - - name: Test coverage - if: matrix.config.os == 'ubuntu-16.04' && matrix.config.r == '3.6-9000' - run: | - Rscript -e "install.packages('covr')" -e 'covr::codecov(token = "${{secrets.CODECOV_TOKEN}}")' diff --git a/CONDUCT.md b/CONDUCT.md index 9c1c6216..2b3225e0 100644 --- a/CONDUCT.md +++ b/CONDUCT.md @@ -1,74 +1,129 @@ + # Contributor Covenant Code of Conduct ## Our Pledge -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. ## Our Standards -Examples of behavior that contributes to creating a positive environment -include: +Examples of behavior that contributes to a positive environment for our +community include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community -Examples of unacceptable behavior by participants include: +Examples of unacceptable behavior include: -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission +* Publishing others' private information, such as a physical or email + address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting -## Our Responsibilities +## Enforcement Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +reported to the project lead. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/NEWS b/NEWS index 8f7432ea..882e7d62 100644 --- a/NEWS +++ b/NEWS @@ -33,7 +33,7 @@ BUG FIXES: * colDiffs() and rowDiffs() gave an error if argument 'dim.' was of type numeric rather than type integer. - * varDiff(), sdDiff(), madDiff(), iqrDiff(), and the corrsponding row- and + * varDiff(), sdDiff(), madDiff(), iqrDiff(), and the corresponding row- and column functions silently treated a 'diff' less than zero as diff = 0. Now an error is produced. @@ -746,7 +746,7 @@ NEW FEATURES: DEPRECATED AND DEFUNCT: - * Calling indexByRow(X) with a matrix 'X' is deprectated. Instead call it + * Calling indexByRow(X) with a matrix 'X' is deprecatated. Instead call it with indexByRow(dim(X)). @@ -1098,7 +1098,7 @@ Version: 0.7.1 [2013-04-23] NEW FEATURES: - * Added argument 'preserveShape' to colRanks(). For backwardcompatibility + * Added argument 'preserveShape' to colRanks(). For backward compatibility the default is preserveShape = FALSE, but it may change in the future. BUG FIXES: diff --git a/README.md b/README.md index 96195a96..140d89b0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ + + + # matrixStats: Functions that Apply to Rows and Columns of Matrices (and to Vectors) The matrixStats package provides highly optimized functions for @@ -48,28 +51,29 @@ R package matrixStats is available on [CRAN](https://cran.r-project.org/package= install.packages("matrixStats") ``` + ### Pre-release version To install the pre-release version that is available in Git branch `develop` on GitHub, use: ```r -remotes::install_github("HenrikBengtsson/matrixStats@develop") +remotes::install_github("HenrikBengtsson/matrixStats", ref="develop") ``` This will install the package from source. Because of this and because this package also compiles native code, Windows users need to have [Rtools](https://cran.r-project.org/bin/windows/Rtools/) installed and macOS users need to have [Xcode](https://developer.apple.com/xcode/) installed. - - ## Contributions -This Git repository uses the [Git Flow](http://nvie.com/posts/a-successful-git-branching-model/) branching model (the [`git flow`](https://github.com/petervanderdoes/gitflow-avh) extension is useful for this). The [`develop`](https://github.com/HenrikBengtsson/matrixStats/tree/develop) branch contains the latest contributions and other code that will appear in the next release, and the [`master`](https://github.com/HenrikBengtsson/matrixStats) branch contains the code of the latest release, which is exactly what is currently on [CRAN](https://cran.r-project.org/package=matrixStats). +This Git repository uses the [Git Flow](https://nvie.com/posts/a-successful-git-branching-model/) branching model (the [`git flow`](https://github.com/petervanderdoes/gitflow-avh) extension is useful for this). The [`develop`](https://github.com/HenrikBengtsson/matrixStats/tree/develop) branch contains the latest contributions and other code that will appear in the next release, and the [`master`](https://github.com/HenrikBengtsson/matrixStats) branch contains the code of the latest release, which is exactly what is currently on [CRAN](https://cran.r-project.org/package=matrixStats). Contributing to this package is easy. Just send a [pull request](https://help.github.com/articles/using-pull-requests/). When you send your PR, make sure `develop` is the destination branch on the [matrixStats repository](https://github.com/HenrikBengtsson/matrixStats). Your PR should pass `R CMD check --as-cran`, which will also be checked by Travis CI and AppVeyor CI when the PR is submitted. +We abide to the [Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/) of Contributor Covenant. + ## Software status -| Resource: | CRAN | Travis CI | AppVeyor | -| ------------- | ------------------- | --------------- | ---------------- | -| _Platforms:_ | _Multiple_ | _Linux & macOS_ | _Windows_ | -| R CMD check | CRAN version | Build status | Build status | -| Test coverage | | Coverage Status | | +| Resource | CRAN | GitHub Actions | Travis CI | AppVeyor CI | +| ------------- | ------------------- | ------------------- | --------------- | ---------------- | +| _Platforms:_ | _Multiple_ | _Multiple_ | _Linux & macOS_ | _Windows_ | +| R CMD check | CRAN version | Build status | Build status | Build status | +| Test coverage | | | Coverage Status | | diff --git a/revdep/run.R b/revdep/run.R index 68aa3573..2128b55a 100755 --- a/revdep/run.R +++ b/revdep/run.R @@ -1,24 +1,4 @@ #!/usr/bin/env Rscript -if (!requireNamespace("revdepcheck")) { - stop('Install revdepcheck: remotes::install_github("r-lib/revdepcheck")') -} -library("revdepcheck") -options(warn = 1L) - -available_cores <- function() { - getenv <- function(name) { - as.integer(Sys.getenv(name, NA_character_)) - } - getopt <- function(name) { - as.integer(getOption(name, NA_integer_)) - } - if (is.finite(n <- getopt("mc.cores") + 1L)) return(n) - if (is.finite(n <- getopt("Ncpus") + 1L)) return(n) - if (is.finite(n <- getenv("PBS_NUM_PPN"))) return(n) - if (is.finite(n <- getenv("SLURM_CPUS_PER_TASK"))) return(n) - if (is.finite(n <- getenv("NSLOTS"))) return(n) - 1L -} precheck <- function() { ## WORKAROUND: Remove checked pkgs that use file links, which otherwise @@ -26,239 +6,4 @@ precheck <- function() { unlink("revdep/checks/aroma.affymetrix", recursive = TRUE) } -check <- function() { - if (file_test("-f", p <- Sys.getenv("R_CHECK_ENVIRON", "~/.R/check.Renviron"))) { - cat(sprintf("R CMD check will use env vars from %s\n", sQuote(p))) - cat(sprintf("To disable, set 'R_CHECK_ENVIRON=false' (a fake pathname)\n")) - } - - envs <- Sys.getenv() - envs <- envs[grep("^_?R_CHECK_", names(envs))] - if (length(envs) > 0L) { - envs <- sprintf(" %02d. %s=%s", seq_along(envs), names(envs), envs) - envs <- paste(envs, collapse="\n") - cat(sprintf("Detected R-specific env vars that may affect R CMD check:\n%s\n", envs)) - } - - precheck() - revdep_check(bioc = TRUE, num_workers = available_cores(), - timeout = as.difftime(30, units = "mins"), quiet = FALSE) -} - - -todo <- function() { - pkgs <- tryCatch(revdep_todo(), error = function(ex) NA) - if (identical(pkgs, NA)) { - cat("Revdepcheck has not been initiated\n") - return() - } - pkgs <- subset(pkgs, status == "todo") - if (nrow(pkgs) == 0) { - cat("There are no packages on the revdepcheck todo list\n") - } else { - cat(sprintf("%d. %s\n", seq_len(nrow(pkgs)), pkgs$package)) - } -} - -parse_pkgs <- function(pkgs) { - pkgs <- unlist(strsplit(pkgs, split = ",", fixed = TRUE)) - pkgs <- gsub("[ \t'\"‘’]", "", pkgs) - sort(unique(pkgs)) -} - -revdep_init <- function() { - if (!revdepcheck:::db_exists(".")) revdepcheck:::db_setup(".") -} - -revdep_todo_reset <- function() { - revdep_init() - db <- revdepcheck:::db(".") - df <- data.frame(package = character(0L), stringsAsFactors = FALSE) - DBI::dbWriteTable(db, "todo", df, overwrite = TRUE, append = FALSE) -} - -revdep_this_package <- local({ - pkg <- NULL - function() { - if (is.null(pkg)) pkg <<- desc::desc(file = "DESCRIPTION")$get("Package") - pkg - } -}) - -revdep_children <- local({ - cache <- list() - function(pkg = NULL) { - if (is.null(pkg)) pkg <- revdep_this_package() - pkgs <- cache[[pkg]] - if (is.null(pkgs)) { - pkgs <- revdepcheck:::cran_revdeps(pkg) - pkgs <- setdiff(pkgs, pkg) ## WORKAROUND - cache[[pkg]] <- pkgs - } - pkgs - } -}) - -revdep_pkgs_with_status <- function(status = c("error", "failure")) { - status <- match.arg(status) - res <- revdepcheck::revdep_summary() - if (status == "failure") { - names(which(sapply(res, FUN = .subset2, "status") == "E")) - } else if (status == "error") { - field <- switch(status, error = "errors") - has_status <- vapply(res, FUN = function(x) { - z <- x[["new"]][[field]] - is.character(z) && any(nchar(z) > 0) - }, FUN.VALUE = NA, USE.NAMES = TRUE) - has_status <- !is.na(has_status) & has_status - names(has_status)[has_status] - } -} - -revdep_preinstall_libs <- function() { - lib_paths <- .libPaths() - lib_paths[1] <- sprintf("%s-revdepcheck", lib_paths[1]) - dir.create(lib_paths[1], recursive = TRUE, showWarnings = FALSE) - lib_paths -} - -revdep_preinstall <- function(pkgs) { - oopts <- options(Ncpus = available_cores()) - lib_paths_org <- .libPaths() - on.exit({ - .libPaths(lib_paths_org) - options(oopts) - }) - .libPaths(revdep_preinstall_libs()) - - pkgs <- unique(pkgs) - message(sprintf("Triggering crancache builds by pre-installing %d packages: %s", length(pkgs), paste(sQuote(pkgs), collapse = ", "))) - message(".libPaths():") - message(paste(paste0(" - ", .libPaths()), collapse = "\n")) - ## Install one-by-one to update cache sooner - for (kk in seq_along(pkgs)) { - pkg <- pkgs[kk] - message(sprintf("Pre-installing package %d of %d: %s (Ncpus = %d)", - kk, length(pkgs), pkg, getOption("Ncpus", 1L))) - crancache::install_packages(pkg, dependencies = c("Depends", "Imports", "LinkingTo", "Suggests")) - } -} - -revdep_preinstall_update <- function() { - oopts <- options(Ncpus = available_cores()) - lib_paths_org <- .libPaths() - on.exit({ - .libPaths(lib_paths_org) - options(oopts) - }) - .libPaths(revdep_preinstall_libs()) - - message("Update crancache for all pre-installing packages:") - message(".libPaths():") - message(paste(paste0(" - ", .libPaths()), collapse = "\n")) - message(sprintf("Ncpus=%d", getOption("Ncpus", 1L))) - crancache::update_packages(ask = FALSE) -} - - -args <- base::commandArgs(trailingOnly = TRUE) -if ("--reset" %in% args) { - revdep_reset() -} else if ("--todo-reset" %in% args) { - revdep_todo_reset() - todo() -} else if ("--todo" %in% args) { - todo() -} else if ("--add" %in% args) { - pos <- which("--add" == args) - if (pos == length(args)) stop("Missing value for option '--add'") - pkgs <- parse_pkgs(args[seq(from = pos + 1L, to = length(args))]) - revdep_add(packages = pkgs) - todo() -} else if ("--rm" %in% args) { - pos <- which("--rm" == args) - if (pos == length(args)) stop("Missing value for option '--rm'") - pkgs <- parse_pkgs(args[seq(from = pos + 1L, to = length(args))]) - revdep_rm(packages = pkgs) - todo() -} else if ("--add-broken" %in% args) { - revdep_add_broken() - todo() -} else if ("--add-error" %in% args) { -# res <- revepcheck::revdep_summary() - pkgs <- revdep_pkgs_with_status("error") - str(pkgs) - revdep_add(packages = pkgs) - todo() -} else if ("--add-all" %in% args) { - revdep_init() - pkgs <- revdep_children() - for (pkg in pkgs) { - pkgs <- c(pkgs, revdepcheck:::cran_revdeps(pkg)) - } - pkgs <- unique(pkgs) - revdep_add(packages = pkgs) - todo() -} else if ("--add-grandchildren" %in% args) { - revdep_init() - pkgs <- NULL - for (pkg in revdep_children()) { - pkgs <- c(pkgs, revdepcheck:::cran_revdeps(pkg)) - } - pkgs <- unique(pkgs) - revdep_add(packages = pkgs) - todo() -} else if ("--show-check" %in% args) { - pos <- which("--show-check" == args) - if (pos == length(args)) stop("Missing value for option '--show-check") - pkgs <- parse_pkgs(args[seq(from = pos + 1L, to = length(args))]) - for (pkg in pkgs) { - for (dir in c("old", "new")) { - path <- file.path("revdep", "checks", pkg, dir, sprintf("%s.Rcheck", pkg)) - if (!utils::file_test("-d", path)) next - pathname <- file.path(path, "00check.log") - cat("-----------------------------------------------\n") - cat(sprintf("%s (%s):\n", pkg, dir)) - cat("-----------------------------------------------\n") - bfr <- readLines(pathname, warn = FALSE) - tail <- tail(bfr, n = 20L) - writeLines(tail) - } - } -} else if ("--list-children" %in% args) { - pkg <- revdep_this_package() - pkgs <- revdepcheck:::cran_revdeps(pkg) - cat(sprintf("[n=%d] %s\n", length(pkgs), paste(pkgs, collapse = " "))) -} else if ("--list-error" %in% args) { - cat(paste(revdep_pkgs_with_status("error"), collapse = " "), "\n", sep="") -} else if ("--list-failure" %in% args) { - cat(paste(revdep_pkgs_with_status("failure"), collapse = " "), "\n", sep="") -} else if ("--add-error" %in% args) { - revdepcheck::revdep_add(packages = revdep_pkgs_with_status("error")) -} else if ("--add-failure" %in% args) { - revdepcheck::revdep_add(packages = revdep_pkgs_with_status("failure")) -} else if ("--preinstall-update" %in% args) { - revdep_preinstall_update() -} else if ("--preinstall-children" %in% args) { - pkg <- revdep_this_package() - pkgs <- revdepcheck:::cran_revdeps(pkg) - revdep_preinstall(pkgs) -} else if ("--preinstall-error" %in% args) { - res <- revdepcheck::revdep_summary() - revdep_preinstall(revdep_pkgs_with_status("error")) -} else if ("--preinstall-failure" %in% args) { - res <- revdepcheck::revdep_summary() - revdep_preinstall(revdep_pkgs_with_status("failure")) -} else if ("--preinstall-todo" %in% args) { - todo <- revdep_todo() - revdep_preinstall(todo$package) -} else if ("--preinstall" %in% args) { - pos <- which("--preinstall" == args) - if (pos == length(args)) stop("Missing value for option '--preinstall'") - pkgs <- parse_pkgs(args[seq(from = pos + 1L, to = length(args))]) - revdep_preinstall(pkgs) -} else { - stopifnot(length(args) == 0L) - check() - revdep_report(all = TRUE) -} +revdepcheck.extras::run()