我在基于 docker 的 R 设置中的可用库方面运行得有些紧张。 因此,包更新是保守且有意识地执行的。新版本或多或少 手工采摘。在这种情况下,我意识到增加包的版本不会抱怨 如果依赖项已安装在比实际需要的版本更小的版本中,则考虑过时的依赖项。
下面显示了一个示例来说明我的意思。该示例是在“干净”的
R 4.1.2
上创建的,除了 R 直接附带的包之外,没有安装任何包。
我知道参数设置
dependencies = FALSE
和upgrade = "never"
会阻止安装/升级依赖项(我需要这些设置来进行严格控制),但是,我预计至少会有一个警告告诉我,例如askpass 1.2.0
至少需要 sys 2.1
或同等地 highr 0.10
至少需要 xfun 0.18
。
大概问题只会在某些功能的运行时开始出现,我想防止这种情况发生。
有什么聪明的方法来处理这个问题吗?
install.packages("remotes", dependencies = FALSE) # 2.4.2.1
remotes::install_version("sys",
version = "2.0",
dependencies = FALSE,
upgrade = "never")
remotes::install_version("askpass",
version = "1.2.0",
dependencies = FALSE,
upgrade = "never")
remotes::install_version("xfun",
version = "0.17",
dependencies = FALSE,
upgrade = "never")
remotes::install_version("highr",
version = "0.10",
dependencies = FALSE,
upgrade = "never")
不确定这是否符合“聪明”的条件,但至少它返回了解决过时依赖问题所需的信息。
# these packages do not interfere with the
# example but are required to run the below code
#install.packages("dplyr")
#install.packages("purrr")
#install.packages("stringr")
library(dplyr) # 1.1.3
library(purrr) # 1.0.2
library(stringr) # 1.5.0
inst_packs <- as.data.frame(installed.packages())
inst_packs_name_version <- inst_packs %>%
select(Package, Version)
# single vector
dependency_info <- unlist(strsplit(c(inst_packs$Depends,
inst_packs$Imports,
inst_packs$LinkingTo),
split = ",",
fixed = TRUE)) %>%
str_squish() %>%
unique() %>%
discard(is.na)
splits <- strsplit(dependency_info, split = "\\(")
package <- str_squish(as.character(map(splits, 1)))
version <- gsub(x = as.character(map(splits, 2)),
pattern = "[^0-9.-]",
replacement = "")
deps <- data.frame(Package = package, Version = version) %>%
# highest Version is up top
arrange(Package, desc(Version)) %>%
# dependencies without version do not need to be considered
# also R is not a relevant dependency here
filter(Version != "" & Package != "R")
deps_uniq <- deps[!duplicated(deps$Package), ] %>%
arrange(Package)
row.names(deps_uniq) <- NULL
relevant_installed <- inst_packs_name_version %>%
filter(Package %in% deps_uniq$Package) %>%
arrange(Package, desc(Version))
# base R packages that are installed by the user too appear more than once
# e.g. "Matrix", "survival"
relevant_installed_uniq <- relevant_installed[!duplicated(relevant_installed$Package),]
row.names(relevant_installed_uniq) <- NULL
# sanity check
if(! all(deps_uniq$Package == relevant_installed_uniq$Package)) {
stop("Different set of packages. Assumptions are not met.")
}
reference_df <- data.frame(Package = deps_uniq$Package,
Version_req = deps_uniq$Version,
Version_inst = relevant_installed_uniq$Version)
# show only packages where a later version than the installed one is required
reference_df %>%
rowwise() %>%
mutate(req_larger_inst = compareVersion(Version_req, Version_inst)) %>%
filter(req_larger_inst > 0)
退货:
# A tibble: 2 × 4
# Rowwise:
Package Version_req Version_inst req_larger_inst
<chr> <chr> <chr> <dbl>
1 sys 2.1 2.0 1
2 xfun 0.18 0.17 1