Skip to content

Commit

Permalink
closes #24
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Hill committed Dec 24, 2017
1 parent 2ff2a73 commit 904a3d9
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 64 deletions.
10 changes: 5 additions & 5 deletions R/compile_iss.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ compile_iss <- function() {
app_dir <- getOption("RInno.app_dir")

# Find the command line compiler for Inno Setup
progs <- c(list.dirs("C:/Program Files", T, F),
list.dirs("C:/Program Files (x86)", T, F))
progs <- c(list.dirs("C:/Program Files", TRUE, FALSE),
list.dirs("C:/Program Files (x86)", TRUE, FALSE))

inno <- progs[grep("Inno Setup", progs)]

if (!dir.exists(inno)) stop("Make sure Inno Setup is installed to 'C:/Program Files'. Call install_inno(), and try again!")
if (!dir.exists(inno)) stop("Make sure Inno Setup is installed to 'C:/Program Files'. Call install_inno(), and try again!", call. = FALSE)

compil32 <- file.path(inno, "Compil32.exe")

if (!file.exists(compil32)) stop(sprintf("Failed to find %s. Install Inno Setup via install_inno(), and try again!", compil32))
if (!file.exists(compil32)) stop(glue::glue("Failed to find {compil32}. Install Inno Setup via install_inno(), and try again!"), call. = FALSE)

iss_file <- file.path(app_dir, paste0(app_name, ".iss"))

system(sprintf('"%s" /cc "%s"', compil32, iss_file))
system(glue::glue('"{compil32}" /cc "{iss_file}"'))
}
34 changes: 16 additions & 18 deletions R/create_app.R
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ create_app <- function(app_name,
dots <- list(...)

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

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

# If not TRUE/FALSE, exit
include_logicals <- c(
Expand All @@ -79,16 +79,14 @@ create_app <- function(app_name,
failed_logical <- !include_logicals %in% "logical"

if (any(failed_logical)) {
stop(glue::glue("{names(include_logicals[which(failed_logical)])} must be TRUE/FALSE."))
stop(glue::glue("{names(include_logicals[which(failed_logical)])} must be TRUE/FALSE."), call. = F)
}

# If app_dir does not exist create it
if (!dir.exists(app_dir)) dir.create(app_dir)

# If R_version is not valid, exit
if (any(length(strsplit(R_version, "\\.")[[1]]) != 3, !grepl("[1-3]\\.[0-9]+\\.[0-9]+", R_version))) {
stop("R_version is not valid.")
}
R_version <- sanitize_R_version(R_version)

# Copy installation scripts
copy_installation(app_dir)
Expand All @@ -102,43 +100,43 @@ create_app <- function(app_name,
create_bat(app_name, app_dir)

# Create app config file
create_config(app_name, app_dir, pkgs, locals = dots$locals,
remotes = dots$remotes, repo = dots$repo, error_log = dots$error_log,
app_repo_url = dots$app_repo_url, auth_user = dots$auth_user,
auth_pw = dots$auth_pw, auth_token = dots$auth_token,
user_browser = dots$user_browser)
create_config(app_name, app_dir, pkgs, locals = locals,
remotes = remotes, 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)

# Build the iss script
iss <- start_iss(app_name)

# C-like directives
iss <- directives(iss, include_R, R_version, include_Pandoc, Pandoc_version,
iss <- directives_section(iss, include_R, R_version, include_Pandoc, Pandoc_version,
include_Chrome, app_version = dots$app_version, publisher = dots$publisher,
main_url = dots$main_url)

# Setup Section
iss <- setup(iss, app_dir, dir_out, app_version = dots$app_version,
iss <- setup_section(iss, app_dir, dir_out, app_version = dots$app_version,
default_dir = dots$default_dir, privilege = dots$privilege,
info_before = dots$info_before, info_after = dots$info_after,
setup_icon = dots$setup_icon, inst_pw = dots$inst_pw,
license_file = dots$license_file, pub_url = dots$pub_url,
sup_url = dots$sup_url, upd_url = dots$upd_url)

# Languages Section
iss <- languages(iss)
iss <- languages_section(iss)

# Tasks Section
iss <- tasks(iss, desktop_icon = dots$desktop_icon)
iss <- tasks_section(iss, desktop_icon = dots$desktop_icon)

# Icons Section
iss <- icons(iss, app_dir, app_desc = dots$app_desc, app_icon = dots$app_icon,
iss <- icons_section(iss, app_dir, app_desc = dots$app_desc, app_icon = dots$app_icon,
prog_menu_icon = dots$prog_menu_icon, desktop_icon = dots$desktop_icon)

# Files Section
iss <- files(iss, app_dir, file_list = dots$file_list)
iss <- files_section(iss, app_dir, file_list = dots$file_list)

# Execution & Pascal code to check registry during installation
iss <- run(iss, dots$R_flags); iss <- code(iss)
iss <- run_section(iss, dots$R_flags); iss <- code_section(iss, R_version)

# Write the Inno Setup script
writeLines(iss, file.path(app_dir, paste0(app_name, ".iss")))
Expand Down
5 changes: 4 additions & 1 deletion R/create_config.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
#' @seealso \code{\link{create_app}}.
#' @export

create_config <- function(app_name, app_dir, pkgs, locals = "none",
create_config <- function(app_name,
app_dir = getwd(),
pkgs = c("jsonlite", "shiny", "magrittr"),
locals = "none",
remotes = "none", repo = "http://cran.rstudio.com", local_path = 'local',
error_log = "error.log", app_repo_url = "none", auth_user = "none",
auth_pw = "none", auth_token = "none", user_browser = "chrome") {
Expand Down
20 changes: 12 additions & 8 deletions R/get_R.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,34 @@
#' @return
#' \code{sprintf('R-\%s-win.exe', R_version)} in \code{app_dir}.
#'
#' @inherit setup seealso
#' @inherit setup_section seealso
#' @author Jonathan M. Hill
#' @export

get_R <- function(app_dir, R_version) {
get_R <- function(app_dir,
R_version = paste0(">=", R.version$major, ".", R.version$minor)) {

R_version <- sanitize_R_version(R_version, clean = TRUE)

latest_R_version <-
unique(stats::na.omit(stringr::str_extract(readLines("https://cran.rstudio.com/bin/windows/base/", warn = F), "[1-3]\\.[0-9]+\\.[0-9]+")))

old_R_versions <- stats::na.omit(stringr::str_extract(readLines("https://cran.rstudio.com/bin/windows/base/old/", warn = F), "[1-3]\\.[0-9]+\\.[0-9]+"))

if (!R_version %in% c(latest_R_version, old_R_versions)) stop(sprintf("That version of R (v%s) does not exist.", R_version))
if (!R_version %in% c(latest_R_version, old_R_versions)) stop(glue::glue("That version of R ({R_version}) does not exist."), call. = F)

if (latest_R_version == R_version) {
base_url <- sprintf("https://cran.r-project.org/bin/windows/base/R-%s-win.exe", R_version)
base_url <- glue::glue("https://cran.r-project.org/bin/windows/base/R-{R_version}-win.exe")
} else {
base_url <- sprintf("https://cran.r-project.org/bin/windows/base/old/%s/R-%s-win.exe", R_version, R_version)
base_url <- glue::glue("https://cran.r-project.org/bin/windows/base/old/{R_version}/R-{R_version}-win.exe")
}

filename <- file.path(app_dir, sprintf("R-%s-win.exe", R_version))
filename <- file.path(app_dir, glue::glue("R-{R_version}-win.exe"))

if (file.exists(filename)) {
cat("Using the copy of R already included:\n", filename)
} else {
cat(sprintf("Downloading R-%s ...\n", R_version))
cat(glue::glue("Downloading R-{R_version} ...\n"))

tryCatch(curl::curl_download(base_url, filename),
error = function(e) {
Expand All @@ -49,6 +53,6 @@ get_R <- function(app_dir, R_version) {
"))
})

if (!file.exists(filename)) stop(sprintf("%s failed to download.", filename))
if (!file.exists(filename)) stop(glue::glue("{filename} failed to download."), call. = F)
}
}
52 changes: 47 additions & 5 deletions R/standardize_pkgs.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#' Standardize package dependencies
#'
#' Standardizes (named or not) character vectors of package dependencies. This creates a standard format for package dependency information stored in config.cfg
#' Standardizes (named or not) character vectors of package dependencies and formats it for config.cfg.
#'
#' @param pkgs Processes \code{pkgs}, and \code{locals}, arguments of \code{\link{create_config}} and \code{\link{create_app}}.
#'
#' @return Package dependency list with version numbers and inequalities. Defaults to \code{paste0(">=", packageVersion(pkg))}.
#'
#' @author William Bradley and Jonathan Hill
#' @export

standardize_pkgs <- function(pkgs) {

Expand Down Expand Up @@ -54,19 +55,60 @@ standardize_pkgs <- function(pkgs) {
pkgs <- lapply(pkg_list, as.character)

# Make sure the results are valid
df <- data.frame(utils::installed.packages())
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("{inequality} for {pkg_name} is not a valid logical operator"), call. = F)
stop(glue::glue("{pkg_name}'s inequality ({inequality}) is not a valid logical operator"), call. = F)
}
if (class(try(numeric_version(required_version))) == "try-error") {
stop(glue::glue("{required_version} for {pkg_name} is not a valid `numeric_version`"), 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% df$Package) stop(glue::glue("{pkg_name} is not installed. Make sure it is in `installed.pacakges()` and try again."), call. = F)
}
mapply(check_pkgs, pkg_list, names(pkg_list))
mapply(check_pkgs, pkgs, names(pkgs))

return(pkgs)
}

#' Sanitize R's version
#'
#' Used to validate R versions and strip off inequalities when necessary.
#'
#' @inheritParams create_app
#' @param clean Boolean. If TRUE, \code{><=} are removed. Defaults to FALSE.
#' @export
sanitize_R_version <- function(R_version, clean = FALSE){

# Check for valid R version
test <- gsub("[<>=[:space:]]", "", R_version)
if (any(length(strsplit(test, "\\.")[[1]]) != 3,
!grepl("[1-3]\\.[0-9]+\\.[0-9]+", test))) {
stop(glue::glue("R_version ({test}) is not valid."), call. = FALSE)
}

# Remove spaces
R_version <- gsub(" ", "", R_version)

# Check the inequality
if (grepl("[<>=]", R_version)) {
breakpoint <- attr(regexpr("[<>=]+", R_version), "match.length")
inequality <- substr(R_version, 1, breakpoint)
if (grepl("=[<>]", inequality)) {
stop(glue::glue("R_version's inequality, {inequality}, is not a valid logical operator"), call. = FALSE)
} else if (nchar(inequality) == 1) {
stop(glue::glue("RInno only supports >=, <= and == in R_version"), call. = FALSE)
} else if (breakpoint > 2) {
stop(glue::glue("R_version = {R_version} is not supported."), call. = FALSE)
}

} else {
# add == if no inequality is specified
R_version <- paste0(">=", R_version)
}
if (clean) R_version <- gsub("[<>=[:space:]]", "", R_version)
return(R_version)
}
58 changes: 36 additions & 22 deletions inst/installation/code.iss
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,33 @@ Type: filesandordirs; Name: "{app}\log";

[Code]
const
RRegKey = 'Software\R-Core\R\{#RVersion}';
ChromeRegKey = 'Software\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe';
IERegKey = 'Software\Microsoft\Windows\CurrentVersion\App Paths\IEXPLORE.EXE';
FFRegKey = 'Software\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe';
var
RVersions: TStringList;
RRegKey: string;
RegPathsFile: string;
SecondLicensePage: TOutputMsgMemoWizardPage;
License2AcceptedRadio: TRadioButton;
License2NotAcceptedRadio: TRadioButton;
// Is R installed?
function RDetected(): boolean;
var
v: Integer;
success: boolean;
begin
success := RegKeyExists(HKLM, RRegKey) or RegKeyExists(HKCU, RRegKey);
for v := 0 to (RVersions.Count - 1) do
begin
if RegKeyExists(HKLM, 'Software\R-Core\R\' + RVersions[v]) or RegKeyExists(HKCU, 'Software\R-Core\R\' + RVersions[v]) then
success := true
if success then
begin
RRegKey := 'Software\R-Core\R\' + RVersions[v];
break;
end;
end;
begin
Result := success;
end;
Expand All @@ -30,7 +40,7 @@ end;
// If R is not detected, it is needed
function RNeeded(): Boolean;
begin
Result := (RDetected = false);
Result := not RDetected;
end;
Expand All @@ -48,7 +58,7 @@ end;
// If Chrome is not detected, it is needed
function ChromeNeeded(): Boolean;
begin
Result := (ChromeDetected = false);
Result := not ChromeDetected;
end;
Expand Down Expand Up @@ -92,7 +102,7 @@ end;
// If Pandoc is not detected, it is needed
function PandocNeeded(): Boolean;
begin
Result := (PandocDetected = false);
Result := not PandocDetected;
end;
// Save installation paths
Expand All @@ -105,8 +115,12 @@ if CurStep = ssPostInstall then begin
ChromePath := '';
IEPath := '';
FFPath := '';
PandocPath := ExpandConstant('{localappdata}\Pandoc\');
PandocPath := ExpandConstant('{localappdata}\Pandoc\');
RegPathsFile := ExpandConstant('{app}\utils\regpaths.json');
if Length(RRegKey) = 0 then
RRegKey := 'Software\R-Core\R\' + RVersions[0];
// Create registry paths file
SaveStringToFile(RegPathsFile, '{' + #13#10, True);
Expand Down Expand Up @@ -134,12 +148,12 @@ if CurStep = ssPostInstall then begin
else
SaveStringToFile(RegPathsFile, '"ff": "none",' + #13#10, True);
// Pandoc RegPath
// ** Last Line in json file (no trailing comma) **
if PandocDetected() then
SaveStringToFile(RegPathsFile, '"pandoc": "' + AddBackSlash(PandocPath) + '"' + #13#10, True)
else
SaveStringToFile(RegPathsFile, '"pandoc": "none"' + #13#10, True);
// Pandoc RegPath
// ** Last Line in json file (no trailing comma) **
if PandocDetected() then
SaveStringToFile(RegPathsFile, '"pandoc": "' + AddBackSlash(PandocPath) + '"' + #13#10, True)
else
SaveStringToFile(RegPathsFile, '"pandoc": "none"' + #13#10, True);
SaveStringToFile(RegPathsFile, '}', True);
end;
Expand All @@ -164,6 +178,15 @@ begin
Result.OnClick := @CheckLicense2Accepted;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
{ Update Next button when user gets to second license page }
if CurPageID = SecondLicensePage.ID then
begin
CheckLicense2Accepted(nil);
end;
end;
procedure InitializeWizard();
var
LicenseFileName: string;
Expand Down Expand Up @@ -193,13 +216,4 @@ begin
{ Initially not accepted }
License2NotAcceptedRadio.Checked := True;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
{ Update Next button when user gets to second license page }
if CurPageID = SecondLicensePage.ID then
begin
CheckLicense2Accepted(nil);
end;
end;
Loading

0 comments on commit 904a3d9

Please sign in to comment.