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).");
 }
Example #3
0
 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);
     }
 }
Example #4
0
/**
 * @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;
 }
Example #25
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();
     }
 }