public function getPEP8Path() { $working_copy = $this->getEngine()->getWorkingCopy(); $prefix = $working_copy->getConfig('lint.pep8.prefix'); $bin = $working_copy->getConfig('lint.pep8.bin'); if ($bin === null && $prefix === null) { $bin = csprintf('/usr/bin/env python2.6 %s', phutil_get_library_root('arcanist') . '/../externals/pep8/pep8.py'); } else { if ($bin === null) { $bin = 'pep8'; } if ($prefix !== null) { if (!Filesystem::pathExists($prefix . '/' . $bin)) { throw new ArcanistUsageException("Unable to find PEP8 binary in a specified directory. Make sure " . "that 'lint.pep8.prefix' and 'lint.pep8.bin' keys are set " . "correctly. If you'd rather use a copy of PEP8 installed " . "globally, you can just remove these keys from your .arcconfig."); } $bin = csprintf("%s/%s", $prefix, $bin); return $bin; } // Look for globally installed PEP8 list($err) = exec_manual('which %s', $bin); if ($err) { throw new ArcanistUsageException("PEP8 does not appear to be installed on this system. Install it " . "(e.g., with 'easy_install pep8') or configure " . "'lint.pep8.prefix' in your .arcconfig to point to the directory " . "where it resides."); } } return $bin; }
public static function newAPIFromWorkingCopyIdentity(ArcanistWorkingCopyIdentity $working_copy) { $root = $working_copy->getProjectRoot(); if (!$root) { throw new ArcanistUsageException("There is no readable '.arcconfig' file in the working directory or " . "any parent directory. Create an '.arcconfig' file to configure arc."); } // check if we're in an svn working copy list($err) = exec_manual('svn info'); if (!$err) { $api = newv('ArcanistSubversionAPI', array($root)); $api->workingCopyIdentity = $working_copy; return $api; } if (Filesystem::pathExists($root . '/.hg')) { $api = newv('ArcanistMercurialAPI', array($root)); $api->workingCopyIdentity = $working_copy; return $api; } $git_root = self::discoverGitBaseDirectory($root); if ($git_root) { if (!Filesystem::pathsAreEquivalent($root, $git_root)) { throw new ArcanistUsageException("'.arcconfig' file is located at '{$root}', but working copy root " . "is '{$git_root}'. Move '.arcconfig' file to the working copy root."); } $api = newv('ArcanistGitAPI', array($root)); $api->workingCopyIdentity = $working_copy; return $api; } throw new ArcanistUsageException("The current working directory is not part of a working copy for a " . "supported version control system (svn, git or mercurial)."); }
public function lintPath($path) { $pep8_bin = $this->getPEP8Path(); $options = $this->getPEP8Options(); list($rc, $stdout) = exec_manual("%C %C %s", $pep8_bin, $options, $this->getEngine()->getFilePathOnDisk($path)); $lines = explode("\n", $stdout); $messages = array(); foreach ($lines as $line) { $matches = null; if (!preg_match('/^(.*?):(\\d+):(\\d+): (\\S+) (.*)$/', $line, $matches)) { continue; } foreach ($matches as $key => $match) { $matches[$key] = trim($match); } $message = new ArcanistLintMessage(); $message->setPath($path); $message->setLine($matches[2]); $message->setChar($matches[3]); $message->setCode($matches[4]); $message->setName('PEP8 ' . $matches[4]); $message->setDescription($matches[5]); if (!$this->isMessageEnabled($matches[4])) { continue; } if ($matches[4][0] == 'E') { $message->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR); } else { $message->setSeverity(ArcanistLintSeverity::SEVERITY_WARNING); } $this->addLintMessage($message); } }
/** * @group console */ function phutil_console_prompt($prompt, $history = '') { echo "\n\n"; $prompt = phutil_console_wrap($prompt . ' ', 4); try { phutil_console_require_tty(); } catch (PhutilConsoleStdinNotInteractiveException $ex) { // Throw after echoing the prompt so the user has some idea what happened. echo $prompt; throw $ex; } $use_history = true; if ($history == '') { $use_history = false; } else { // Test if bash is available by seeing if it can run `true`. list($err) = exec_manual('bash -c %s', 'true'); if ($err) { $use_history = false; } } if (!$use_history) { echo $prompt; $response = fgets(STDIN); } else { // There's around 0% chance that readline() is available directly in PHP, // so we're using bash/read/history instead. $command = csprintf('bash -c %s', csprintf('history -r %s 2>/dev/null; ' . 'read -e -p %s; ' . 'echo "$REPLY"; ' . 'history -s "$REPLY" 2>/dev/null; ' . 'history -w %s 2>/dev/null', $history, $prompt, $history)); // execx() doesn't work with input, phutil_passthru() doesn't return output. $response = shell_exec($command); } return rtrim($response, "\r\n"); }
protected function executeChecks() { if (phutil_is_windows()) { $bin_name = 'where'; } else { $bin_name = 'which'; } if (!Filesystem::binaryExists($bin_name)) { $message = pht("Without '%s', Phabricator can not test for the availability " . "of other binaries.", $bin_name); $this->raiseWarning($bin_name, $message); // We need to return here if we can't find the 'which' / 'where' binary // because the other tests won't be valid. return; } if (!Filesystem::binaryExists('diff')) { $message = pht("Without 'diff', Phabricator will not be able to generate or render " . "diffs in multiple applications."); $this->raiseWarning('diff', $message); } else { $tmp_a = new TempFile(); $tmp_b = new TempFile(); $tmp_c = new TempFile(); Filesystem::writeFile($tmp_a, 'A'); Filesystem::writeFile($tmp_b, 'A'); Filesystem::writeFile($tmp_c, 'B'); list($err) = exec_manual('diff %s %s', $tmp_a, $tmp_b); if ($err) { $this->newIssue('bin.diff.same')->setName(pht("Unexpected 'diff' Behavior"))->setMessage(pht("The 'diff' binary on this system has unexpected behavior: " . "it was expected to exit without an error code when passed " . "identical files, but exited with code %d.", $err)); } list($err) = exec_manual('diff %s %s', $tmp_a, $tmp_c); if (!$err) { $this->newIssue('bin.diff.diff')->setName(pht("Unexpected 'diff' Behavior"))->setMessage(pht("The 'diff' binary on this system has unexpected behavior: " . "it was expected to exit with a nonzero error code when passed " . "differing files, but did not.")); } } $table = new PhabricatorRepository(); $vcses = queryfx_all($table->establishConnection('r'), 'SELECT DISTINCT versionControlSystem FROM %T', $table->getTableName()); foreach ($vcses as $vcs) { switch ($vcs['versionControlSystem']) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $binary = 'git'; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $binary = 'svn'; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $binary = 'hg'; break; default: $binary = null; break; } if (!$binary) { continue; } if (!Filesystem::binaryExists($binary)) { $message = pht('You have at least one repository configured which uses this ' . 'version control system. It will not work without the VCS binary.'); $this->raiseWarning($binary, $message); } } }
private function getBinaryPath() { if ($this->symbolsBinary === null) { list($err, $stdout) = exec_manual('which javelinsymbols'); $this->symbolsBinary = $err ? false : rtrim($stdout); } return $this->symbolsBinary; }
/** * Generate a raw diff from two raw files. This is a lower-level API than * @{method:generateChangesetFromFileContent}, but may be useful if you need * to use a custom parser configuration, as with Diffusion. * * @param string Entire previous file content. * @param string Entire current file content. * @return string Raw diff between the two files. * @task diff */ public function generateRawDiffFromFileContent($old, $new) { $options = array(); if ($this->ignoreWhitespace) { $options[] = '-bw'; } // Generate diffs with full context. $options[] = '-U65535'; $old_name = nonempty($this->oldName, '/dev/universe') . ' 9999-99-99'; $new_name = nonempty($this->newName, '/dev/universe') . ' 9999-99-99'; $options[] = '-L'; $options[] = $old_name; $options[] = '-L'; $options[] = $new_name; $old_tmp = new TempFile(); $new_tmp = new TempFile(); Filesystem::writeFile($old_tmp, $old); Filesystem::writeFile($new_tmp, $new); list($err, $diff) = exec_manual('diff %Ls %s %s', $options, $old_tmp, $new_tmp); if (!$err) { // This indicates that the two files are the same (or, possibly, the // same modulo whitespace differences, which is why we can't do this // check trivially before running `diff`). Build a synthetic, changeless // diff so that we can still render the raw, unchanged file instead of // being forced to just say "this file didn't change" since we don't have // the content. $entire_file = explode("\n", $old); foreach ($entire_file as $k => $line) { $entire_file[$k] = ' ' . $line; } $len = count($entire_file); $entire_file = implode("\n", $entire_file); // TODO: If both files were identical but missing newlines, we probably // get this wrong. Unclear if it ever matters. // This is a bit hacky but the diff parser can handle it. $diff = "--- {$old_name}\n" . "+++ {$new_name}\n" . "@@ -1,{$len} +1,{$len} @@\n" . $entire_file . "\n"; } else { if ($this->ignoreWhitespace) { // Under "-bw", `diff` is inconsistent about emitting "\ No newline // at end of file". For instance, a long file with a change in the // middle will emit a contextless "\ No newline..." at the end if a // newline is removed, but not if one is added. A file with a change // at the end will emit the "old" "\ No newline..." block only, even // if the newline was not removed. Since we're ostensibly ignoring // whitespace changes, just drop these lines if they appear anywhere // in the diff. $lines = explode("\n", $diff); foreach ($lines as $key => $line) { if (isset($line[0]) && $line[0] == '\\') { unset($lines[$key]); } } $diff = implode("\n", $lines); } } return $diff; }
private function getControlDirectory($path) { if (!Filesystem::pathExists($path)) { list($err) = exec_manual('mkdir -p %s', $path); if ($err) { throw new Exception(pht("%s requires the directory '%s' to exist, but it does not exist " . "and could not be created. Create this directory or update " . "'%s' / '%s' in your configuration to point to an existing " . "directory.", 'phd', $path, 'phd.pid-directory', 'phd.log-directory')); } } return $path; }
private function getControlDirectory($path) { if (!Filesystem::pathExists($path)) { list($err) = exec_manual('mkdir -p %s', $path); if ($err) { throw new Exception("phd requires the directory '{$path}' to exist, but it does not " . "exist and could not be created. Create this directory or update " . "'phd.pid-directory' / 'phd.log-directory' in your configuration " . "to point to an existing directory."); } } return $path; }
public function getVersion() { // NOTE: `jsonlint --version` returns a non-zero exit status. list($err, $stdout) = exec_manual('%C --version', $this->getExecutableCommand()); $matches = array(); if (preg_match('/^(?P<version>\\d+\\.\\d+\\.\\d+)$/', $stdout, $matches)) { return $matches['version']; } else { return false; } }
public static function renderDifferences($old, $new, $context_lines = 3, $diff_options = "-L 'Old Value' -L 'New Value'") { if ((string) $old === (string) $new) { $new .= "\n(Old and new values are identical.)"; } $file_old = new TempFile(); $file_new = new TempFile(); Filesystem::writeFile($file_old, (string) $old . "\n"); Filesystem::writeFile($file_new, (string) $new . "\n"); list($err, $stdout) = exec_manual('diff %C -U %s %s %s', $diff_options, $context_lines, $file_old, $file_new); return $stdout; }
protected function execute(ConduitAPIRequest $request) { $path = xhpast_get_binary_path(); if (!Filesystem::pathExists($path)) { throw new ConduitException('ERR-NOT-FOUND'); } list($err, $stdout) = exec_manual('%s --version', $path); if ($err) { throw new ConduitException('ERR-COMMAND-FAILED'); } return trim($stdout); }
protected function executeChecks() { $pygment = PhabricatorEnv::getEnvConfig('pygments.enabled'); if ($pygment) { list($err) = exec_manual('pygmentize -h'); if ($err) { $summary = pht('You enabled pygments but the pygmentize script is not ' . 'actually available, your $PATH is probably broken.'); $message = pht('The environmental variable $PATH does not contain ' . 'pygmentize. You have enabled pygments, which requires ' . 'pygmentize to be available in your $PATH variable.'); $this->newIssue('pygments.enabled')->setName(pht('pygmentize Not Found'))->setSummary($summary)->setMessage($message)->addRelatedPhabricatorConfig('pygments.enabled')->addPhabricatorConfig('environment.append-paths'); } } }
public function getDefaultBinary() { $binary = 'go'; if (Filesystem::binaryExists($binary)) { // Vet is only accessible through 'go vet' or 'go tool vet' // Let's manually try to find out if it's installed. list($err, $stdout, $stderr) = exec_manual('go tool vet'); if ($err === 3) { throw new ArcanistMissingLinterException(sprintf("%s\n%s", pht('Unable to locate "go vet" to run linter %s. You may need ' . 'to install the binary, or adjust your linter configuration.', get_class($this)), pht('TO INSTALL: %s', $this->getInstallInstructions()))); } } return $binary; }
public static function getMercurialVersion() { list($err, $stdout, $stderr) = exec_manual('hg --version --quiet'); // NOTE: At least on OSX, recent versions of Mercurial report this // string in this format: // // Mercurial Distributed SCM (version 3.1.1+20140916) $matches = null; $pattern = '/^Mercurial Distributed SCM \\(version ([\\d.]+)/m'; if (preg_match($pattern, $stdout, $matches)) { return $matches[1]; } return null; }
public function decryptSecret(PhutilOpaqueEnvelope $secret, PhutilOpaqueEnvelope $password) { $tmp = new TempFile(); Filesystem::writeFile($tmp, $secret->openEnvelope()); if (!Filesystem::binaryExists('ssh-keygen')) { throw new Exception(pht('Decrypting SSH keys requires the `ssh-keygen` binary, but it ' . 'is not available in PATH. Either make it available or strip the ' . 'password fromt his SSH key manually before uploading it.')); } list($err, $stdout, $stderr) = exec_manual('ssh-keygen -p -P %P -N %s -f %s', $password, '', (string) $tmp); if ($err) { return null; } else { return new PhutilOpaqueEnvelope(Filesystem::readFile($tmp)); } }
public function getLintPath() { $bin = 'cpplint.py'; // Search under current dir list($err) = exec_manual('which %s/%s', $this->linterDir(), $bin); if (!$err) { return $this->linterDir() . '/' . $bin; } // Look for globally installed cpplint.py list($err) = exec_manual('which %s', $bin); if ($err) { throw new ArcanistUsageException("cpplint.py does not appear to be installed on this system. Install " . "it (e.g., with 'wget \"http://google-styleguide.googlecode.com/" . "svn/trunk/cpplint/cpplint.py\"') " . "in your .arcconfig to point to the directory where it resides. " . "Also don't forget to chmod a+x cpplint.py!"); } return $bin; }
public function lintPath($path) { $bin = $this->getLintPath(); $options = $this->getLintOptions(); list($rc, $stdout, $stderr) = exec_manual("%C %C --inline-suppr --xml-version=2 -q %s", $bin, $options, $this->getEngine()->getFilePathOnDisk($path)); if ($rc === 1) { throw new Exception("cppcheck failed to run correctly:\n" . $stderr); } $dom = new DOMDocument(); libxml_clear_errors(); if ($dom->loadXML($stderr) === false || libxml_get_errors()) { throw new ArcanistUsageException('cppcheck Linter failed to load ' . 'output. Something happened when running cppcheck. ' . "Output:\n{$stderr}" . "\nTry running lint with --trace flag to get more details."); } $errors = $dom->getElementsByTagName('error'); foreach ($errors as $error) { $loc_node = $error->getElementsByTagName('location'); if (!$loc_node) { continue; } $location = $loc_node->item(0); if (!$location) { continue; } $file = $location->getAttribute('file'); $line = $location->getAttribute('line'); $id = $error->getAttribute('id'); $severity = $error->getAttribute('severity'); $msg = $error->getAttribute('msg'); $inconclusive = $error->getAttribute('inconclusive'); $verbose_msg = $error->getAttribute('verbose'); $severity_code = ArcanistLintSeverity::SEVERITY_WARNING; if ($inconclusive) { $severity_code = ArcanistLintSeverity::SEVERITY_ADVICE; } else { if (stripos($severity, 'error') !== false) { $severity_code = ArcanistLintSeverity::SEVERITY_ERROR; } } $message = new ArcanistLintMessage(); $message->setPath($path); $message->setLine($line); $message->setCode($severity); $message->setName($id); $message->setDescription($msg); $message->setSeverity($severity_code); $this->addLintMessage($message); } }
private function getSBTPath() { $sbt_bin = "sbt"; // Use the SBT prefix specified in the config file $working_copy = $this->getEngine()->getWorkingCopy(); $prefix = $working_copy->getConfig('lint.scala_sbt.prefix'); if ($prefix !== null) { $sbt_bin = $prefix . $sbt_bin; } if (!Filesystem::pathExists($sbt_bin)) { list($err) = exec_manual('which %s', $sbt_bin); if ($err) { throw new ArcanistUsageException("SBT does not appear to be installed on this system. Install it or " . "add 'lint.scala_sbt.prefix' in your .arcconfig to point to " . "the directory where it resides."); } } return $sbt_bin; }
/** * @group xhpast */ function xhpast_is_available() { static $available; if ($available === null) { $available = false; $bin = xhpast_get_binary_path(); if (Filesystem::pathExists($bin)) { list($err, $stdout) = exec_manual('%s --version', $bin); if (!$err) { $version = trim($stdout); if ($version === "xhpast version 5.5.8/1e") { $available = true; } } } } return $available; }
public function getLintPath() { $working_copy = $this->getEngine()->getWorkingCopy(); $prefix = $working_copy->getConfig('lint.cpplint.prefix'); $bin = $working_copy->getConfig('lint.cpplint.bin', 'cpplint.py'); if ($prefix !== null) { if (!Filesystem::pathExists($prefix . '/' . $bin)) { throw new ArcanistUsageException("Unable to find cpplint.py binary in a specified directory. Make " . "sure that 'lint.cpplint.prefix' and 'lint.cpplint.bin' keys are " . "set correctly. If you'd rather use a copy of cpplint installed " . "globally, you can just remove these keys from your .arcconfig."); } $bin = csprintf("%s/%s", $prefix, $bin); return $bin; } // Look for globally installed cpplint.py list($err) = exec_manual('which %s', $bin); if ($err) { throw new ArcanistUsageException("cpplint.py does not appear to be installed on this system. Install " . "it (e.g., with 'wget \"http://google-styleguide.googlecode.com/" . "svn/trunk/cpplint/cpplint.py\"') or configure 'lint.cpplint.prefix' " . "in your .arcconfig to point to the directory where it resides. " . "Also don't forget to chmod a+x cpplint.py!"); } return $bin; }
public function getFlake8Path() { $working_copy = $this->getEngine()->getWorkingCopy(); $prefix = $working_copy->getConfig('lint.flake8.prefix'); $bin = $working_copy->getConfig('lint.flake8.bin', 'flake8'); if ($prefix !== null) { if (!Filesystem::pathExists($prefix . '/' . $bin)) { throw new ArcanistUsageException("Unable to find flake8 binary in a specified directory. Make sure " . "that 'lint.flake8.prefix' and 'lint.flake8.bin' keys are set " . "correctly. If you'd rather use a copy of flake8 installed " . "globally, you can just remove these keys from your .arcconfig."); } $bin = csprintf("%s/%s", $prefix, $bin); return $bin; } // Look for globally installed flake8 list($err) = exec_manual('which %s', $bin); if ($err) { throw new ArcanistUsageException("flake8 does not appear to be installed on this system. Install it " . "(e.g., with 'easy_install flake8') or configure " . "'lint.flake8.prefix' in your .arcconfig to point to the directory " . "where it resides."); } return $bin; }
public function runJs() { // First, check to see if karma is on $PATH: list($err, $stdout, $_) = exec_manual("which karma"); if ($err != 0) { $result = new ArcanistUnitTestResult(); $result->setName("Karma not found. Skipping js tests..."); $result->setResult(ArcanistUnitTestResult::RESULT_SKIP); $result->setDuration(0); return array($result); } // Karma IS on the path. $old_dir = getcwd(); $project_root = $this->getWorkingCopy()->getProjectRoot(); chdir($project_root . '/client/js'); exec_manual("karma start karma-conf-oneshot.js"); chdir($old_dir); // Read from the text-results.xml file. $xml = file_get_contents($project_root . '/client/test-results.xml'); $doc = new SimpleXMLElement($xml); // Destroy the test-results.xml file. unlink($project_root . '/client/test-results.xml'); // Extract all the test cases. $results = array(); foreach ($doc->testsuite as $suite) { $suite_name = $suite['name']; foreach ($suite->testcase as $case) { $case_name = $case['name']; $time = $case['time']; $fixture_name = substr($case['classname'], strlen($suite_name) + 1); // Did we fail? $failure = (string) $case->failure; // Convert each to a ArcanistUnitTestResult $result = new ArcanistUnitTestResult(); $result->setName($fixture_name . ' ' . $case_name); $result->setResult($failure ? ArcanistUnitTestResult::RESULT_FAIL : ArcanistUnitTestResult::RESULT_PASS); $result->setUserData($failure); $result->setDuration($time); $results[] = $result; } } return $results; }
public function execute(PhutilArgumentParser $args) { $console = PhutilConsole::getConsole(); $root = dirname(__FILE__) . '/../../../..'; if (!Filesystem::binaryExists('mxmlc')) { throw new PhutilArgumentUsageException(pht("The `mxmlc` binary was not found in PATH. This compiler binary " . "is required to rebuild the Aphlict client.\n\n" . "Adjust your PATH, or install the Flex SDK from:\n\n" . " http://flex.apache.org\n\n" . "You may also be able to install it with `npm`:\n\n" . " \$ npm install flex-sdk\n\n" . "(Note: you should only need to rebuild Aphlict if you are " . "developing Phabricator.)")); } $argv = array("-source-path={$root}/externals/vegas/src", '-static-link-runtime-shared-libraries=true', '-warnings=true', '-strict=true'); if ($args->getArg('debug')) { $argv[] = '-debug=true'; } list($err, $stdout, $stderr) = exec_manual('mxmlc %Ls -output=%s %s', $argv, $root . '/webroot/rsrc/swf/aphlict.swf', $root . '/support/aphlict/client/src/AphlictClient.as'); if ($err) { $console->writeErr($stderr); return 1; } $console->writeOut("Done.\n"); return 0; }
public function lintPath($path) { list($err, $_, $stderr) = exec_manual("gofmt -w -s %s", $this->getEngine()->getFilePathOnDisk($path)); if ($err) { $lines = explode("\n", $stderr); foreach ($lines as $line) { $matches = null; if (!preg_match('/[^:]+:(\\d+):(\\d+): (.*)$/', $line, $matches)) { continue; } $message = new ArcanistLintMessage(); $message->setPath($path); $message->setLine($matches[1]); $message->setChar($matches[2]); $message->setName($this->getLinterName() . " Parse error"); $message->setDescription($matches[3]); $this->addLintMessage($message); } } }
public function run() { $roots = array('libphutil' => dirname(phutil_get_library_root('phutil')), 'arcanist' => dirname(phutil_get_library_root('arcanist'))); foreach ($roots as $lib => $root) { echo phutil_console_format("%s\n", pht('Upgrading %s...', $lib)); $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root); $configuration_manager = clone $this->getConfigurationManager(); $configuration_manager->setWorkingCopyIdentity($working_copy); $repository = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager); if (!Filesystem::pathExists($repository->getMetadataPath())) { throw new ArcanistUsageException(pht("%s must be in its git working copy to be automatically upgraded. " . "This copy of %s (in '%s') is not in a git working copy.", $lib, $lib, $root)); } $this->setRepositoryAPI($repository); // NOTE: Don't use requireCleanWorkingCopy() here because it tries to // amend changes and generally move the workflow forward. We just want to // abort if there are local changes and make the user sort things out. $uncommitted = $repository->getUncommittedStatus(); if ($uncommitted) { $message = pht('You have uncommitted changes in the working copy for this ' . 'library:'); $list = id(new PhutilConsoleList())->setWrap(false)->addItems(array_keys($uncommitted)); id(new PhutilConsoleBlock())->addParagraph($message)->addList($list)->draw(); throw new ArcanistUsageException(pht('`arc upgrade` can only upgrade clean working copies.')); } $branch_name = $repository->getBranchName(); if ($branch_name != 'master' && $branch_name != 'stable') { throw new ArcanistUsageException(pht("%s must be on either branch '%s' or '%s' to be automatically " . "upgraded. " . "This copy of %s (in '%s') is on branch '%s'.", $lib, 'master', 'stable', $lib, $root, $branch_name)); } chdir($root); try { execx('git pull --rebase'); } catch (Exception $ex) { // If we failed, try to go back to the old state, then throw the // original exception. exec_manual('git rebase --abort'); throw $ex; } } echo phutil_console_format("**%s** %s\n", pht('Updated!'), pht('Your copy of arc is now up to date.')); return 0; }
protected function executeChecks() { $pygment = PhabricatorEnv::getEnvConfig('pygments.enabled'); if ($pygment) { if (!Filesystem::binaryExists('pygmentize')) { $summary = pht('You enabled pygments but the %s script is not ' . 'actually available, your %s is probably broken.', 'pygmentize', '$PATH'); $message = pht('The environmental variable %s does not contain %s. ' . 'You have enabled pygments, which requires ' . '%s to be available in your %s variable.', '$PATH', 'pygmentize', 'pygmentize', '$PATH'); $this->newIssue('pygments.enabled')->setName(pht('%s Not Found', 'pygmentize'))->setSummary($summary)->setMessage($message)->addRelatedPhabricatorConfig('pygments.enabled')->addPhabricatorConfig('environment.append-paths'); } else { list($err) = exec_manual('pygmentize -h'); if ($err) { $summary = pht('You have enabled pygments and the %s script is ' . 'available, but does not seem to work.', 'pygmentize'); $message = pht('Phabricator has %s available in %s, but the binary ' . 'exited with an error code when run as %s. Check that it is ' . 'installed correctly.', phutil_tag('tt', array(), 'pygmentize'), phutil_tag('tt', array(), '$PATH'), phutil_tag('tt', array(), 'pygmentize -h')); $this->newIssue('pygments.failed')->setName(pht('%s Not Working', 'pygmentize'))->setSummary($summary)->setMessage($message)->addRelatedPhabricatorConfig('pygments.enabled')->addPhabricatorConfig('environment.append-paths'); } } } else { $summary = pht('Pygments should be installed and enabled ' . 'to provide advanced syntax highlighting.'); $message = pht('Phabricator can highlight a few languages by default, ' . 'but installing and enabling Pygments (a third-party highlighting ' . "tool) will add syntax highlighting for many more languages. \n\n" . 'For instructions on installing and enabling Pygments, see the ' . '%s configuration option.' . "\n\n" . 'If you do not want to install Pygments, you can ignore this issue.', phutil_tag('tt', array(), 'pygments.enabled')); $this->newIssue('pygments.noenabled')->setName(pht('Install Pygments to Improve Syntax Highlighting'))->setSummary($summary)->setMessage($message)->addRelatedPhabricatorConfig('pygments.enabled'); } }
private function getJSHintPath() { $working_copy = $this->getEngine()->getWorkingCopy(); $prefix = $working_copy->getConfig('lint.jshint.prefix'); $bin = $working_copy->getConfig('lint.jshint.bin'); if ($bin === null) { $bin = "jshint"; } if ($prefix !== null) { $bin = $prefix . "/" . $bin; if (!Filesystem::pathExists($bin)) { throw new ArcanistUsageException("Unable to find JSHint binary in a specified directory. Make sure " . "that 'lint.jshint.prefix' and 'lint.jshint.bin' keys are set " . "correctly. If you'd rather use a copy of JSHint installed " . "globally, you can just remove these keys from your .arcconfig"); } return $bin; } // Look for globally installed JSHint list($err) = phutil_is_windows() ? exec_manual('where %s', $bin) : exec_manual('which %s', $bin); if ($err) { throw new ArcanistUsageException("JSHint does not appear to be installed on this system. Install it " . "(e.g., with 'npm install jshint -g') or configure " . "'lint.jshint.prefix' in your .arcconfig to point to the directory " . "where it resides."); } return $bin; }
private function discoverCommit($commit, $epoch) { $uri = $this->getBaseSVNLogURI(); $discover = array($commit => $epoch); $upper_bound = $commit; $limit = 1; while ($upper_bound > 1 && !$this->isKnownCommit($upper_bound)) { // Find all the unknown commits on this path. Note that we permit // importing an SVN subdirectory rather than the entire repository, so // commits may be nonsequential. list($err, $xml, $stderr) = exec_manual('svn log --xml --non-interactive --quiet --limit %d %s@%d', $limit, $uri, $upper_bound - 1); if ($err) { if (preg_match('/(path|File) not found/', $stderr)) { // We've gone all the way back through history and this path was not // affected by earlier commits. break; } else { throw new Exception("svn log error #{$err}: {$stderr}"); } } $discover += $this->parseSVNLogXML($xml); $upper_bound = min(array_keys($discover)); // Discover 2, 4, 8, ... 256 logs at a time. This allows us to initially // import large repositories fairly quickly, while pulling only as much // data as we need in the common case (when we've already imported the // repository and are just grabbing one commit at a time). $limit = min($limit * 2, 256); } // NOTE: We do writes only after discovering all the commits so that we're // never left in a state where we've missed commits -- if the discovery // script terminates it can always resume and restore the import to a good // state. This is also why we sort the discovered commits so we can do // writes forward from the smallest one. ksort($discover); foreach ($discover as $commit => $epoch) { $this->recordCommit($commit, $epoch); } }
public function writePatchToDisk() { $path = $this->lintResult->getFilePathOnDisk(); $data = $this->getModifiedFileContent(); $ii = null; do { $lint = $path . '.linted' . $ii++; } while (file_exists($lint)); // Copy existing file to preserve permissions. 'chmod --reference' is not // supported under OSX. if (Filesystem::pathExists($path)) { // This path may not exist if we're generating a new file. execx('cp -p %s %s', $path, $lint); } Filesystem::writeFile($lint, $data); list($err) = exec_manual('mv -f %s %s', $lint, $path); if ($err) { throw new Exception("Unable to overwrite path `{$path}', patched version was left " . "at `{$lint}'."); } foreach ($this->applyMessages as $message) { $message->didApplyPatch(); } }