22local({
33
44 # the requested version of renv
5- version <- " 1.0.11 "
5+ version <- " 1.1.0 "
66 attr(version , " sha" ) <- NULL
77
88 # the project directory
@@ -42,7 +42,7 @@ local({
4242 return (FALSE )
4343
4444 # next, check environment variables
45- # TODO: prefer using the configuration one in the future
45+ # prefer using the configuration one in the future
4646 envvars <- c(
4747 " RENV_CONFIG_AUTOLOADER_ENABLED" ,
4848 " RENV_AUTOLOADER_ENABLED" ,
@@ -209,10 +209,6 @@ local({
209209
210210 }
211211
212- startswith <- function (string , prefix ) {
213- substring(string , 1 , nchar(prefix )) == prefix
214- }
215-
216212 bootstrap <- function (version , library ) {
217213
218214 friendly <- renv_bootstrap_version_friendly(version )
@@ -563,6 +559,9 @@ local({
563559
564560 # prepare download options
565561 token <- renv_bootstrap_github_token()
562+ if (is.null(token ))
563+ token <- " "
564+
566565 if (nzchar(Sys.which(" curl" )) && nzchar(token )) {
567566 fmt <- " --location --fail --header \" Authorization: token %s\" "
568567 extra <- sprintf(fmt , token )
@@ -951,8 +950,14 @@ local({
951950 }
952951
953952 renv_bootstrap_validate_version_dev <- function (version , description ) {
953+
954954 expected <- description [[" RemoteSha" ]]
955- is.character(expected ) && startswith(expected , version )
955+ if (! is.character(expected ))
956+ return (FALSE )
957+
958+ pattern <- sprintf(" ^\\ Q%s\\ E" , version )
959+ grepl(pattern , expected , perl = TRUE )
960+
956961 }
957962
958963 renv_bootstrap_validate_version_release <- function (version , description ) {
@@ -1132,10 +1137,10 @@ local({
11321137
11331138 renv_bootstrap_exec <- function (project , libpath , version ) {
11341139 if (! renv_bootstrap_load(project , libpath , version ))
1135- renv_bootstrap_run(version , libpath )
1140+ renv_bootstrap_run(project , libpath , version )
11361141 }
11371142
1138- renv_bootstrap_run <- function (version , libpath ) {
1143+ renv_bootstrap_run <- function (project , libpath , version ) {
11391144
11401145 # perform bootstrap
11411146 bootstrap(version , libpath )
@@ -1146,7 +1151,7 @@ local({
11461151
11471152 # try again to load
11481153 if (requireNamespace(" renv" , lib.loc = libpath , quietly = TRUE )) {
1149- return (renv :: load(project = getwd() ))
1154+ return (renv :: load(project = project ))
11501155 }
11511156
11521157 # failed to download or load renv; warn the user
@@ -1192,98 +1197,101 @@ local({
11921197 jsonlite :: fromJSON(txt = text , simplifyVector = FALSE )
11931198 }
11941199
1195- renv_json_read_default <- function (file = NULL , text = NULL ) {
1196-
1197- # find strings in the JSON
1198- text <- paste(text %|| % readLines(file , warn = FALSE ), collapse = " \n " )
1199- pattern <- ' ["](?:(?:\\\\ .)|(?:[^"\\\\ ]))*?["]'
1200- locs <- gregexpr(pattern , text , perl = TRUE )[[1 ]]
1201-
1202- # if any are found, replace them with placeholders
1203- replaced <- text
1204- strings <- character ()
1205- replacements <- character ()
1206-
1207- if (! identical(c(locs ), - 1L )) {
1208-
1209- # get the string values
1210- starts <- locs
1211- ends <- locs + attr(locs , " match.length" ) - 1L
1212- strings <- substring(text , starts , ends )
1213-
1214- # only keep those requiring escaping
1215- strings <- grep(" [[\\ ]{}:]" , strings , perl = TRUE , value = TRUE )
1216-
1217- # compute replacements
1218- replacements <- sprintf(' "\0 32%i\0 32"' , seq_along(strings ))
1219-
1220- # replace the strings
1221- mapply(function (string , replacement ) {
1222- replaced <<- sub(string , replacement , replaced , fixed = TRUE )
1223- }, strings , replacements )
1200+ renv_json_read_patterns <- function () {
1201+
1202+ list (
1203+
1204+ # objects
1205+ list (" {" , " \t\n\t object(\t\n\t " ),
1206+ list (" }" , " \t\n\t )\t\n\t " ),
1207+
1208+ # arrays
1209+ list (" [" , " \t\n\t array(\t\n\t " ),
1210+ list (" ]" , " \n\t\n )\n\t\n " ),
1211+
1212+ # maps
1213+ list (" :" , " \t\n\t =\t\n\t " )
1214+
1215+ )
1216+
1217+ }
12241218
1219+ renv_json_read_envir <- function () {
1220+
1221+ envir <- new.env(parent = emptyenv())
1222+
1223+ envir [[" +" ]] <- `+`
1224+ envir [[" -" ]] <- `-`
1225+
1226+ envir [[" object" ]] <- function (... ) {
1227+ result <- list (... )
1228+ names(result ) <- as.character(names(result ))
1229+ result
12251230 }
1226-
1227- # transform the JSON into something the R parser understands
1228- transformed <- replaced
1229- transformed <- gsub(" {}" , " `names<-`(list(), character())" , transformed , fixed = TRUE )
1230- transformed <- gsub(" [[{]" , " list(" , transformed , perl = TRUE )
1231- transformed <- gsub(" []}]" , " )" , transformed , perl = TRUE )
1232- transformed <- gsub(" :" , " =" , transformed , fixed = TRUE )
1233- text <- paste(transformed , collapse = " \n " )
1234-
1235- # parse it
1236- json <- parse(text = text , keep.source = FALSE , srcfile = NULL )[[1L ]]
1237-
1238- # construct map between source strings, replaced strings
1239- map <- as.character(parse(text = strings ))
1240- names(map ) <- as.character(parse(text = replacements ))
1241-
1242- # convert to list
1243- map <- as.list(map )
1244-
1245- # remap strings in object
1246- remapped <- renv_json_read_remap(json , map )
1247-
1248- # evaluate
1249- eval(remapped , envir = baseenv())
1250-
1231+
1232+ envir [[" array" ]] <- list
1233+
1234+ envir [[" true" ]] <- TRUE
1235+ envir [[" false" ]] <- FALSE
1236+ envir [[" null" ]] <- NULL
1237+
1238+ envir
1239+
12511240 }
12521241
1253- renv_json_read_remap <- function (json , map ) {
1254-
1255- # fix names
1256- if (! is.null(names(json ))) {
1257- lhs <- match(names(json ), names(map ), nomatch = 0L )
1258- rhs <- match(names(map ), names(json ), nomatch = 0L )
1259- names(json )[rhs ] <- map [lhs ]
1242+ renv_json_read_remap <- function (object , patterns ) {
1243+
1244+ # repair names if necessary
1245+ if (! is.null(names(object ))) {
1246+
1247+ nms <- names(object )
1248+ for (pattern in patterns )
1249+ nms <- gsub(pattern [[2L ]], pattern [[1L ]], nms , fixed = TRUE )
1250+ names(object ) <- nms
1251+
12601252 }
1261-
1262- # fix values
1263- if (is.character(json ))
1264- return (map [[json ]] %|| % json )
1265-
1266- # handle true, false, null
1267- if (is.name(json )) {
1268- text <- as.character(json )
1269- if (text == " true" )
1270- return (TRUE )
1271- else if (text == " false" )
1272- return (FALSE )
1273- else if (text == " null" )
1274- return (NULL )
1253+
1254+ # repair strings if necessary
1255+ if (is.character(object )) {
1256+ for (pattern in patterns )
1257+ object <- gsub(pattern [[2L ]], pattern [[1L ]], object , fixed = TRUE )
12751258 }
1259+
1260+ # recurse for other objects
1261+ if (is.recursive(object ))
1262+ for (i in seq_along(object ))
1263+ object [i ] <- list (renv_json_read_remap(object [[i ]], patterns ))
1264+
1265+ # return remapped object
1266+ object
1267+
1268+ }
12761269
1277- # recurse
1278- if (is.recursive(json )) {
1279- for (i in seq_along(json )) {
1280- json [i ] <- list (renv_json_read_remap(json [[i ]], map ))
1281- }
1282- }
1270+ renv_json_read_default <- function (file = NULL , text = NULL ) {
12831271
1284- json
1272+ # read json text
1273+ text <- paste(text %|| % readLines(file , warn = FALSE ), collapse = " \n " )
1274+
1275+ # convert into something the R parser will understand
1276+ patterns <- renv_json_read_patterns()
1277+ transformed <- text
1278+ for (pattern in patterns )
1279+ transformed <- gsub(pattern [[1L ]], pattern [[2L ]], transformed , fixed = TRUE )
1280+
1281+ # parse it
1282+ rfile <- tempfile(" renv-json-" , fileext = " .R" )
1283+ on.exit(unlink(rfile ), add = TRUE )
1284+ writeLines(transformed , con = rfile )
1285+ json <- parse(rfile , keep.source = FALSE , srcfile = NULL )[[1L ]]
12851286
1287+ # evaluate in safe environment
1288+ result <- eval(json , envir = renv_json_read_envir())
1289+
1290+ # fix up strings if necessary
1291+ renv_json_read_remap(result , patterns )
1292+
12861293 }
1294+
12871295
12881296 # load the renv profile, if any
12891297 renv_bootstrap_profile_load(project )
0 commit comments