2016-07-31 2 views
5

저는 패키지 개발자이며 내 패키지를 사용하는 데 필요한 최소 R 버전을 DESCRIPTION 파일에 기재하려고합니다.모든 패키지 종속성에 대한 최소 R 버전 결정

available.packages은 패키지의 설명을 파싱합니다. 그러나 가져 오기 및 종속 필드는 쉼표로 구분 된 텍스트이고 패키지에 버전 요구 사항이 포함되어 있기 때문에 결과가 쉽게 재귀 종속성을 조회 할 수 없습니다.

설명 된 솔루션은 Listing R Package Dependencies Without Installing Packages입니다. 재귀 솔루션은 아닙니다. 중첩 된 종속성에 R> 3.3이 필요한 경우이를 알고 싶습니다.

최소한 CR의 최소 버전을보고 특정 CRAN 패키지에 대해 가져온, 링크 및 의존 패키지를보고 싶습니다. 최소한의 R 또는 패키지 버전을 설정 한 패키지 또는 패키지를 나열하는 것이 더 좋습니다.

높은 버전 요구 사항이있는 종속성을 제거함으로써 해결할 수없는 제도적으로 오래된 R 버전으로 더 많은 사람들에게 서비스를 제공 할 수 있습니다. 일부는 아직 R 2.x에 있습니다.

+0

,하지만 하나의 방법 일 수 있습니다 우선 R 버전의 날짜를 확인한 다음 나중에 패키지를 설치하지 마십시오. (R 스크립트가 아닐 것입니다.) 포괄적 인 바이너리 저장소가 없으므로 특정 버전의 R 및 특정 OS에 적합한 빌드 도구 세트를 사용할 수 있어야합니다. 다른 방법은 useRs가 뒤로 가고 그 문제를 해결할 이유를 결정하는 것입니다. –

+1

그리고이 질문에 대한 두 번째 대답은 재귀적인 해결책을 제시했습니다. 어쩌면 이것이 중복 된 것일 수도 있습니다 (체크 표시가 된 해결책이 완전히 만족 스럽더라도)? 나는 마킹을 복제물로 잡을 것이지만 요구 사항에 대한보다 완전한 설명을 포함하도록 질문을 편집하지 않는 한 마킹 할 것입니다. –

+1

