1 /* 2 * SessionRenv.cpp 3 * 4 * Copyright (C) 2021 by RStudio, PBC 5 * 6 * Unless you have received this program directly from RStudio pursuant 7 * to the terms of a commercial license agreement with RStudio, then 8 * this program is licensed to you under the terms of version 3 of the 9 * GNU Affero General Public License. This program is distributed WITHOUT 10 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, 11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the 12 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. 13 * 14 */ 15 16 #include "SessionRenv.hpp" 17 18 #include <shared_core/Error.hpp> 19 #include <core/Exec.hpp> 20 21 #include <r/RExec.hpp> 22 #include <r/RJson.hpp> 23 24 #include <session/SessionModuleContext.hpp> 25 #include <session/projects/SessionProjects.hpp> 26 27 28 using namespace rstudio::core; 29 30 namespace rstudio { 31 namespace session { 32 namespace module_context { 33 isRequiredRenvInstalled()34bool isRequiredRenvInstalled() 35 { 36 return isPackageVersionInstalled("renv", "0.9.2"); 37 } 38 isRenvActive()39bool isRenvActive() 40 { 41 return !core::system::getenv("RENV_PROJECT").empty(); 42 } 43 44 namespace { 45 renvStateAsJson(const std::string method)46core::json::Value renvStateAsJson(const std::string method) 47 { 48 json::Value resultJson; 49 Error error = 50 r::exec::RFunction(method) 51 .call(&resultJson); 52 53 if (error) 54 { 55 LOG_ERROR(error); 56 return json::Object(); 57 } 58 59 if (resultJson.getType() != json::Type::OBJECT) 60 { 61 error = systemError(boost::system::errc::invalid_argument, ERROR_LOCATION); 62 LOG_ERROR(error); 63 return json::Object(); 64 } 65 66 return resultJson; 67 68 } 69 70 } // end anonymous namespace 71 renvOptionsAsJson()72core::json::Value renvOptionsAsJson() 73 { 74 return renvStateAsJson(".rs.renv.options"); 75 } 76 renvContextAsJson()77core::json::Value renvContextAsJson() 78 { 79 return renvStateAsJson(".rs.renv.context"); 80 } 81 82 } // end namespace module_context 83 } // end namespace session 84 } // end namespace rstudio 85 86 namespace rstudio { 87 namespace session { 88 namespace modules { 89 namespace renv { 90 91 namespace { 92 onConsolePrompt(const std::string &)93void onConsolePrompt(const std::string& /* prompt */) 94 { 95 // use RENV_PROJECT environment variable to detect if renv active 96 std::string renvProject = core::system::getenv("RENV_PROJECT"); 97 if (renvProject.empty()) 98 return; 99 100 // validate that it matches the project currently open in RStudio 101 // (we could consider relaxing this in the future) 102 const FilePath& projDir = projects::projectContext().directory(); 103 if (!projDir.isEquivalentTo(FilePath(renvProject))) 104 return; 105 106 Error error = r::exec::RFunction(".rs.renv.refresh") .call(); 107 if (error) 108 LOG_ERROR(error); 109 } 110 111 } // end anonymous namespace 112 initialize()113Error initialize() 114 { 115 using namespace module_context; 116 117 // initialize renv after session init (need to make sure 118 // all other RStudio startup code runs first) 119 events().onConsolePrompt.connect(onConsolePrompt); 120 121 using boost::bind; 122 ExecBlock initBlock; 123 initBlock.addFunctions() 124 (bind(sourceModuleRFile, "SessionRenv.R")); 125 126 return initBlock.execute(); 127 } 128 129 } // end namespace renv 130 } // end namespace modules 131 } // end namespace session 132 } // end namespace rstudio 133