Skip to content

Commit

Permalink
Merge branch 'release/1.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Hill committed Sep 20, 2018
2 parents d4355c1 + 655909a commit 0a87d90
Show file tree
Hide file tree
Showing 25 changed files with 167 additions and 285 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Package: RInno
Type: Package
OS_type: windows
Title: An Installation Framework for Shiny Apps
Version: 1.0.0.9000
Version: 1.0.0
Authors@R: c(
person("Jon", "Hill", email = "[email protected]", role = c("aut", "cre", "cph")),
person("W. Lee", "Pang", role = c("aut", "cph"), comment = "DesktopDeployR project at https://github.com/wleepang/DesktopDeployR"),
Expand Down
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export(add_pkgs)
export(code_section)
export(compile_iss)
export(copy_installation)
export(cran_version)
export(create_app)
export(create_bat)
export(create_config)
Expand Down
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* Thanks Dean Attali ([@daattali](https://github.com/daattali/)) for this feature request
* Fixed `error_log` so that its name can be customized properly
* Cleaned up installation paths
* Added Firefox to the browser search path in `app.R`:
* Added Firefox to the browser search path in `launch_app.R`:
1. Chrome
2. Firefox
3. Internet Explorer
Expand Down
2 changes: 1 addition & 1 deletion R/copy_installation.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' This function moves files stored in \code{system.file('installation', package = 'RInno')} to \code{app_dir}:
#' \itemize{
#' \item Icons for installer and app, \emph{setup.ico}, \emph{default.ico} and \emph{default.png}.
#' \item Files that manage app start up, \emph{utils/package_manager.R} and \emph{utils/app.R}.
#' \item Files that manage app start up, \emph{utils/package_manager.R} and \emph{utils/launch_app.R}.
#' \item First/last page of the installation wizard, \emph{infobefore.txt} and \emph{infoafter.txt}.
#' \item Batch support files, \emph{utils/wsf/run.wsf}, \emph{utils/wsf/js/run.js}, \emph{utils/wsf/js/json2.js}, and \emph{utils/wsf/js/JSON.minify.js}.
#' }
Expand Down
25 changes: 21 additions & 4 deletions R/create_app.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#' Creates the following files in \code{app_dir}:
#' \itemize{
#' \item Icons for installer and app, \emph{setup.ico} and \emph{default.ico} respectively.
#' \item Files that manage app start up, \emph{utils/package_manager.R}, \emph{utils/ensure.R}, and \emph{utils/app.R}.
#' \item Files that manage app start up, \emph{utils/package_manager.R}, \emph{utils/ensure.R}, and \emph{utils/launch_app.R}.
#' \item First/last page of the installer, \emph{infobefore.txt} and \emph{infoafter.txt}.
#' \item Batch support files, \emph{utils/wsf/run.wsf}, \emph{utils/wsf/js/run.js}, \emph{utils/wsf/js/json2.js}, \emph{utils/wsf/js/JSON.minify.js}.
#' \item A configuration file, \emph{config.cfg}. See \code{\link{create_config}} for details.
Expand All @@ -19,6 +19,7 @@
#' @param pkgs Character vector of package dependencies. Remote development versions are supported via \code{remotes}. \code{pkgs} are downloaded into \code{file.path(app_dir, pkgs_path)} as Windows binary packages (.zip). If you build binary packages and store them there before calling \code{create_app}, they will be included as well.
#' @param pkgs_path Default location inside the app working directory to install package dependencies This defaults to \code{pkgs_path = "bin"}
#' @param remotes Character vector of GitHub repository addresses in the format \code{username/repo[/subdir][\@ref|#pull]} for GitHub package dependencies.
#' @param locals Character vector of local package dependencies. Deprecated as of v1.0.0. Use \code{pkgs} instead.
#' @param include_R To include R in the installer, \code{include_R = TRUE}. The version of R specified by \code{R_version} is used. The installer will check each user's registry and only install R if necessary.
#' @param R_version R version to use. Supports inequalities. Defaults to: \code{paste0(">=", R.version$major, '.', R.version$minor)}.
#' @param include_Pandoc To include Pandoc in the installer, \code{include_Pandoc = TRUE}. If installing a flexdashboard app, some users may need a copy of Pandoc. The installer will check the user's registry for the version of Pandoc specified in \code{Pandoc_version} and only install it if necessary.
Expand Down Expand Up @@ -58,6 +59,7 @@ create_app <- function(
pkgs_path = "bin",
repo = "https://cran.rstudio.com",
remotes = "none",
locals = NULL,
app_repo_url = "none",
auth_user = "none",
auth_pw = "none",
Expand All @@ -78,11 +80,26 @@ create_app <- function(
# To capture arguments for other function calls
dots <- list(...)

# 1.0.0 deprecation messages
if (!is.null(locals)) {
warning("locals is deprecated. Please use pkgs instead.", call. = FALSE)
pkgs <- pkgs %>% standardize_pkgs %>% add_pkgs(locals)
}
if (user_browser != "electron") {
warning(glue::glue("user_browser = {glue::double_quote(user_browser)} will be deprecated in the next release. Please use user_browser = \"electron\" in the future."), call. = FALSE)
}
if (include_Chrome) {
warning("include_Chrome will be deprecated in the next release. Please use user_browser = \"electron\"", call. = FALSE)
}
if (!is.null(dots$ping_site)) {
warning("ping_site is deprecated in favor of self-contained dependency management in the .exe.", call. = FALSE)
}

# If app_name is not a character, exit
if (class(app_name) != "character") stop("app_name must be a character.", call. = F)
if (class(app_name) != "character") stop("app_name must be a character.", call. = FALSE)

# If dir_out is not a character, exit
if (class(dir_out) != "character") stop("dir_out must be a character.", call. = F)
if (class(dir_out) != "character") stop("dir_out must be a character.", call. = FALSE)

# If not TRUE/FALSE, exit
logicals <- c(
Expand Down Expand Up @@ -132,7 +149,7 @@ create_app <- function(
repo = repo, error_log = dots$error_log,
app_repo_url = app_repo_url, auth_user = auth_user,
auth_pw = auth_pw, auth_token = auth_token,
user_browser = user_browser, ping_site = dots$ping_site)
user_browser = user_browser)

# Build the iss script
start_iss(app_name) %>%
Expand Down
13 changes: 6 additions & 7 deletions R/create_config.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#' @param auth_pw Bitbucket password matching the above username.
#' @param auth_token To install from a private Github repo, generate a personal access token (PAT) in \url{https://github.com/settings/tokens} and supply to this argument. This is safer than using a password because you can easily delete a PAT without affecting any others.
#' @param user_browser Character for the default browser. Options include "chrome", "firefox", and "ie."
#' @param ping_site URL of a site to ping to check internet connectivity. Defaults to "www.ficonsulting.com".
#'
#' @author Jonathan M. Hill
#'
Expand All @@ -22,7 +21,7 @@ create_config <- function(app_name, app_dir = getwd(),
remotes = "none",
repo = "https://cran.rstudio.com",
error_log = "error.log", app_repo_url = "none", auth_user = "none",
auth_pw = "none", auth_token = "none", user_browser = "electron", ping_site = "www.ficonsulting.com") {
auth_pw = "none", auth_token = "none", user_browser = "electron") {

# Reset defaults if empty
for (formal in names(formals(create_config))) {
Expand All @@ -37,7 +36,8 @@ create_config <- function(app_name, app_dir = getwd(),
if (!dir.exists(file.path(app_dir, "utils"))) dir.create(file.path(app_dir, "utils"))

# Make sure initial packages & shiny are included
pkgs <- add_pkgs(pkgs, c("jsonlite", "shiny"))
pkgs <- pkgs %>% standardize_pkgs()
pkgs <- pkgs %>% add_pkgs(c("jsonlite", "shiny"))

if (app_repo_url != "none") {
# Fail early
Expand Down Expand Up @@ -67,7 +67,7 @@ create_config <- function(app_name, app_dir = getwd(),

if (length(flex_file) > 0) {
# Make sure flexdashboard and rmarkdown are included in the dependency list
pkgs <- add_pkgs(pkgs, c("flexdashboard", "rmarkdown"))
pkgs <- pkgs %>% add_pkgs(c("flexdashboard", "rmarkdown"))
cat("This flexdashboard will be used:\n - ", flex_file, "\n")
} else {
flex_file <- "none"
Expand All @@ -83,7 +83,7 @@ create_config <- function(app_name, app_dir = getwd(),
list(
appname = app_name,
pkgs = list(
pkgs_names = standardize_pkgs(pkgs, string = TRUE),
pkgs_names = standardize_pkgs(pkgs),
pkgs_loc = file.path(pkgs_path, list.files(file.path(app_dir, pkgs_path)))
),
logging = error_log,
Expand All @@ -94,7 +94,6 @@ create_config <- function(app_name, app_dir = getwd(),
auth_token = auth_token,
user_browser = tolower(user_browser),
nativefier = file.path("nativefier-app", list.files(file.path(app_dir, "nativefier-app"), pattern = ".exe", recursive = TRUE)),
flex_file = flex_file,
ping_site = ping_site),
flex_file = flex_file),
file.path(app_dir, "utils/config.cfg"), pretty = T, auto_unbox = T)
}
2 changes: 1 addition & 1 deletion R/download_packages.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ download_packages <- function(app_dir, pkgs_path, pkgs, repo, remotes, auth_user
if (any(lapply(pkgs, class) != "character")) stop("`pkgs` must be a character vector.", call. = FALSE)

# Standardize pkgs
standard_deps <- standardize_pkgs(pkgs, check_version = TRUE, string = TRUE)
standard_deps <- standardize_pkgs(pkgs)

# Find all the pkg dependencies
pkg_deps <- tools::package_dependencies(packages = standard_deps, recursive = TRUE) %>%
Expand Down
134 changes: 19 additions & 115 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' @importFrom magrittr %>%
#' @param lhs A value or the magrittr placeholder.
#' @param rhs A function call using the magrittr semantics.
#' @seealso \code{\link[magrittr]{\%>\%}}
#' @seealso \code{\link[magrittr]{magrittr}}
#' @export
`%>%` <- magrittr::`%>%`

Expand All @@ -12,95 +12,37 @@
#' Standardizes (named or not) character vectors of package dependencies and formats it for config.cfg.
#'
#' @param pkgs Processes \code{pkgs}, and \code{pkgs}, arguments of \code{\link{create_config}} and \code{\link{create_app}}.
#' @param check_version Boolean. If true, check to make sure the package version is not ahead of CRAN.
#'
#' @return Package dependency list with version numbers and inequalities. Defaults to \code{paste0(">=", packageVersion(pkg))}.
#' @return Package dependency list
#'
#' @author William Bradley and Jonathan Hill
#' @keywords internal
#' @export
standardize_pkgs <- function(pkgs, check_version = FALSE, string = FALSE) {
standardize_pkgs <- function(pkgs) {

if (pkgs[1] == "none") return("none")

# remove spaces, create a list and vectors to control the process
pkgs <- gsub(" ", "", pkgs)
pkg_list <- as.list(pkgs)
no_version <- names(pkg_list) == ""
no_inequality <- !grepl("[<>=]", pkgs)
# deprecation message
if (!is.null(names(pkgs))) {
warning("Package versions are no longer supported. Please develop your app using the most recent CRAN version.", call. = FALSE)

# No versions are specified
if (length(no_version) == 0) {
version <- names(pkgs) != ""

tryCatch(
pkg_list <- lapply(pkg_list, utils::packageVersion),

error = function(e) {
stop(e$message,
"\n\nPlease provide versions of `pkgs` if they are not installed in the development environment.", call. = FALSE)
})

names(pkg_list) <- pkgs

# add greater than or equal to
pkg_list <- lapply(pkg_list, function(x) paste0(">=", x))

# Some versions are specified
} else if (sum(no_version) > 0) {

tryCatch(
pkg_list[no_version] <- lapply(pkg_list[no_version], utils::packageVersion),

error = function(e) {
stop(e$message, "\n\nPlease provide versions of `pkgs` if they are not installed in the development environment.", call. = FALSE)
})

names(pkg_list)[no_version] <- pkgs[no_version]

# add greater than or equal to
pkg_list[no_inequality] <- lapply(pkg_list[no_inequality], function(x) paste0(">=", x))

# All versions are specified
} else {
# add greater than or equal to
pkg_list[no_inequality] <- lapply(pkg_list[no_inequality], function(x) paste0(">=", x))
}

# convert to character for JSON
pkgs <- lapply(pkg_list, as.character)

# Make sure the results are valid
installed_pkgs <- data.frame(utils::installed.packages(), row.names = NULL)

check_pkgs <- function(pkg, pkg_name) {
breakpoint <- attr(regexpr("[<>=]+", pkg), "match.length")
inequality <- substr(pkg, 1, breakpoint)
required_version <- substr(pkg, breakpoint + 1, nchar(pkg))

if (nchar(inequality) > 2 | grepl("=[<>]", inequality)) {
stop(glue::glue("{pkg_name}'s inequality ({inequality}) is not a valid logical operator"), call. = F)
}
if (class(try(numeric_version(required_version), silent = TRUE)) == "try-error") {
stop(glue::glue("{required_version} is not a valid `numeric_version` for {pkg_name} "), call. = F)
}
if (!pkg_name %in% installed_pkgs$Package) {
stop(glue::glue("{pkg_name} is not installed. Make sure it is in `installed.pacakges()` and try again."), call. = F)
}
if (check_version) {
pkg_cran_version <- cran_version(pkg_name)
if (is.null(cran_version)) stop("Can't connect to CRAN")
if (numeric_version(required_version) > pkg_cran_version) {
stop(glue::glue("{pkg_name} v{required_version} is ahead of CRAN - v{cran_version(pkg_name)}. Please add it to `remotes` to use {pkg_name}'s development version from Github/Bitbucket or decrease its version to one published on CRAN."), call. = FALSE)
}
if (length(version) != 0) {
pkgs[version] <- names(pkgs[version])
}
}
mapply(check_pkgs, pkgs, names(pkgs))

if (string) {
return(names(pkgs))
} else {
return(pkgs)
# Make sure pkgs are installed
installed_pkgs <- data.frame(utils::installed.packages(), row.names = NULL, stringsAsFactors = FALSE)
missing_pkgs <- !pkgs %in% installed_pkgs$Package
if (any(missing_pkgs)) {
stop(glue::glue("{pkgs[missing_pkgs]} is not installed. Please install it and try again."), call. = FALSE)
}

names(pkgs) <- NULL

return(pkgs)
}


Expand Down Expand Up @@ -155,41 +97,6 @@ sanitize_R_version <- function(R_version, clean = FALSE, R_version_min = "3.0.2"
}


#' Check CRAN for package version
#'
#' @param pkg_name String. Package name as published on CRAN.
#' @param cran_url String. First part of the cannonical form of a package website on CRAN.
#'
#' @return The package's version as a \code{numeric_version}.
#'
#' @examples
#' cran_version("shiny")
#' @keywords internal
#' @export
cran_version = function(pkg_name, cran_url = "http://cran.r-project.org/package=") {

# Create URL
cran_pkg_loc = paste0(cran_url, pkg_name)

# Establish connection
suppressWarnings(conn <- try(url(cran_pkg_loc), silent = TRUE))

# If connection, read in webpage
if (all(class(conn) != "try-error") ) {
suppressWarnings(cran_pkg_page <- try(readLines(conn), silent = TRUE))
close(conn)
} else {
return(NULL)
}

# Use regex to find version info
version_line = cran_pkg_page[grep("Version:", cran_pkg_page) + 1]
version_line = gsub("<(td|\\/td)>","",version_line)
numeric_version(version_line)

}


#' Add package to named vector
#'
#' Adds (named or not) package dependencies to a named vector of packages.
Expand All @@ -208,10 +115,7 @@ cran_version = function(pkg_name, cran_url = "http://cran.r-project.org/package=
#' @export
add_pkgs <- function(pkgs, pkg) {

pkg_strings <- pkg %in% pkgs
pkg_names <- pkg %in% names(pkgs)

needed_pkgs <- pkg[!(pkg_names | pkg_strings)]
needed_pkgs <- pkg[!pkg %in% pkgs]

if (length(needed_pkgs) > 0) {
pkgs <- c(pkgs, needed_pkgs)
Expand Down
2 changes: 1 addition & 1 deletion README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ create_app(
`create_app` passes its arguments to most of the other support functions in RInno. You can (and probably should) specify most things there and they will get passed on. Alternatively, you can provide instructions directly to those support functions like this:

```
# Copy installation scripts (JavaScript, icons, infobefore.txt, package_manager.R, app.R)
# Copy installation scripts (JavaScript, icons, infobefore.txt, package_manager.R, launch_app.R)
copy_installation(app_dir = "my/app/path")
# If your users need R installed:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ If you would like to create a custom installer from within R, you can slowly bui

`create_app` passes its arguments to most of the other support functions in RInno. You can (and probably should) specify most things there and they will get passed on. Alternatively, you can provide instructions directly to those support functions like this:

# Copy installation scripts (JavaScript, icons, infobefore.txt, package_manager.R, app.R)
# Copy installation scripts (JavaScript, icons, infobefore.txt, package_manager.R, launch_app.R)
copy_installation(app_dir = "my/app/path")

# If your users need R installed:
Expand Down
4 changes: 2 additions & 2 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## This update
* numerous bug fixes and feature requests
* major release with updates to package dependency management strategy and user interface

## Test environments
* local OS Windows 7 x64, R 3.5.0
* local OS Windows 7 x64, R 3.5.1

## R CMD check results
There were 0 errors, 0 Warnings and 0 NOTES on Windows OS. There are warnings/notes on Mac/Linux
Expand Down
2 changes: 1 addition & 1 deletion inst/doc/Introduction.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ create_app(
`create_app` passes its arguments to most of the other support functions in RInno. You can (and probably should) specify most things there and they will get passed on. Alternatively, you can provide instructions directly to those support functions like this:

```
# Copy installation scripts (JavaScript, icons, infobefore.txt, package_manager.R, app.R)
# Copy installation scripts (JavaScript, icons, infobefore.txt, package_manager.R, launch_app.R)
copy_installation(app_dir = "my/app/path")
# If your users need R installed:
Expand Down
Loading

0 comments on commit 0a87d90

Please sign in to comment.