@@ -291,7 +291,7 @@
Loading
291 291
  DESCRIPTIONpaths <- file.path(packageTD, "DESCRIPTION")
292 292
  pkgDTNeedNew <- pkgDT[objsExist == FALSE] 
293 293
  if (NROW(pkgDTNeedNew)) {
294 -
    message("available.packages() doesn't have correct information on package dependencies for ",
294 +
    message("available.packages() does not have correct information on package dependencies for ",
295 295
            paste(Package, collapse = ", "), 
296 296
            " because they are Archive versions; downloading their respective tar.gz files")
297 297
    pkgFilename <- paste0(pkgDTNeedNew$Package, "_", 

@@ -6,7 +6,7 @@
Loading
6 6
#' Determine package dependencies
7 7
#'
8 8
#' This will first look in local filesystem (in \code{.libPaths()}) and will use
9 -
#' a local package to find its dependencies. If the package doesn't exist locally, 
9 +
#' a local package to find its dependencies. If the package does not exist locally, 
10 10
#' including whether it is the correct version, then it will look in (currently) 
11 11
#' \code{CRAN} and its archives (if the current \code{CRAN} version is not
12 12
#' the desired version to check). It will also look on \code{GitHub} if the 
@@ -289,7 +289,7 @@
Loading
289 289
          td <- tempdir2(pkgName)
290 290
          packageTD <- file.path(td, pkgName)
291 291
          if (!dir.exists(packageTD)) {
292 -
            message("available.packages() doesn't have correct information on package dependencies for ", pkgName, 
292 +
            message("available.packages() does not have correct information on package dependencies for ", pkgName, 
293 293
                    "; downloading tar.gz")
294 294
            verNum <- extractVersionNumber(pkg)
295 295
            if (is.na(verNum)) {

@@ -0,0 +1,169 @@
Loading
1 +
#' Setup a project library, cache, options
2 +
#' 
3 +
#' This can be placed as the first line of any/all scripts and it will
4 +
#' be create a reproducible, self-contained project with R packages. 
5 +
#' Some of these have direct relationships with \code{RequireOptions}
6 +
#' and arguments in \code{setLibPaths} and \code{Require}.
7 +
#' @param RPackageFolders One or more folders where R packages are 
8 +
#'   installed to and loaded from. In the case of more than one 
9 +
#'   folder provided, installation will only happen in the first one.
10 +
#' @param RPackageCache See \code{?RequireOptions}.
11 +
#' @param buildBinaries See \code{?RequireOptions}.
12 +
#' @inheritParams setLibPaths
13 +
#' @export
14 +
#' @rdname setup
15 +
#' 
16 +
#' @examples 
17 +
#' # Place this as the first line of a project
18 +
#' \dontrun{
19 +
#' Require::setup()
20 +
#' 
21 +
#' # To turn it off and return to normal
22 +
#' Require::setupOff()
23 +
#' }
24 +
#'   
25 +
setup <- function(RPackageFolders = getOption("RPackageFolders", "R"), 
26 +
                  RPackageCache = getOption("RPackageCache", "~/.cache/R/RequirePkgCache"), 
27 +
                  buildBinaries = getOption("buildBinaries", TRUE), 
28 +
                  standAlone = getOption("standAlone", TRUE)) {
29 +
  RPackageFolders <- checkPath(RPackageFolders, create = TRUE)
30 +
  RPackageCache <- checkPath(RPackageCache, create = TRUE)
31 +
  # hasCranCache <- any(dir.exists(file.path(.libPaths(), "crancache")))
32 +
  # usingCranCache <- FALSE
33 +
  # 
34 +
  # if (hasCranCache && !isFALSE(getOption("Require.useCranCache"))) { # if NULL or TRUE go here
35 +
  #   rvn <- paste0(R.version$major, '.', strsplit(R.version$minor, split = '\\.')[[1]][1])
36 +
  #   os <- tolower(.Platform$OS.type)
37 +
  #   extra <- file.path('cran','bin', os,'contrib', rvn, fsep = "/")
38 +
  #   usingCranCache <- !endsWith(RPackageCache, extra)
39 +
  #   if (usingCranCache) {
40 +
  #     if (interactive()) {
41 +
  #       message("crancache is installed; would you like to have Require and ",
42 +
  #               "crancache share the cache? If N, then Require will use ",
43 +
  #               RPackageCache)
44 +
  #       useSameCache <- readline("Use same cache? (Y or N)")
45 +
  #       if (identical(tolower(useSameCache), "y")) {
46 +
  #         stop(paste0("To use crancache cached packages, please rerun:\n",
47 +
  #                     "setup(RPackageCache = normalizePath(file.path(crancache::get_cache_dir(),'",extra,"'),
48 +
  #                            winslash = '/'))"))
49 +
  #       }
50 +
  #     }
51 +
  #   } else {
52 +
  #     usingCranCache <- TRUE
53 +
  #   }
54 +
  # }
55 +
  copyRequireAndDeps(RPackageFolders)
56 +
  
57 +
  newOpts <- list("Require.RPackageCache" = RPackageCache,
58 +
                  "Require.buildBinaries" = buildBinaries)#,
59 +
                  #"Require.useCranCache" = usingCranCache)
60 +
  opts <- options(newOpts)
61 +
  co <- capture.output(type = "message", 
62 +
                       setLibPaths(RPackageFolders, standAlone = standAlone, 
63 +
                                   updateRprofile = TRUE))
64 +
  if (!any(grepl(alreadyInRprofileMessage, co)))
65 +
    if (getOption("Require.setupVerbose", TRUE)) 
66 +
      silence <- lapply(co, message)
67 +
  ro <- RequireOptions()
68 +
  roNames <- names(newOpts)
69 +
  names(roNames) <- roNames
70 +
  nonStandardOpt <- !unlist(lapply(roNames, function(optNam) identical(ro[[optNam]], opts[[optNam]])))
71 +
  if (any(nonStandardOpt)) {
72 +
    rp <- readLines(".Rprofile")
73 +
    lineWithPrevious <- grepl("### Previous", rp)
74 +
    if (any(lineWithPrevious)) {
75 +
      lineWithPrevious <- which(lineWithPrevious)
76 +
      post <- seq(length(rp) - lineWithPrevious) + lineWithPrevious
77 +
      pre <- seq(lineWithPrevious)
78 +
      nameNonStandards <- names(nonStandardOpt)[nonStandardOpt]
79 +
      optsToAdd <- unlist(lapply(nameNonStandards, function(nns) {
80 +
        paste0("### Previous option: ", nns, " = ", opts[[nns]])
81 +
      }))
82 +
      newOptsToAdd <- unlist(lapply(nameNonStandards, function(nns) {
83 +
        paste0("options('", nns, "' = '", newOpts[[nns]], "')")
84 +
      }))
85 +
      newRP <- c(rp[pre], optsToAdd, newOptsToAdd, rp[post])
86 +
      cat(newRP, file = ".Rprofile", sep = "\n")
87 +
    }
88 +
  }
89 +
    
90 +
}
91 +
92 +
#' @rdname setup
93 +
#' @export
94 +
#' @param removePackages Logical. If \code{TRUE}, then all packages that
95 +
#'   were installed in the custom library will be deleted when \code{setupOff}
96 +
#'   is run. The default is \code{FALSE}, and when \code{TRUE} is selected,
97 +
#'   and it is an interactive session, the user will be prompted to confirm
98 +
#'   deletions.
99 +
setupOff <- function(removePackages = FALSE) {
100 +
  lps <- .libPaths()
101 +
  if (file.exists(".Rprofile")) {
102 +
    rp <- readLines(".Rprofile")
103 +
    lineWithPrevious <- grepl("### Previous option", rp)
104 +
    options(RequireOptions())
105 +
    if (any(lineWithPrevious)) {
106 +
      lineWithPrevious <- which(lineWithPrevious)
107 +
      silence <- lapply(lineWithPrevious, function(lwp) {
108 +
        opt <- gsub("### Previous option: ", "", rp[lwp])
109 +
        opt <- strsplit(opt, " = ")[[1]]
110 +
        newOpt <- list(opt[2])
111 +
        names(newOpt) <- opt[1]
112 +
        options(newOpt)
113 +
      })
114 +
    }
115 +
    setLibPaths()
116 +
    if (isTRUE(removePackages)) {
117 +
      if (interactive() && getOption("Require.setupVerbose", TRUE) ) {
118 +
        message("You have requested to remove all packages in ", lps[1])
119 +
        out <- readline("Is this correct? Y (delete all) or N (do not delete all)")
120 +
        if (identical(tolower(out), "n"))
121 +
          removePackages <- FALSE
122 +
      } 
123 +
      if (isTRUE(removePackages))
124 +
        unlink(lps[1], recursive = TRUE)
125 +
    }
126 +
  } else {
127 +
    message("Project is not setup yet; nothing to do")
128 +
  }
129 +
}
130 +
131 +
copyRequireAndDeps <- function(RPackageFolders) {
132 +
  lps <- .libPaths()
133 +
  names(lps) <- lps
134 +
  pkgs <- c("Require", "remotes", "data.table")
135 +
  for (pkg in pkgs) {
136 +
    theNewPath <- file.path(rpackageFolder(RPackageFolders), pkg)
137 +
    newPathExists <- dir.exists(theNewPath)
138 +
    for (lp in lps) {
139 +
      thePath <- file.path(lp, pkg)
140 +
      pkgInstalledAlready <- dir.exists(thePath)
141 +
      if (isTRUE(pkgInstalledAlready)) {
142 +
        fromFiles <- dir(thePath, recursive = TRUE, full.names = TRUE)
143 +
        if (!newPathExists) {
144 +
          if (getOption("Require.setupVerbose", TRUE)) 
145 +
            message("Placing copy of ", pkg, " in ", RPackageFolders)
146 +
          dirs <- unique(dirname(fromFiles))
147 +
          dirs <- gsub(thePath, theNewPath, dirs)
148 +
          lapply(dirs, checkPath, create = TRUE)
149 +
        }
150 +
        
151 +
        toFiles <- gsub(thePath, theNewPath, fromFiles)
152 +
        
153 +
        if (newPathExists) {
154 +
          newPathVersion <- DESCRIPTIONFileVersionV(file.path(theNewPath, "DESCRIPTION"))
155 +
          oldPathVersion <- DESCRIPTIONFileVersionV(file.path(thePath, "DESCRIPTION"))
156 +
          comp <- compareVersion(newPathVersion, oldPathVersion)
157 +
          if (comp > -1) break
158 +
          if (getOption("Require.setupVerbose", TRUE)) 
159 +
            message("Updating version of ", pkg, " in ", RPackageFolders)
160 +
          unlink(toFiles)
161 +
        }
162 +
        file.link(fromFiles, toFiles)
163 +
        break
164 +
      }
165 +
    }
166 +
  }
167 +
168 +
169 +
}

@@ -131,7 +131,7 @@
Loading
131 131
              dir.create(file.path(pth), recursive = TRUE, showWarnings = FALSE)
132 132
            })
133 133
          } else {
134 -
            stop(paste("Specified path", normPath(path), "doesn't exist.",
134 +
            stop(paste("Specified path", normPath(path), "does not exist.",
135 135
                       "Create it and try again."))
136 136
          }
137 137
        }

@@ -442,7 +442,7 @@
Loading
442 442
443 443
#' @rdname DESCRIPTION-helpers
444 444
#' @param file A file path to a DESCRIPTION file
445 -
#' @param other Any other keyword in a DESCRIPTION file that preceeds a ":". The rest of the line will be
445 +
#' @param other Any other keyword in a DESCRIPTION file that precedes a ":". The rest of the line will be
446 446
#'   retrieved.
447 447
DESCRIPTIONFileOtherV <- function(file, other = "RemoteSha") {
448 448
  # origLocal <- Sys.setlocale(locale = "C") # required to deal with non English characters in Author names

@@ -3,7 +3,7 @@
Loading
3 3
#' This will set the \code{.libPaths()} by either adding a new path to
4 4
#' it if \code{standAlone = FALSE}, or will concatenate
5 5
#' \code{c(libPath, tail(.libPaths(), 1))} if \code{standAlone = TRUE}. Currently,
6 -
#' the default is to make this new \code{.libPaths()} "sticky", meaning it beomces 
6 +
#' the default is to make this new \code{.libPaths()} "sticky", meaning it becomes 
7 7
#' associated with the current directory even through a restart of R. It does this
8 8
#' by adding and/updating the .Rprofile file in the current directory. If this
9 9
#' current director is a project, then the project will have the new \code{.libPaths()}
@@ -77,7 +77,8 @@
Loading
77 77
78 78
  environment(shim_fun) <- shim_env
79 79
  shim_fun(unique(libPaths))
80 -
  message(".libPaths() is now: ", paste(.libPaths(), collapse = ", "))
80 +
  if (getOption("Require.setupVerbose", TRUE)) 
81 +
    message(".libPaths() is now: ", paste(.libPaths(), collapse = ", "))
81 82
  return(invisible(oldLibPaths))
82 83
}
83 84
@@ -94,7 +95,8 @@
Loading
94 95
      }
95 96
    }
96 97
    if (any(grepl(setLibPathsStartText, readLines(".Rprofile")))) {
97 -
      message(alreadyInRprofileMessage)
98 +
      if (getOption("Require.setupVerbose", TRUE)) 
99 +
        message(alreadyInRprofileMessage)
98 100
    } else {
99 101
      bodyFn <- format(body(Require::setLibPaths))
100 102
      lineWCheckPath <- grepl("checkPath.normPath|checkLibPaths", bodyFn)
@@ -120,9 +122,10 @@
Loading
120 122
                  paste0("._libPaths <- c('", paste(libPaths, collapse = "', '"), "')"), 
121 123
                  paste0("._standAlone <- ", standAlone), 
122 124
                  bodyFn, 
123 -
                  resetRprofileMessage(updateRprofile),
125 +
                  if (getOption("Require.setupVerbose", TRUE)) resetRprofileMessage(updateRprofile),
124 126
                  paste0(commentCharsForSetLibPaths, "end ####"))
125 -
      message("Updating ", updateRprofile, "; this will set new libPaths for R packages even after restarting R")
127 +
      if (getOption("Require.setupVerbose", TRUE)) 
128 +
        message("Updating ", updateRprofile, "; this will set new libPaths for R packages even after restarting R")
126 129
      cat(bodyFn, file = ".Rprofile", append = TRUE, sep = "\n")
127 130
    }
128 131
  }
