Exemplo n.º 1
0
 public function lintPath($path)
 {
     $working_copy = $this->getEngine()->getWorkingCopy();
     $pyflakes_path = $working_copy->getConfig('lint.pyflakes.path');
     $pyflakes_prefix = $working_copy->getConfig('lint.pyflakes.prefix');
     // Default to just finding pyflakes in the users path
     $pyflakes_bin = 'pyflakes';
     $python_path = '';
     // If a pyflakes path was specified, then just use that as the
     // pyflakes binary and assume that the libraries will be imported
     // correctly.
     //
     // If no pyflakes path was specified and a pyflakes prefix was
     // specified, then use the binary from this prefix and add it to
     // the PYTHONPATH environment variable so that the libs are imported
     // correctly.  This is useful when pyflakes is installed into a
     // non-default location.
     if ($pyflakes_path !== null) {
         $pyflakes_bin = $pyflakes_path;
     } else {
         if ($pyflakes_prefix !== null) {
             $pyflakes_bin = $pyflakes_prefix . '/bin/pyflakes';
             $python_path = $pyflakes_prefix . '/lib/python2.6/site-packages:';
         }
     }
     $options = $this->getPyFlakesOptions();
     $f = new ExecFuture("/usr/bin/env PYTHONPATH=%s\$PYTHONPATH " . "{$pyflakes_bin} {$options}", $python_path);
     $f->write($this->getData($path));
     try {
         list($stdout, $_) = $f->resolvex();
     } catch (CommandException $e) {
         // PyFlakes will return an exit code of 1 if warnings/errors
         // are found but print nothing to stderr in this case.  Therefore,
         // if we see any output on stderr or a return code other than 1 or 0,
         // pyflakes failed.
         if ($e->getError() !== 1 || $e->getStderr() !== '') {
             throw $e;
         } else {
             $stdout = $e->getStdout();
         }
     }
     $lines = explode("\n", $stdout);
     $messages = array();
     foreach ($lines as $line) {
         $matches = null;
         if (!preg_match('/^(.*?):(\\d+): (.*)$/', $line, $matches)) {
             continue;
         }
         foreach ($matches as $key => $match) {
             $matches[$key] = trim($match);
         }
         $message = new ArcanistLintMessage();
         $message->setPath($path);
         $message->setLine($matches[2]);
         $message->setCode($this->getLinterName());
         $message->setDescription($matches[3]);
         $message->setSeverity(ArcanistLintSeverity::SEVERITY_WARNING);
         $this->addLintMessage($message);
     }
 }
Exemplo n.º 2
0
 /**
  * Returns an array of the full canonical paths to all the Maven directories
  * (directories containing pom.xml files) in the project.
  */
 private function findMavenDirectories()
 {
     if (file_exists($this->project_root . "/.git")) {
         // The fastest way to find all the pom.xml files is to let git scan
         // its index.
         $future = new ExecFuture('git ls-files \\*/pom.xml');
     } else {
         // Not a git repo. Do it the old-fashioned way.
         $future = new ExecFuture('find . -name pom.xml -print');
     }
     // TODO: This will find *all* the pom.xml files in the working copy.
     // Need to obey the optional paths argument to "arc unit" to let users
     // run just a subset of tests.
     $future->setCWD($this->project_root);
     list($stdout) = $future->resolvex();
     $poms = explode("\n", trim($stdout));
     if (!$poms) {
         throw new Exception("No pom.xml files found");
     }
     $maven_dirs = array_map(function ($pom) {
         $maven_dir = dirname($pom);
         return realpath($this->project_root . '/' . $maven_dir);
     }, $poms);
     return $maven_dirs;
 }
 private function runTests()
 {
     $root = $this->getWorkingCopy()->getProjectRoot();
     $script = $this->getConfiguredScript();
     $path = $this->getConfiguredTestResultPath();
     foreach (glob($root . DIRECTORY_SEPARATOR . $path . "/*.xml") as $filename) {
         // Remove existing files so we cannot report old results
         $this->unlink($filename);
     }
     // Provide changed paths to process
     putenv("ARCANIST_DIFF_PATHS=" . implode(PATH_SEPARATOR, $this->getPaths()));
     $future = new ExecFuture('%C %s', $script, $path);
     $future->setCWD($root);
     $err = null;
     try {
         $future->resolvex();
     } catch (CommandException $exc) {
         $err = $exc;
     }
     $results = $this->parseTestResults($root . DIRECTORY_SEPARATOR . $path);
     if ($err) {
         $result = new ArcanistUnitTestResult();
         $result->setName('Unit Test Script');
         $result->setResult(ArcanistUnitTestResult::RESULT_BROKEN);
         $result->setUserData("ERROR: Command failed with code {$err->getError()}\nCOMMAND: `{$err->getCommand()}`");
         $results[] = $result;
     }
     return $results;
 }
