Skip to content
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)
}
Loading