# Metadata-only ABI triage so the full build avoids downloading every source. # Mirrors bincraft::abi_classify rules 1-2; "ambiguous" packages still need a # source grep via bincraft::needs_per_minor_recompile(). classify_from_metadata <- function(needs_compilation, linking_to, risky_deps) { nc <- if (length(needs_compilation) == 0L || is.na(needs_compilation)) { "" } else { tolower(trimws(needs_compilation)) } if (!identical(nc, "yes")) { return("not-sensitive") } lt <- if (length(linking_to) == 0L || is.na(linking_to)) "" else linking_to linked <- trimws(unlist(strsplit(lt, "[,\n]"))) linked <- sub("\\s*\\(.*\\)$", "", linked) # strip "(>= x)" constraints linked <- linked[nzchar(linked)] if (any(linked %in% risky_deps)) { return("sensitive") } "ambiguous" } parse_build_args <- function(args) { sensitive_only <- "--sensitive-only" %in% args pos <- args[!startsWith(args, "--")] list( sensitive_only = sensitive_only, split_into = as.integer(pos[1L]), split_index = as.integer(pos[2L]), ncpus = as.integer(pos[3L]) ) } # Bound the {pkgcache} metadata dir, which otherwise grows without limit: the # "patched" repo mints a new content hash on every PACKAGES change, so each build # writes a fresh ~70 MB _metadata/pkgs-.rds (+ patched-/) that is # never reused. Keep the `keep` newest entries by mtime; only remove entries # older than `min_age_secs`, so a concurrent split-job's in-flight files are # never deleted (each build uses a unique hash, so aged entries are # unreferenced). Stable repo dirs (CRAN-*, BioC*, INLA-*) and pkg/ downloads are # not matched and thus preserved. Returns the number of entries removed. trim_pkgcache_metadata <- function(cache_dir = Sys.getenv("R_PKG_CACHE_DIR"), keep = 20L, min_age_secs = 600) { meta <- file.path(cache_dir, "R", "pkgcache", "_metadata") if (!nzchar(cache_dir) || !dir.exists(meta)) { return(0L) } entries <- c( Sys.glob(file.path(meta, "patched-*")), Sys.glob(file.path(meta, "pkgs-*.rds")) ) if (length(entries) == 0L) { return(0L) } info <- file.info(entries) order_new_first <- order(info$mtime, decreasing = TRUE) ranked <- entries[order_new_first] ranked_mtime <- info$mtime[order_new_first] if (length(ranked) <= keep) { return(0L) } candidates <- ranked[(keep + 1L):length(ranked)] candidate_age <- as.numeric(Sys.time()) - as.numeric(ranked_mtime[(keep + 1L):length(ranked)]) removable <- candidates[candidate_age >= min_age_secs] if (length(removable) == 0L) { return(0L) } unlink(removable, recursive = TRUE, force = TRUE) length(removable) }