If you would like to account for potential syntax errors when
sourcing in your autos, you can wrap
rprofile() in purrr::safely(). This function
will attempt to set the autos and return a list containing the result
and any error that occurred.
Let’s show an example. First we’ll make an example configuration file
that will automatically source your autos. We’ll intentionally add a
syntax error to show how safely() works.
Here is our configuration file, which will automatically source the
autos from the DEV and PROD directories:
default:
  autos:
    projects: !expr list(
      "DEV" = file.path("demo", "DEV", "username", "project1", "functions"),
      "PROD" = file.path("demo", "PROD", "project1", "functions")
      )We will do a little work here to create the directory, place a script
into the directory. We’ll add a syntax error by leaving off a closing
} in test_error.R script in the PROD
folder.
# create the temp directory
dir <- fs::file_temp()
dir.create(dir)
dir.create(file.path(dir, "/demo/PROD/project1/functions"), recursive = TRUE)
# write a function to the folder with an error
file_conn <- file(file.path(dir, "/demo/PROD/project1/functions/test_error.R"))
writeLines(
"test <- function(){print('test')", file_conn)
close(file_conn)
# write the config
config_path <- file.path(dir, "_envsetup.yml")
file_conn <- file(config_path)
writeLines(
  paste0(
"default:
  autos:
    PROD: '", dir,"/demo/PROD/project1/functions'"
  ), file_conn)
close(file_conn)So if we call rprofile() passing in this config file, we
will get an error because of the syntax error in
test_error.R:
library(envsetup)
envsetup_config <- config::get(file = config_path)
rprofile(envsetup_config)
#> Assigned paths to R_GlobalEnv
#> Sourcing file:  '/shared/R_Temp/nmasel/RtmpKbVJua/file1962b1314414d1/demo/PROD/project1/functions/test_error.R'
#> Error in `map2()`:
#> ℹ In index: 1.
#> ℹ With name: PROD.
#> Caused by error in `map()`:
#> ℹ In index: 1.
#> Caused by error in `parse()`:
#> ! 2:0: unexpected end of input
#> 1: test <- function(){print('test')
#>    ^To handle this error, we can use purrr::safely() to wrap
the rprofile() function. This will allow us to catch the
error and handle it gracefully.
safely_rprofile <- purrr::safely(rprofile)
ret <- safely_rprofile(envsetup_config)
#> Assigned paths to R_GlobalEnv
#> Sourcing file:  '/shared/R_Temp/nmasel/RtmpKbVJua/file1962b1314414d1/demo/PROD/project1/functions/test_error.R'We still have an error, but safely allow the setup to continue. We
can check the result of the safely_rprofile() function to
see if there was an error, identify the issue and correct the syntax
error in the function.
# check for errors and return if any occurred
if(!is.null(ret$error)) {
  print(ret$error)
}
#> <error/purrr_error_indexed>
#> Error in `map2()`:
#> ℹ In index: 1.
#> ℹ With name: PROD.
#> Caused by error in `map()`:
#> ℹ In index: 1.
#> Caused by error in `parse()`:
#> ! 2:0: unexpected end of input
#> 1: test <- function(){print('test')
#>    ^
#> ---
#> Backtrace:
#>      ▆
#>   1. └─purrr (local) safely_rprofile(envsetup_config)
#>   2.   ├─purrr:::capture_error(.f(...), otherwise, quiet)
#>   3.   │ └─base::tryCatch(...)
#>   4.   │   └─base (local) tryCatchList(expr, classes, parentenv, handlers)
#>   5.   │     └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]])
#>   6.   │       └─base (local) doTryCatch(return(expr), name, parentenv, handler)
#>   7.   └─envsetup (local) .f(...)
#>   8.     └─envsetup:::set_autos(config$autos, overwrite = overwrite)
#>   9.       └─purrr::walk2(...)
#>  10.         └─purrr::map2(.x, .y, .f, ..., .progress = .progress)
#>  11.           └─purrr:::map2_("list", .x, .y, .f, ..., .progress = .progress)
#>  12.             ├─purrr:::with_indexed_errors(...)
#>  13.             │ └─base::withCallingHandlers(...)
#>  14.             ├─purrr:::call_with_cleanup(...)
#>  15.             └─envsetup (local) .f(.x[[i]], .y[[i]], ...)
#>  16.               └─envsetup:::attach_auto(.x, .y, overwrite = overwrite)
#>  17.                 └─purrr::walk(collated_r_scripts, source_warn_conflicts, overwrite = overwrite)
#>  18.                   └─purrr::map(.x, .f, ..., .progress = .progress)
#>  19.                     └─purrr:::map_("list", .x, .f, ..., .progress = .progress)
#>  20.                       ├─purrr:::with_indexed_errors(...)
#>  21.                       │ └─base::withCallingHandlers(...)
#>  22.                       ├─purrr:::call_with_cleanup(...)
#>  23.                       └─envsetup (local) .f(.x[[i]], ...)
#>  24.                         └─base::sys.source(file, envir = new_env)
#>  25.                           └─base::parse(n = -1, file = file, srcfile = NULL, keep.source = FALSE)