Exemplo n.º 4
0
 public function testMultipleResolves()
 {
     // It should be safe to call resolve(), resolvex(), resolveKill(), etc.,
     // as many times as you want on the same process.
     $future = new ExecFuture('echo quack');
     $future->resolve();
     $future->resolvex();
     list($err) = $future->resolveKill();
     $this->assertEqual(0, $err);
 }
 public function run()
 {
     $working_copy = $this->getWorkingCopy();
     $this->projectRoot = $working_copy->getProjectRoot();
     $junit_tmp = new TempFile();
     $cover_tmp = new TempFile();
     $future = $this->buildTestFuture($junit_tmp, $cover_tmp);
     $future->resolvex();
     $future = new ExecFuture('coverage xml -o %s', $cover_tmp);
     $future->setCWD($this->projectRoot);
     $future->resolvex();
     return $this->parseTestResults($junit_tmp, $cover_tmp);
 }
 public function testCloseExecWriteChannel()
 {
     $future = new ExecFuture('cat');
     // If this test breaks, we want to explode, not hang forever.
     $future->setTimeout(5);
     $exec_channel = new PhutilExecChannel($future);
     $exec_channel->write('quack');
     $exec_channel->closeWriteChannel();
     // If `closeWriteChannel()` did what it is supposed to, this will just
     // echo "quack" and exit with no error code. If the channel did not close,
     // this will time out after 5 seconds and throw.
     $future->resolvex();
     $this->assertTrue(true);
 }
 private function checkRequirements()
 {
     $working_copy = $this->getWorkingCopy();
     $project_root = $working_copy->getProjectRoot();
     $piplint_files = $this->getConfigurationManager()->getConfigFromAnySource('unit.piplint.files');
     if (empty($piplint_files)) {
         return;
     }
     $args = array('piplint');
     $args = array_merge($args, $piplint_files);
     $cmd = implode(' ', $args);
     $future = new ExecFuture($cmd);
     $future->setCWD($project_root);
     $future->resolvex();
 }
 public function willLintPaths(array $paths)
 {
     $script = $this->getConfiguredScript();
     $root = $this->getEngine()->getWorkingCopy()->getProjectRoot();
     $futures = array();
     foreach ($paths as $path) {
         $future = new ExecFuture('%C %s', $script, $path);
         $future->setCWD($root);
         $futures[$path] = $future;
     }
     foreach (Futures($futures)->limit(4) as $path => $future) {
         list($stdout) = $future->resolvex();
         $this->output[$path] = $stdout;
     }
 }
Exemplo n.º 9
0
 public function run()
 {
     $working_copy = $this->getWorkingCopy();
     $this->projectRoot = $working_copy->getProjectRoot();
     $junit_tmp = new TempFile();
     $cover_tmp = new TempFile();
     $future = $this->buildTestFuture($junit_tmp, $cover_tmp);
     list($err, $stdout, $stderr) = $future->resolve();
     if (!Filesystem::pathExists($junit_tmp)) {
         throw new CommandException(pht('Command failed with error #%s!', $err), $future->getCommand(), $err, $stdout, $stderr);
     }
     $future = new ExecFuture('coverage xml -o %s', $cover_tmp);
     $future->setCWD($this->projectRoot);
     $future->resolvex();
     return $this->parseTestResults($junit_tmp, $cover_tmp);
 }
Exemplo n.º 10
0
 public function startProjectBuilds($async, $diff_id = null)
 {
     // Push the source up to the master repo so that Jenkins
     // can pull it down and build it
     $gitcmd = "git push origin HEAD:refs/autobuilds/{$diff_id}";
     $git_future = new ExecFuture($gitcmd);
     $git_future->resolvex();
     $url = $this->getJobURI();
     // Initiate a git poll for the mysql jobs in Jenkins
     $cmd = "curl --max-time 5 -s {$url}";
     $future = new ExecFuture($cmd);
     if ($async === true) {
         echo "Launching a build on the Jenkins server...\n";
         $future->resolvex();
     }
 }
