Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

elegantly extract R package dependencies of a package not listed on CRAN

Tags:

r

Given the DESCRIPTION file of an R package, I would like to obtain a list of the package dependencies (e.g. Depends, Imports, Suggests). It seems like this should be a solved problem (e.g. by devtools::install_github) but I cannot seem to come up with an elegant way to do this. My current solution is to rely on an unexported function from tools:

## adapted.from biocLite("pkgDepTools")
cleanPkgField <- function(val) {
    if (is.na(val))
      return(character(0))
    val <- names(tools:::.split_dependencies(val))
    if (is.null(val))
      return(character(0))
    val <- val[! val %in% "R"]
    if (length(val))
      return(val)
    return(character(0))
}

get_deps <- function(dp){
  dcf <- read.dcf(paste0(dp, "/DESCRIPTION"))
  suggests <- imports <- depends <- NULL
  if("Suggests" %in% colnames(dcf))
  suggests <- cleanPkgField(dcf[,"Suggests"])
  if("Imports" %in% colnames(dcf))
  imports <- cleanPkgField(dcf[,"Imports"])
  if("Depends" %in% colnames(dcf))
  depends <- cleanPkgField(dcf[,"Depends"])

  c(suggests, imports, depends)

  ## Doesn't work for packages not on CRAN
#  unlist(tools::package_dependencies(package_names, available.packages(),
#         which=c("Depends", "Imports", "Suggests"), recursive=FALSE))
}

where dp is the package directory. This seems to work, but it feels like there should be an extant function to do this, or at least something cleaner than relying on the hidden and non-exported .split_dependencies() function in the tools package.

Note that the more widely cited way to get dependencies for a package is not to rely on the DESCRIPTION file at all, but rather to use something like tools::package_dependencies which assumes the package can be found on some CRAN-like repository, e.g. these SO questions:

  • Only download sources of a package and all dependencies,
  • Update a specific R package and its dependencies

note that while the problem description is the same, the fact that the package is not on CRAN (or similar repository) makes that approach impossible.

like image 481
cboettig Avatar asked May 13 '15 19:05

cboettig


1 Answers

This is at least a bit simpler and doesn't rely on any unexported functions:

get_deps <- function(path) {
    dcf <- read.dcf(file.path(path, "DESCRIPTION"))
    jj <- intersect(c("Depends", "Imports", "Suggests"), colnames(dcf))
    val <- unlist(strsplit(dcf[, jj], ","), use.names=FALSE)
    val <- gsub("\\s.*", "", trimws(val))
    val[val != "R"]
}

## Test it out on a source package with no imports ...
get_deps("C:/R/Source/Library/raster")
##  [1] "methods"   "sp"        "rgdal"     "rgeos"     "ncdf"      "ncdf4"    
##  [7] "igraph"    "snow"      "tcltk"     "rasterVis"

## ... and an installed package with no dependencies at all
get_deps("C:/R/Library/RColorBrewer/")
# named character(0)
like image 181
Josh O'Brien Avatar answered Oct 20 '22 12:10

Josh O'Brien