detect_platform <- function() {
me <- list(
os = R.Version()$os,
arch = R.Version()$arch,
rver = get_minor_r_version(getRversion())
)
if (me$os %in% c("linux-dietlibc", "linux-gnu", "linux-musl",
"linux-uclibc", "linux-unknown")) {
me$os <- "linux"
}
me
}
pak_stream <- function(stream) {
if (stream == "auto") {
version <- unclass(package_version(utils::packageVersion("pak")))[[1]]
stream <- if (length(version) >= 4 && version[4] == 9999) {
"rc"
} else if (length(version) >= 4 && version[4] >= 9000) {
"devel"
} else {
"stable"
}
}
stream
}
pak_repo <- function(stream = "auto") {
stream <- pak_stream(stream)
paste0("https://r-lib.github.io/p/pak/", stream, "/")
}
pak_repo_metadata <- function(repo = NULL, stream = "auto") {
repo <- repo %||% pak_repo(stream)
url <- paste0(repo, "metadata.json")
tmp <- tempfile()
on.exit(unlink(tmp), add = TRUE)
utils::download.file(url, tmp, mode = "wb", quiet = TRUE)
df <- json$parse_file(tmp)
meta <- do.call(rbind, lapply(df, as.data.frame, stringsAsFactors = FALSE))
rver <- sub("R ", "", sapply(strsplit(meta$Built, ";"), "[[", 1))
meta$RVersion <- get_minor_r_version(rver)
meta
}
#' Update pak itself
#'
#' Use this function to update the released or development version of pak.
#'
#' @param force Whether to force an update, even if no newer version is
#' available.
#' @param stream Whether to update to the
#' * `"stable"`,
#' * `"rc"` (release candidate) or
#' * `"devel"` (development) version.
#' * `"auto"` updates to the same stream as the current one.
#'
#' Often there is no release candidate version, then `"rc"` also
#' installs the stable version.
#'
#' @return Nothing.
#'
#' @export
pak_update <- function(
force = FALSE,
stream = c("auto", "stable", "rc", "devel")) {
stopifnot(is_flag(force))
stream <- match.arg(stream)
stream <- pak_stream(stream)
repo <- pak_repo()
if (!is.null(.getNamespace("pak")$.__DEVTOOLS__)) {
lib <- .libPaths()[1]
warning(
"`load_all()`-d pak package, updating in default library at\n ",
"`", lib, "`",
immediate. = TRUE
)
} else {
lib <- dirname(getNamespaceInfo("pak", "path"))
}
repo <- pak_repo(stream)
meta <- pak_repo_metadata(repo)
me <- detect_platform()
cand <- which(
meta$OS == me$os &
meta$Arch == me$arch &
meta$RVersion == me$rver
)
if (length(cand) == 0) {
pak_update_unsupported_platform(stream, me, meta)
} else if (length(cand) > 1) {
warning("Multiple pak candidates are available for this platform, ",
"this should not happen. Using the first one.")
cand <- cand[1]
}
check_mac_cran_r(me, meta)
upd <- should_update_to(meta[cand, , drop = FALSE])
if (!upd && !force) {
message("\nCurrent version is the latest, no need to update.")
return(invisible())
}
url <- paste0(repo, me$os, "/", me$arch, "/", meta$File[cand])
tgt <- file.path(tempdir(), meta$File[cand])
utils::download.file(url, tgt, mode = "wb")
date <- get_built_date(meta$Built[cand])
message("\nUpdating to version ", meta$Version[cand], " (", date, ")\n")
# Otherwise the subprocess might be locking some DLLs
try(pkg_data$remote$kill(), silent = TRUE)
# Windows cannot install binaries with arbitrary names, apparently.
ext <- tools::file_ext(tgt)
if (.Platform$OS.type == "windows" && ext == "zip") {
dir.create(tmp <- tempfile(), recursive = TRUE)
on.exit(unlink(tmp, recursive = TRUE), add = TRUE)
tgt2 <- file.path(tmp, "pak.zip")
if (!file.copy(tgt, tgt2)) {
stop("Failed to copy downloaded file :(")
}
tgt <- tgt2
}
utils::install.packages(tgt, repos = NULL, type = "source", lib = lib)
attached <- "package:pak" %in% search()
message("\nReloading pak.")
# Try to use it to see if it was successful
suppressWarnings(tryCatch({
eapply(asNamespace("pak"), base::force, all.names = TRUE)
unloadNamespace("pak")
# This works around the help lazy load DB errors
intern <- base::.Internal
lazyLoadDBflush <- function(...) NULL
tryCatch(
intern(lazyLoadDBflush(file.path(lib, "pak", "help", "pak.rdb"))),
error = function(e) NULL
)
loadNamespace("pak")
if (attached) library(pak)
suppressWarnings(tools::Rd_db(package = "pak"))
}, error = function(err) {
message("\nFailed to reload pak. Please restart your R session.")
}))
invisible()
}
pak_update_unsupported_platform <- function(stream, me, meta) {
message("pak has ", stream, " binaries for the following platforms:")
meta$OS <- sub("^darwin", "macOS darwin", meta$OS)
meta$OS <- sub("^mingw32", "Windows (mingw32)", meta$OS)
pl <- paste0(meta$OS, ", ", meta$Arch)
rv <- tapply(
meta$RVersion,
pl,
function(x) paste0("R ", sort(x), ".x"),
simplify = FALSE
)
pl2 <- sapply(rv, paste, collapse = ", ")
message(paste0(" * ", names(pl2), ", ", pl2, "\n"))
stop(
"pak is not available for ", me$os, ", ",
me$arch, ", R ", me$rver, ".x. Aborting now"
)
# TODO: tell how to install from source
}
check_mac_cran_r <- function(me, meta) {
if (! grepl("^darwin", me$os)) return()
if (.Platform$pkgType == "source") {
stop(
"pak only has binaries for the CRAN build of R, and this ",
"seems to be a brew or another non-CRAN build."
)
# TODO: tell how to install from source
}
}
should_update_to <- function(new) {
# check if the right platform was installed
current <- R.Version()$platform
if (!platform_match(pak_sitrep_data$platform, current)) {
message("\npak platform mismatch, trying to update to fix this...")
return(TRUE)
}
# otherwise use version number first
dsc <- utils::packageDescription("pak")
if (package_version(dsc$Version) < new$Version) return(TRUE)
# or the build date
blt_cur <- get_built_date(dsc$Built)
blt_new <- get_built_date(new$Built)
if (is.na(blt_cur) || blt_cur < blt_new) return(TRUE)
FALSE
}
get_built_date <- function(x) {
if (!is_string(x)) return(NA_character_)
# We can compare these dates as strings, so no need to parse
strsplit(x, "[ ]*;[ ]*")[[1]][3]
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.