Exemplo n.º 11
0
 public static function newFromArcBundle($path)
 {
     $path = Filesystem::resolvePath($path);
     $future = new ExecFuture(csprintf('tar tfO %s', $path));
     list($stdout, $file_list) = $future->resolvex();
     $file_list = explode("\n", trim($file_list));
     if (in_array('meta.json', $file_list)) {
         $future = new ExecFuture(csprintf('tar xfO %s meta.json', $path));
         $meta_info = $future->resolveJSON();
         $version = idx($meta_info, 'version', 0);
         $project_name = idx($meta_info, 'projectName');
         $base_revision = idx($meta_info, 'baseRevision');
         $revision_id = idx($meta_info, 'revisionID');
         $encoding = idx($meta_info, 'encoding');
         // this arc bundle was probably made before we started storing meta info
     } else {
         $version = 0;
         $project_name = null;
         $base_revision = null;
         $revision_id = null;
         $encoding = null;
     }
     $future = new ExecFuture(csprintf('tar xfO %s changes.json', $path));
     $changes = $future->resolveJSON();
     foreach ($changes as $change_key => $change) {
         foreach ($change['hunks'] as $key => $hunk) {
             list($hunk_data) = execx('tar xfO %s hunks/%s', $path, $hunk['corpus']);
             $changes[$change_key]['hunks'][$key]['corpus'] = $hunk_data;
         }
     }
     foreach ($changes as $change_key => $change) {
         $changes[$change_key] = ArcanistDiffChange::newFromDictionary($change);
     }
     $obj = new ArcanistBundle();
     $obj->changes = $changes;
     $obj->diskPath = $path;
     $obj->setProjectID($project_name);
     $obj->setBaseRevision($base_revision);
     $obj->setRevisionID($revision_id);
     $obj->setEncoding($encoding);
     return $obj;
 }
 private function runTests()
 {
     $root = $this->getWorkingCopy()->getProjectRoot();
     $script = $this->getConfiguredScript();
     $path = $this->getConfiguredTestResultPath();
     foreach (glob($path . "/*.xml") as $filename) {
         // Remove existing files so we cannot report old results
         $this->unlink($filename);
     }
     $future = new ExecFuture('%C %s', $script, $path);
     $future->setCWD($root);
     try {
         $future->resolvex();
     } catch (CommandException $exc) {
         if ($exc->getError() != 0) {
             throw $exc;
         }
     }
     return $this->parseTestResults($path);
 }
Exemplo n.º 13
0
 public static function rebuildPackages($root)
 {
     $packages = JavelinSyncSpec::getPackageMap();
     $data = array();
     foreach ($packages as $package => $items) {
         $content = array();
         foreach ($items as $item) {
             if (empty($data[$item])) {
                 $data[$item] = Filesystem::readFile($root . '/src/' . $item);
             }
             $content[] = $data[$item];
         }
         $content = implode("\n\n", $content);
         echo "Writing {$package}.dev.js...\n";
         Filesystem::writeFile($root . '/pkg/' . $package . '.dev.js', $content);
         echo "Writing {$package}.min.js...\n";
         $exec = new ExecFuture($root . '/support/jsxmin/jsxmin __DEV__:0');
         $exec->write($content);
         list($stdout) = $exec->resolvex();
         Filesystem::writeFile($root . '/pkg/' . $package . '.min.js', $stdout);
     }
 }
Exemplo n.º 14
0
 public function run()
 {
     $results = array();
     $build_start = microtime(true);
     $config_manager = $this->getConfigurationManager();
     if ($this->getEnableCoverage() !== false) {
         $command = $config_manager->getConfigFromAnySource('unit.engine.tap.cover');
     } else {
         $command = $config_manager->getConfigFromAnySource('unit.engine.tap.command');
     }
     $timeout = $config_manager->getConfigFromAnySource('unit.engine.tap.timeout');
     if (!$timeout) {
         $timeout = 15;
     }
     $future = new ExecFuture('%C', $command);
     $future->setTimeout($timeout);
     $result = new ArcanistUnitTestResult();
     $result->setName($command ? $command : 'unknown');
     try {
         list($stdout, $stderr) = $future->resolvex();
         $result->setResult(ArcanistUnitTestResult::RESULT_PASS);
         if ($this->getEnableCoverage() !== false) {
             $coverage = $this->readCoverage('coverage/cobertura-coverage.xml');
             $result->setCoverage($coverage);
         }
     } catch (CommandException $exc) {
         $result->setResult(ArcanistUnitTestResult::RESULT_FAIL);
         if ($future->getWasKilledByTimeout()) {
             print "Process stdout:\n" . $exc->getStdout() . "\nProcess stderr:\n" . $exc->getStderr() . "\nExceeded timeout of {$timeout} secs.\nMake unit tests faster.";
         } else {
             $result->setUserdata($exc->getStdout() . $exc->getStderr());
         }
     }
     $result->setDuration(microtime(true) - $build_start);
     $results[] = $result;
     return $results;
 }
