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; }