1 /* 2 * RVersions.hpp 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 #ifndef CORE_R_UTIL_R_VERSIONS_HPP 17 #define CORE_R_UTIL_R_VERSIONS_HPP 18 19 #define kRStudioRVersionsPath "RS_R_VERSIONS_PATH" 20 21 #include <vector> 22 #include <iosfwd> 23 24 #include <shared_core/FilePath.hpp> 25 26 #include <shared_core/json/Json.hpp> 27 28 #include <core/system/Environment.hpp> 29 30 #include <core/r_util/RVersionInfo.hpp> 31 32 namespace rstudio { 33 namespace core { 34 namespace r_util { 35 36 class RVersion 37 { 38 public: RVersion()39 RVersion() {} RVersion(const std::string & number,const core::system::Options & environment)40 RVersion(const std::string& number, const core::system::Options& environment) 41 : number_(number), environment_(environment) 42 { 43 setLabel(std::string()); 44 setModule(std::string()); 45 setPrelaunchScript(std::string()); 46 setRepo(std::string()); 47 setLibrary(std::string()); 48 } 49 50 public: empty() const51 bool empty() const { return number_.empty(); } 52 homeDir() const53 FilePath homeDir() const 54 { 55 return FilePath(core::system::getenv(environment_, "R_HOME")); 56 } 57 setHomeDir(const FilePath & filePath)58 void setHomeDir(const FilePath& filePath) 59 { 60 core::system::setenv(&environment_, "R_HOME", filePath.getAbsolutePath()); 61 } 62 number() const63 const std::string& number() const { return number_; } setNumber(const std::string & number)64 void setNumber(const std::string& number) { number_ = number; } 65 environment() const66 const core::system::Options& environment() const { return environment_; } setEnvironment(const core::system::Options & environment)67 void setEnvironment(const core::system::Options& environment) { environment_ = environment; } 68 label() const69 const std::string& label() const { return label_; } setLabel(const std::string & label)70 void setLabel(const std::string& label) 71 { 72 label_ = label; 73 core::system::setenv(&environment_, "RSTUDIO_R_VERSION_LABEL", label); 74 } 75 module() const76 const std::string& module() const { return module_; } setModule(const std::string & module)77 void setModule(const std::string& module) 78 { 79 module_ = module; 80 core::system::setenv(&environment_, "RSTUDIO_R_MODULE", module); 81 } 82 prelaunchScript() const83 const std::string& prelaunchScript() const { return prelaunchScript_; } setPrelaunchScript(const std::string & prelaunchScript)84 void setPrelaunchScript(const std::string& prelaunchScript) 85 { 86 prelaunchScript_ = prelaunchScript; 87 core::system::setenv(&environment_, "RSTUDIO_R_PRELAUNCH_SCRIPT", prelaunchScript); 88 } 89 repo() const90 const std::string& repo() const { return repo_; } setRepo(const std::string & repo)91 void setRepo(const std::string& repo) 92 { 93 repo_ = repo; 94 core::system::setenv(&environment_, "RSTUDIO_R_REPO", repo); 95 } 96 library() const97 const std::string& library() const { return library_; } setLibrary(const std::string & library)98 void setLibrary(const std::string& library) 99 { 100 library_ = library; 101 102 // only set R_LIBS_SITE env var if it is non-empty 103 // setting an empty site library will cause the default system configuration to be lost 104 if (!library.empty()) 105 core::system::setenv(&environment_, "R_LIBS_SITE", library); 106 } 107 operator <(const RVersion & other) const108 bool operator<(const RVersion& other) const 109 { 110 RVersionNumber ver = RVersionNumber::parse(number()); 111 RVersionNumber otherVer = RVersionNumber::parse(other.number()); 112 113 if (ver == otherVer) 114 return homeDir().getAbsolutePath() < other.homeDir().getAbsolutePath(); 115 else 116 return ver < otherVer; 117 } 118 operator ==(const RVersion & other) const119 bool operator==(const RVersion& other) const 120 { 121 return number() == other.number() && 122 homeDir().getAbsolutePath() == other.homeDir().getAbsolutePath() && 123 (label() == other.label() || (label().empty() || other.label().empty())); 124 } 125 126 private: 127 std::string number_; 128 core::system::Options environment_; 129 std::string label_; 130 std::string module_; 131 std::string prelaunchScript_; 132 std::string repo_; 133 std::string library_; 134 }; 135 136 std::ostream& operator<<(std::ostream& os, const RVersion& version); 137 138 std::vector<RVersion> enumerateRVersions( 139 std::vector<FilePath> rHomePaths, 140 std::vector<r_util::RVersion> rEntries, 141 bool scanForOtherVersions, 142 const FilePath& ldPathsScript, 143 const std::string& ldLibraryPath, 144 const FilePath& modulesBinaryPath); 145 146 RVersion selectVersion(const std::string& number, 147 const std::string& rHomeDir, 148 const std::string& label, 149 std::vector<RVersion> versions); 150 151 json::Object rVersionToJson(const r_util::RVersion& version); 152 153 r_util::RVersion rVersionFromJson(const json::Object& versionJson); 154 155 Error rVersionsFromJson(const json::Array& versionsJson, 156 std::vector<RVersion>* pVersions); 157 158 json::Array versionsToJson(const std::vector<r_util::RVersion>& versions); 159 160 Error writeRVersionsToFile(const FilePath& filePath, 161 const std::vector<r_util::RVersion>& versions); 162 163 Error readRVersionsFromFile(const FilePath& filePath, 164 std::vector<r_util::RVersion>* pVersions); 165 166 Error validatedReadRVersionsFromFile(const FilePath& filePath, 167 std::vector<r_util::RVersion>* pVersions); 168 169 } // namespace r_util 170 } // namespace core 171 } // namespace rstudio 172 173 #endif // CORE_R_UTIL_R_VERSIONS_HPP 174 175