Exemplo n.º 15
0
 /**
  * @task internal
  */
 private function launchDaemon()
 {
     $root = dirname(phutil_get_library_root('arcanist'));
     $bin = $root . '/scripts/hgdaemon/hgdaemon_server.php';
     $proxy = new ExecFuture('%s %s --idle-limit 15 --quiet %C', $bin, $this->workingCopy, $this->skipHello ? '--skip-hello' : null);
     $proxy->resolvex();
 }
Exemplo n.º 16
0
 /**
  * If the `Build` directory exists, we assume that this is a multi-platform
  * project that requires generation of C# project files. Because we want to
  * test that the generation and subsequent build is whole, we need to
  * regenerate any projects in case the developer has added files through an
  * IDE and then forgotten to add them to the respective `.definitions` file.
  * By regenerating the projects we ensure that any missing definition entries
  * will cause the build to fail.
  *
  * @return array   Array of test results.
  */
 private function generateProjects()
 {
     // No "Build" directory; so skip generation of projects.
     if (!is_dir(Filesystem::resolvePath($this->projectRoot . '/Build'))) {
         return array();
     }
     // No "Protobuild.exe" file; so skip generation of projects.
     if (!is_file(Filesystem::resolvePath($this->projectRoot . '/Protobuild.exe'))) {
         return array();
     }
     // Work out what platform the user is building for already.
     $platform = phutil_is_windows() ? 'Windows' : 'Linux';
     $files = Filesystem::listDirectory($this->projectRoot);
     foreach ($files as $file) {
         if (strtolower(substr($file, -4)) == '.sln') {
             $parts = explode('.', $file);
             $platform = $parts[count($parts) - 2];
             break;
         }
     }
     $regenerate_start = microtime(true);
     $regenerate_future = new ExecFuture('%C Protobuild.exe --resync %s', $this->runtimeEngine, $platform);
     $regenerate_future->setCWD(Filesystem::resolvePath($this->projectRoot));
     $results = array();
     $result = new ArcanistUnitTestResult();
     $result->setName("(regenerate projects for {$platform})");
     try {
         $regenerate_future->resolvex();
         $result->setResult(ArcanistUnitTestResult::RESULT_PASS);
     } catch (CommandException $exc) {
         if ($exc->getError() > 1) {
             throw $exc;
         }
         $result->setResult(ArcanistUnitTestResult::RESULT_FAIL);
         $result->setUserdata($exc->getStdout());
     }
     $result->setDuration(microtime(true) - $regenerate_start);
     $results[] = $result;
     return $results;
 }
 private static function discoverGitBaseDirectory($root)
 {
     try {
         // NOTE: This awkward construction is to make sure things work on Windows.
         $future = new ExecFuture('git rev-parse --show-cdup');
         $future->setCWD($root);
         list($stdout) = $future->resolvex();
         return Filesystem::resolvePath(rtrim($stdout, "\n"), $root);
     } catch (CommandException $ex) {
         // This might be because the $root isn't a Git working copy, or the user
         // might not have Git installed at all so the `git` command fails. Assume
         // that users trying to work with git working copies will have a working
         // `git` binary.
         return null;
     }
 }
 protected final function launchDaemon($class, array $argv, $debug)
 {
     $daemon = $this->findDaemonClass($class);
     $console = PhutilConsole::getConsole();
     if ($debug) {
         if ($argv) {
             $console->writeOut(pht("Launching daemon \"%s\" in debug mode (not daemonized) " . "with arguments %s.\n", $daemon, csprintf('%LR', $argv)));
         } else {
             $console->writeOut(pht("Launching daemon \"%s\" in debug mode (not daemonized).\n", $daemon));
         }
     } else {
         if ($argv) {
             $console->writeOut(pht("Launching daemon \"%s\" with arguments %s.\n", $daemon, csprintf('%LR', $argv)));
         } else {
             $console->writeOut(pht("Launching daemon \"%s\".\n", $daemon));
         }
     }
     foreach ($argv as $key => $arg) {
         $argv[$key] = escapeshellarg($arg);
     }
     $flags = array();
     if ($debug || PhabricatorEnv::getEnvConfig('phd.trace')) {
         $flags[] = '--trace';
     }
     if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) {
         $flags[] = '--verbose';
     }
     if (!$debug) {
         $flags[] = '--daemonize';
     }
     if (!$debug) {
         $log_file = $this->getLogDirectory() . '/daemons.log';
         $flags[] = csprintf('--log=%s', $log_file);
     }
     $pid_dir = $this->getPIDDirectory();
     // TODO: This should be a much better user experience.
     Filesystem::assertExists($pid_dir);
     Filesystem::assertIsDirectory($pid_dir);
     Filesystem::assertWritable($pid_dir);
     $flags[] = csprintf('--phd=%s', $pid_dir);
     $command = csprintf('./phd-daemon %s %C %C', $daemon, implode(' ', $flags), implode(' ', $argv));
     $phabricator_root = dirname(phutil_get_library_root('phabricator'));
     $daemon_script_dir = $phabricator_root . '/scripts/daemon/';
     if ($debug) {
         // Don't terminate when the user sends ^C; it will be sent to the
         // subprocess which will terminate normally.
         pcntl_signal(SIGINT, array(__CLASS__, 'ignoreSignal'));
         echo "\n    phabricator/scripts/daemon/ \$ {$command}\n\n";
         phutil_passthru('(cd %s && exec %C)', $daemon_script_dir, $command);
     } else {
         $future = new ExecFuture('exec %C', $command);
         // Play games to keep 'ps' looking reasonable.
         $future->setCWD($daemon_script_dir);
         $future->resolvex();
     }
 }
 /**
  * @task pull
  */
 private function resolveUpdateFuture(PhabricatorRepository $repository, ExecFuture $future, $min_sleep)
 {
     $monogram = $repository->getMonogram();
     $this->log(pht('Resolving update for "%s".', $monogram));
     try {
         list($stdout, $stderr) = $future->resolvex();
     } catch (Exception $ex) {
         $proxy = new PhutilProxyException(pht('Error while updating the "%s" repository.', $repository->getMonogram()), $ex);
         phlog($proxy);
         return time() + $min_sleep;
     }
     if (strlen($stderr)) {
         $stderr_msg = pht('Unexpected output while updating repository "%s": %s', $monogram, $stderr);
         phlog($stderr_msg);
     }
     $smart_wait = $repository->loadUpdateInterval($min_sleep);
     $this->log(pht('Based on activity in repository "%s", considering a wait of %s ' . 'seconds before update.', $repository->getMonogram(), new PhutilNumber($smart_wait)));
     return time() + $smart_wait;
 }
