对于一组(已安装)R 软件包,我如何确定所有依赖项是否至少是给定设置所需的最低版本?

问题描述 投票:0回答:1

我在基于 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")
r dependencies remotes
1个回答
0
投票

不确定这是否符合“聪明”的条件,但至少它返回了解决过时依赖问题所需的信息。

# 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
© www.soinside.com 2019 - 2024. All rights reserved.