예제 #1
0
/**
 * Format text for terminal output. This function behaves like `sprintf`,
 * except that all the normal conversions (like "%s") will be properly escaped,
 * and additional conversions are supported:
 *
 *   %B (Block)
 *     Escapes text, but preserves tabs and newlines.
 *
 *   %R (Raw String)
 *     Inserts raw, unescaped text. DANGEROUS!
 *
 * Particularly, this will escape terminal control characters.
 */
function tsprintf($pattern)
{
    $args = func_get_args();
    $args[0] = PhutilConsoleFormatter::interpretFormat($args[0]);
    $string = xsprintf('xsprintf_terminal', null, $args);
    return new PhutilTerminalString($string);
}
 public static function getDisableANSI()
 {
     if (self::$disableANSI === null) {
         if (phutil_is_windows()) {
             self::$disableANSI = true;
         } else {
             if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
                 self::$disableANSI = true;
             } else {
                 self::$disableANSI = false;
             }
         }
     }
     return self::$disableANSI;
 }
 public static function getDisableANSI()
 {
     if (self::$disableANSI === null) {
         $term = phutil_utf8_strtolower(getenv("TERM"));
         if (phutil_is_windows() && $term !== "cygwin" && $term !== "ansi") {
             self::$disableANSI = true;
         } else {
             if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
                 self::$disableANSI = true;
             } else {
                 self::$disableANSI = false;
             }
         }
     }
     return self::$disableANSI;
 }
예제 #4
0
 public static function getDisableANSI()
 {
     if (self::$disableANSI === null) {
         $term = phutil_utf8_strtolower(getenv('TERM'));
         // ansicon enables ANSI support on Windows
         if (!$term && getenv('ANSICON')) {
             $term = 'ansi';
         }
         if (phutil_is_windows() && $term !== 'cygwin' && $term !== 'ansi') {
             self::$disableANSI = true;
         } else {
             if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
                 self::$disableANSI = true;
             } else {
                 self::$disableANSI = false;
             }
         }
     }
     return self::$disableANSI;
 }
