8  Update R - Bare Bones

Author

Chrissy h Roberts

8.1 Bare bones updater for R.

An annoying feature of R is that updating the R version doesn’t always (if ever) pull all of your installed packages in to the new version.

Updater packages for R are also a bit hit and miss.

The updateR package is quite popular, but I haven’t had much luck with it.

It is here if you want to try it…

devtools::install_github(“AndreaCirilloAC/updateR”)

My approach takes the long way round, by creating an installer script for all the currently installed packages. It then saves this script, which you can run once you’ve updated R.

Doing it this way accounts for weird behaviour where installing packages from within loops or apply commands doesn’t handle dependencies well and leads to lots of packages failing to install.

This script contains some code from the updateR package, which has never worked for me on its own.

This method can take a while, but in my opinion does a much better job of comprehensively rebuilding your catalogue of libraries

Obviously this only works with CRAN packages, but will spit out a list of packages you need to manually install at the end.

8.2 Update R

8.2.1 Libraries

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(xml2)
library(rvest)
library(askpass)

8.2.2 Define functions

Most of these are copies or modifications of the updateR functions.

8.2.2.1 list_packages

list_packages <- function() {
  all_pkg <- installed.packages() %>%
    as.data.frame() %>%
    pull(Package)
  base_pkg <- installed.packages() %>%
    as.data.frame() %>%
    filter(Priority == "base") %>%
    pull(Package)
  all_pkg[!all_pkg %in% base_pkg]
}

8.2.2.2 list available versions

list_available_versions<-function(){
  cran <- "http://cran.rstudio.com/bin/macosx/"
  version_regex <- "(\\d+)?\\.(\\d+)?\\.(\\d+)?"
  page <- read_html(cran)
  file_url <- page %>%
    html_nodes(xpath = "//td/a")
  file_url
}

8.2.2.3 latest_r_version

Change ver to match your system requirements. Default is my own need for macOS non arm. (ver = 3)

latest_r_version <- function(ver=3) {
  cran <- "http://cran.rstudio.com/bin/macosx/"
  version_regex <- "(\\d+)?\\.(\\d+)?\\.(\\d+)?"
  page <- read_html(cran)
  file_url <- page %>%
    html_nodes(xpath = "//td/a") %>% .[ver] %>%
    html_attr("href") %>%
    paste(cran, ., sep = "")
  minimal <- page %>%
    html_nodes(xpath = '//table[1]//tr[1]//td[2]') %>%
    html_text() %>%
    trimws() %>%
    regmatches(., regexpr("macOS.*higher.", .)) %>%
    regmatches(., regexpr("\\d+.\\d+", .))
  r_latest <- regmatches(file_url, regexpr(version_regex, file_url))
  r_current <- paste(version$major, version$minor, sep = ".")
  r_latest_numeric <- as.numeric(sub("^(\\d)\\.", "\\1", r_latest))
  r_current_numeric <- as.numeric(sub("^(\\d)\\.", "\\1", r_current))
  
  structure(
    list(update_avail = ifelse(r_latest_numeric > r_current_numeric, T, F),
         latest = r_latest,
         url = file_url),
    current = paste(version$major, version$minor, sep = "."),
    OS_minimal = as.numeric(minimal)
  )
}

8.2.2.4 ask_password

ask_password <- function() {
  askpass::askpass(sprintf("Enter password for %s: ", system2("whoami", stdout = TRUE)))
}

8.2.2.5 write_package_reinstaller

write_package_reinstaller <- function(){
      # Make a list of currently installed packages
      packcmds<-NA
      packages<-list_packages()
    
      # Loop through and create an install script
      for (i in 1:length(packages))
      {
      packcmds[i]<-paste("install.packages('",packages[i],"',dependencies = T)",sep = "")
      }
    
    #write installer script to file
    write.table(x = packcmds,file = "packages.install.script.R",quote = F,row.names = F,col.names=FALSE)
 
}

8.2.2.6 update_R

This is a modified version of the update_R function from updateR.

update_R<-function(force=FALSE,ver)
{
  check<-latest_r_version(ver = ver)
  
  if(check$update_avail==FALSE){message("Current version is up to date, nothing to be done")}
  
  if(check$update_avail==TRUE | force == TRUE)
  {
   
    admin_password <- ask_password()
    username <- system('whoami', intern = TRUE)
    command <- paste0("echo '", admin_password, "' | sudo -S -l")
    out <- system(command, intern = TRUE)
    if (length(out) == 0) {
      stop(sprintf("current user %s does not have admin privileges", username))
    }
    folderpath <- sprintf("/Users/%s/Downloads/",
                          system2("whoami", stdout = TRUE))
    pkgfile <- regmatches(check$url, regexpr("R.*$", check$url))
    fullpath <- sprintf("%s%s", folderpath, pkgfile)
    # download package, set folder for download
    message("Downloading new version of R")
    download.file(check$url, fullpath)
    
    message("Installinf new version of R")
    {
      message(paste0("Installing R-", check$latest, "…please wait"))
      command <-
        paste0("echo '",
               admin_password,
               "' | sudo -S installer -pkg ",
               "'",
               fullpath,
               "'",
               " -target /")
      system(command, ignore.stdout = TRUE)
      arg <- paste0("--check-signature ", fullpath)
      system2("pkgutil", arg)
    }
  }
}

8.2.2.7 reinstall_all_packages

reinstall_all_packages <- function(){

    message("Reinstalling packages from source file")
    source("packages.install.script.R")
    
    new.packages<-list_packages()
    needinstall<-packages[packages%in%new.packages==FALSE]
    needinstall<-factor(unique(needinstall))
    
    message(needinstall)
  }

8.2.3 Run the Updater

8.2.3.1 Save the List of packages

#write_package_reinstaller()

8.2.3.2 Find the appropriate version of R for your machine

#list_available_versions()

8.2.3.3 Update R

#update_R(ver=3)

8.2.3.4 Update R

#reinstall_all_packages()