Skip to content

Commit

Permalink
Merge pull request #8 from robertzk/packages_from_github
Browse files Browse the repository at this point in the history
Ramd::packages can install from GitHub
  • Loading branch information
robertzk committed Jan 20, 2016
2 parents 87b541d + 25b90ab commit 1ef26c0
Show file tree
Hide file tree
Showing 15 changed files with 416 additions and 33 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ before_install:
- ./travis-tool.sh bootstrap
install:
- ./travis-tool.sh install_deps
- ./travis-tool.sh install_r testthat testthatsomemore
- "./travis-tool.sh github_package jimhester/covr"
- Rscript -e 'if (!require("covr")) devtools::install_github("kirillseva/covr")'
- Rscript -e 'if (!require("testthat")) devtools::install_github("hadley/testthat")'
- Rscript -e 'if (!require("testthatsomemore")) devtools::install_github("robertzk/testthatsomemore")'
script: ./travis-tool.sh run_tests
after_failure:
- ./travis-tool.sh dump_logs
Expand Down
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ Description: A "define" function is provided that allows
for inclusion of external scripts without polluting
the global namespace and makes it easier to
write modular R code.
Version: 0.2.2
Version: 0.3
Author: Robert Krzyzanowski <technoguyrob@gmail.com>
Maintainer: Robert Krzyzanowski <technoguyrob@gmail.com>
Depends:
R (>= 3.0.0)
Suggests:
testthat,
devtools,
testthatsomemore
License: GPL (>= 2)
License: MIT + file LICENSE
LazyData: true
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by roxygen2 (4.1.0.9000): do not edit by hand
# Generated by roxygen2 (4.1.1): do not edit by hand

export(define)
export(packages)
Expand Down
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Version 0.3

* `packages` will now install from GitHub when the package name contains a '/'.
* `packages` will now take `verbose = TRUE` to announce the installations.
* Add test coverage for `packages` and `load_package`.
* Deprecate space separation for `packages` (instead, must pass multiple arguments).

# Version 0.2.1