불행히도 이것은 잠재적 인 위험에 처할 수 있습니다. 당신은 ['rodham'] (https://cran.rstudio.com/web/packages/rodham/)과 같은 패키지를 가지고 있는데 그것은 _claim_> = 2.1.0이지만 _actually_ need> = 3.2.0은 함수 ('trimws()')는 3.2.0에서 소개되었으며 2.1.0에서는 사용할 수 없습니다. 3.2.0이 종료되고 CRAN 테스트가 현재 버전과 devel 버전에만있는 경우 CRAN에 도입 되었기 때문에이 종속성 오류가 누락됩니다. 나는 각각의 R 버전으로 도커 이미지를 만들고, 판 버전을 결정하기 위해 pkg 테스트를 실행하는 것이 더 낫다고 생각합니다. 매우 자동화가 가능합니다. – hrbrmstr

답변

4
min_r_version <- function(package="ggplot2", exclude_main_pkg=TRUE) { 

    purrr::walk(c("tools", "purrr", "devtools", "stringi", "tidyr", "dplyr"), 
       require, character.only=TRUE) 

    deps <- package_dependencies(package, recursive=TRUE) 

    if (exclude_main_pkg) { 
    pkgs <- deps[[1]] 
    } else { 
    pkgs <- c(package, deps[[1]]) 
    } 

    available.packages() %>% 
    as_data_frame() %>% 
    filter(Package %in% pkgs) %>% 
    select(Depends) %>% 
    unlist() -> pkg_list 

    # if main pkg only relied on core R packages (i.e. pkgs that aren't in CRAN) and we 
    # excluded the pkg itself from the min version calculation, this is an edge case we need 
    # to handle. 

    if (length(pkg_list) == 0) return("Unspecified") 

    stri_split_regex(pkg_list, "[,]") %>% 
    unlist() %>% 
    trimws() %>% 
    stri_match_all_regex(c("^R$|^R \\(.*\\)$")) %>% 
    unlist() %>% 
    discard(is.na(.)) %>% 
    unique() %>% 
    stri_replace_all_regex("[R >=\\(\\)]", "") %>% 
    data_frame(vs=.) %>% 
    separate(vs, c("a", "b", "c"), fill="right") %>% 
    mutate(c=ifelse(is.na(c), 0, c)) %>% 
    arrange(a, b, c) %>% 
    tail(1) %>% 
    unite(min, a:c, sep=".") -> vs 

    return(vs$min) 

} 

# did we handle the edge cases well enought? 
base <- c("base", "compiler", "datasets", "grDevices", "graphics", "grid", "methods", "parallel", "profile", "splines", "stats", "stats4", "tcltk", "tools", "translations") 
(base_reqs <- purrr::map_chr(base, min_r_version)) 
## [1] "Unspecified" "Unspecified" "Unspecified" "Unspecified" "Unspecified" 
## [6] "Unspecified" "Unspecified" "Unspecified" "Unspecified" "Unspecified" 
## [11] "Unspecified" "Unspecified" "Unspecified" "Unspecified" "Unspecified" 

# a few of the "core" contributed pkgs rely on a pkg or two outside of base 
# but many only rely on base packages, to this is another gd edge case to 
# text for. 
contrib <- c("KernSmooth", "MASS", "Matrix", "boot", "class", "cluster", "codetools", "foreign", "lattice", "mgcv", "nlme", "nnet", "rpart", "spatial", "survival") 
contrib_reqs <- purrr::map_chr(contrib, min_r_version) 
## [1] "Unspecified" "Unspecified" "3.0.0"  "Unspecified" "3.1.0"  
## [6] "Unspecified" "Unspecified" "Unspecified" "Unspecified" "3.0.2"  
## [11] "3.0.0"  "Unspecified" "Unspecified" "Unspecified" "3.0.1"  

# See what the min version of R shld be for some of my pkgs 
min_r_version("ggalt") # I claim R (>= 3.0.0) in DESCRIPTION 
## [1] "3.1.2" 

min_r_version("curlconverter") # I claim R (>= 3.0.0) in DESCRIPTION 
## [1] "3.1.2" 

min_r_version("iptools") # I claim R (>= 3.0.0) in DESCRIPTION 
## [1] "3.0.0" 
+0

와우. 좋아, 고마워. 이것이 우리가 변경하고자하는 변수이기 때문에 질의 된 패키지 자체의 R 요구 사항을 제외합니까? –

+0

지금 우리가 제외 할 경우 특정 엣지 케이스를 처리하기위한 'if-else'로직이 필요하기 때문에 포함되어 있지만이 프로세스의 핵심 로직입니다. – hrbrmstr

+1

업데이트 된 기능은 지정된 pkg를 제외하고 상기 엣지 케이스를 처리하도록 지원합니다. 내가 생각하지 못하는 다른 경우가있을 수 있습니다. – hrbrmstr

0

@hrbrmstr에서 아이디어를 기반으로하고 기본 기능을 작성, 지금은 다음과 같은 기능을 사용하고 있습니다 : 나는 당신이이 프로젝트에 상당한 관심을 모집합니다 의심

min_r_version <- function(pkg) { 
    requireNamespace("tools") 
    requireNamespace("utils") 
    avail <- utils::available.packages(utils::contrib.url(repo)) 
    deps <- tools::package_dependencies(pkg, db = avail, recursive = TRUE) 
    if (is.null(deps)) 
    stop("package not found") 

    pkgs <- deps[[1]] 
    repo = getOption("repo") 
    if (is.null(repo)) 
    repo <- "https://cloud.r-project.org" 

    matches <- avail[ , "Package"] %in% pkgs 
    pkg_list <- avail[matches, "Depends"] 
    vers <- grep("^R$|^R \\(.*\\)$", pkg_list, value = TRUE) 
    vers <- gsub("[^0-9.]", "", vers) 
    if (length(vers) == 0) 
    return("Not specified") 

    max_ver = vers[1] 
    if (length(vers) == 1) 
    return(max_ver) 

    for (v in 2:length(vers)) 
    if (utils::compareVersion(vers[v], max_ver) > 0) 
     max_ver <- vers[v] 

    max_ver 
} 
관련 문제