Exemplo n.º 20
0
 private function parseTestResultFile($target)
 {
     $path = "bazel-testlogs/" . str_replace(":", "/", substr($target, 2)) . "/test.cache_status";
     $future = new ExecFuture("bazel-bin/kythe/go/util/tools/print_test_status %s", $path);
     $future->setCWD($this->project_root);
     return json_decode($future->resolvex()[0]);
 }
Exemplo n.º 21
0
$files = array('core/init.js', 'core/util.js', 'core/install.js', 'core/Event.js', 'core/Stratcom.js', 'lib/behavior.js', 'lib/Request.js', 'lib/Vector.js', 'lib/DOM.js', 'lib/JSON.js', 'lib/Mask.js', 'lib/Workflow.js', 'lib/URI.js', 'lib/control/typeahead/Typeahead.js', 'lib/control/typeahead/source/TypeaheadSource.js', 'lib/control/typeahead/source/TypeaheadPreloadedSource.js', 'lib/control/typeahead/source/TypeaheadOnDemandSource.js', 'lib/control/typeahead/normalizer/TypeaheadNormalizer.js', 'lib/control/tokenizer/Tokenizer.js', 'docs/Base.js');
$packages = array('init' => array('core/init.js'), 'javelin' => array('core/util.js', 'core/install.js', 'core/Event.js', 'core/Stratcom.js', 'lib/behavior.js', 'lib/Request.js', 'lib/Vector.js', 'lib/DOM.js', 'lib/JSON.js', 'lib/URI.js'), 'typeahead' => array('lib/control/typeahead/Typeahead.js', 'lib/control/typeahead/normalizer/TypeaheadNormalizer.js', 'lib/control/typeahead/source/TypeaheadSource.js', 'lib/control/typeahead/source/TypeaheadPreloadedSource.js', 'lib/control/typeahead/source/TypeaheadOnDemandSource.js', 'lib/control/tokenizer/Tokenizer.js'), 'workflow' => array('lib/Mask.js', 'lib/Workflow.js'));
$root = Filesystem::resolvePath($argv[1]) . '/html/js/javelin/';
$data = array();
foreach ($files as $file) {
    echo "Reading {$file}...\n";
    $content = Filesystem::readFile($root . $file);
    // Strip out Facebook-specific bookkeeping code.
    $content = preg_replace("@/\\*\\+([a-z]+)\\*/.*?/\\*-\\1\\*/([ ]*\n)*@s", "\n", $content);
    $data[$file] = $content;
}
$local = dirname(dirname(__FILE__));
foreach ($data as $file => $content) {
    echo "Writing {$file}...\n";
    execx('mkdir -p %s', $local . '/src/' . dirname($file));
    Filesystem::writeFile($local . '/src/' . $file, $content);
}
foreach ($packages as $package => $items) {
    $content = array();
    foreach ($items as $item) {
        $content[] = $data[$item];
    }
    $content = implode("\n\n", $content);
    echo "Writing {$package}.dev.js...\n";
    Filesystem::writeFile($local . '/pkg/' . $package . '.dev.js', $content);
    echo "Writing {$package}.min.js...\n";
    $exec = new ExecFuture($local . '/support/jsxmin/jsxmin __DEV__:0');
    $exec->write($content);
    list($stdout) = $exec->resolvex();
    Filesystem::writeFile($local . '/pkg/' . $package . '.min.js', $stdout);
}
Exemplo n.º 22
0
 public function launchDaemon($daemon, array $argv, $debug = false)
 {
     $symbols = $this->loadAvailableDaemonClasses();
     $symbols = ipull($symbols, 'name', 'name');
     if (empty($symbols[$daemon])) {
         throw new Exception("Daemon '{$daemon}' is not loaded, misspelled or abstract.");
     }
     $libphutil_root = dirname(phutil_get_library_root('phutil'));
     $launch_daemon = $libphutil_root . '/scripts/daemon/';
     foreach ($argv as $key => $arg) {
         $argv[$key] = escapeshellarg($arg);
     }
     $flags = array();
     if ($debug || PhabricatorEnv::getEnvConfig('phd.trace')) {
         $flags[] = '--trace';
     }
     if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) {
         $flags[] = '--verbose';
     }
     if (!$debug) {
         $flags[] = '--daemonize';
     }
     $bootloader = PhutilBootloader::getInstance();
     foreach ($bootloader->getAllLibraries() as $library) {
         if ($library == 'phutil') {
             // No need to load libphutil, it's necessarily loaded implicitly by the
             // daemon itself.
             continue;
         }
         $flags[] = csprintf('--load-phutil-library=%s', phutil_get_library_root($library));
     }
     $flags[] = csprintf('--conduit-uri=%s', PhabricatorEnv::getURI('/api/'));
     if (!$debug) {
         $log_file = $this->getLogDirectory() . '/daemons.log';
         $flags[] = csprintf('--log=%s', $log_file);
     }
     $pid_dir = $this->getPIDDirectory();
     // TODO: This should be a much better user experience.
     Filesystem::assertExists($pid_dir);
     Filesystem::assertIsDirectory($pid_dir);
     Filesystem::assertWritable($pid_dir);
     $flags[] = csprintf('--phd=%s', $pid_dir);
     $command = csprintf('./launch_daemon.php %s %C %C', $daemon, implode(' ', $flags), implode(' ', $argv));
     if ($debug) {
         // Don't terminate when the user sends ^C; it will be sent to the
         // subprocess which will terminate normally.
         pcntl_signal(SIGINT, array('PhabricatorDaemonControl', 'ignoreSignal'));
         echo "\n    libphutil/scripts/daemon/ \$ {$command}\n\n";
         phutil_passthru('(cd %s && exec %C)', $launch_daemon, $command);
     } else {
         $future = new ExecFuture('exec %C', $command);
         // Play games to keep 'ps' looking reasonable.
         $future->setCWD($launch_daemon);
         $future->resolvex();
     }
 }
 /**
  * Run the script on each file to be linted.
  *
  * @task lint
  */
 public function willLintPaths(array $paths)
 {
     $root = $this->getProjectRoot();
     $futures = array();
     foreach ($paths as $path) {
         $future = new ExecFuture('%C %s', $this->script, $path);
         $future->setCWD($root);
         $futures[$path] = $future;
     }
     $futures = id(new FutureIterator($futures))->limit(4);
     foreach ($futures as $path => $future) {
         list($stdout) = $future->resolvex();
         $this->output[$path] = $stdout;
     }
 }