예제 #5
0
 private function getHeader()
 {
     $output = '';
     if ($this->borders) {
         $output .= $this->formatSeparator('=');
     }
     if (!$this->showHeader) {
         return $output;
     }
     $columns = array();
     foreach ($this->columns as $key => $column) {
         $columns[] = PhutilConsoleFormatter::formatString('**%s**', $this->alignString($column['title'], $this->getWidth($key), idx($column, 'align', self::ALIGN_LEFT)));
     }
     $output .= $this->formatRow($columns);
     if ($this->borders) {
         $output .= $this->formatSeparator('=');
     }
     return $output;
 }
 public function run()
 {
     $this->console = PhutilConsole::getConsole();
     $this->runRepositoryAPISetup();
     if ($this->getArgument('no-diff')) {
         $this->removeScratchFile('diff-result.json');
         $data = $this->runLintUnit();
         $this->writeScratchJSONFile('diff-result.json', $data);
         return 0;
     }
     $this->runDiffSetupBasics();
     $background = $this->getArgument('background', true);
     if ($this->isRawDiffSource() || phutil_is_windows()) {
         $background = false;
     }
     if ($background) {
         $argv = $this->getPassedArguments();
         if (!PhutilConsoleFormatter::getDisableANSI()) {
             array_unshift($argv, '--ansi');
         }
         $script = phutil_get_library_root('arcanist') . '/../scripts/arcanist.php';
         if ($argv) {
             $lint_unit = new ExecFuture('php %s --recon diff --no-diff %Ls', $script, $argv);
         } else {
             $lint_unit = new ExecFuture('php %s --recon diff --no-diff', $script);
         }
         $lint_unit->write('', true);
         $lint_unit->start();
     }
     $commit_message = $this->buildCommitMessage();
     $this->dispatchEvent(ArcanistEventType::TYPE_DIFF_DIDBUILDMESSAGE, array('message' => $commit_message));
     if (!$this->shouldOnlyCreateDiff()) {
         $revision = $this->buildRevisionFromCommitMessage($commit_message);
     }
     if ($background) {
         $server = new PhutilConsoleServer();
         $server->addExecFutureClient($lint_unit);
         $server->setHandler(array($this, 'handleServerMessage'));
         $server->run();
         list($err) = $lint_unit->resolve();
         $data = $this->readScratchJSONFile('diff-result.json');
         if ($err || !$data) {
             throw new Exception('Unable to read results from background linting and unit testing. ' . 'You can try running arc diff again with --background 0');
         }
     } else {
         $server = $this->console->getServer();
         $server->setHandler(array($this, 'handleServerMessage'));
         $data = $this->runLintUnit();
     }
     $lint_result = $data['lintResult'];
     $this->unresolvedLint = $data['unresolvedLint'];
     $this->postponedLinters = $data['postponedLinters'];
     $unit_result = $data['unitResult'];
     $this->testResults = $data['testResults'];
     if ($this->getArgument('nolint')) {
         $this->excuses['lint'] = $this->getSkipExcuse('Provide explanation for skipping lint or press Enter to abort:', 'lint-excuses');
     }
     if ($this->getArgument('nounit')) {
         $this->excuses['unit'] = $this->getSkipExcuse('Provide explanation for skipping unit tests or press Enter to abort:', 'unit-excuses');
     }
     $changes = $this->generateChanges();
     if (!$changes) {
         throw new ArcanistUsageException("There are no changes to generate a diff from!");
     }
     $diff_spec = array('changes' => mpull($changes, 'toDictionary'), 'lintStatus' => $this->getLintStatus($lint_result), 'unitStatus' => $this->getUnitStatus($unit_result)) + $this->buildDiffSpecification();
     $conduit = $this->getConduit();
     $diff_info = $conduit->callMethodSynchronous('differential.creatediff', $diff_spec);
     $this->diffID = $diff_info['diffid'];
     $event = $this->dispatchEvent(ArcanistEventType::TYPE_DIFF_WASCREATED, array('diffID' => $diff_info['diffid'], 'lintResult' => $lint_result, 'unitResult' => $unit_result));
     $this->updateLintDiffProperty();
     $this->updateUnitDiffProperty();
     $this->updateLocalDiffProperty();
     $this->resolveDiffPropertyUpdates();
     $output_json = $this->getArgument('json');
     if ($this->shouldOnlyCreateDiff()) {
         if (!$output_json) {
             echo phutil_console_format("Created a new Differential diff:\n" . "        **Diff URI:** __%s__\n\n", $diff_info['uri']);
         } else {
             $human = ob_get_clean();
             echo json_encode(array('diffURI' => $diff_info['uri'], 'diffID' => $this->getDiffID(), 'human' => $human)) . "\n";
             ob_start();
         }
     } else {
         $revision['diffid'] = $this->getDiffID();
         if ($commit_message->getRevisionID()) {
             $result = $conduit->callMethodSynchronous('differential.updaterevision', $revision);
             foreach (array('edit-messages.json', 'update-messages.json') as $file) {
                 $messages = $this->readScratchJSONFile($file);
                 unset($messages[$revision['id']]);
                 $this->writeScratchJSONFile($file, $messages);
             }
             echo "Updated an existing Differential revision:\n";
         } else {
             $revision = $this->dispatchWillCreateRevisionEvent($revision);
             $result = $conduit->callMethodSynchronous('differential.createrevision', $revision);
             $revised_message = $conduit->callMethodSynchronous('differential.getcommitmessage', array('revision_id' => $result['revisionid']));
             if ($this->shouldAmend()) {
                 $repository_api = $this->getRepositoryAPI();
                 if ($repository_api->supportsAmend()) {
                     echo "Updating commit message...\n";
                     $repository_api->amendCommit($revised_message);
                 } else {
                     echo "Commit message was not amended. Amending commit message is " . "only supported in git and hg (version 2.2 or newer)";
                 }
             }
             echo "Created a new Differential revision:\n";
         }
         $uri = $result['uri'];
         echo phutil_console_format("        **Revision URI:** __%s__\n\n", $uri);
         if ($this->getArgument('plan-changes')) {
             $conduit->callMethodSynchronous('differential.createcomment', array('revision_id' => $result['revisionid'], 'action' => 'rethink'));
             echo "Planned changes to the revision.\n";
         }
     }
     echo "Included changes:\n";
     foreach ($changes as $change) {
         echo '  ' . $change->renderTextSummary() . "\n";
     }
     if ($output_json) {
         ob_get_clean();
     }
     $this->removeScratchFile('create-message');
     return 0;
 }
 /**
  * Parse "standard" arguments and apply their effects:
  *
  *    --trace             Enable service call tracing.
  *    --no-ansi           Disable ANSI color/style sequences.
  *    --xprofile <file>   Write out an XHProf profile.
  *    --help              Show help.
  *
  * @return this
  *
  * @phutil-external-symbol function xhprof_enable
  */
 public function parseStandardArguments()
 {
     try {
         $this->parsePartial(array(array('name' => 'trace', 'help' => pht('Trace command execution and show service calls.'), 'standard' => true), array('name' => 'no-ansi', 'help' => pht('Disable ANSI terminal codes, printing plain text with ' . 'no color or style.'), 'conflicts' => array('ansi' => null), 'standard' => true), array('name' => 'ansi', 'help' => pht("Use formatting even in environments which probably " . "don't support it."), 'standard' => true), array('name' => 'xprofile', 'param' => 'profile', 'help' => pht('Profile script execution and write results to a file.'), 'standard' => true), array('name' => 'help', 'short' => 'h', 'help' => pht('Show this help.'), 'standard' => true), array('name' => 'show-standard-options', 'help' => pht('Show every option, including standard options like this one.'), 'standard' => true), array('name' => 'recon', 'help' => pht('Start in remote console mode.'), 'standard' => true)));
     } catch (PhutilArgumentUsageException $ex) {
         $this->printUsageException($ex);
         exit(self::PARSE_ERROR_CODE);
     }
     if ($this->getArg('trace')) {
         PhutilServiceProfiler::installEchoListener();
     }
     if ($this->getArg('no-ansi')) {
         PhutilConsoleFormatter::disableANSI(true);
     }
     if ($this->getArg('ansi')) {
         PhutilConsoleFormatter::disableANSI(false);
     }
     if ($this->getArg('help')) {
         $this->showHelp = true;
     }
     $xprofile = $this->getArg('xprofile');
     if ($xprofile) {
         if (!function_exists('xhprof_enable')) {
             throw new Exception(pht("To use '%s', you must install XHProf.", '--xprofile'));
         }
         xhprof_enable(0);
         register_shutdown_function(array($this, 'shutdownProfiler'));
     }
     $recon = $this->getArg('recon');
     if ($recon) {
         $remote_console = PhutilConsole::newRemoteConsole();
         $remote_console->beginRedirectOut();
         PhutilConsole::setConsole($remote_console);
     } else {
         if ($this->getArg('trace')) {
             $server = new PhutilConsoleServer();
             $server->setEnableLog(true);
             $console = PhutilConsole::newConsoleForServer($server);
             PhutilConsole::setConsole($console);
         }
     }
     return $this;
 }
예제 #8
0
 public static function disableANSI($disable)
 {
     self::$disableANSI = $disable;
 }