<commit_before>/*
 * SessionBuild.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionBuild.hpp"

#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/format.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <core/Exec.hpp>
#include <core/system/Process.hpp>
#include <core/system/ShellUtils.hpp>

#include <session/projects/SessionProjects.hpp>
#include <session/SessionModuleContext.hpp>

using namespace core;

namespace session {
namespace modules { 
namespace build {

namespace {

class Build : boost::noncopyable,
              public boost::enable_shared_from_this<Build>
{
public:
   static boost::shared_ptr<Build> create(const std::string& type)
   {
      boost::shared_ptr<Build> pBuild(new Build());
      pBuild->start(type);
      return pBuild;
   }

private:
   Build()
      : isRunning_(false), terminationRequested_(false)
   {
   }

   void start(const std::string& type)
   {
      ClientEvent event(client_events::kBuildStatus, "started");
      module_context::enqueClientEvent(event);

      isRunning_ = true;

      // read build options
      Error error = projects::projectContext().readBuildOptions(&options_);
      if (error)
      {
         terminateWithError("reading build options file", error);
         return;
      }

      // callbacks
      core::system::ProcessCallbacks cb;
      cb.onContinue = boost::bind(&Build::onContinue,
                                  Build::shared_from_this());
      cb.onStdout = boost::bind(&Build::onOutput,
                                Build::shared_from_this(), _2);
      cb.onStderr = boost::bind(&Build::onOutput,
                                Build::shared_from_this(), _2);
      cb.onExit =  boost::bind(&Build::onCompleted,
                                Build::shared_from_this(),
                                _1);

      // execute build
      executeBuild(type, cb);
   }


   void executeBuild(const std::string& type,
                     const core::system::ProcessCallbacks& cb)
   {
      // options
      core::system::ProcessOptions options;
      options.terminateChildren = true;
      options.redirectStdErrToStdOut = true;

      const core::r_util::RProjectConfig& config =
                                          projects::projectContext().config();
      if (config.buildType == r_util::kBuildTypePackage)
      {
         FilePath packagePath = projectPath(config.packagePath);
         options.workingDir = packagePath.parent();
         executePackageBuild(type, packagePath, options, cb);
      }
      else if (config.buildType == r_util::kBuildTypeMakefile)
      {
         FilePath makefilePath = projectPath(config.makefilePath);
         options.workingDir = makefilePath;
         executeMakefileBuild(type, options, cb);
      }
      else if (config.buildType == r_util::kBuildTypeCustom)
      {
         FilePath scriptPath = projectPath(config.customScriptPath);
         options.workingDir = scriptPath.parent();
         executeCustomBuild(type, scriptPath, options, cb);
      }
      else
      {
         terminateWithError("Unrecognized build type: " + config.buildType);
      }
   }

   void executePackageBuild(const std::string& type,
                            const FilePath& packagePath,
                            const core::system::ProcessOptions& options,
                            const core::system::ProcessCallbacks& cb)
   {
      // R bin directory
      FilePath rBinDir;
      Error error = module_context::rBinDir(&rBinDir);
      if (error)
      {
         terminateWithError("attempting to locate R binary", error);
         return;
      }

      // R binary and intial args
      FilePath rProgram;
      std::vector<std::string> args;
  #ifdef _WIN32
      rProgram = rBinDir.childPath("Rcmd.exe");
  #else
      rProgram = rBinDir.childPath("R");
      args.push_back("CMD");
#endif

      if (type == "build-all")
      {
         args.push_back("INSTALL");
      }
      else if (type == "check-package")
      {
         args.push_back("check");
      }
      args.push_back(packagePath.filename());

      // run process
      module_context::processSupervisor().runProgram(rProgram.absolutePath(),
                                                     args,
                                                     options,
                                                     cb);
   }
<commit_msg>use ShellCommand for invoking pkg build<commit_after>/*
 * SessionBuild.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionBuild.hpp"

#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/format.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <core/Exec.hpp>
#include <core/system/Process.hpp>
#include <core/system/ShellUtils.hpp>

#include <session/projects/SessionProjects.hpp>
#include <session/SessionModuleContext.hpp>

using namespace core;

namespace session {
namespace modules { 
namespace build {

namespace {

class Build : boost::noncopyable,
              public boost::enable_shared_from_this<Build>
{
public:
   static boost::shared_ptr<Build> create(const std::string& type)
   {
      boost::shared_ptr<Build> pBuild(new Build());
      pBuild->start(type);
      return pBuild;
   }

private:
   Build()
      : isRunning_(false), terminationRequested_(false)
   {
   }

   void start(const std::string& type)
   {
      ClientEvent event(client_events::kBuildStatus, "started");
      module_context::enqueClientEvent(event);

      isRunning_ = true;

      // read build options
      Error error = projects::projectContext().readBuildOptions(&options_);
      if (error)
      {
         terminateWithError("reading build options file", error);
         return;
      }

      // callbacks
      core::system::ProcessCallbacks cb;
      cb.onContinue = boost::bind(&Build::onContinue,
                                  Build::shared_from_this());
      cb.onStdout = boost::bind(&Build::onOutput,
                                Build::shared_from_this(), _2);
      cb.onStderr = boost::bind(&Build::onOutput,
                                Build::shared_from_this(), _2);
      cb.onExit =  boost::bind(&Build::onCompleted,
                                Build::shared_from_this(),
                                _1);

      // execute build
      executeBuild(type, cb);
   }


   void executeBuild(const std::string& type,
                     const core::system::ProcessCallbacks& cb)
   {
      // options
      core::system::ProcessOptions options;
      options.terminateChildren = true;
      options.redirectStdErrToStdOut = true;

      const core::r_util::RProjectConfig& config =
                                          projects::projectContext().config();
      if (config.buildType == r_util::kBuildTypePackage)
      {
         FilePath packagePath = projectPath(config.packagePath);
         options.workingDir = packagePath.parent();
         executePackageBuild(type, packagePath, options, cb);
      }
      else if (config.buildType == r_util::kBuildTypeMakefile)
      {
         FilePath makefilePath = projectPath(config.makefilePath);
         options.workingDir = makefilePath;
         executeMakefileBuild(type, options, cb);
      }
      else if (config.buildType == r_util::kBuildTypeCustom)
      {
         FilePath scriptPath = projectPath(config.customScriptPath);
         options.workingDir = scriptPath.parent();
         executeCustomBuild(type, scriptPath, options, cb);
      }
      else
      {
         terminateWithError("Unrecognized build type: " + config.buildType);
      }
   }

   void executePackageBuild(const std::string& type,
                            const FilePath& packagePath,
                            const core::system::ProcessOptions& options,
                            const core::system::ProcessCallbacks& cb)
   {
      // R bin directory
      FilePath rBinDir;
      Error error = module_context::rBinDir(&rBinDir);
      if (error)
      {
         terminateWithError("attempting to locate R binary", error);
         return;
      }

      // base command

#ifdef _WIN32
      shell_utils::ShellCommand rCmd(rBinDir.childPath("Rcmd.exe"));
#else
      shell_utils::ShellCommand rCmd(rBinDir.childPath("R"));
      rCmd << "CMD";
#endif

      if (type == "build-all")
      {
         rCmd << "INSTALL";
         rCmd << packagePath.filename();
      }
      else if (type == "check-package")
      {
         rCmd << "check";
         rCmd << packagePath.filename();
      }

      // run command
      module_context::processSupervisor().runCommand(rCmd, options, cb);
   }

{'fraction_non_alphanumeric': 0.11008197593952944, 'fraction_numerical': 0.002980943255615884, 'mean_word_length': 2.3112442721184348, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4879289', 'n_tokens_mistral': 2624, 'n_tokens_neox': 2536, 'n_words': 559}