From b7266e2bbe25e486ecf1606796b47112f6e708de Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:26:49 +0100 Subject: [PATCH 01/14] Strip additional details from check output --- DESCRIPTION | 2 +- NAMESPACE | 1 - NEWS.md | 6 ++++++ R/pkg_origin.R | 12 +----------- R/results.R | 5 +++++ R/utils.R | 4 ++-- man/pkg_origin.Rd | 3 --- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 838f5ba..6c9362d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -Version: 0.5.1 +Version: 0.5.1.9000 Authors@R: c( person( diff --git a/NAMESPACE b/NAMESPACE index 8362e7a..0affc8a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -138,7 +138,6 @@ export(new_rev_dep_checker) export(pkg_origin) export(pkg_origin_archive) export(pkg_origin_base) -export(pkg_origin_is_base) export(pkg_origin_local) export(pkg_origin_remote) export(pkg_origin_repo) diff --git a/NEWS.md b/NEWS.md index a0116a3..270a3a7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# checked 0.5.1.9000 (development) + +* Add timers striping to `strip_details_from_issue()` to avoid false-positives. + +* Remove `pkg_origin_is_base()` helper function and use memoised `base_pkgs()`. + # checked 0.5.1 * Export STATUS vector to make external statuses analysis easier. diff --git a/R/pkg_origin.R b/R/pkg_origin.R index 40ebedd..77e24c4 100644 --- a/R/pkg_origin.R +++ b/R/pkg_origin.R @@ -74,7 +74,7 @@ pkg_origin_repo <- function(package, repos, ...) { try_pkg_origin_repo <- function(package, repos, ...) { - if (isTRUE(pkg_origin_is_base(package))) { + if (package %in% base_pkgs()) { pkg_origin_base(package, ...) } else if (package %in% available_packages(repos = repos)[, "Package"]) { pkg_origin_repo(package = package, repos = repos, ...) @@ -84,16 +84,6 @@ try_pkg_origin_repo <- function(package, repos, ...) { } -#' @export -#' @rdname pkg_origin -pkg_origin_is_base <- function(package, ...) { - is_base <- package == "R" - is_inst <- package %in% utils::installed.packages()[, "Package"] - is_base[is_inst] <- utils::installed.packages()[package[is_inst], "Priority"] == "base" # nolint - is_base -} - - #' @export #' @rdname pkg_origin pkg_origin_base <- function(package, ...) { diff --git a/R/results.R b/R/results.R index dc7fd3a..7f22bab 100644 --- a/R/results.R +++ b/R/results.R @@ -427,6 +427,11 @@ strip_details_from_issue <- function(x) { pattern = "See(.*?)for details", replacement = "See for details" ) + x <- gsub( + x = x, + pattern = "\\[([^]]*)\\]", + replacement = "[]", + ) gsub( x = x, pattern = "[[:space:]]", diff --git a/R/utils.R b/R/utils.R index 9f45281..e090a41 100644 --- a/R/utils.R +++ b/R/utils.R @@ -34,9 +34,9 @@ hashes <- function(x, ...) { vcapply(x, hash, ...) } -base_pkgs <- function() { +base_pkgs <- memoise::memoise(function() { c("R", utils::installed.packages(priority = "base")[, "Package"]) -} +}) is_package_installed <- function(pkg, lib.loc = .libPaths()) { path <- find.package(pkg, lib.loc = lib.loc, quiet = TRUE) diff --git a/man/pkg_origin.Rd b/man/pkg_origin.Rd index 333ced9..db1a53e 100644 --- a/man/pkg_origin.Rd +++ b/man/pkg_origin.Rd @@ -3,7 +3,6 @@ \name{pkg_origin} \alias{pkg_origin} \alias{pkg_origin_repo} -\alias{pkg_origin_is_base} \alias{pkg_origin_base} \alias{pkg_origin_unknown} \alias{pkg_origin_local} @@ -15,8 +14,6 @@ pkg_origin(package, ..., .class = c()) pkg_origin_repo(package, repos, ...) -pkg_origin_is_base(package, ...) - pkg_origin_base(package, ...) pkg_origin_unknown(package, ...) From 72208ce417dd6d064194ecb9fcec51a0070a662a Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:14:15 +0100 Subject: [PATCH 02/14] Update check process regexp --- DESCRIPTION | 2 +- NEWS.md | 5 ++++- R/check_process.R | 21 ++++++++++++--------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 6c9362d..781fa53 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -Version: 0.5.1.9000 +Version: 0.5.1.9001 Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index 270a3a7..b47f1ec 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,12 @@ -# checked 0.5.1.9000 (development) +# checked 0.5.2 (development) * Add timers striping to `strip_details_from_issue()` to avoid false-positives. * Remove `pkg_origin_is_base()` helper function and use memoised `base_pkgs()`. +* Update `RE_CHECK` to capture even more edge cases while parsing R CMD check + output. + # checked 0.5.1 * Export STATUS vector to make external statuses analysis easier. diff --git a/R/check_process.R b/R/check_process.R index 916306b..efd2c21 100644 --- a/R/check_process.R +++ b/R/check_process.R @@ -1,7 +1,6 @@ # Regular Expression for Parsing R CMD check checks # nolint start, styler: off RE_CHECK <- paste0( - "(?<=^|\\n)", # must start at beginning of string OR right after a newline "\\* checking ", # literal "* checking " "(?.*?)", # capture check name/content (non-greedy) as "check" " \\.\\.\\.", # followed by literal " ..." @@ -11,23 +10,27 @@ RE_CHECK <- paste0( "\\n", # or: a normal detail line starting on the next line "(?:[ \\t]{2,}", # either indented (2+ spaces/tabs) "|\\*(?! (?:DONE|checking )))", # or a '*' line that is NOT "* DONE" and NOT "* checking ..." - "[^\\n]*(?:\\n|$)", # consume the rest of that detail line (to newline/end) + "[^\\n]*?", # consume content... + "(?:\\n|$|(?=\\* (?:DONE|checking )))", # ...until newline/end OR before next "* DONE"/"* checking" ")*", "[ \\t]*", # allow extra spaces/tabs after "..." on the SAME line "(?:", # position the engine right before a status token if one exists # Case 1: status token is on the current line (possibly preceded by comment text) - "(?:[^\\n]*[ \\t]+)?(?=(?:[A-Z]{2}[A-Z0-9_-]*)\\s*(?:\\n|$))", + "(?:(?:(?!\\* (?:DONE|checking ))[^\\n])*[ \\t]+)?", + "(?=(?:[A-Z]{2}[A-Z0-9_-]*)\\s*(?:\\n|$|\\* (?:DONE|checking )))", "|", # Case 2: status token is on the next line: # consume remainder of current line + newline + optional indent, - # but only if the next thing is a status token at end-of-line - "[^\\n]*\\n[ \\t]*(?=(?:[A-Z]{2}[A-Z0-9_-]*)\\s*(?:\\n|$))", + # but only if the next thing is a status token at end-of-line (or right before next marker) + "(?:(?!\\* (?:DONE|checking ))[^\\n])*\\n[ \\t]*", + "(?=(?:[A-Z]{2}[A-Z0-9_-]*)\\s*(?:\\n|$|\\* (?:DONE|checking )))", "|", - # Case 3: no status token (eat remainder/comment and stop here) - "[^\\n]*", + # Case 3: no status token (eat remainder/comment and stop here), + # but do NOT swallow the next "* checking/* DONE" if it's glued to this line + "[^\\n]*?(?=\\n|$|\\* (?:DONE|checking ))", ")", - "(?(?:[A-Z]{2}[A-Z0-9_-]*)|)", # capture status token, or capture empty string if absent - "(?=\\s*(?:\\n|$))" # must end at newline/end (allow trailing whitespace) + "(?(?:[A-Z]{2}[A-Z0-9_-]*)|)", # status token OR empty string + "(?=\\s*(?:\\n|$|\\* (?:DONE|checking )))" # terminated by newline/end OR next marker ) # nolint end, styler: on From 1a80c42b369049be194b248d89c2b59b711c1659 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:46:58 +0100 Subject: [PATCH 03/14] Prevent infinite loops when finishing processes --- DESCRIPTION | 2 +- NEWS.md | 3 +++ R/check_process.R | 7 +++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 781fa53..de30cea 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -Version: 0.5.1.9001 +Version: 0.5.1.9002 Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index b47f1ec..757566c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,9 @@ * Update `RE_CHECK` to capture even more edge cases while parsing R CMD check output. +* Finish check process even if checks seem incomplete but 3 or mire minutes have + passed since the process ended to avoid infinite loops. + # checked 0.5.1 * Export STATUS vector to make external statuses analysis easier. diff --git a/R/check_process.R b/R/check_process.R index efd2c21..a8e2f34 100644 --- a/R/check_process.R +++ b/R/check_process.R @@ -77,8 +77,11 @@ check_process <- R6::R6Class( # In some cases, check subprocess might suffer from a race condition, when # process itself finished, but the final results of the last subcheck # are not yet available to parse. Therefore we allow the process to - # finalize only if the last subcheck has reported status. - if (checks[length(checks)] != "") { + # finalize only if the last subcheck has reported status. However + # if we stuck in this state for longer than 3 minutes we should + # try to finish anyway, to prevent possible infinite loops. + if (checks[length(checks)] != "" | + Sys.time() - private$time_finish >= as.difftime(3, units = "mins")) { self$save_results() private$cache_parsed_results() private$free_file_descriptors() From d2c6c63802d5b863eb05e6158a7f0dd333f7d278 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Thu, 5 Mar 2026 03:47:36 +0100 Subject: [PATCH 04/14] Hotfix timeout condition --- R/check_process.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/check_process.R b/R/check_process.R index a8e2f34..eec9b13 100644 --- a/R/check_process.R +++ b/R/check_process.R @@ -80,8 +80,8 @@ check_process <- R6::R6Class( # finalize only if the last subcheck has reported status. However # if we stuck in this state for longer than 3 minutes we should # try to finish anyway, to prevent possible infinite loops. - if (checks[length(checks)] != "" | - Sys.time() - private$time_finish >= as.difftime(3, units = "mins")) { + if (checks[length(checks)] != "" || + (Sys.time() - self$get_time_finish() >= as.difftime(3, units = "mins"))) { self$save_results() private$cache_parsed_results() private$free_file_descriptors() From ffeab8565fa925255a2ac32423d8888d40d67192 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:46:39 +0100 Subject: [PATCH 05/14] Further improve finishing process --- DESCRIPTION | 2 +- NEWS.md | 2 ++ R/check_process.R | 7 ++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index de30cea..bd2cb84 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -Version: 0.5.1.9002 +Version: 0.5.1.9003 Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index 757566c..16fb1cd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ * Finish check process even if checks seem incomplete but 3 or mire minutes have passed since the process ended to avoid infinite loops. +* Further improvements to the check process finisher. + # checked 0.5.1 * Export STATUS vector to make external statuses analysis easier. diff --git a/R/check_process.R b/R/check_process.R index eec9b13..9b1e6a1 100644 --- a/R/check_process.R +++ b/R/check_process.R @@ -71,8 +71,8 @@ check_process <- R6::R6Class( if (!self$is_alive()) callback(self) }, finish = function() { - # self$checks active binding calls poll_output so there is not need - # to call it explicitly + # Make sure results are polled + self$poll_output() checks <- self$checks # In some cases, check subprocess might suffer from a race condition, when # process itself finished, but the final results of the last subcheck @@ -80,8 +80,9 @@ check_process <- R6::R6Class( # finalize only if the last subcheck has reported status. However # if we stuck in this state for longer than 3 minutes we should # try to finish anyway, to prevent possible infinite loops. + time_finished <- self$get_time_finish() %||% Sys.time() if (checks[length(checks)] != "" || - (Sys.time() - self$get_time_finish() >= as.difftime(3, units = "mins"))) { + ((Sys.time() - time_finished) >= as.difftime(3, units = "mins"))) { self$save_results() private$cache_parsed_results() private$free_file_descriptors() From 243c82c9f2084f8cadaecf2d732f66b58e4c8eed Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:14:28 +0100 Subject: [PATCH 06/14] resolve conflicts --- DESCRIPTION | 4 ++ NEWS.md | 18 ++++++++ R/check_process.R | 8 +++- R/utils-igraph.R | 91 ++++++++++++++++++++++++++-------------- man/graph_dedup_attrs.Rd | 5 ++- 5 files changed, 91 insertions(+), 35 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 838f5ba..583487d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,10 @@ Package: checked Title: Systematically Run R CMD Checks +<<<<<<< Updated upstream Version: 0.5.1 +======= +Version: 0.5.2 +>>>>>>> Stashed changes Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index a0116a3..2843be2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,21 @@ +# checked 0.5.2 + +* Add timers striping to `strip_details_from_issue()` to avoid false-positives. + +* Remove `pkg_origin_is_base()` helper function and use memoised `base_pkgs()`. + +* Update `RE_CHECK` to capture even more edge cases while parsing R CMD check + output. + +* Finish check process even if checks seem incomplete but 3 or mire minutes have + passed since the process ended to avoid infinite loops. + +* Further improvements to the check process finisher. + +* Make `graph_dedup_attrs` rebuild the graph from scratch with deduplicated + attributes rather than manipulating the exiting graph. I significantly speeds + up the function. + # checked 0.5.1 * Export STATUS vector to make external statuses analysis easier. diff --git a/R/check_process.R b/R/check_process.R index 916306b..1023c9a 100644 --- a/R/check_process.R +++ b/R/check_process.R @@ -74,8 +74,12 @@ check_process <- R6::R6Class( # In some cases, check subprocess might suffer from a race condition, when # process itself finished, but the final results of the last subcheck # are not yet available to parse. Therefore we allow the process to - # finalize only if the last subcheck has reported status. - if (checks[length(checks)] != "") { + # finalize only if the last subcheck has reported status. However + # if we stuck in this state for longer than 3 minutes we should + # try to finish anyway, to prevent possible infinite loops. + time_finished <- self$get_time_finish() %||% Sys.time() + if (checks[length(checks)] != "" || + ((Sys.time() - time_finished) >= as.difftime(3, units = "mins"))) { self$save_results() private$cache_parsed_results() private$free_file_descriptors() diff --git a/R/utils-igraph.R b/R/utils-igraph.R index 3b74be3..22f8070 100644 --- a/R/utils-igraph.R +++ b/R/utils-igraph.R @@ -44,48 +44,75 @@ star_graph <- function(...) { #' Primarily intended for cleaning up the result of an [`igraph::union()`], #' which adds duplicated attributes when attributes of the same name exist in #' multiple graphs. Searches for suffixes and consolidates attributes, -#' taking the attribute from the first non-NA value observed. +#' taking the attribute from the first non-NA value observed. The function +#' rebuilds the graph from scratch as accessing attributes once, operating on +#' lists and then assigning them to a new graph is significantly faster than +#' manipulating attribiutes of the existing graph. #' #' @param g task_graph object #' #' @keywords internal graph_dedup_attrs <- function(g) { - # pattern appended to duplicated attributes re <- "_\\d+$" + v_all <- igraph::vertex_attr(g) + e_all <- igraph::edge_attr(g) + v_attr_names <- names(v_all) + e_attr_names <- names(e_all) + v_dup <- grep(re, v_attr_names, value = TRUE) + e_dup <- grep(re, e_attr_names, value = TRUE) - # de-duplicate vertex attributes - v_attrs <- igraph::vertex_attr_names(g) - v_dup_attrs <- grep(re, v_attrs, value = TRUE) - v_dup_group <- sub(re, "", v_dup_attrs) - v_dup_attrs <- split(v_dup_attrs, v_dup_group) - for (i in seq_along(v_dup_attrs)) { - attr_name <- names(v_dup_attrs[i]) - attr_value <- igraph::vertex_attr(g, v_dup_attrs[[i]][[1L]]) - g <- igraph::delete_vertex_attr(g, v_dup_attrs[[i]][[1L]]) - for (attr_dup_name in v_dup_attrs[[i]][-1L]) { - is_na <- is.na(attr_value) - attr_value[is_na] <- igraph::vertex_attr(g, attr_dup_name)[is_na] - g <- igraph::delete_vertex_attr(g, attr_dup_name) + # Nothing to deduplicate + if (length(v_dup) == 0 && length(e_dup) == 0) return(g) + + first_non_na <- function(list) { + out <- list[[1]] + if (!any(is.na(out))) return(out) + + for (i in seq(2, length(list))) { + is_na <- is.na(out) + if (any(is_na)) out[is_na] <- list[[i]][is_na] } - g <- igraph::set_vertex_attr(g, attr_name, value = attr_value) + out } - # de-duplicate edge attributes - e_attrs <- igraph::edge_attr_names(g) - e_dup_attrs <- grep(re, e_attrs, value = TRUE) - e_dup_group <- sub(re, "", e_dup_attrs) - e_dup_attrs <- split(e_dup_attrs, e_dup_group) - for (i in seq_along(e_dup_attrs)) { - attr_name <- names(e_dup_attrs[i]) - attr_value <- igraph::edge_attr(g, e_dup_attrs[[i]][[1L]]) - g <- igraph::delete_edge_attr(g, e_dup_attrs[[i]][[1L]]) - for (attr_dup_name in e_dup_attrs[[i]][-1L]) { - is_na <- is.na(attr_value) - attr_value[is_na] <- igraph::edge_attr(g, attr_dup_name)[is_na] - g <- igraph::delete_edge_attr(g, attr_dup_name) - } - g <- igraph::set_edge_attr(g, attr_name, value = attr_value) + groups <- split(v_dup, sub(re, "", v_dup)) + for (base in names(groups)) { + cols <- groups[[base]] + v_all[[base]] <- first_non_na(v_all[cols]) + } + v_all[v_dup] <- NULL + + groups <- split(e_dup, sub(re, "", e_dup)) + for (base in names(groups)) { + cols <- groups[[base]] + e_all[[base]] <- first_non_na(e_all[cols]) + } + e_all[e_dup] <- NULL + + vertices <- data.frame(name = V(g)$name) + + for (attr in setdiff(names(v_all), "name")) { + vertices[[attr]] <- v_all[[attr]] } - g + # Build edges data.frame (keeps current edge order) + el <- igraph::as_edgelist(g, names = TRUE) + edges <- data.frame( + from = el[, 1], + to = el[, 2] + ) + + for (attr in names(e_all)) { + edges[[attr]] <- e_all[[attr]] + } + + # Rebuild graph + g_rebuilt <- igraph::graph_from_data_frame( + d = edges, + directed = TRUE, + vertices = vertices + ) + + class(g_rebuilt) <- class(g) + g_rebuilt } diff --git a/man/graph_dedup_attrs.Rd b/man/graph_dedup_attrs.Rd index 5c3112e..0d62326 100644 --- a/man/graph_dedup_attrs.Rd +++ b/man/graph_dedup_attrs.Rd @@ -13,6 +13,9 @@ graph_dedup_attrs(g) Primarily intended for cleaning up the result of an \code{\link[igraph:union]{igraph::union()}}, which adds duplicated attributes when attributes of the same name exist in multiple graphs. Searches for suffixes and consolidates attributes, -taking the attribute from the first non-NA value observed. +taking the attribute from the first non-NA value observed. The function +rebuilds the graph from scratch as accessing attributes once, operating on +lists and then assigning them to a new graph is significantly faster than +manipulating attribiutes of the existing graph. } \keyword{internal} From dc4fad877bb7f340c8f0b8b469fba4c98ab0fdf6 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:15:11 +0100 Subject: [PATCH 07/14] resolve conflicts --- DESCRIPTION | 4 ---- 1 file changed, 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 583487d..a6cf16e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,10 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -<<<<<<< Updated upstream -Version: 0.5.1 -======= Version: 0.5.2 ->>>>>>> Stashed changes Authors@R: c( person( From 8094e198f6424843068f5ccbe88e71fd871cccf3 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:19:40 +0100 Subject: [PATCH 08/14] Add dev to gitlabci --- .github/workflows/R-CMD-check.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 0df5e77..2e51132 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -2,9 +2,9 @@ # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: push: - branches: [main, master] + branches: [main, master, dev] pull_request: - branches: [main, master] + branches: [main, master, dev] name: R-CMD-check From f59143f40efe493944fe274a0e659e2b17393ec7 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Tue, 7 Apr 2026 14:21:22 +0200 Subject: [PATCH 09/14] Make reporters accept additional values --- DESCRIPTION | 2 +- NEWS.md | 9 +++++++++ R/reporter.R | 24 ++++++++++++++++-------- R/reporter_basic_tty.R | 10 +++++++--- man/reporters.Rd | 12 +++++++++--- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index a6cf16e..67f2ef0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -Version: 0.5.2 +Version: 0.5.2.9000 Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index 2843be2..017cff1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,12 @@ +# checked (development) + +* Make is possible to construct reporter environments with additional values + to better control their behavior. + +* Add `checks_only` parameter to `reporter_basic_tty` which if set to TRUE + will make the reporter broadcast only check tasks instead of both + install and check. + # checked 0.5.2 * Add timers striping to `strip_details_from_issue()` to avoid false-positives. diff --git a/R/reporter.R b/R/reporter.R index ace72b6..f3731ce 100644 --- a/R/reporter.R +++ b/R/reporter.R @@ -20,32 +20,40 @@ #' #' A line-feed reporter presenting output one line at a time, providing #' a reporter with minimal assumptions about terminal capabilities. +#' +#' @param checks_only whether basic tty reporter should report only check tasks. +#' @param ... additional values which should be assigned to the reported +#' environment. #' #' @family reporters #' @name reporters NULL -reporter <- function(type) { +reporter <- function(type, ...) { type <- paste0("reporter_", type) - structure(new.env(parent = baseenv()), class = c(type, "reporter")) + reporter_options <- list(...) + structure( + list2env(reporter_options, parent = baseenv(), hash = TRUE), + class = c(type, "reporter") + ) } #' @rdname reporters #' @export -reporter_ansi_tty <- function() { - reporter("ansi_tty") +reporter_ansi_tty <- function(...) { + reporter("ansi_tty", ...) } #' @rdname reporters #' @export -reporter_ansi_tty2 <- function() { - reporter("ansi_tty2") +reporter_ansi_tty2 <- function(...) { + reporter("ansi_tty2", ...) } #' @rdname reporters #' @export -reporter_basic_tty <- function() { - reporter("basic_tty") +reporter_basic_tty <- function(checks_only = FALSE, ...) { + reporter("basic_tty", checks_only = checks_only, ...) } #' @rdname reporters diff --git a/R/reporter_basic_tty.R b/R/reporter_basic_tty.R index 946d56e..9dab184 100644 --- a/R/reporter_basic_tty.R +++ b/R/reporter_basic_tty.R @@ -7,11 +7,15 @@ report_start_setup.reporter_basic_tty <- function( ) { # start with all tasks initialized as pending v <- igraph::V(checker$graph) - v_actionable <- v[is_actionable_task(v$task)] + v_reportable <- if (reporter$checks_only) { + v[is_check(v$task)] + } else { + v[is_actionable_task(v$task)] + } # named factor vector, names as task aliases and value of last reported status - reporter$status <- rep(STATUS$pending, times = length(v_actionable)) - names(reporter$status) <- v_actionable$name + reporter$status <- rep(STATUS$pending, times = length(v_reportable)) + names(reporter$status) <- v_reportable$name reporter$time_start <- Sys.time() diff --git a/man/reporters.Rd b/man/reporters.Rd index b2f8c13..feb2287 100644 --- a/man/reporters.Rd +++ b/man/reporters.Rd @@ -8,14 +8,20 @@ \alias{reporter_default} \title{Check checker Runner Reporters} \usage{ -reporter_ansi_tty() +reporter_ansi_tty(...) -reporter_ansi_tty2() +reporter_ansi_tty2(...) -reporter_basic_tty() +reporter_basic_tty(checks_only = FALSE, ...) reporter_default() } +\arguments{ +\item{...}{additional values which should be assigned to the reported +environment.} + +\item{checks_only}{whether basic tty reporter should report only check tasks.} +} \description{ Reporters are used to configure how output is communicated while running a \code{\link{checker}}. They range from glossy command-line tools intended for From 7499c2226ba4a4864bc0eb7bc9144dfc16cf6a69 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:47:16 +0200 Subject: [PATCH 10/14] Add done tasks conuter --- R/reporter.R | 2 +- R/reporter_basic_tty.R | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/R/reporter.R b/R/reporter.R index f3731ce..fc0ba80 100644 --- a/R/reporter.R +++ b/R/reporter.R @@ -20,7 +20,7 @@ #' #' A line-feed reporter presenting output one line at a time, providing #' a reporter with minimal assumptions about terminal capabilities. -#' +#' #' @param checks_only whether basic tty reporter should report only check tasks. #' @param ... additional values which should be assigned to the reported #' environment. diff --git a/R/reporter_basic_tty.R b/R/reporter_basic_tty.R index 9dab184..1ec4ef4 100644 --- a/R/reporter_basic_tty.R +++ b/R/reporter_basic_tty.R @@ -48,8 +48,17 @@ report_status.reporter_basic_tty <- function(reporter, checker, envir) { "pending" = "queued", "in progress" = cli::cli_fmt(cli::cli_text("started")), "done" = { + pkgs_done <- reporter$status == STATUS$done # nolint + # +1 to acount for the task that is currently processed + fmt_count <- + cli::col_grey(" [{sum(pkgs_done)+1}/{length(pkgs_done)}]") + if (is.null(p)) { - cli::cli_fmt(cli::cli_text("finished (restored)")) + cli::cli_fmt( + cli::cli_text( + "finished", cli::format_inline(fmt_count), " (restored)" + ) + ) } else if (p$get_r_exit_status() != 0) { # checks processes don't have logs associated with it message <- if (!is.null(p$log)) { @@ -74,6 +83,7 @@ report_status.reporter_basic_tty <- function(reporter, checker, envir) { fmt_warning <- "{.warn {ewn[[2]]} WARNING{?/S}}" fmt_note <- "{.note {ewn[[3]]} NOTE{?/S}}" fmt_duration <- " {.time_taken ({format_time(dur)})}" + cli::cli_fmt(cli::cli_text( "finished", if (sum(ewn) > 0) " with ", @@ -82,6 +92,7 @@ report_status.reporter_basic_tty <- function(reporter, checker, envir) { if (ewn[[2]] > 0) cli::format_inline(fmt_warning), if (ewn[[3]] > 0) cli::format_inline(fmt_note) )), + cli::format_inline(fmt_count), if (!is.null(dur)) cli::format_inline(fmt_duration) )) } From a90dc4da5f4f85ba7887a22a5b8053ab000e8026 Mon Sep 17 00:00:00 2001 From: maksymis <32574056+maksymiuks@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:19:54 +0200 Subject: [PATCH 11/14] Update snapshot for basic tty --- tests/testthat/_snaps/reporters.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/testthat/_snaps/reporters.md b/tests/testthat/_snaps/reporters.md index 6806e4f..5c29a37 100644 --- a/tests/testthat/_snaps/reporters.md +++ b/tests/testthat/_snaps/reporters.md @@ -11,18 +11,18 @@ Message Checks [][install] rev.both.dependency started - [][install] rev.both.dependency finished () + [][install] rev.both.dependency finished [1/7] () [][install] pkg.ok.error started - [][install] pkg.ok.error finished () + [][install] pkg.ok.error finished [2/7] () [][install] pkg.ok.error started [][check] rev.both.ok started - [][install] pkg.ok.error finished () - [][check] rev.both.ok finished with 1 NOTE () + [][install] pkg.ok.error finished [3/7] () + [][check] rev.both.ok finished with 1 NOTE [4/7] () [][check] rev.both.error started - [][check] rev.both.error finished with 1 NOTE () + [][check] rev.both.error finished with 1 NOTE [5/7] () [][check] rev.both.ok started - [][check] rev.both.ok finished with 1 NOTE () + [][check] rev.both.ok finished with 1 NOTE [6/7] () [][check] rev.both.error started - [][check] rev.both.error finished with 1 ERROR, 1 WARNING () + [][check] rev.both.error finished with 1 ERROR, 1 WARNING [7/7] () Finished in From 1f2fec2556e8fdf6748830f4901939e22302f9a4 Mon Sep 17 00:00:00 2001 From: Szymon Maksymiuk <32574056+maksymiuks@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:11:35 +0200 Subject: [PATCH 12/14] Update pacage installation process (#92) * Update pacage installation process * Initial changes * Customization API changes * Update news * Increase timeout for install * Add self keyword --- DESCRIPTION | 2 +- NEWS.md | 8 ++++- R/checker.R | 16 ++++++++-- R/install.R | 14 ++++++--- R/lib.R | 4 +++ R/next_task.R | 26 ++++++++++------- R/options.R | 14 ++++++++- R/pkg_origin.R | 11 +++---- R/plan.R | 36 ++++++++++++++++------- R/remotes.R | 29 +++++++++++++----- R/task.R | 3 ++ R/task_graph.R | 60 ++++++++++++++++++++++++++------------ R/utils-deps.R | 17 +++++------ R/utils-paths.R | 6 ++-- R/utils-pkg-source.R | 7 +++-- R/utils.R | 21 +++++++++++-- man/checker.Rd | 9 ++++++ man/install_task.Rd | 3 ++ man/options.Rd | 21 +++++++++++++ man/options_params.Rd | 9 ++++++ man/plan_local_checks.Rd | 10 ++++++- man/plan_local_install.Rd | 14 ++++++++- man/plan_rev_dep_checks.Rd | 10 ++++++- man/task_graph.Rd | 5 +++- 24 files changed, 271 insertions(+), 84 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index a529ff2..01a5994 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -Version: 0.5.2.9001 +Version: 0.5.3 Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index 465bf6c..9c7724b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# checked (development) +# checked 0.5.3 * Make is possible to construct reporter environments with additional values to better control their behavior. @@ -10,6 +10,12 @@ * Address changes related to default parameters changes in `callr` and resulting NULL comparison in `checked` (@gaborcsardi, #93) +* Multiple API changes facilitating additional customization for tasks. + +* Ensure packages destined into isolated libraries are always installed. + +* Redesign logs by grouping them into package specific directories. + # checked 0.5.2 * Add timers striping to `strip_details_from_issue()` to avoid false-positives. diff --git a/R/checker.R b/R/checker.R index 16adfb5..d631a3d 100644 --- a/R/checker.R +++ b/R/checker.R @@ -82,6 +82,11 @@ checker <- R6::R6Class( #' @param restore `logical` value, whether output directory should be #' unlinked before running checks. If `FALSE`, an attempt will me made to #' restore previous progress from the same `output`. + #' @param dependencies A vector of length one or a named list. + #' Compatible with [`as_pkg_dependencies`]. + #' @param upgrade `logical` value, whether packages should be upgraded + #' if more recent version is discovered in available sources. Remotes + #' packages, if allowed to be used, are always installed and prioritized. #' @param ... Additional arguments unused #' #' @return [checker]. @@ -95,6 +100,8 @@ checker <- R6::R6Class( lib.loc = .libPaths(), repos = getOption("repos"), restore = options::opt("restore"), + dependencies = TRUE, + upgrade = FALSE, ... ) { check_past_output(output, restore, ask = interactive()) @@ -110,8 +117,9 @@ checker <- R6::R6Class( lib.loc ) private$repos <- repos + private$upgrade <- upgrade - self$graph <- task_graph(self$plan, repos) + self$graph <- task_graph(self$plan, repos, dependencies = dependencies) private$restore_complete_checks() }, @@ -183,7 +191,8 @@ checker <- R6::R6Class( node = next_node, g = self$graph, output = self$output, - lib.loc = private$lib.loc + lib.loc = private$lib.loc, + upgrade = private$upgrade ) if (is.null(process)) { @@ -240,6 +249,9 @@ checker <- R6::R6Class( # task loop counter gc_needed = FALSE, + # upgrade flag + upgrade = FALSE, + start_node = function(node) { task_graph_package_status(self$graph, node) <- STATUS$`in progress` private$start_node_meta_parents(node) diff --git a/R/install.R b/R/install.R index af17f08..0ab1056 100644 --- a/R/install.R +++ b/R/install.R @@ -12,16 +12,20 @@ install_process <- R6::R6Class( lib = .libPaths()[[1]], libpaths = .libPaths(), available_packages_filters = getOption("available_packages_filters"), - log = NULL + log = NULL, + env = callr::rcmd_safe_env() ) { if (!dir.exists(lib)) dir.create(lib, recursive = TRUE) private$package <- pkgs self$log <- log private$callr_r_bg( function(..., escalate_warning, available_packages_filters) { - options(available_packages_filters = available_packages_filters) + options( + timeout = 600, + available_packages_filters = available_packages_filters + ) withCallingHandlers( - utils::install.packages(...), + utils::install.packages(..., quiet = FALSE, verbose = TRUE), warning = function(w) { if (escalate_warning(w)) { print(w$message) @@ -43,7 +47,9 @@ install_process <- R6::R6Class( libpath = libpaths, stdout = self$log, stderr = "2>&1", - system_profile = TRUE + system_profile = options::opt("install_system_profile"), + user_profile = options::opt("install_user_profile"), + env = env ) }, get_duration = function() { diff --git a/R/lib.R b/R/lib.R index 5cdb860..15eabbf 100644 --- a/R/lib.R +++ b/R/lib.R @@ -50,6 +50,10 @@ format.lib_path <- function(x, ...) { "library" } +is_lib_path_default <- function(task) { + inherits(task$lib, "lib_path_default") +} + #' Get Library Location #' #' @param x An object describing a library location diff --git a/R/next_task.R b/R/next_task.R index b832ba1..c2691f6 100644 --- a/R/next_task.R +++ b/R/next_task.R @@ -62,36 +62,42 @@ start_task.install_task <- function( g, output, lib.loc, + upgrade, ... ) { task <- node$task[[1]] + libpaths <- unique(c( task_graph_libpaths(g, node, lib.loc = lib.loc, output = output), lib.loc )) install_parameters <- install_params(task$origin) - if (any(inherits(task$origin, c("pkg_origin_base", "pkg_origin_unknown")))) { - return(NULL) - } + is_base <- any( + inherits(task$origin, c("pkg_origin_base", "pkg_origin_unknown")) + ) + if (is_base) return(NULL) # install_parameters$package is a valid package name only for # pkg_origin_repo. Otherwise it's a path to the source package in which case # is_package_installed returns FALSE (as it should) - if (is_package_installed(install_parameters$package, libpaths)) { - return(NULL) - } + is_installed <- is_package_installed( + install_parameters$package, + libpaths, + upgrade %nif% task$origin$version + ) + if (is_installed && is_lib_path_default(task)) return(NULL) install_process$new( install_parameters$package, lib = lib(task, lib.loc = lib.loc, lib.root = path_libs(output)), libpaths = libpaths, - repos = task$origin$repos, + repos = install_parameters$repos, dependencies = FALSE, type = task$type, - INSTALL_opts = c(), # TODO - log = path_install_log(output, node$name[[1]]), - env = c() # TODO + INSTALL_opts = task$INSTALL_opts, + log = path_install_log(output, package(task), node$name[[1]]), + env = task$env ) } diff --git a/R/options.R b/R/options.R index e5be46d..a81f764 100644 --- a/R/options.R +++ b/R/options.R @@ -67,7 +67,19 @@ options::define_options( envvar_fn = structure( function(raw, ...) trimws(strsplit(raw, " ")[[1]]), desc = "space-separated R CMD check flags" - ) + ), + + "named `character` vector of environment variables to use during + the package installation.", + install_envvars = callr::rcmd_safe_env(), + + "`logical` used as `sytem_profile` parameter passed to the `callr::r_bg()` + function used to install packages", + install_system_profile = FALSE, + + "value used as `user_profile` parameter passed to the `callr::r_bg()` + function used to install packages", + install_user_profile = "project" ) #' @eval options::as_roxygen_docs() diff --git a/R/pkg_origin.R b/R/pkg_origin.R index 77e24c4..6a8e458 100644 --- a/R/pkg_origin.R +++ b/R/pkg_origin.R @@ -57,16 +57,13 @@ pkg_origin_repo <- function(package, repos, ...) { ap_pkg <- available_packages(repos = repos)[package, ] version <- package_version(ap_pkg["Version"]) - source <- strip_src_contrib(ap_pkg["Repository"]) - if (any(which <- startsWith(repos, source))) { - source <- repos[which][1] - } + repo <- strip_src_contrib(ap_pkg["Repository"], repos = repos) pkg_origin( package = package, version = version, - source = source, - repos = repos, + source = repo, + repos = repo, ..., .class = "pkg_origin_repo" ) @@ -204,7 +201,7 @@ pkg_deps.pkg_origin_local <- function( indirect_deps <- pkg_dependencies( packages = direct_deps$name, - dependencies = dependencies, + dependencies = "hard", db = db ) indirect_deps$depth <- rep.int("indirect", NROW(indirect_deps)) diff --git a/R/plan.R b/R/plan.R index eda9c32..25fbeba 100644 --- a/R/plan.R +++ b/R/plan.R @@ -7,12 +7,16 @@ #' #' @param path path to the package source. #' @param repos repository used to identify reverse dependencies. +#' @param remotes_dependencies A vector of length one or a named list. +#' Compatible with [`as_pkg_dependencies`]. Used to filter out remotes +#' dependencies. #' #' @family plan #' @export plan_rev_dep_checks <- function( path, - repos = getOption("repos") + repos = getOption("repos"), + remotes_dependencies = TRUE ) { path <- check_path_is_pkg_source(path) ap <- available_packages(repos = repos) @@ -75,7 +79,7 @@ plan_rev_dep_checks <- function( g <- task_graph_class(g) if (remotes_permitted()) { - remotes_graph(g) + remotes_graph(g, dependencies = remotes_dependencies) } else { g } @@ -131,6 +135,9 @@ plan_rev_dep_release_check <- function(origin, revdep, repos) { #' @param package A path to either package, directory with packages or name #' of the package (details) #' @param repos repository used to identify packages when name is provided. +#' @param remotes_dependencies A vector of length one or a named list. +#' Compatible with [`as_pkg_dependencies`]. Used to filter out remotes +#' dependencies. #' #' @details #' `package` parameter has two different allowed values: @@ -145,7 +152,8 @@ plan_rev_dep_release_check <- function(origin, revdep, repos) { #' @export plan_local_checks <- function( package, - repos = getOption("repos") + repos = getOption("repos"), + remotes_dependencies = TRUE ) { task <- meta_task( @@ -179,7 +187,7 @@ plan_local_checks <- function( star_plan_template(c( list(task), local_checks_tasks - )) + ), remotes_dependencies) } @@ -189,11 +197,18 @@ plan_local_checks <- function( #' #' @param package A path to package source. #' @param repos repository used to identify packages when name is provided. +#' @param remotes_dependencies A vector of length one or a named list. +#' Compatible with [`as_pkg_dependencies`]. Used to filter out remotes +#' dependencies. +#' @param INSTALL_opts Options to set while the root package is being installed. +#' Check [`utils::install.packages`] for details. #' #' @family plan plan_local_install <- function( package, - repos = getOption("repos") + repos = getOption("repos"), + remotes_dependencies = TRUE, + INSTALL_opts = c() ) { m_task <- meta_task( @@ -202,16 +217,17 @@ plan_local_install <- function( ) i_task <- install_task( - origin = pkg_origin_local(package) + origin = pkg_origin_local(package), + INSTALL_opts = INSTALL_opts ) star_plan_template(list( m_task, i_task - )) + ), remotes_dependencies) } -star_plan_template <- function(tasks) { +star_plan_template <- function(tasks, remotes_dependencies) { g <- star_graph( task = tasks ) @@ -220,8 +236,8 @@ star_plan_template <- function(tasks) { g <- task_graph_class(g) - if (remotes_permitted()) { - remotes_graph(g) + if (remotes_permitted() && !isFALSE(remotes_dependencies)) { + remotes_graph(g, dependencies = remotes_dependencies) } else { g } diff --git a/R/remotes.R b/R/remotes.R index 198dafc..23e5c6f 100644 --- a/R/remotes.R +++ b/R/remotes.R @@ -3,9 +3,14 @@ remotes_graph <- function(x, ...) { } #' @export -remotes_graph.task_graph <- function(x, ...) { +remotes_graph.task_graph <- function(x, ..., dependencies = TRUE) { vs <- V(x) - remotes_subgraphs <- lapply(vs, remotes_graph, vs = vs) + remotes_subgraphs <- lapply( + vs, + remotes_graph, + vs = vs, + dependencies = dependencies + ) task_graph_class( suppressWarningsRegex( @@ -23,13 +28,13 @@ remotes_graph.task_graph <- function(x, ...) { #' @export remotes_graph.integer <- function(x, ..., vs) { - remotes_graph(vs[[x]]) + remotes_graph(vs[[x]], ...) } #' @export #' @method remotes_graph igraph.vs remotes_graph.igraph.vs <- function(x, ...) { - remotes_graph(x$task) + remotes_graph(x$task, ...) } #' @export @@ -40,15 +45,23 @@ remotes_graph.task <- function(x, ...) { } #' @export -remotes_graph.install_task <- function(x, ...) { +remotes_graph.install_task <- function(x, ..., dependencies = TRUE) { remote_tasks <- get_remote_tasks(x) if (length(remote_tasks) == 0) return(igraph::make_empty_graph()) remote_tasks_names <- vcapply(remote_tasks, package) + dependencies <- as_pkg_dependencies(dependencies)$direct x_deps <- pkg_deps(x$origin) - x_remote_deps <- x_deps[ - x_deps$package == package(x) & x_deps$name %in% remote_tasks_names, - ] + x_remote_deps <- x_deps[x_deps$package == package(x) & + x_deps$name %in% remote_tasks_names & + x_deps$type %in% dependencies, ] + + if (NROW(x_remote_deps) == 0) return(igraph::make_empty_graph()) + + # Filter out deps out of scopr + remote_tasks <- remote_tasks[remote_tasks_names %in% x_remote_deps$name] + remote_tasks_names <- + remote_tasks_names[remote_tasks_names %in% x_remote_deps$name] # Sort tasks according to same key remote_tasks <- remote_tasks[order(remote_tasks_names)] diff --git a/R/task.R b/R/task.R index 940b480..5186b2a 100644 --- a/R/task.R +++ b/R/task.R @@ -53,6 +53,7 @@ print.task <- function(x, ...) { #' @param lib Any object that can be passed to [lib()] to generate a library #' path. #' @inheritParams utils::install.packages +#' @inheritParams callr::r_bg #' #' @family tasks #' @export @@ -61,6 +62,7 @@ install_task <- function( type = package_install_type(origin), INSTALL_opts = NULL, lib = lib_path(origin), + env = options::opt("install_envvars"), ... ) { task( @@ -68,6 +70,7 @@ install_task <- function( type = type, INSTALL_opts = INSTALL_opts, lib = lib, + env = env, ..., .subclass = "install" ) diff --git a/R/task_graph.R b/R/task_graph.R index 8f79499..6861cf9 100644 --- a/R/task_graph.R +++ b/R/task_graph.R @@ -14,6 +14,8 @@ #' @param x a `plan` object, containing a list of related steps. #' @param repos `repos`, as expected by [`tools::package_dependencies()`] to #' determine package relationships. +#' @param dependencies A vector of length one or a named list. Compatible with +#' [`as_pkg_dependencies`]. #' @param ... params passed to helper methods. #' @return A `data.frame` that can be used to build #' [`igraph::make_graph`] edges. @@ -26,18 +28,27 @@ #' @keywords internal #' #' @importFrom igraph V E -task_graph <- function(x, repos = getOption("repos"), ...) { +task_graph <- function( + x, repos = getOption("repos"), dependencies = TRUE, ... +) { UseMethod("task_graph") } #' @export -task_graph.task <- function(x, repos = getOption("repos"), ...) { - df <- pkg_deps(x$origin, repos = repos, dependencies = TRUE) +task_graph.task <- function( + x, + repos = getOption("repos"), + dependencies = TRUE, + ... +) { + df <- pkg_deps(x$origin, repos = repos, dependencies = dependencies) # Distinguish direct dependencies of the package form possible indirect # in the same data.frame which could come from suggested loops. This ensures # there is a separate node for the root task. - df$package[df$depth == "direct"] <- - paste(df$package[df$depth == "direct"], "root", sep = "-") + if (inherits(x, "check_task")) { + df$package[df$depth == "direct"] <- + paste(df$package[df$depth == "direct"], "root", sep = "-") + } colmap <- c("package" = "from", "name" = "to") rename <- match(names(df), names(colmap)) to_rename <- !is.na(rename) @@ -47,17 +58,14 @@ task_graph.task <- function(x, repos = getOption("repos"), ...) { E(g_dep)$relation <- RELATION$dep E(g_dep)$type <- DEP[E(g_dep)$type] - V(g_dep)$task <- lapply( - V(g_dep)$name, - function(p) { - if (endsWith(p, "-root")) { - x - } else { - origin <- try_pkg_origin_repo(package = p, repos = repos) - install_task(origin = origin) - } + V(g_dep)$task <- lapply(V(g_dep)$name, function(p) { + if (endsWith(p, "-root") || (inherits(x, "install_task") && p == package(x))) { # nolint + x + } else { + origin <- try_pkg_origin_repo(package = p, repos = repos) + install_task(origin = origin) } - ) + }) V(g_dep)$name <- vcapply(V(g_dep)$task, as_vertex_name) @@ -65,7 +73,9 @@ task_graph.task <- function(x, repos = getOption("repos"), ...) { } #' @export -task_graph.task_graph <- function(x, repos = getOption("repos"), ...) { +task_graph.task_graph <- function( + x, repos = getOption("repos"), dependencies = TRUE, ... +) { # only use dependency edges when populating graph nodes <- V(x)[is_actionable_task(V(x)$task)] @@ -82,7 +92,7 @@ task_graph.task_graph <- function(x, repos = getOption("repos"), ...) { subtree <- igraph::induced_subgraph(x, nh) # build dependency graph, with fallback installation task - deps <- task_graph(nh[[1]]$task, repos = repos) + deps <- task_graph(nh[[1]]$task, repos = repos, dependencies = dependencies) # merge trees on package names # NOTE: attributes (tasks) are preserved in the order they appear @@ -94,8 +104,12 @@ task_graph.task_graph <- function(x, repos = getOption("repos"), ...) { deduplicate_task_graph(subtree) }) + # then merge all the full check task task trees into a single graph g <- graph_dedup_attrs(igraph::union(x, check_task_neighborhoods)) + # Make sure orphaned packages, so those that do not lead to any meta tasks, + # are skipped + g <- task_graph_removed_orphaned(g) E(g)$type <- DEP[E(g)$type] V(g)$status <- STATUS$pending @@ -138,8 +152,16 @@ deduplicate_task_graph <- function(g) { ) } } - isolated <- which(igraph::degree(g) == 0) - igraph::delete_vertices(g, isolated) + g +} + +task_graph_removed_orphaned <- function(g) { + # The only package without "in" vertex should be meta tasks + vs <- igraph::V(g) + + isolated <- igraph::degree(g, mode = "in") == 0 & !is_meta(vs$task) + + igraph::delete_vertices(g, vs[isolated]) } dep_edges <- function(edges, dependencies = TRUE) { diff --git a/R/utils-deps.R b/R/utils-deps.R index 3122dcd..8f5399c 100644 --- a/R/utils-deps.R +++ b/R/utils-deps.R @@ -19,22 +19,21 @@ as_pkg_dependencies <- function(x) { x <- "hard" } else if (identical(x, TRUE)) { x <- "most" - } else if (identical(x, FALSE)) { + } else if (identical(x, FALSE) || identical(x, "self")) { x <- character(0L) } - deptypes <- c("Depends", "Imports", "LinkingTo", "Suggests", "Enhances") - if (is.character(x)) { + if ((is.character(x) || is.factor(x)) && length(x) > 0) { x <- switch(x, - "all" = deptypes, - "most" = c("Depends", "Imports", "LinkingTo", "Suggests"), - "hard" = c("Depends", "Imports", "LinkingTo"), - "soft" = c("Suggests", "Enhances"), - x + "all" = DEP, + "most" = DEP[c("Depends", "Imports", "LinkingTo", "Suggests")], + "hard" = DEP[c("Depends", "Imports", "LinkingTo")], + "soft" = DEP[c("Suggests", "Enhances")], + DEP[x] ) } - stopifnot(all(x %in% deptypes)) + stopifnot(all(x %in% DEP)) x } diff --git a/R/utils-paths.R b/R/utils-paths.R index 1ff40a1..ba14d53 100644 --- a/R/utils-paths.R +++ b/R/utils-paths.R @@ -67,9 +67,9 @@ path_checker_lib <- function(path) { normalizePath(p) } -path_install_log <- function(path, package, name = "lib") { - dir_create(p <- file.path(path_logs(path), name)) - normalizePath(file.path(p, sprintf("%s.log", package)), mustWork = FALSE) +path_install_log <- function(path, package, task) { + dir_create(p <- file.path(path_logs(path), package)) + normalizePath(file.path(p, sprintf("%s.log", task)), mustWork = FALSE) } path_logs <- function(path) { diff --git a/R/utils-pkg-source.R b/R/utils-pkg-source.R index 48719d5..67f8e80 100644 --- a/R/utils-pkg-source.R +++ b/R/utils-pkg-source.R @@ -1,5 +1,8 @@ -strip_src_contrib <- function(x) { - sub("/src/contrib$", "", x) +strip_src_contrib <- function(x, repos) { + match <- vlapply(repos, function(r) { + utils::contrib.url(r) == x + }) + repos[match] } check_dependencies <- function(dependencies) { diff --git a/R/utils.R b/R/utils.R index e090a41..20b82ce 100644 --- a/R/utils.R +++ b/R/utils.R @@ -38,9 +38,24 @@ base_pkgs <- memoise::memoise(function() { c("R", utils::installed.packages(priority = "base")[, "Package"]) }) -is_package_installed <- function(pkg, lib.loc = .libPaths()) { - path <- find.package(pkg, lib.loc = lib.loc, quiet = TRUE) - length(path) > 0 +is_package_installed <- function(pkg, lib.loc = .libPaths(), version = NULL) { + if (is.null(version)) { + path <- find.package(pkg, lib.loc = lib.loc, quiet = TRUE) + length(path) > 0 + } else { + tryCatch( + utils::packageVersion(pkg, lib.loc) >= version, + error = function(e) FALSE + ) + } +} + +`%nif%` <- function(lhs, rhs) { + if (isTRUE(lhs)) { + rhs + } else { + NULL + } } .callr <- as.list(getNamespace("callr"), all.names = TRUE)[c( diff --git a/man/checker.Rd b/man/checker.Rd index f5cbff3..f16eb06 100644 --- a/man/checker.Rd +++ b/man/checker.Rd @@ -81,6 +81,8 @@ and installation order are embedded. lib.loc = .libPaths(), repos = getOption("repos"), restore = options::opt("restore"), + dependencies = TRUE, + upgrade = FALSE, ... )}\if{html}{\out{}} } @@ -106,6 +108,13 @@ generating task graph and later pulling dependencies.} unlinked before running checks. If \code{FALSE}, an attempt will me made to restore previous progress from the same \code{output}.} +\item{\code{dependencies}}{A vector of length one or a named list. +Compatible with \code{\link{as_pkg_dependencies}}.} + +\item{\code{upgrade}}{\code{logical} value, whether packages should be upgraded +if more recent version is discovered in available sources. Remotes +packages, if allowed to be used, are always installed and prioritized.} + \item{\code{...}}{Additional arguments unused} } \if{html}{\out{}} diff --git a/man/install_task.Rd b/man/install_task.Rd index 0663971..385aa3e 100644 --- a/man/install_task.Rd +++ b/man/install_task.Rd @@ -9,6 +9,7 @@ install_task( type = package_install_type(origin), INSTALL_opts = NULL, lib = lib_path(origin), + env = options::opt("install_envvars"), ... ) } @@ -33,6 +34,8 @@ install_task( \item{lib}{Any object that can be passed to \code{\link[=lib]{lib()}} to generate a library path.} +\item{env}{Environment variables to set for the child process.} + \item{...}{ further arguments to be passed to \code{\link[utils]{download.file}}, \code{\link[utils]{available.packages}}, or to the functions for binary diff --git a/man/options.Rd b/man/options.Rd index c00ce40..71c9de2 100644 --- a/man/options.Rd +++ b/man/options.Rd @@ -99,6 +99,27 @@ the R CMD check.\item{default: }{\preformatted{c(`_R_CHECK_FORCE_SUGGESTS_` = "f \item{envvar: }{R_CHECKED_CHECK_ARGS (space-separated R CMD check flags)} }} +\item{install_envvars}{\describe{ +named \code{character} vector of environment variables to use during +the package installation.\item{default: }{\preformatted{callr::rcmd_safe_env()}} +\item{option: }{checked.install_envvars} +\item{envvar: }{R_CHECKED_INSTALL_ENVVARS (evaluated if possible, raw string otherwise)} +}} + +\item{install_system_profile}{\describe{ +\code{logical} used as \code{sytem_profile} parameter passed to the \code{callr::r_bg()} +function used to install packages\item{default: }{\preformatted{FALSE}} +\item{option: }{checked.install_system_profile} +\item{envvar: }{R_CHECKED_INSTALL_SYSTEM_PROFILE (evaluated if possible, raw string otherwise)} +}} + +\item{install_user_profile}{\describe{ +value used as \code{user_profile} parameter passed to the \code{callr::r_bg()} +function used to install packages\item{default: }{\preformatted{"project"}} +\item{option: }{checked.install_user_profile} +\item{envvar: }{R_CHECKED_INSTALL_USER_PROFILE (evaluated if possible, raw string otherwise)} +}} + } } diff --git a/man/options_params.Rd b/man/options_params.Rd index 4e68647..4402e65 100644 --- a/man/options_params.Rd +++ b/man/options_params.Rd @@ -16,8 +16,14 @@ are discovered when generating results. "never" means that no errors are thrown. If "issues" then errors are emitted only on issues, whereas "potential issues" stands for error on both issues and potential issues. (Defaults to \code{"never"}, overwritable using option 'checked.results_error_on' or environment variable 'R_CHECKED_RESULTS_ERROR_ON')} +\item{install_envvars}{named \code{character} vector of environment variables to use during +the package installation. (Defaults to \code{callr::rcmd_safe_env()}, overwritable using option 'checked.install_envvars' or environment variable 'R_CHECKED_INSTALL_ENVVARS')} + \item{check_args}{\code{character} vector of args passed to the R CMD check. (Defaults to \code{c("--timings", "--ignore-vignettes", "--no-manual", "--as-cran")}, overwritable using option 'checked.check_args' or environment variable 'R_CHECKED_CHECK_ARGS')} +\item{install_system_profile}{\code{logical} used as \code{sytem_profile} parameter passed to the \code{callr::r_bg()} +function used to install packages (Defaults to \code{FALSE}, overwritable using option 'checked.install_system_profile' or environment variable 'R_CHECKED_INSTALL_SYSTEM_PROFILE')} + \item{results_keep}{character vector indicating which packages should be included in the results. "all" means that all packages are kept. If "issues" then only packages with issues identified, whereas "potential_issues" stands for keeping @@ -38,6 +44,9 @@ the R CMD check. (Defaults to \verb{c(}\emph{R_CHECK_FORCE_SUGGESTS}\verb{= "fal running checks. If \code{FALSE}, an attempt will me made to restore previous progress from the same \code{output} (Defaults to \code{NA}, overwritable using option 'checked.restore' or environment variable 'R_CHECKED_RESTORE')} +\item{install_user_profile}{value used as \code{user_profile} parameter passed to the \code{callr::r_bg()} +function used to install packages (Defaults to \code{"project"}, overwritable using option 'checked.install_user_profile' or environment variable 'R_CHECKED_INSTALL_USER_PROFILE')} + \item{tty_default_height}{deafult tty height used for the ANSI reporter. Used only if correct values could not be acquired with system('tput lines') (Defaults to \code{50}, overwritable using option 'checked.tty_default_height' or environment variable 'R_CHECKED_TTY_DEFAULT_HEIGHT')} } diff --git a/man/plan_local_checks.Rd b/man/plan_local_checks.Rd index 34f3e14..6916c83 100644 --- a/man/plan_local_checks.Rd +++ b/man/plan_local_checks.Rd @@ -4,13 +4,21 @@ \alias{plan_local_checks} \title{Plan R CMD Checks} \usage{ -plan_local_checks(package, repos = getOption("repos")) +plan_local_checks( + package, + repos = getOption("repos"), + remotes_dependencies = TRUE +) } \arguments{ \item{package}{A path to either package, directory with packages or name of the package (details)} \item{repos}{repository used to identify packages when name is provided.} + +\item{remotes_dependencies}{A vector of length one or a named list. +Compatible with \code{\link{as_pkg_dependencies}}. Used to filter out remotes +dependencies.} } \description{ Generates a plan for running R CMD check for a specified set of packages. diff --git a/man/plan_local_install.Rd b/man/plan_local_install.Rd index 8346cb5..aed52d5 100644 --- a/man/plan_local_install.Rd +++ b/man/plan_local_install.Rd @@ -4,12 +4,24 @@ \alias{plan_local_install} \title{Plan source package installation} \usage{ -plan_local_install(package, repos = getOption("repos")) +plan_local_install( + package, + repos = getOption("repos"), + remotes_dependencies = TRUE, + INSTALL_opts = c() +) } \arguments{ \item{package}{A path to package source.} \item{repos}{repository used to identify packages when name is provided.} + +\item{remotes_dependencies}{A vector of length one or a named list. +Compatible with \code{\link{as_pkg_dependencies}}. Used to filter out remotes +dependencies.} + +\item{INSTALL_opts}{Options to set while the root package is being installed. +Check \code{\link[utils:install.packages]{utils::install.packages}} for details.} } \description{ Generates a plan for running installing a package from source. diff --git a/man/plan_rev_dep_checks.Rd b/man/plan_rev_dep_checks.Rd index a61a5a6..9708ecb 100644 --- a/man/plan_rev_dep_checks.Rd +++ b/man/plan_rev_dep_checks.Rd @@ -4,12 +4,20 @@ \alias{plan_rev_dep_checks} \title{Plan Reverse Dependency Checks} \usage{ -plan_rev_dep_checks(path, repos = getOption("repos")) +plan_rev_dep_checks( + path, + repos = getOption("repos"), + remotes_dependencies = TRUE +) } \arguments{ \item{path}{path to the package source.} \item{repos}{repository used to identify reverse dependencies.} + +\item{remotes_dependencies}{A vector of length one or a named list. +Compatible with \code{\link{as_pkg_dependencies}}. Used to filter out remotes +dependencies.} } \description{ Generates a plan for running reverse dependency check for certain diff --git a/man/task_graph.Rd b/man/task_graph.Rd index e01a62f..6a2b2df 100644 --- a/man/task_graph.Rd +++ b/man/task_graph.Rd @@ -4,7 +4,7 @@ \alias{task_graph} \title{Build task graph edges} \usage{ -task_graph(x, repos = getOption("repos"), ...) +task_graph(x, repos = getOption("repos"), dependencies = TRUE, ...) } \arguments{ \item{x}{a \code{plan} object, containing a list of related steps.} @@ -12,6 +12,9 @@ task_graph(x, repos = getOption("repos"), ...) \item{repos}{\code{repos}, as expected by \code{\link[tools:package_dependencies]{tools::package_dependencies()}} to determine package relationships.} +\item{dependencies}{A vector of length one or a named list. Compatible with +\code{\link{as_pkg_dependencies}}.} + \item{...}{params passed to helper methods.} } \value{ From 986ad05a6706615a589e399ee8017b1ab64e6ec5 Mon Sep 17 00:00:00 2001 From: Szymon Maksymiuk <32574056+maksymiuks@users.noreply.github.com> Date: Wed, 17 Jun 2026 17:17:13 +0200 Subject: [PATCH 13/14] Ensure non-standrd sources packages are always isntalled (#95) --- NEWS.md | 3 ++- R/next_task.R | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9c7724b..d8e81bc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,7 +12,8 @@ * Multiple API changes facilitating additional customization for tasks. -* Ensure packages destined into isolated libraries are always installed. +* Ensure packages destined into isolated libraries or those coming from + non-standard sources are always installed. * Redesign logs by grouping them into package specific directories. diff --git a/R/next_task.R b/R/next_task.R index c2691f6..a392601 100644 --- a/R/next_task.R +++ b/R/next_task.R @@ -86,7 +86,11 @@ start_task.install_task <- function( libpaths, upgrade %nif% task$origin$version ) - if (is_installed && is_lib_path_default(task)) return(NULL) + + if (is_installed && + is_lib_path_default(task) && + inherits(task$origin, "pkg_origin_repo")) + return(NULL) install_process$new( install_parameters$package, From 89cb838249d97c7231345003ea072e04278728ad Mon Sep 17 00:00:00 2001 From: Szymon Maksymiuk <32574056+maksymiuks@users.noreply.github.com> Date: Mon, 22 Jun 2026 15:01:06 +0200 Subject: [PATCH 14/14] Basic tty improvements (#97) * Basic tty improvements * Fix options --- DESCRIPTION | 2 +- NEWS.md | 6 ++++++ R/checker.R | 8 ++++++++ R/install.R | 39 ++++++++++++++++++++++++++------------- R/next_task.R | 4 +--- R/reporter.R | 8 ++++++-- R/reporter_basic_tty.R | 27 +++++++++++++++++++++------ R/run.R | 6 +++--- man/checker.Rd | 14 ++++++++++++++ man/reporters.Rd | 4 +++- man/run.Rd | 2 +- 11 files changed, 90 insertions(+), 30 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 01a5994..de0725c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: checked Title: Systematically Run R CMD Checks -Version: 0.5.3 +Version: 0.5.4 Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index d8e81bc..7534ead 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# checked 0.5.4 + +* Improve error messaging when using basic_tty + +* Various improvements to reporters and minor display tweaks + # checked 0.5.3 * Make is possible to construct reporter environments with additional values diff --git a/R/checker.R b/R/checker.R index d631a3d..272fb16 100644 --- a/R/checker.R +++ b/R/checker.R @@ -228,6 +228,14 @@ checker <- R6::R6Class( all(V(self$graph)$status == STATUS$done) } + }, + #' @description + #' Tasks + #' + #' Returns what type of tasks the checker consists of and returns a unique + #' vector of primary classes + tasks = function() { + unique(vcapply(V(self$graph)$task, function(x) class(x)[[1]])) } ), private = list( diff --git a/R/install.R b/R/install.R index 0ab1056..93adbae 100644 --- a/R/install.R +++ b/R/install.R @@ -19,29 +19,22 @@ install_process <- R6::R6Class( private$package <- pkgs self$log <- log private$callr_r_bg( - function(..., escalate_warning, available_packages_filters) { + function(..., available_packages_filters) { options( timeout = 600, available_packages_filters = available_packages_filters ) - withCallingHandlers( + invisible(capture.output(withCallingHandlers( utils::install.packages(..., quiet = FALSE, verbose = TRUE), warning = function(w) { - if (escalate_warning(w)) { - print(w$message) - stop(w$message) - } else { - print(w$message) - warning(w) - } + print(w$message) } - ) + ), split = TRUE)) }, args = list( private$package, ..., lib = lib, - escalate_warning = is_install_failure_warning, available_packages_filters = available_packages_filters ), libpath = libpaths, @@ -49,6 +42,7 @@ install_process <- R6::R6Class( stderr = "2>&1", system_profile = options::opt("install_system_profile"), user_profile = options::opt("install_user_profile"), + cmdargs = c("--slave", "--no-save", "--no-restore", "--vanilla"), env = env ) }, @@ -68,7 +62,26 @@ install_process <- R6::R6Class( if (is.function(f <- private$finish_callback)) f(self) }, get_r_exit_status = function() { - as.integer(inherits(try(self$get_result(), silent = TRUE), "try-error")) + res <- self$get_results_safe() + if (inherits(self$get_results_safe(), "callr_error")) { + 1L + } else if (any(is_install_failure_warning(res))) { + 1L + } else { + 0L + } + + }, + get_results_safe = function() { + tryCatch( + gsub("\\n", "\n", self$get_result(), fixed = TRUE), + error = function(e) { + e + }, + warning = function(w) { + w + } + ) } ), private = list( @@ -115,5 +128,5 @@ is_install_failure_warning <- function(w) { ) re <- paste0("(", paste0(patterns, collapse = "|"), ")") - grepl(re, w$message) + grepl(re, w) } diff --git a/R/next_task.R b/R/next_task.R index a392601..8d9731a 100644 --- a/R/next_task.R +++ b/R/next_task.R @@ -87,9 +87,7 @@ start_task.install_task <- function( upgrade %nif% task$origin$version ) - if (is_installed && - is_lib_path_default(task) && - inherits(task$origin, "pkg_origin_repo")) + if (is_installed && is_lib_path_default(task) && inherits(task$origin, "pkg_origin_repo")) # nolint return(NULL) install_process$new( diff --git a/R/reporter.R b/R/reporter.R index fc0ba80..3b5c43b 100644 --- a/R/reporter.R +++ b/R/reporter.R @@ -22,6 +22,7 @@ #' a reporter with minimal assumptions about terminal capabilities. #' #' @param checks_only whether basic tty reporter should report only check tasks. +#' @param checker checker object required to properly derive default reporter. #' @param ... additional values which should be assigned to the reported #' environment. #' @@ -58,8 +59,11 @@ reporter_basic_tty <- function(checks_only = FALSE, ...) { #' @rdname reporters #' @export -reporter_default <- function() { - if (cli::is_ansi_tty()) { +reporter_default <- function(checker = NULL) { + is_revdep <- + !is.null(checker) && "rev_dep_check_meta_task" %in% checker$tasks() + + if (cli::is_ansi_tty() && is_revdep) { reporter_ansi_tty() } else if (cli::is_dynamic_tty()) { reporter_basic_tty() diff --git a/R/reporter_basic_tty.R b/R/reporter_basic_tty.R index 1ec4ef4..1880570 100644 --- a/R/reporter_basic_tty.R +++ b/R/reporter_basic_tty.R @@ -19,7 +19,13 @@ report_start_setup.reporter_basic_tty <- function( reporter$time_start <- Sys.time() - cli::cli_text("<", utils::packageName(), "> Checks") + type <- if (all(vlapply(v_reportable$task, inherits, "install_task"))) { + "> Installs" + } else { + "> Checks" + } + + cli::cli_text("<", utils::packageName(), type) } #' @export @@ -41,6 +47,7 @@ report_status.reporter_basic_tty <- function(reporter, checker, envir) { p <- node$process + failure_message <- NULL # report stating of new checks if (!identical(node$status, reporter$status[[node$name]])) { status <- switch( # nolint @@ -61,12 +68,19 @@ report_status.reporter_basic_tty <- function(reporter, checker, envir) { ) } else if (p$get_r_exit_status() != 0) { # checks processes don't have logs associated with it - message <- if (!is.null(p$log)) { - sprintf("failed (log: '%s')", p$log) - } else { - "failed" + failure_message <- if (inherits(p, "install_process")) { + paste( + p$get_results_safe(), + if (file.exists(p$log)) sprintf("\nfull log: '%s'", p$log), + sep = "\n", + collapse = "\n" + ) } - cli::cli_fmt(cli::cli_text(message)) + cli::cli_fmt( + cli::cli_text( + "failed", cli::format_inline(fmt_count) + ) + ) } else { dur <- if (!is.null(p$get_duration)) { p$get_duration() @@ -103,6 +117,7 @@ report_status.reporter_basic_tty <- function(reporter, checker, envir) { type <- format_task_type(node$task) # nolint (used via glue) prefix <- cli::col_cyan("[{format_time(time)}][{type}] ") cli::cli_text(prefix, "{.pkg {package(node$task)}} {status}") + if (!is.null(failure_message)) cli::cli_text(failure_message) reporter$status[[node$name]] <- node$status } } diff --git a/R/run.R b/R/run.R index 01005b5..2b12df6 100644 --- a/R/run.R +++ b/R/run.R @@ -13,12 +13,12 @@ #' most expressive command-line reporter given your terminal capabilities. #' #' @export -run <- function(checker, ..., reporter = reporter_default()) { +run <- function(checker, ..., reporter = reporter_default(checker)) { UseMethod("run") } #' @export -run.character <- function(checker, ..., reporter = reporter_default()) { +run.character <- function(checker, ..., reporter = reporter_default(checker)) { checker <- new_rev_dep_checker(checker, ...) report_start_setup( reporter, @@ -30,7 +30,7 @@ run.character <- function(checker, ..., reporter = reporter_default()) { } #' @export -run.checker <- function(checker, ..., reporter = reporter_default()) { +run.checker <- function(checker, ..., reporter = reporter_default(checker)) { on.exit(add = TRUE, { checker$terminate() report_finalize(reporter, checker) diff --git a/man/checker.Rd b/man/checker.Rd index f16eb06..10116f2 100644 --- a/man/checker.Rd +++ b/man/checker.Rd @@ -62,6 +62,7 @@ be created and stored.} \item \href{#method-checker-step}{\code{checker$step()}} \item \href{#method-checker-start_next_task}{\code{checker$start_next_task()}} \item \href{#method-checker-is_done}{\code{checker$is_done()}} +\item \href{#method-checker-tasks}{\code{checker$tasks()}} \item \href{#method-checker-clone}{\code{checker$clone()}} } } @@ -194,6 +195,19 @@ Checks whether all the scheduled tasks were successfully executed. \if{html}{\out{
}}\preformatted{checker$is_done()}\if{html}{\out{
}} } +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-checker-tasks}{}}} +\subsection{Method \code{tasks()}}{ +Tasks + +Returns what type of tasks the checker consists of and returns a unique +vector of primary classes +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{checker$tasks()}\if{html}{\out{
}} +} + } \if{html}{\out{
}} \if{html}{\out{}} diff --git a/man/reporters.Rd b/man/reporters.Rd index feb2287..05041c4 100644 --- a/man/reporters.Rd +++ b/man/reporters.Rd @@ -14,13 +14,15 @@ reporter_ansi_tty2(...) reporter_basic_tty(checks_only = FALSE, ...) -reporter_default() +reporter_default(checker = NULL) } \arguments{ \item{...}{additional values which should be assigned to the reported environment.} \item{checks_only}{whether basic tty reporter should report only check tasks.} + +\item{checker}{checker object required to properly derive default reporter.} } \description{ Reporters are used to configure how output is communicated while running diff --git a/man/run.Rd b/man/run.Rd index e6d7993..94cc504 100644 --- a/man/run.Rd +++ b/man/run.Rd @@ -4,7 +4,7 @@ \alias{run} \title{Run a Series of \verb{R CMD check}s} \usage{ -run(checker, ..., reporter = reporter_default()) +run(checker, ..., reporter = reporter_default(checker)) } \arguments{ \item{checker}{\code{character} or \code{checker} If a \code{character} value is