From 15ded69426a858b764fb216e176c6404e323e38e Mon Sep 17 00:00:00 2001 From: Craig Williams Date: Thu, 16 Jun 2022 11:27:01 +0100 Subject: [PATCH] Function to grab the available packages listed on CRAN --- NAMESPACE | 1 + R/fetch_available_packages.R | 41 +++++++++++++++++++++++++++++++++ R/utils.R | 24 +++++++++++++++++++ man/check_pacman_dir.Rd | 14 +++++++++++ man/fetch_available_packages.Rd | 19 +++++++++++++++ man/get_cran_repo.Rd | 14 +++++++++++ man/list_depends.Rd | 6 +++-- 7 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 R/fetch_available_packages.R create mode 100644 R/utils.R create mode 100644 man/check_pacman_dir.Rd create mode 100644 man/fetch_available_packages.Rd create mode 100644 man/get_cran_repo.Rd diff --git a/NAMESPACE b/NAMESPACE index 6c3c1ff..8102891 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,3 +1,4 @@ # Generated by roxygen2: do not edit by hand +export(fetch_available_packages) export(list_depends) diff --git a/R/fetch_available_packages.R b/R/fetch_available_packages.R new file mode 100644 index 0000000..71d0624 --- /dev/null +++ b/R/fetch_available_packages.R @@ -0,0 +1,41 @@ +# Requires utils.R + +.fetch_available_packages <- function(refetch) { + check_pacman_dir() + fn <- ".pacman/packages.rds" + if (file.exists(fn)) { + ts <- as.POSIXct("1970-01-01 00:00:00", tz = "GMT") + as.numeric(Sys.Date() + 1) * 86400 + if (refetch || (ts < file.mtime(fn))) { + unlink(fn) + } + } + if (!file.exists(fn)) { + download.file(sprintf("%s/src/contrib/PACKAGES.rds", get_cran_repo()), fn) + } + con <- gzfile(fn, "rb") + on.exit(close(con), add = TRUE) + packages <- readRDS(con) + packages <- as.data.frame(packages) + packages <- packages[is.na(packages$Path),] + packages <- packages[,c("Package", "Version")] + colnames(packages) <- c("package", "version") + rownames(packages) <- 1:nrow(packages) + return(packages[,c("package", "version")]) +} + +#' Fetch the current (or check the cache) list of packages available for install +#' from the CRAN repositories. +#' +#' @param refetch Boolean indicating if the local cache should be invalidated. +#' +#' @return A data frame of available packages and their versions +#' @export +fetch_available_packages <- function(refetch = FALSE) { + tryCatch( + { + .fetch_available_packages(refetch) + }, + warning = function(e) list(), + error = function(e) list() + ) +} diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 0000000..85b4cfa --- /dev/null +++ b/R/utils.R @@ -0,0 +1,24 @@ + +#' Checks the current project has a valid pacman directory structure +#' +#' @return invisible boolean TRUE if the structure is valid, FALSE otherwise +check_pacman_dir <- function() { + if (!dir.exists("./.pacman")) { + if (!dir.create("./.pacman")) { + return(invisible(FALSE)) + } + } + invisible(TRUE) +} + +#' Returns the CRAN repository source or requests the user select one +#' +#' @return string CRAN repository URL +get_cran_repo <- function() { + repo <- getOption("repos")[[1]] + if (repo == "@CRAN@") { + chooseCRANmirror() + repo <- getOption("repos")[[1]] + } + repo +} \ No newline at end of file diff --git a/man/check_pacman_dir.Rd b/man/check_pacman_dir.Rd new file mode 100644 index 0000000..87d5046 --- /dev/null +++ b/man/check_pacman_dir.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{check_pacman_dir} +\alias{check_pacman_dir} +\title{Checks the current project has a valid pacman directory structure} +\usage{ +check_pacman_dir() +} +\value{ +invisible boolean TRUE if the structure is valid, FALSE otherwise +} +\description{ +Checks the current project has a valid pacman directory structure +} diff --git a/man/fetch_available_packages.Rd b/man/fetch_available_packages.Rd new file mode 100644 index 0000000..880e1de --- /dev/null +++ b/man/fetch_available_packages.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fetch_available_packages.R +\name{fetch_available_packages} +\alias{fetch_available_packages} +\title{Fetch the current (or check the cache) list of packages available for install +from the CRAN repositories.} +\usage{ +fetch_available_packages(refetch = FALSE) +} +\arguments{ +\item{refetch}{Boolean indicating if the local cache should be invalidated.} +} +\value{ +A data frame of available packages and their versions +} +\description{ +Fetch the current (or check the cache) list of packages available for install +from the CRAN repositories. +} diff --git a/man/get_cran_repo.Rd b/man/get_cran_repo.Rd new file mode 100644 index 0000000..d4b5139 --- /dev/null +++ b/man/get_cran_repo.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{get_cran_repo} +\alias{get_cran_repo} +\title{Returns the CRAN repository source or requests the user select one} +\usage{ +get_cran_repo() +} +\value{ +string CRAN repository URL +} +\description{ +Returns the CRAN repository source or requests the user select one +} diff --git a/man/list_depends.Rd b/man/list_depends.Rd index 103142c..58b2e33 100644 --- a/man/list_depends.Rd +++ b/man/list_depends.Rd @@ -2,7 +2,8 @@ % Please edit documentation in R/list_depends.R \name{list_depends} \alias{list_depends} -\title{Recursively find all the installed dependencies of one or more packages.} +\title{Recursively find all the installed dependencies of one or more installed +packages.} \usage{ list_depends(depends) } @@ -13,5 +14,6 @@ list_depends(depends) A data frame with the dependency tree } \description{ -Recursively find all the installed dependencies of one or more packages. +Recursively find all the installed dependencies of one or more installed +packages. }