Exemplo n.º 24
0
 /**
  * Sends mail using the $Sendmail program.
  * @param string $header The message headers
  * @param string $body The message body
  * @access protected
  * @return bool
  */
 protected function SendmailSend($header, $body)
 {
     if ($this->Sender != '') {
         $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
     } else {
         $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
     }
     if ($this->SingleTo === true) {
         foreach ($this->SingleToArray as $key => $val) {
             $mail = new ExecFuture('%C', $sendmail);
             $mail->write("To: {$val}\n", true);
             $mail->write($header . $body);
             $mail->resolvex();
         }
     } else {
         $mail = new ExecFuture('%C', $sendmail);
         $mail->write($header . $body);
         $mail->resolvex();
     }
     return true;
 }
Exemplo n.º 25
0
 private static function discoverGitBaseDirectory($root)
 {
     try {
         // NOTE: This awkward construction is to make sure things work on Windows.
         $future = new ExecFuture('git rev-parse --show-cdup');
         $future->setCWD($root);
         list($stdout) = $future->resolvex();
         return Filesystem::resolvePath(rtrim($stdout, "\n"), $root);
     } catch (CommandException $ex) {
         if (preg_match('/^fatal: Not a git repository/', $ex->getStdErr())) {
             return null;
         }
         throw $ex;
     }
 }
 /**
  * @task pull
  */
 private function resolveUpdateFuture(PhabricatorRepository $repository, ExecFuture $future, $min_sleep)
 {
     $monogram = $repository->getMonogram();
     $this->log(pht('Resolving update for "%s".', $monogram));
     try {
         list($stdout, $stderr) = $future->resolvex();
     } catch (Exception $ex) {
         $proxy = new PhutilProxyException(pht('Error while updating the "%s" repository.', $repository->getMonogram()), $ex);
         phlog($proxy);
         return time() + $min_sleep;
     }
     if (strlen($stderr)) {
         $stderr_msg = pht('Unexpected output while updating repository "%s": %s', $monogram, $stderr);
         phlog($stderr_msg);
     }
     // For now, continue respecting this deprecated setting for raising the
     // minimum pull frequency.
     // TODO: Remove this some day once this code has been completely stable
     // for a while.
     $sleep_for = (int) $repository->getDetail('pull-frequency');
     $min_sleep = max($sleep_for, $min_sleep);
     $smart_wait = $repository->loadUpdateInterval($min_sleep);
     $this->log(pht('Based on activity in repository "%s", considering a wait of %s ' . 'seconds before update.', $repository->getMonogram(), new PhutilNumber($smart_wait)));
     return time() + $smart_wait;
 }
 private function executeDaemonLaunchCommand($command, $daemon_script_dir, array $config, $run_as_user = null)
 {
     $is_sudo = false;
     if ($run_as_user) {
         // If anything else besides sudo should be
         // supported then insert it here (runuser, su, ...)
         $command = csprintf('sudo -En -u %s -- %C', $run_as_user, $command);
         $is_sudo = true;
     }
     $future = new ExecFuture('exec %C', $command);
     // Play games to keep 'ps' looking reasonable.
     $future->setCWD($daemon_script_dir);
     $future->write(json_encode($config));
     list($stdout, $stderr) = $future->resolvex();
     if ($is_sudo) {
         // On OSX, `sudo -n` exits 0 when the user does not have permission to
         // switch accounts without a password. This is not consistent with
         // sudo on Linux, and seems buggy/broken. Check for this by string
         // matching the output.
         if (preg_match('/sudo: a password is required/', $stderr)) {
             throw new Exception(pht('sudo exited with a zero exit code, but emitted output ' . 'consistent with failure under OSX.'));
         }
     }
 }