@@ -140,7 +143,8 @@
Loading
140 143
        ll <- readLines(updateRprofile)
141 144
        bounds <- which(grepl("#### setLibPaths", ll))
142 145
        if (length(bounds)) {
143 -
          message("removing custom libPaths in .Rprofile")
146 +
          if (getOption("Require.setupVerbose", TRUE)) 
147 +
            message("removing custom libPaths in .Rprofile")
144 148
          if (identical("", ll[bounds[1] - 1])) {
145 149
            bounds[1] <- bounds[1] - 1
146 150
          }
@@ -162,7 +166,9 @@
Loading
162 166
      } else {
163 167
        noChange <- TRUE
164 168
      }
165 -
      if (isTRUE(noChange)) message("There was no custom libPaths setting in .Rprofile; nothing changed")
169 +
      if (isTRUE(noChange)) 
170 +
        if (getOption("Require.setupVerbose", TRUE)) 
171 +
          message("There was no custom libPaths setting in .Rprofile; nothing changed")
166 172
167 173
      return(invisible())
168 174
    }
Files Coverage
R 0.22%
Project Totals (11 files) 0.22%
1
comment: false
2

3
coverage:
4
  status:
5
    project:
6
      default:
7
        target: auto
8
        threshold: 1%
9
        informational: true
10
    patch:
11
      default:
12
        target: auto
13
        threshold: 1%
14
        informational: true
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading