FilePath getProjectUserDataDir(const ErrorLocation& location) { // get the project directory FilePath projectDir = projects::projectContext().directory(); // presume that the project dir is the data dir then check // for a .Ruserdata directory as an alternative FilePath dataDir = projectDir; FilePath ruserdataDir = projectDir.childPath(".Ruserdata"); if (ruserdataDir.exists()) { // create user-specific subdirectory if necessary FilePath userDir = ruserdataDir.childPath(core::system::username()); Error error = userDir.ensureDirectory(); if (!error) { dataDir = userDir; } else { core::log::logError(error, location); } } // return the data dir return dataDir; }
std::string detectBuildType(const FilePath& projectFilePath, const RProjectBuildDefaults& buildDefaults, RProjectConfig* pConfig) { FilePath projectDir = projectFilePath.parent(); if (r_util::isPackageDirectory(projectDir)) { setBuildPackageDefaults("", buildDefaults ,pConfig); } else if (projectDir.childPath("pkg/DESCRIPTION").exists()) { setBuildPackageDefaults("pkg", buildDefaults, pConfig); } else if (projectDir.childPath("Makefile").exists()) { pConfig->buildType = kBuildTypeMakefile; pConfig->makefilePath = ""; } else if (isWebsiteDirectory(projectDir)) { pConfig->buildType = kBuildTypeWebsite; pConfig->websitePath = ""; } else { pConfig->buildType = kBuildTypeNone; } return pConfig->buildType; }
bool RVersionsScanner::detectSystemRVersion(core::r_util::RVersion* pVersion, std::string* pErrMsg) { // return cached version if we have it if (!systemVersion_.empty()) { *pVersion = systemVersion_; return true; } // check for which R override FilePath rWhichRPath; if (!whichROverride_.empty()) rWhichRPath = FilePath(whichROverride_); // if it's a directory then see if we can find the script if (rWhichRPath.isDirectory()) { FilePath rScriptPath = rWhichRPath.childPath("bin/R"); if (rScriptPath.exists()) rWhichRPath = rScriptPath; } // attempt to detect R version bool result = detectRVersion(rWhichRPath, pVersion, pErrMsg); // if we detected it then cache it if (result) systemVersion_ = *pVersion; // return result return result; }
Error RPackageInfo::read(const FilePath& packageDir) { // parse DCF file FilePath descFilePath = packageDir.childPath("DESCRIPTION"); if (!descFilePath.exists()) return core::fileNotFoundError(descFilePath, ERROR_LOCATION); std::string errMsg; std::map<std::string,std::string> fields; Error error = text::parseDcfFile(descFilePath, true, &fields, &errMsg); if (error) return error; // Package field std::map<std::string,std::string>::const_iterator it; it = fields.find("Package"); if (it != fields.end()) name_ = it->second; else return fieldNotFoundError(descFilePath, "Package", ERROR_LOCATION); // Version field it = fields.find("Version"); if (it != fields.end()) version_ = it->second; else return fieldNotFoundError(descFilePath, "Version", ERROR_LOCATION); // Linking to field it = fields.find("LinkingTo"); if (it != fields.end()) linkingTo_ = it->second; return Success(); }
Error RPackageInfo::read(const FilePath& packageDir) { // parse DCF file FilePath descFilePath = packageDir.childPath("DESCRIPTION"); if (!descFilePath.exists()) return core::fileNotFoundError(descFilePath, ERROR_LOCATION); std::string errMsg; std::map<std::string,std::string> fields; Error error = text::parseDcfFile(descFilePath, true, &fields, &errMsg); if (error) return error; error = readField(fields, "Package", &name_, descFilePath, ERROR_LOCATION); if (error) return error; error = readField(fields, "Version", &version_, descFilePath, ERROR_LOCATION); if (error) return error; readField(fields, "Depends", &depends_); readField(fields, "Imports", &imports_); readField(fields, "Suggests", &suggests_); readField(fields, "LinkingTo", &linkingTo_); readField(fields, "SystemRequirements", &systemRequirements_); readField(fields, "Type", &type_, kPackageType); return Success(); }
void handleHelpHomeRequest(const core::http::Request& request, const std::string& jsCallbacks, core::http::Response* pResponse) { // get the resource path FilePath helpResPath = options().rResourcesPath().complete("help_resources"); // resolve the file reference std::string path = http::util::pathAfterPrefix(request, "/help/doc/home/"); // if it's empty then this is the root template if (path.empty()) { std::map<std::string,std::string> variables; variables["js_callbacks"] = jsCallbacks; text::TemplateFilter templateFilter(variables); pResponse->setNoCacheHeaders(); pResponse->setFile(helpResPath.childPath("index.htm"), request, templateFilter); } // otherwise it's just a file reference else { FilePath filePath = helpResPath.complete(path); pResponse->setCacheableFile(filePath, request); } }
explicit ActiveSessions(const FilePath& rootStoragePath) { storagePath_ = rootStoragePath.childPath("session-storage"); Error error = storagePath_.ensureDirectory(); if (error) LOG_ERROR(error); }
FilePath projectFromDirectory(const FilePath& directoryPath) { // first use simple heuristic of a case sentitive match between // directory name and project file name FilePath projectFile = directoryPath.childPath( directoryPath.filename() + ".Rproj"); if (projectFile.exists()) return projectFile; // didn't satisfy it with simple check so do scan of directory std::vector<FilePath> children; Error error = directoryPath.children(&children); if (error) { LOG_ERROR(error); return FilePath(); } // build a vector of children with .rproj extensions. at the same // time allow for a case insensitive match with dir name and return that std::string projFileLower = string_utils::toLower(projectFile.filename()); std::vector<FilePath> rprojFiles; for (std::vector<FilePath>::const_iterator it = children.begin(); it != children.end(); ++it) { if (!it->isDirectory() && (it->extensionLowerCase() == ".rproj")) { if (string_utils::toLower(it->filename()) == projFileLower) return *it; else rprojFiles.push_back(*it); } } // if we found only one rproj file then return it if (rprojFiles.size() == 1) { return rprojFiles.at(0); } // more than one, take most recent else if (rprojFiles.size() > 1 ) { projectFile = rprojFiles.at(0); for (std::vector<FilePath>::const_iterator it = rprojFiles.begin(); it != rprojFiles.end(); ++it) { if (it->lastWriteTime() > projectFile.lastWriteTime()) projectFile = *it; } return projectFile; } // didn't find one else { return FilePath(); } }
std::vector<std::string> collectFirstRunDocs(const FilePath& projectFile) { // docs to return std::vector<std::string> docs; // get the scratch path FilePath scratchPath; Error error = computeScratchPaths(projectFile, &scratchPath, nullptr); if (error) { LOG_ERROR(error); return docs; } // check for first run file FilePath firstRunDocsPath = scratchPath.childPath(kFirstRunDocs); if (firstRunDocsPath.exists()) { Error error = core::readStringVectorFromFile(firstRunDocsPath, &docs); if (error) LOG_ERROR(error); // remove since this is a one-time only thing firstRunDocsPath.remove(); } return docs; }
// IN: Array<String> paths, String targetPath Error moveFiles(const ::core::json::JsonRpcRequest& request, json::JsonRpcResponse* pResponse) { json::Array files; std::string targetPath; Error error = json::readParams(request.params, &files, &targetPath); if (error) return error ; // extract vector of FilePath std::vector<FilePath> filePaths ; Error extractError = extractFilePaths(files, &filePaths) ; if (extractError) return extractError ; // create FilePath for target directory FilePath targetDirPath = module_context::resolveAliasedPath(targetPath); if (!targetDirPath.isDirectory()) return Error(json::errc::ParamInvalid, ERROR_LOCATION); // move the files for (std::vector<FilePath>::const_iterator it = filePaths.begin(); it != filePaths.end(); ++it) { // move the file FilePath targetPath = targetDirPath.childPath(it->filename()) ; Error moveError = it->move(targetPath) ; if (moveError) return moveError ; } return Success() ; }
FileLogWriter::FileLogWriter(const std::string& programIdentity, int logLevel, const FilePath& logDir) : programIdentity_(programIdentity), logLevel_(logLevel) { logDir.ensureDirectory(); logFile_ = logDir.childPath(programIdentity + ".log"); rotatedLogFile_ = logDir.childPath(programIdentity + ".rotated.log"); if (!logFile_.exists()) { // swallow errors -- we can't log so it doesn't matter core::appendToFile(logFile_, ""); } }
FileLogWriter::FileLogWriter(const std::string& programIdentity, int logLevel, const FilePath& logDir) : programIdentity_(programIdentity), logLevel_(logLevel) { logDir.ensureDirectory(); logFile_ = logDir.childPath(programIdentity + ".log"); }
FilePath uniqueFilePath(const FilePath& parent, const std::string& prefix) { // try up to 100 times then fallback to a uuid for (int i=0; i<100; i++) { // get a shortened uuid std::string shortentedUuid = core::system::generateShortenedUuid(); // form full path FilePath uniqueDir = parent.childPath(prefix + shortentedUuid); // return if it doesn't exist if (!uniqueDir.exists()) return uniqueDir; } // if we didn't succeed then return prefix + uuid return parent.childPath(prefix + core::system::generateUuid(false)); }
FilePath userSettingsPath(const FilePath& userHomeDirectory, const std::string& appName) { std::string lower = appName; boost::to_lower(lower); FilePath path = userHomeDirectory.childPath("." + lower); Error error = path.ensureDirectory(); if (error) { LOG_ERROR(error); } return path; }
Error PersistentState::initialize() { serverMode_ = (session::options().programMode() == kSessionProgramModeServer); // always the same so that we can supporrt a restart of // the session without reloading the client page desktopClientId_ = "33e600bb-c1b1-46bf-b562-ab5cba070b0e"; FilePath scratchPath = module_context::scopedScratchPath(); activeClientIdPath_ = scratchPath.childPath(kActiveClientId); FilePath statePath = scratchPath.complete("persistent-state"); return settings_.initialize(statePath); }
void addFirstRunDoc(const FilePath& projectFile, const std::string& doc) { FilePath scratchPath; Error error = computeScratchPaths(projectFile, &scratchPath, nullptr); if (error) { LOG_ERROR(error); return; } std::ostringstream ostr; ostr << doc << std::endl; error = core::appendToFile(scratchPath.childPath(kFirstRunDocs), ostr.str()); if (error) LOG_ERROR(error); }
std::string packageNameFromDirectory(const FilePath& dir) { if (dir.childPath("DESCRIPTION").exists()) { RPackageInfo pkgInfo; Error error = pkgInfo.read(dir); if (error) { LOG_ERROR(error); return ""; } return pkgInfo.name(); } else { return ""; } }
bool isPackageDirectory(const FilePath& dir) { if (dir.childPath("DESCRIPTION").exists()) { RPackageInfo pkgInfo; Error error = pkgInfo.read(dir); if (error) { LOG_ERROR(error); return false; } return pkgInfo.type() == kPackageType; } else { return false; } }
FilePath viewInBrowserPath() { if (s_presentationState.viewInBrowserPath.empty()) { FilePath viewDir = module_context::tempFile("view", "dir"); Error error = viewDir.ensureDirectory(); if (!error) { s_presentationState.viewInBrowserPath = viewDir.childPath("presentation.html"); } else { LOG_ERROR(error); } } return s_presentationState.viewInBrowserPath; }
Error createRdShell(const json::JsonRpcRequest& request, json::JsonRpcResponse* pResponse) { std::string name, type; Error error = json::readParams(request.params, &name, &type); if (error) return error; // suppress output so that R doesn't write the Rd message to the console r::session::utils::SuppressOutputInScope suppressOutputScope; // if we are within a package development environment then use that // as the basis for the new document if (projects::projectContext().config().buildType == r_util::kBuildTypePackage) { // read package info FilePath packageDir = projects::projectContext().buildTargetPath(); r_util::RPackageInfo pkgInfo; Error error = pkgInfo.read(packageDir); if (error) { LOG_ERROR(error); return defaultRdResponse(name, type, pResponse); } // lookup the object in the package first std::string filePath; error = r::exec::RFunction(".rs.createShellRd", name, type, pkgInfo.name()).call(&filePath); if (error) return error; // if it was found then read it if (!filePath.empty()) { FilePath rdFilePath(string_utils::systemToUtf8(filePath)); FilePath manFilePath = packageDir.childPath("man").childPath( rdFilePath.filename()); if (!manFilePath.exists()) { Error error = rdFilePath.copy(manFilePath); if (error) return error; json::Object resultJson; resultJson["path"] = module_context::createAliasedPath(manFilePath); resultJson["contents"] = json::Value(); pResponse->setResult(resultJson); } else { std::string contents; error = core::readStringFromFile(rdFilePath, &contents, string_utils::LineEndingPosix); if (error) return error; json::Object resultJson; resultJson["path"] = json::Value(); resultJson["contents"] = contents; pResponse->setResult(resultJson); } return Success(); } else { return defaultRdResponse(name, type, pResponse); } } else { return defaultRdResponse(name, type, pResponse); } }
Error createProject(const json::JsonRpcRequest& request, json::JsonRpcResponse* pResponse) { // read params std::string projectFile; json::Value newPackageJson; json::Value newShinyAppJson; Error error = json::readParams(request.params, &projectFile, &newPackageJson, &newShinyAppJson); if (error) return error; FilePath projectFilePath = module_context::resolveAliasedPath(projectFile); if (!newShinyAppJson.is_null()) { // error if the shiny app dir already exists FilePath appDir = projectFilePath.parent(); if (appDir.exists()) return core::fileExistsError(ERROR_LOCATION); // now create it Error error = appDir.ensureDirectory(); if (error) return error; // copy ui.R and server.R into the project const char * const kUI = "ui.R"; const char * const kServer = "server.R"; std::string shinyVer; if (module_context::isPackageVersionInstalled("shiny", "0.9")) shinyVer = "shiny-0.9"; else shinyVer = "shiny"; FilePath shinyDir = session::options().rResourcesPath().childPath( "templates/" + shinyVer); error = shinyDir.childPath(kUI).copy(appDir.childPath(kUI)); if (error) LOG_ERROR(error); error = shinyDir.childPath(kServer).copy(appDir.childPath(kServer)); if (error) LOG_ERROR(error); // add first run actions for the source files addFirstRunDoc(projectFilePath, kUI); addFirstRunDoc(projectFilePath, kServer); // create the project file return r_util::writeProjectFile(projectFilePath, ProjectContext::buildDefaults(), ProjectContext::defaultConfig()); } // default project else { // create the project directory if necessary error = projectFilePath.parent().ensureDirectory(); if (error) return error; // create the project file if (!projectFilePath.exists()) { return r_util::writeProjectFile(projectFilePath, ProjectContext::buildDefaults(), ProjectContext::defaultConfig()); } else { return Success(); } } }
void handleFileUploadRequest(const http::Request& request, http::Response* pResponse) { // response content type must always be text/html to be handled // properly by the browser/gwt on the client side pResponse->setContentType("text/html"); // get fields const http::File& file = request.uploadedFile("file"); std::string targetDirectory = request.formFieldValue("targetDirectory"); // first validate that we got the required fields if (file.name.empty() || targetDirectory.empty()) { json::setJsonRpcError(json::errc::ParamInvalid, pResponse); return; } // now validate the file if ( !validateUploadedFile(file, pResponse) ) return ; // form destination path FilePath destDir = module_context::resolveAliasedPath(targetDirectory); FilePath destPath = destDir.childPath(file.name); // establish whether this is a zip file and create appropriate temp file path bool isZip = destPath.extensionLowerCase() == ".zip"; FilePath tempFilePath = module_context::tempFile("upload", isZip ? "zip" : "bin"); // attempt to write the temp file Error saveError = core::writeStringToFile(tempFilePath, file.contents); if (saveError) { LOG_ERROR(saveError); json::setJsonRpcError(saveError, pResponse); return; } // detect any potential overwrites json::Array overwritesJson; if (isZip) { Error error = detectZipFileOverwrites(tempFilePath, destDir, &overwritesJson); if (error) { LOG_ERROR(error); json::setJsonRpcError(error, pResponse); return; } } else { if (destPath.exists()) overwritesJson.push_back(module_context::createFileSystemItem(destPath)); } // set the upload information as the result json::Object uploadTokenJson; uploadTokenJson[kUploadFilename] = file.name; uploadTokenJson[kUploadedTempFile] = tempFilePath.absolutePath(); uploadTokenJson[kUploadTargetDirectory] = destDir.absolutePath(); json::Object uploadJson; uploadJson["token"] = uploadTokenJson; uploadJson["overwrites"] = overwritesJson; json::setJsonRpcResult(uploadJson, pResponse); }
Error getRPrefs(const json::JsonRpcRequest& request, json::JsonRpcResponse* pResponse) { // get general prefs json::Object generalPrefs; generalPrefs["save_action"] = userSettings().saveAction(); generalPrefs["load_rdata"] = userSettings().loadRData(); generalPrefs["rprofile_on_resume"] = userSettings().rProfileOnResume(); generalPrefs["initial_working_dir"] = module_context::createAliasedPath( userSettings().initialWorkingDirectory()); // get history prefs json::Object historyPrefs; historyPrefs["always_save"] = userSettings().alwaysSaveHistory(); historyPrefs["remove_duplicates"] = userSettings().removeHistoryDuplicates(); // get packages prefs json::Object packagesPrefs; packagesPrefs["use_devtools"] = userSettings().useDevtools(); packagesPrefs["cran_mirror"] = toCRANMirrorJson( userSettings().cranMirror()); packagesPrefs["use_internet2"] = userSettings().useInternet2(); packagesPrefs["bioconductor_mirror"] = toBioconductorMirrorJson( userSettings().bioconductorMirror()); packagesPrefs["cleanup_after_check_success"] = userSettings().cleanupAfterRCmdCheck(); packagesPrefs["viewdir_after_check_failure"] = userSettings().viewDirAfterRCmdCheck(); packagesPrefs["hide_object_files"] = userSettings().hideObjectFiles(); // get projects prefs json::Object projectsPrefs; projectsPrefs["restore_last_project"] = userSettings().alwaysRestoreLastProject(); // get source control prefs json::Object sourceControlPrefs; sourceControlPrefs["vcs_enabled"] = userSettings().vcsEnabled(); FilePath gitExePath = userSettings().gitExePath(); if (gitExePath.empty()) gitExePath = git::detectedGitExePath(); sourceControlPrefs["git_exe_path"] = gitExePath.absolutePath(); FilePath svnExePath = userSettings().svnExePath(); if (svnExePath.empty()) svnExePath = svn::detectedSvnExePath(); sourceControlPrefs["svn_exe_path"] = svnExePath.absolutePath(); FilePath terminalPath = userSettings().vcsTerminalPath(); if (terminalPath.empty()) terminalPath = detectedTerminalPath(); sourceControlPrefs["terminal_path"] = terminalPath.absolutePath(); sourceControlPrefs["use_git_bash"] = userSettings().vcsUseGitBash(); FilePath sshKeyDir = modules::source_control::defaultSshKeyDir(); FilePath rsaSshKeyPath = sshKeyDir.childPath("id_rsa"); sourceControlPrefs["rsa_key_path"] = module_context::createAliasedPath(rsaSshKeyPath); sourceControlPrefs["have_rsa_key"] = rsaSshKeyPath.exists(); // get compile pdf prefs json::Object compilePdfPrefs; compilePdfPrefs["clean_output"] = userSettings().cleanTexi2DviOutput(); compilePdfPrefs["enable_shell_escape"] = userSettings().enableLaTeXShellEscape(); // initialize and set result object json::Object result; result["general_prefs"] = generalPrefs; result["history_prefs"] = historyPrefs; result["packages_prefs"] = packagesPrefs; result["projects_prefs"] = projectsPrefs; result["source_control_prefs"] = sourceControlPrefs; result["compile_pdf_prefs"] = compilePdfPrefs; result["spelling_prefs_context"] = session::modules::spelling::spellingPrefsContextAsJson(); pResponse->setResult(result); return Success(); }