Exemplo n.º 28
0
 /**
  * Determine the make variables, by calling 'make printvars' in the
  * build directory.
  *
  * @param   buildDir      The determined build directory
  * @return  map<str,str>  Map of printed make variables to values
  */
 public static function getMakeVars($buildDir)
 {
     $litFuture = new ExecFuture('make -C %s printvars', $buildDir);
     list($stdout, $stderr) = $litFuture->resolvex(10);
     print $stderr;
     $makeVars = array();
     foreach (explode("\n", $stdout) as $line) {
         $components = explode(':', $line);
         if (count($components) == 3) {
             $makeVars[trim($components[1])] = trim($components[2]);
         }
     }
     return $makeVars;
 }
 public function loadChangesetsForCommit($identifier)
 {
     $byte_limit = HeraldCommitAdapter::getEnormousByteLimit();
     $time_limit = HeraldCommitAdapter::getEnormousTimeLimit();
     $vcs = $this->getRepository()->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             // For git and hg, we can use normal commands.
             $drequest = DiffusionRequest::newFromDictionary(array('repository' => $this->getRepository(), 'user' => $this->getViewer(), 'commit' => $identifier));
             $raw_diff = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)->setTimeout($time_limit)->setByteLimit($byte_limit)->setLinesOfContext(0)->loadRawDiff();
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             // TODO: This diff has 3 lines of context, which produces slightly
             // incorrect "added file content" and "removed file content" results.
             // This may also choke on binaries, but "svnlook diff" does not support
             // the "--diff-cmd" flag.
             // For subversion, we need to use `svnlook`.
             $future = new ExecFuture('svnlook diff -t %s %s', $this->subversionTransaction, $this->subversionRepository);
             $future->setTimeout($time_limit);
             $future->setStdoutSizeLimit($byte_limit);
             $future->setStderrSizeLimit($byte_limit);
             list($raw_diff) = $future->resolvex();
             break;
         default:
             throw new Exception(pht("Unknown VCS '%s!'", $vcs));
     }
     if (strlen($raw_diff) >= $byte_limit) {
         throw new Exception(pht('The raw text of this change is enormous (larger than %d ' . 'bytes). Herald can not process it.', $byte_limit));
     }
     if (!strlen($raw_diff)) {
         // If the commit is actually empty, just return no changesets.
         return array();
     }
     $parser = new ArcanistDiffParser();
     $changes = $parser->parseDiff($raw_diff);
     $diff = DifferentialDiff::newEphemeralFromRawChanges($changes);
     return $diff->getChangesets();
 }
 public function launchDaemon($daemon, array $argv, $debug = false)
 {
     $symbols = $this->loadAvailableDaemonClasses();
     $symbols = ipull($symbols, 'name', 'name');
     if (empty($symbols[$daemon])) {
         throw new Exception("Daemon '{$daemon}' is not known.");
     }
     $pid_dir = $this->getControlDirectory('pid');
     $log_dir = $this->getControlDirectory('log') . '/daemons.log';
     $libphutil_root = dirname(phutil_get_library_root('phutil'));
     $launch_daemon = $libphutil_root . '/scripts/daemon/';
     // TODO: This should be a much better user experience.
     Filesystem::assertExists($pid_dir);
     Filesystem::assertIsDirectory($pid_dir);
     Filesystem::assertWritable($pid_dir);
     foreach ($argv as $key => $arg) {
         $argv[$key] = escapeshellarg($arg);
     }
     $bootloader = PhutilBootloader::getInstance();
     $all_libraries = $bootloader->getAllLibraries();
     $non_default_libraries = array_diff($all_libraries, array('phutil', 'phabricator'));
     $extra_libraries = array();
     foreach ($non_default_libraries as $library) {
         $extra_libraries[] = csprintf('--load-phutil-library=%s', phutil_get_library_root($library));
     }
     $command = csprintf("./launch_daemon.php " . "%s " . "--load-phutil-library=%s " . "%C " . "--conduit-uri=%s " . "--phd=%s " . ($debug ? '--trace ' : '--daemonize '), $daemon, phutil_get_library_root('phabricator'), implode(' ', $extra_libraries), PhabricatorEnv::getURI('/api/'), $pid_dir);
     if (!$debug) {
         // If we're running "phd debug", send output straight to the console
         // instead of to a logfile.
         $command = csprintf("%C --log=%s", $command, $log_dir);
     }
     // Append the daemon's argv.
     $command = csprintf("%C %C", $command, implode(' ', $argv));
     if ($debug) {
         // Don't terminate when the user sends ^C; it will be sent to the
         // subprocess which will terminate normally.
         pcntl_signal(SIGINT, array('PhabricatorDaemonControl', 'ignoreSignal'));
         echo "\n    libphutil/scripts/daemon/ \$ {$command}\n\n";
         phutil_passthru('(cd %s && exec %C)', $launch_daemon, $command);
     } else {
         $future = new ExecFuture('exec %C', $command);
         // Play games to keep 'ps' looking reasonable.
         $future->setCWD($launch_daemon);
         $future->resolvex();
     }
 }