Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 102 additions & 3 deletions R/sysreqs.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,77 @@ sysreqs_db_list <- function(sysreqs_platform = NULL) {
)
}

check_sysreqs_enabled <- function() {
sysreqs_enabled <- remote(
function() {
config <- pkgdepends::current_config()
config$get("sysreqs")
}
)

if (!sysreqs_enabled) {
cli::cli_alert_info(
"System requirements checking is disabled in the config."
)
cli::cli_alert_info(
"Use {.code Sys.setenv('PKG_SYSREQS' = 'TRUE')}
or {.code options(pkg.sysreqs = TRUE)}."
)

# Return an empty data frame with the expected structure
result <- data.frame(
system_package = character(0),
installed = logical(0),
packages = I(list()),
pre_install = I(list()),
post_install = I(list())
)
class(result) <- c("pkg_sysreqs_check_result", class(result))
return(pak_preformat(result))
}

return(NULL)
}

sysreqs_check_installed <- function(packages = NULL, library = .libPaths()[1]) {
load_extra("pillar")
remote(

# Check if sysreqs is enabled, return early if disabled
disabled_result <- check_sysreqs_enabled()
if (!is.null(disabled_result)) {
return(invisible(disabled_result))
}

result <- remote(
function(...) {
ret <- pkgdepends::sysreqs_check_installed(...)
asNamespace("pak")$pak_preformat(ret)
},
list(packages = packages, library = library)
)

# Inform about detection method
if (nrow(result) > 0) {
cli::cli_alert_info(
"System packages checked via system package manager only."
)
cli::cli_alert_info(
"Software in non-standard locations may not be detected."
)
}

result
}

sysreqs_fix_installed <- function(packages = NULL, library = .libPaths()[1]) {
load_extra("pillar")

# Check if sysreqs is enabled, return early if disabled
disabled_result <- check_sysreqs_enabled()
if (!is.null(disabled_result)) {
return(invisible(disabled_result))
}

invisible(remote(
function(...) {
ret <- pkgdepends::sysreqs_fix_installed(...)
Expand All @@ -62,6 +120,7 @@ sysreqs_fix_installed <- function(packages = NULL, library = .libPaths()[1]) {
))
}


#' Calculate system requirements of one of more packages
#'
#' @inheritParams pkg_install
Expand Down Expand Up @@ -110,7 +169,15 @@ pkg_sysreqs <- function(
sysreqs_platform = NULL
) {
load_extra("pillar")
remote(
# Check if sysreqs support is enabled
sysreqs_enabled <- remote(
function() {
config <- pkgdepends::current_config()
config$get("sysreqs")
}
)

result <- remote(
function(...) {
get("pkg_sysreqs_internal", asNamespace("pak"))(...)
},
Expand All @@ -121,6 +188,26 @@ pkg_sysreqs <- function(
sysreqs_platform = sysreqs_platform
)
)

# Add informational message if results are shown
if (sysreqs_enabled && length(result$install_scripts) > 0) {
cli::cli_alert_info(
"System packages detected via system package manager only."
)
cli::cli_alert_info(
"Software in non-standard locations may require manual verification."
)
} else if (!sysreqs_enabled) {
cli::cli_alert_info(
"System requirements lookup is disabled."
)
cli::cli_alert_info(
"Enable with {.code Sys.setenv('PKG_SYSREQS' = 'TRUE')}
or {.code options(pkg.sysreqs = TRUE)}."
)
}

result
}

pkg_sysreqs_internal <- function(
Expand Down Expand Up @@ -180,6 +267,17 @@ format.pak_sysreqs <- function(x, ...) {
out
}

# Add warning message about detection limitations
warning_msg <- c(
"",
cli$rule(left = "System package detection", col = "yellow"),
paste(
cli$col_yellow(cli$symbol$warning),
"System packages are detected via the system package manager only."
),
"Software installed in non-standard locations may not be detected."
)

c(
cli$rule(left = "Install scripts", right = label),
x$pre_install,
Expand All @@ -195,7 +293,8 @@ format.pak_sysreqs <- function(x, ...) {
" ",
vcapply(pkgs, function(x) paste(cisort(x), collapse = ", "))
)
}
},
warning_msg
)
}

Expand Down
36 changes: 36 additions & 0 deletions R/sysreqsdocs.R
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,39 @@ sysreqs_fix_installed <- sysreqs_fix_installed
#' sysreqs_list_system_packages()[1:10,]

sysreqs_list_system_packages

#' System requirements detection limitations
#'
#' @description
#' System requirements detection in pak only considers packages installed via the system package manager.
#' Supported package managers include:
#' * `apt` on Debian/Ubuntu systems
#' * `yum`/`dnf` on RedHat/CentOS/Fedora systems
#' * `zypper` on openSUSE/SUSE systems
#' * `apk` on Alpine systems
#'
#' pak does **not** detect software installed via:
#' * Environment modules (e.g., lmod, environment modules)
#' * Custom compilation from source
#' * Alternative package managers (e.g., conda, spack, nix, homebrew)
#' * User-space installations
#' * Software loaded via environment variables
#'
#' If your system has software installed in non-standard locations, you may need to:
#' * Install the required system packages via your system package manager
#' * Disable system requirements checking with `PKG_SYSREQS=FALSE`
#' * Use `options(pkg.sysreqs = FALSE)` to disable system requirements globally
#'
#' Use [sysreqs_status()] to check your current configuration.
#'
#' @name sysreqs_detection_limitations
#' @family system requirements functions
#' @keywords internal
#' @examplesIf Sys.getenv("IN_PKGDOWN") == "true"
#' # Check current system requirements status
#' sysreqs_status()
#'
#' # Disable system requirements globally
#' options(pkg.sysreqs = FALSE)

check_sysreqs_enabled
65 changes: 65 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,68 @@ rbind_expand <- function(..., .list = list()) {
cisort <- function(x) {
x[order(tolower(x))]
}

sysreqs_status <- function() {
config_info <- remote(
function() {
config <- pkgdepends::current_config()
list(
enabled = config$get("sysreqs"),
platform = config$get("sysreqs_platform"),
supported = pkgdepends::sysreqs_is_supported()
)
}
)

# Check source of configuration
env_sysreqs <- Sys.getenv("PKG_SYSREQS", "")
opt_sysreqs <- getOption("pkg.sysreqs", NULL)

config_source <- if (nzchar(env_sysreqs)) {
"environment variable PKG_SYSREQS"
} else if (!is.null(opt_sysreqs)) {
"option pkg.sysreqs"
} else {
"default"
}

cli::cli_h2("System Requirements Configuration")

if (config_info$enabled) {
cli::cli_alert_success(
"System requirements: {.strong enabled} (via {config_source})"
)

cli::cli_alert_info(
"Platform: {.val {config_info$platform}}"
)
cli::cli_alert_info(
"Platform supported: {.val {config_info$supported}}"
)
cli::cli_alert_warning(
"Detection method: {.strong system package manager only}"
)
cli::cli_text("")
cli::cli_text(
"
Software in non-standard locations will {.strong not} be detected:"
)
cli::cli_ul(c(
"Environment modules (lmod)",
"Custom compilation from source",
"Alternative package managers (conda, spack, nix)",
"User-space installations"
))
} else {
cli::cli_alert_info(
"System requirements: {.strong disabled} (via {config_source})"
)
cli::cli_text("")
cli::cli_text("To enable system requirements:")
cli::cli_code("Sys.setenv('PKG_SYSREQS' = 'TRUE')")
cli::cli_text("or")
cli::cli_code("options(pkg.sysreqs = TRUE)")
}

invisible(config_info)
}