* The `define` function takes an `envir` argument that can be used
Expand Down
99 changes: 92 additions & 7 deletions R/load_package.r
Original file line number Diff line number Diff line change
@@ -1,15 +1,100 @@
#' Load a package and install it if necessary
#'
#' @name load_package
#' @param name Name of package
#' @param name character. Name of package.
#' @param verbose logical. Whether or not to announce each installation.
#' @examples
#' \dontrun{
#' load_package('glmnet')
#' load_package("glmnet")
#' load_package("robertzk/Ramd")
#' load_package("robertzk/Ramd@@v0.3") # Can load from versions
#' load_package("robertzk/Ramd@@0.3")
#' load_package("robertzk/Ramd@@fbe1aa0e36df289b27881d077635352e6debdbc1") # Can load from refs
#' load_package(list("FeiYeYe/xgboost", subdir = "R-package")) # Can load from subdirectories
#' }
load_package <- function(name) {
if (!require(name, character.only = TRUE)) {
install.packages(name, dependencies = TRUE)
if (!require(name, character.only = TRUE))
stop(paste('Package', name, 'not found'))
load_package <- function(name, verbose = FALSE) {
metadata <- name[-1] # For tracking things like subdir
name <- name[[1]]

if (package_is_installed(name)) {
if (isTRUE(verbose)) { message(name, " already installed.") }
return(TRUE)
}

handle_version_mismatches(name, verbose)

if (is_github_package(name)) {
remote <- "GitHub"
install_from_github(name, metadata, remote, verbose)
} else {
remote <- "CRAN"
install_from_cran(name, remote, verbose)
}

if (!package_is_installed(name)) {
stop(paste("Package", name, "not found on", remote, "."))
}
TRUE
}

handle_version_mismatches <- function(name, verbose) {
if (is_version_mismatch(name)) {
if (isTRUE(verbose)) {
message("Removing prior installation of ", name_from_github_name(name))
}
utils::remove.packages(name)
}
}

install_from_github <- function(name, metadata, remote, verbose) {
ensure_devtools_installed()
if (isTRUE(verbose)) { announce(name, remote) }
if (length(metadata) > 0) {
do.call(devtools::install_github, c(list(name), metadata))
} else {
devtools::install_github(name)
}
}

install_from_cran <- function(name, remote, verbose) {
if (isTRUE(verbose)) { announce(name, remote) }
utils::install.packages(name) # install from CRAN
}

announce <- function(name, remote) {
message("Installing ", name, " from ", remote, ".")
}


name_from_github_name <- function(name) {
strsplit(strsplit(name, "/")[[1]][[2]], "@")[[1]][[1]]
}


is_github_package <- function(name) {
# Checks for github repos, e.g., robertzk/Ramd
grepl("/", name, fixed = TRUE)
}


is_version_mismatch <- function(name) {
is_versionable <- function(name) {
grepl("@", name, fixed = TRUE) &&
grepl("^[v0-9.]*$", get_version_from_ref(name))
}
get_version_from_ref <- function(name) {
# extract 0.3 from robertzk/Ramd@v0.3
name <- strsplit(name, "@")[[1]][[2]]
if (grepl("v", name, fixed = TRUE)) {
name <- strsplit(name, "v")[[1]][[2]]
}
name
}

is_version_mismatch <- function(name) {
utils::packageVersion(name) != package_version(get_version_from_ref(name))
}

# Checks for specified refs or package names, e.g. robertzk/Ramd@v0.3
is_github_package(name) && is_versionable(name) && is_version_mismatch(name)
}
24 changes: 16 additions & 8 deletions R/packages.r
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
#' Load a bunch of packages
#'
#' @param ... List of packages
#' @export
#' @param verbose logical. Whether or not to announce installations and
#' package startup messages.
#' @examples
#' \dontrun{
#' packages('glmnet', 'caret')
#' packages('glmnet caret')
#' packages(list('glmnet', 'caret'), c('e1071', 'parallel multicore'), 'stringr')
#' packages("glmnet") # Can install from CRAN
#' packages("robertzk/Ramd") # Can install from GitHub
#' packages("glmnet", "caret") # can load multiple packages in one call
#' packages("robertzk/Ramd", "hadley/dplyr", "peterhurford/batchman") # Can load multiple
#' packages("robertzk/Ramd", "glmnet") # Can install from both CRAN and GitHub
#' packages("robertzk/Ramd@@v0.3") # Can load from versions
#' packages("robertzk/Ramd@@0.3")
#' packages("robertzk/Ramd@@fbe1aa0e36df289b27881d077635352e6debdbc1") # Can load from refs
#' packages(list("FeiYeYe/xgboost", subdir = "R-package")) # Can load from subdirectories
#' }
packages <- function(...) {
split_packages <- function(string) strsplit(string, '[^a-zA-Z.$0-9_]+')[[1]]
pkgs <- unlist(lapply(unlist(list(...)), split_packages))
suppressPackageStartupMessages(sapply(pkgs, load_package))
#' @export
packages <- function(..., verbose = FALSE) {
pkgs <- unique(list(...))
if (isTRUE(verbose)) { vapply(pkgs, load_package, verbose = TRUE, logical(1)) }
else { suppressPackageStartupMessages(vapply(pkgs, load_package, logical(1))) }
TRUE
}
11 changes: 11 additions & 0 deletions R/utils.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ensure_devtools_installed <- function() {
package_is_installed("devtools")
stop("Devtools must be installed first. Run `install.packages('devtools')`.")
}

package_is_installed <- function(name) {
if (is_github_package(name)) {
name <- name_from_github_name(name)
}
name %in% utils::installed.packages()[,1]
}
2 changes: 1 addition & 1 deletion man/Ramd.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.1.0.9000): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/Ramd-package.r
\docType{package}
\name{Ramd}
Expand Down
2 changes: 1 addition & 1 deletion man/define.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.1.0.9000): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/define.r
\name{define}
\alias{define}
Expand Down
2 changes: 1 addition & 1 deletion man/load_dependency.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.1.0.9000): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/load_dependency.r
\name{load_dependency}
\alias{load_dependency}
Expand Down
15 changes: 11 additions & 4 deletions man/load_package.Rd
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
% Generated by roxygen2 (4.1.0.9000): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/load_package.r
\name{load_package}
\alias{load_package}
\title{Load a package and install it if necessary}
\usage{
load_package(name)
load_package(name, verbose = FALSE)
}
\arguments{
\item{name}{Name of package}
\item{name}{character. Name of package.}

\item{verbose}{logical. Whether or not to announce each installation.}
}
\description{
Load a package and install it if necessary
}
\examples{
\dontrun{
load_package('glmnet')
load_package("glmnet")
load_package("robertzk/Ramd")
load_package("robertzk/Ramd@v0.3") # Can load from versions
load_package("robertzk/Ramd@0.3")
load_package("robertzk/Ramd@fbe1aa0e36df289b27881d077635352e6debdbc1") # Can load from refs
load_package(list("FeiYeYe/xgboost", subdir = "R-package")) # Can load from subdirectories
}
}

19 changes: 14 additions & 5 deletions man/packages.Rd
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
% Generated by roxygen2 (4.1.0.9000): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/packages.r
\name{packages}
\alias{packages}
\title{Load a bunch of packages}
\usage{
packages(...)
packages(..., verbose = FALSE)
}
\arguments{
\item{...}{List of packages}

\item{verbose}{logical. Whether or not to announce installations and
package startup messages.}
}
\description{
Load a bunch of packages
}
\examples{
\dontrun{
packages('glmnet', 'caret)
packages('glmnet caret')
packages(list('glmnet', 'caret'), c('e1071', 'parallel multicore'), 'stringr')
packages("glmnet") # Can install from CRAN
packages("robertzk/Ramd") # Can install from GitHub
packages("glmnet", "caret") # can load multiple packages in one call
packages("robertzk/Ramd", "hadley/dplyr", "peterhurford/batchman") # Can load multiple
packages("robertzk/Ramd", "glmnet") # Can install from both CRAN and GitHub
packages("robertzk/Ramd@v0.3") # Can load from versions
packages("robertzk/Ramd@0.3")
packages("robertzk/Ramd@fbe1aa0e36df289b27881d077635352e6debdbc1") # Can load from refs
packages(list("FeiYeYe/xgboost", subdir = "R-package")) # Can load from subdirectories
}
}

2 changes: 1 addition & 1 deletion man/pp.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.1.0.9000): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/pp.r
\name{pp}
\alias{pp}
Expand Down
Loading

0 comments on commit 1ef26c0

Please sign in to comment.