예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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();
}
예제 #5
0
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();
}
예제 #6
0
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);
   }
}
예제 #7
0
 explicit ActiveSessions(const FilePath& rootStoragePath)
 {
    storagePath_ = rootStoragePath.childPath("session-storage");
    Error error = storagePath_.ensureDirectory();
    if (error)
       LOG_ERROR(error);
 }
예제 #8
0
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();
   }
}
예제 #9
0
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;
}
예제 #10
0
// 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() ;
}
예제 #11
0
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_, "");
   }
}
예제 #12
0
FileLogWriter::FileLogWriter(const std::string& programIdentity,
                             int logLevel,
                             const FilePath& logDir)
                                : programIdentity_(programIdentity),
                                  logLevel_(logLevel)
{
   logDir.ensureDirectory();

   logFile_ = logDir.childPath(programIdentity + ".log");
}
예제 #13
0
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));
}
예제 #14
0
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;
}
예제 #15
0
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);
}
예제 #16
0
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);
}
예제 #17
0
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 "";
   }
}
예제 #18
0
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;
   }
}
예제 #19
0
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;
}
예제 #20
0
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);
   }
}
예제 #21
0
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();
      }
   }
}
예제 #22
0
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);   
}
예제 #23
0
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();
}