mirror of
https://we.phorge.it/source/arcanist.git
synced 2025-01-25 22:18:18 +01:00
Add a "--raw" flag to "arc diff"
Summary: Some Mercurial users at Dropbox have very specific diff preparation needs. Allow "arc" to read an arbitrary diff off stdin. This disables most features. Test Plan: Ran "git diff HEAD | arc diff --raw", "git show | arc diff --raw", "hg diff --rev 8 | arc diff --raw". Reviewers: btrahan, jungejason, Makinde Reviewed By: btrahan CC: aran, btrahan Maniphest Tasks: T617 Differential Revision: https://secure.phabricator.com/D1323
This commit is contained in:
parent
560b339ad3
commit
c49e9863d4
1 changed files with 155 additions and 53 deletions
|
@ -53,7 +53,7 @@ EOTEXT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public function requiresWorkingCopy() {
|
public function requiresWorkingCopy() {
|
||||||
return true;
|
return !$this->isRawDiffSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function requiresConduit() {
|
public function requiresConduit() {
|
||||||
|
@ -65,7 +65,7 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
public function requiresRepositoryAPI() {
|
public function requiresRepositoryAPI() {
|
||||||
return true;
|
return !$this->isRawDiffSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDiffID() {
|
public function getDiffID() {
|
||||||
|
@ -105,6 +105,39 @@ EOTEXT
|
||||||
"When updating a revision under git, edit revision information ".
|
"When updating a revision under git, edit revision information ".
|
||||||
"before updating.",
|
"before updating.",
|
||||||
),
|
),
|
||||||
|
'raw' => array(
|
||||||
|
'help' =>
|
||||||
|
"Read diff from stdin, not from the working copy. This disables ".
|
||||||
|
"many Arcanist/Phabricator features which depend on having access ".
|
||||||
|
"to the working copy.",
|
||||||
|
'conflicts' => array(
|
||||||
|
'less-context' => null,
|
||||||
|
'apply-patches' => '--raw disables lint.',
|
||||||
|
'never-apply-patches' => '--raw disables lint.',
|
||||||
|
'advice' => '--raw disables lint.',
|
||||||
|
'lintall' => '--raw disables lint.',
|
||||||
|
|
||||||
|
'create' => '--raw and --create both need stdin. '.
|
||||||
|
'Use --raw-command.',
|
||||||
|
'edit' => '--raw and --edit both need stdin. '.
|
||||||
|
'Use --raw-command.',
|
||||||
|
'raw-command' => null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'raw-command' => array(
|
||||||
|
'param' => 'command',
|
||||||
|
'help' =>
|
||||||
|
"Generate diff by executing a specified command, not from the ".
|
||||||
|
"working copy. This disables many Arcanist/Phabricator features ".
|
||||||
|
"which depend on having access to the working copy.",
|
||||||
|
'conflicts' => array(
|
||||||
|
'less-context' => null,
|
||||||
|
'apply-patches' => '--raw-command disables lint.',
|
||||||
|
'never-apply-patches' => '--raw-command disables lint.',
|
||||||
|
'advice' => '--raw-command disables lint.',
|
||||||
|
'lintall' => '--raw-command disables lint.',
|
||||||
|
),
|
||||||
|
),
|
||||||
'create' => array(
|
'create' => array(
|
||||||
'help' => "(EXPERIMENTAL) Create a new revision.",
|
'help' => "(EXPERIMENTAL) Create a new revision.",
|
||||||
'conflicts' => array(
|
'conflicts' => array(
|
||||||
|
@ -130,7 +163,7 @@ EOTEXT
|
||||||
'only' => array(
|
'only' => array(
|
||||||
'help' =>
|
'help' =>
|
||||||
"Only generate a diff, without running lint, unit tests, or other ".
|
"Only generate a diff, without running lint, unit tests, or other ".
|
||||||
"auxiliary steps.",
|
"auxiliary steps. See also --preview.",
|
||||||
'conflicts' => array(
|
'conflicts' => array(
|
||||||
'preview' => null,
|
'preview' => null,
|
||||||
'message' => '--only does not affect revisions.',
|
'message' => '--only does not affect revisions.',
|
||||||
|
@ -217,11 +250,17 @@ EOTEXT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run() {
|
public function isRawDiffSource() {
|
||||||
$repository_api = $this->getRepositoryAPI();
|
return $this->getArgument('raw') || $this->getArgument('raw-command');
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->getArgument('less-context')) {
|
public function run() {
|
||||||
$repository_api->setDiffLinesOfContext(3);
|
|
||||||
|
if ($this->requiresRepositoryAPI()) {
|
||||||
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
if ($this->getArgument('less-context')) {
|
||||||
|
$repository_api->setDiffLinesOfContext(3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$output_json = $this->getArgument('json');
|
$output_json = $this->getArgument('json');
|
||||||
|
@ -232,7 +271,10 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
$conduit = $this->getConduit();
|
$conduit = $this->getConduit();
|
||||||
$this->requireCleanWorkingCopy();
|
|
||||||
|
if ($this->requiresWorkingCopy()) {
|
||||||
|
$this->requireCleanWorkingCopy();
|
||||||
|
}
|
||||||
|
|
||||||
$paths = $this->generateAffectedPaths();
|
$paths = $this->generateAffectedPaths();
|
||||||
|
|
||||||
|
@ -249,13 +291,8 @@ EOTEXT
|
||||||
"There are no changes to generate a diff from!");
|
"There are no changes to generate a diff from!");
|
||||||
}
|
}
|
||||||
|
|
||||||
$change_list = array();
|
|
||||||
foreach ($changes as $change) {
|
|
||||||
$change_list[] = $change->toDictionary();
|
|
||||||
}
|
|
||||||
|
|
||||||
$diff_spec = array(
|
$diff_spec = array(
|
||||||
'changes' => $change_list,
|
'changes' => mpull($changes, 'toDictionary'),
|
||||||
'lintStatus' => $this->getLintStatus($lint_result),
|
'lintStatus' => $this->getLintStatus($lint_result),
|
||||||
'unitStatus' => $this->getUnitStatus($unit_result),
|
'unitStatus' => $this->getUnitStatus($unit_result),
|
||||||
) + $this->buildDiffSpecification();
|
) + $this->buildDiffSpecification();
|
||||||
|
@ -386,8 +423,14 @@ EOTEXT
|
||||||
'revision_id' => $result['revisionid'],
|
'revision_id' => $result['revisionid'],
|
||||||
));
|
));
|
||||||
|
|
||||||
echo "Updating commit message...\n";
|
if ($this->requiresRepositoryAPI()) {
|
||||||
$repository_api->amendGitHeadCommit($revised_message);
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
if (($repository_api instanceof ArcanistGitAPI) &&
|
||||||
|
!$this->isHistoryImmutable()) {
|
||||||
|
echo "Updating commit message...\n";
|
||||||
|
$repository_api->amendGitHeadCommit($revised_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
echo "Created a new Differential revision:\n";
|
echo "Created a new Differential revision:\n";
|
||||||
}
|
}
|
||||||
|
@ -403,8 +446,6 @@ EOTEXT
|
||||||
echo ' '.$change->renderTextSummary()."\n";
|
echo ' '.$change->renderTextSummary()."\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->diffID = $diff_info['diffid'];
|
|
||||||
|
|
||||||
if ($output_json) {
|
if ($output_json) {
|
||||||
ob_get_clean();
|
ob_get_clean();
|
||||||
}
|
}
|
||||||
|
@ -418,6 +459,10 @@ EOTEXT
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isRawDiffSource()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
if ($repository_api instanceof ArcanistSubversionAPI) {
|
if ($repository_api instanceof ArcanistSubversionAPI) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -436,6 +481,10 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateAffectedPaths() {
|
private function generateAffectedPaths() {
|
||||||
|
if ($this->isRawDiffSource()) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
if ($repository_api instanceof ArcanistSubversionAPI) {
|
if ($repository_api instanceof ArcanistSubversionAPI) {
|
||||||
$file_list = new FileList($this->getArgument('paths', array()));
|
$file_list = new FileList($this->getArgument('paths', array()));
|
||||||
|
@ -495,9 +544,32 @@ EOTEXT
|
||||||
|
|
||||||
|
|
||||||
protected function generateChanges() {
|
protected function generateChanges() {
|
||||||
|
$parser = new ArcanistDiffParser();
|
||||||
|
|
||||||
|
$is_raw = $this->isRawDiffSource();
|
||||||
|
if ($is_raw) {
|
||||||
|
|
||||||
|
if ($this->getArgument('raw')) {
|
||||||
|
file_put_contents('php://stderr', "Reading diff from stdin...\n");
|
||||||
|
$raw_diff = file_get_contents('php://stdin');
|
||||||
|
} else if ($this->getArgument('raw-command')) {
|
||||||
|
list($raw_diff) = execx($this->getArgument('raw-command'));
|
||||||
|
} else {
|
||||||
|
throw new Exception("Unknown raw diff source.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$changes = $parser->parseDiff($raw_diff);
|
||||||
|
foreach ($changes as $key => $change) {
|
||||||
|
// Remove "message" changes, e.g. from "git show".
|
||||||
|
if ($change->getType() == ArcanistDiffChangeType::TYPE_MESSAGE) {
|
||||||
|
unset($changes[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $changes;
|
||||||
|
}
|
||||||
|
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
|
||||||
$parser = new ArcanistDiffParser();
|
|
||||||
if ($repository_api instanceof ArcanistSubversionAPI) {
|
if ($repository_api instanceof ArcanistSubversionAPI) {
|
||||||
$paths = $this->generateAffectedPaths();
|
$paths = $this->generateAffectedPaths();
|
||||||
$this->primeSubversionWorkingCopyData($paths);
|
$this->primeSubversionWorkingCopyData($paths);
|
||||||
|
@ -864,7 +936,8 @@ EOTEXT
|
||||||
*/
|
*/
|
||||||
private function runLint($paths) {
|
private function runLint($paths) {
|
||||||
if ($this->getArgument('nolint') ||
|
if ($this->getArgument('nolint') ||
|
||||||
$this->getArgument('only')) {
|
$this->getArgument('only') ||
|
||||||
|
$this->isRawDiffSource()) {
|
||||||
return ArcanistLintWorkflow::RESULT_SKIP;
|
return ArcanistLintWorkflow::RESULT_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,7 +1001,8 @@ EOTEXT
|
||||||
*/
|
*/
|
||||||
private function runUnit($paths) {
|
private function runUnit($paths) {
|
||||||
if ($this->getArgument('nounit') ||
|
if ($this->getArgument('nounit') ||
|
||||||
$this->getArgument('only')) {
|
$this->getArgument('only') ||
|
||||||
|
$this->isRawDiffSource()) {
|
||||||
return ArcanistUnitWorkflow::RESULT_SKIP;
|
return ArcanistUnitWorkflow::RESULT_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,6 +1061,7 @@ EOTEXT
|
||||||
*/
|
*/
|
||||||
private function buildCommitMessage() {
|
private function buildCommitMessage() {
|
||||||
$is_create = $this->getArgument('create');
|
$is_create = $this->getArgument('create');
|
||||||
|
$is_raw = $this->isRawDiffSource();
|
||||||
|
|
||||||
$message = null;
|
$message = null;
|
||||||
if ($is_create) {
|
if ($is_create) {
|
||||||
|
@ -996,7 +1071,13 @@ EOTEXT
|
||||||
} else {
|
} else {
|
||||||
return $this->getCommitMessageFromUser();
|
return $this->getCommitMessageFromUser();
|
||||||
}
|
}
|
||||||
} else if (!$this->shouldOnlyCreateDiff()) {
|
}
|
||||||
|
|
||||||
|
if ($is_raw) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->shouldOnlyCreateDiff()) {
|
||||||
return $this->getGitCommitMessage();
|
return $this->getGitCommitMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,9 +1179,11 @@ EOTEXT
|
||||||
// $ arc diff
|
// $ arc diff
|
||||||
//
|
//
|
||||||
// ...you shouldn't have to retype the update message.
|
// ...you shouldn't have to retype the update message.
|
||||||
$repository_api = $this->getRepositoryAPI();
|
if ($this->requiresRepositoryAPI()) {
|
||||||
if ($repository_api instanceof ArcanistGitAPI) {
|
$repository_api = $this->getRepositoryAPI();
|
||||||
$comments = $this->getGitUpdateMessage();
|
if ($repository_api instanceof ArcanistGitAPI) {
|
||||||
|
$comments = $this->getGitUpdateMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$template =
|
$template =
|
||||||
|
@ -1275,47 +1358,62 @@ EOTEXT
|
||||||
*/
|
*/
|
||||||
private function buildDiffSpecification() {
|
private function buildDiffSpecification() {
|
||||||
|
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$base_revision = null;
|
||||||
$working_copy = $this->getWorkingCopy();
|
$base_path = null;
|
||||||
|
$vcs = null;
|
||||||
$base_revision = $repository_api->getSourceControlBaseRevision();
|
|
||||||
$base_path = $repository_api->getSourceControlPath();
|
|
||||||
$vcs = $repository_api->getSourceControlSystemName();
|
|
||||||
$repo_uuid = null;
|
$repo_uuid = null;
|
||||||
$parent = null;
|
$parent = null;
|
||||||
if ($repository_api instanceof ArcanistGitAPI) {
|
$source_path = null;
|
||||||
$info = $this->getGitParentLogInfo();
|
$branch = null;
|
||||||
if ($info['parent']) {
|
|
||||||
$parent = $info['parent'];
|
if ($this->requiresRepositoryAPI()) {
|
||||||
|
$repository_api = $this->getRepositoryAPI();
|
||||||
|
|
||||||
|
$base_revision = $repository_api->getSourceControlBaseRevision();
|
||||||
|
$base_path = $repository_api->getSourceControlPath();
|
||||||
|
$vcs = $repository_api->getSourceControlSystemName();
|
||||||
|
$source_path = $repository_api->getPath();
|
||||||
|
$branch = $repository_api->getBranchName();
|
||||||
|
|
||||||
|
if ($repository_api instanceof ArcanistGitAPI) {
|
||||||
|
$info = $this->getGitParentLogInfo();
|
||||||
|
if ($info['parent']) {
|
||||||
|
$parent = $info['parent'];
|
||||||
|
}
|
||||||
|
if ($info['base_revision']) {
|
||||||
|
$base_revision = $info['base_revision'];
|
||||||
|
}
|
||||||
|
if ($info['base_path']) {
|
||||||
|
$base_path = $info['base_path'];
|
||||||
|
}
|
||||||
|
if ($info['uuid']) {
|
||||||
|
$repo_uuid = $info['uuid'];
|
||||||
|
}
|
||||||
|
} else if ($repository_api instanceof ArcanistSubversionAPI) {
|
||||||
|
$repo_uuid = $repository_api->getRepositorySVNUUID();
|
||||||
|
} else if ($repository_api instanceof ArcanistMercurialAPI) {
|
||||||
|
// TODO: Provide this information.
|
||||||
|
} else {
|
||||||
|
throw new Exception("Unsupported repository API!");
|
||||||
}
|
}
|
||||||
if ($info['base_revision']) {
|
}
|
||||||
$base_revision = $info['base_revision'];
|
|
||||||
}
|
$project_id = null;
|
||||||
if ($info['base_path']) {
|
if ($this->requiresWorkingCopy()) {
|
||||||
$base_path = $info['base_path'];
|
$project_id = $this->getWorkingCopy()->getProjectID();
|
||||||
}
|
|
||||||
if ($info['uuid']) {
|
|
||||||
$repo_uuid = $info['uuid'];
|
|
||||||
}
|
|
||||||
} else if ($repository_api instanceof ArcanistSubversionAPI) {
|
|
||||||
$repo_uuid = $repository_api->getRepositorySVNUUID();
|
|
||||||
} else if ($repository_api instanceof ArcanistMercurialAPI) {
|
|
||||||
// TODO: Provide this information.
|
|
||||||
} else {
|
|
||||||
throw new Exception("Unsupported repository API!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'sourceMachine' => php_uname('n'),
|
'sourceMachine' => php_uname('n'),
|
||||||
'sourcePath' => $repository_api->getPath(),
|
'sourcePath' => $source_path,
|
||||||
'branch' => $repository_api->getBranchName(),
|
'branch' => $branch,
|
||||||
'sourceControlSystem' => $vcs,
|
'sourceControlSystem' => $vcs,
|
||||||
'sourceControlPath' => $base_path,
|
'sourceControlPath' => $base_path,
|
||||||
'sourceControlBaseRevision' => $base_revision,
|
'sourceControlBaseRevision' => $base_revision,
|
||||||
'parentRevisionID' => $parent,
|
'parentRevisionID' => $parent,
|
||||||
'repositoryUUID' => $repo_uuid,
|
'repositoryUUID' => $repo_uuid,
|
||||||
'creationMethod' => 'arc',
|
'creationMethod' => 'arc',
|
||||||
'arcanistProject' => $working_copy->getProjectID(),
|
'arcanistProject' => $project_id,
|
||||||
'authorPHID' => $this->getUserPHID(),
|
'authorPHID' => $this->getUserPHID(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1384,6 +1482,10 @@ EOTEXT
|
||||||
* @task diffprop
|
* @task diffprop
|
||||||
*/
|
*/
|
||||||
private function updateLocalDiffProperty() {
|
private function updateLocalDiffProperty() {
|
||||||
|
if ($this->isRawDiffSource()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$local_info = $this->getRepositoryAPI()->getLocalCommitInformation();
|
$local_info = $this->getRepositoryAPI()->getLocalCommitInformation();
|
||||||
if (!$local_info) {
|
if (!$local_info) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Reference in a new issue