From 103a19e09b187f6f8396bcf923e6aefb9d793356 Mon Sep 17 00:00:00 2001 From: Jim Hester Date: Mon, 23 Jul 2018 17:13:44 -0400 Subject: [PATCH] Allow warning on error rather than exiting Fixes #105 Fixes #121 --- R/zzz.R | 8 ++++++++ src/dir.cc | 10 ++++++++-- src/error.cc | 20 +++++++++++++++----- src/error.h | 2 +- src/link.cc | 9 +++++++-- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/R/zzz.R b/R/zzz.R index 3a1372770..2c6b9a30e 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,3 +1,7 @@ +fs_default_options <- list( + fs.should_error = TRUE +) + # nocov start .onLoad <- function(...) { register_s3_method("pillar", "pillar_shaft", "fs_path") @@ -11,6 +15,10 @@ register_s3_method("pillar", "type_sum", "fs_perms") register_s3_method("testthat", "compare", "fs_perms") + op <- options() + toset <- !(names(fs_default_options) %in% names(op)) + if(any(toset)) options(fs_default_options[toset]) + invisible() } diff --git a/src/dir.cc b/src/dir.cc index 3a889a0c5..a8a2b8440 100644 --- a/src/dir.cc +++ b/src/dir.cc @@ -54,7 +54,10 @@ void dir_map( CollectorList* value) { uv_fs_t req; uv_fs_scandir(uv_default_loop(), &req, path, 0, NULL); - stop_for_error(req, "Failed to search directory '%s'", path); + if (stop_for_error(req, "Failed to search directory '%s'", path) == false) { + uv_fs_req_cleanup(&req); + return; + } uv_dirent_t e; for (int next_res = uv_fs_scandir_next(&req, &e); next_res != UV_EOF; @@ -84,7 +87,10 @@ void dir_map( dir_map(fun, name.c_str(), all, file_type, true, value); } if (next_res != UV_EOF) { - stop_for_error(req, "Failed to search directory '%s'", path); + if (stop_for_error(req, "Failed to search directory '%s'", path) == + false) { + break; + } } } uv_fs_req_cleanup(&req); diff --git a/src/error.cc b/src/error.cc index ea8c328c1..fc9daf7ac 100644 --- a/src/error.cc +++ b/src/error.cc @@ -2,12 +2,12 @@ #define BUFSIZE 8192 -SEXP error_condition(uv_fs_t req, const char* loc, const char* format, ...) { +bool error_condition(uv_fs_t req, const char* loc, const char* format, ...) { SEXP condition, c, signalConditionFun, out; va_list ap; if (req.result >= 0) { - return R_NilValue; + return true; } int err = req.result; uv_fs_req_cleanup(&req); @@ -15,10 +15,16 @@ SEXP error_condition(uv_fs_t req, const char* loc, const char* format, ...) { const char* nms[] = {"message", ""}; PROTECT(condition = Rf_mkNamed(VECSXP, nms)); + int should_error = Rf_asLogical(Rf_GetOption1(Rf_install("fs.should_error"))); + PROTECT(c = Rf_allocVector(STRSXP, 4)); SET_STRING_ELT(c, 0, Rf_mkChar(uv_err_name(err))); SET_STRING_ELT(c, 1, Rf_mkChar("fs_error")); - SET_STRING_ELT(c, 2, Rf_mkChar("error")); + if (should_error) { + SET_STRING_ELT(c, 2, Rf_mkChar("error")); + } else { + SET_STRING_ELT(c, 2, Rf_mkChar("warning")); + } SET_STRING_ELT(c, 3, Rf_mkChar("condition")); char buf[BUFSIZE]; @@ -32,12 +38,16 @@ SEXP error_condition(uv_fs_t req, const char* loc, const char* format, ...) { SET_VECTOR_ELT(condition, 0, Rf_mkString(buf)); Rf_setAttrib(condition, R_ClassSymbol, c); Rf_setAttrib(condition, Rf_mkString("location"), Rf_mkString(loc)); - signalConditionFun = Rf_findFun(Rf_install("stop"), R_BaseEnv); + if (should_error) { + signalConditionFun = Rf_findFun(Rf_install("stop"), R_BaseEnv); + } else { + signalConditionFun = Rf_findFun(Rf_install("warning"), R_BaseEnv); + } SEXP call = PROTECT(Rf_lang2(signalConditionFun, condition)); PROTECT(out = Rf_eval(call, R_GlobalEnv)); UNPROTECT(4); - return out; + return false; } diff --git a/src/error.h b/src/error.h index 3b80f1729..9aec935f0 100644 --- a/src/error.h +++ b/src/error.h @@ -20,7 +20,7 @@ extern "C" { #define stop_for_error2(req, format, one, two) \ error_condition(req, __FILE__ ":" STRING(__LINE__), format, one, two) -SEXP error_condition(uv_fs_t req, const char* loc, const char* format, ...); +bool error_condition(uv_fs_t req, const char* loc, const char* format, ...); #ifdef __cplusplus } diff --git a/src/link.cc b/src/link.cc index 098d5752f..14544dbda 100644 --- a/src/link.cc +++ b/src/link.cc @@ -40,7 +40,9 @@ void link_create_symbolic_(CharacterVector path, CharacterVector new_path) { // check that the link points to where we want to point to uv_fs_t l_req; uv_fs_readlink(uv_default_loop(), &l_req, n, NULL); - stop_for_error(l_req, "Failed to read link '%s'", n); + if (stop_for_error(l_req, "Failed to read link '%s'", n) == false) { + continue; + } if (strcmp(path_tidy_((const char*)l_req.ptr).c_str(), p) == 0) { uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&l_req); @@ -61,7 +63,10 @@ CharacterVector readlink_(CharacterVector path) { uv_fs_t req; const char* p = CHAR(STRING_ELT(path, i)); uv_fs_readlink(uv_default_loop(), &req, p, NULL); - stop_for_error(req, "Failed to read link '%s'", p); + if (stop_for_error(req, "Failed to read link '%s'", p) == false) { + SET_STRING_ELT(out, i, NA_STRING); + continue; + } SET_STRING_ELT(out, i, Rf_mkCharCE((const char*)req.ptr, CE_UTF8)); uv_fs_req_cleanup(&req); }