Changeset View
Changeset View
Standalone View
Standalone View
arcanist/workflow/ArcanistScriptedDiffWorkflow.php
- This file was added.
<?php | |||||
/** | |||||
* Check scripted diff.validity | |||||
*/ | |||||
final class ArcanistScriptedDiffWorkflow extends ArcanistWorkflow { | |||||
const SCRIPTED_DIFF_START = '-BEGIN VERIFY SCRIPT-'; | |||||
const SCRIPTED_DIFF_END = '-END VERIFY SCRIPT-'; | |||||
const RESULT_OKAY = 0; | |||||
const RESULT_WARNINGS = 1; | |||||
const RESULT_ERRORS = 2; | |||||
const RESULT_SKIP = 3; | |||||
private function getScriptFromCommitMessage($message) { | |||||
$pattern = | |||||
'/'.self::SCRIPTED_DIFF_START.'(.+)'.self::SCRIPTED_DIFF_END.'/s'; | |||||
if (preg_match($pattern, $message, $matches)) { | |||||
return ltrim($matches[1]); | |||||
} | |||||
return null; | |||||
} | |||||
public function getWorkflowName() { | |||||
return 'scripted-diff'; | |||||
} | |||||
public function getCommandSynopses() { | |||||
return phutil_console_format(<<<EOTEXT | |||||
**scripted-diff** | |||||
EOTEXT | |||||
); | |||||
} | |||||
public function getCommandHelp() { | |||||
return phutil_console_format(<<<EOTEXT | |||||
Supports: git | |||||
Check a scripted-diff commit matches the working directory content | |||||
EOTEXT | |||||
); | |||||
} | |||||
public function requiresWorkingCopy() { | |||||
return true; | |||||
} | |||||
public function requiresRepositoryAPI() { | |||||
return true; | |||||
} | |||||
private function render_to_console($result, $failureReason = '') { | |||||
$out = null; | |||||
switch($result) { | |||||
case self::RESULT_OKAY: | |||||
$out = phutil_console_format( | |||||
"**<bg:green> %s </bg>** %s\n", | |||||
pht('OKAY'), | |||||
pht('Scripted-diff check is successful')); | |||||
break; | |||||
case self::RESULT_ERRORS: | |||||
$out = phutil_console_format( | |||||
"**<bg:red> %s </bg>** %s\n", | |||||
pht('FAILED'), | |||||
pht($failureReason)); | |||||
break; | |||||
default: | |||||
/* If there is nothing to display. */ | |||||
break; | |||||
} | |||||
if ($out) { | |||||
PhutilConsole::getConsole()->writeOut($out); | |||||
} | |||||
} | |||||
public function run() { | |||||
$root = $this->getWorkingCopy()->getProjectRoot(); | |||||
$api = $this->getRepositoryAPI(); | |||||
/* Git is the only source control system supported. */ | |||||
if ($api->getSourceControlSystemName() !== 'git') { | |||||
return self::RESULT_SKIP; | |||||
} | |||||
$headCommit = $api->getHeadCommit(); | |||||
$script = $this->getScriptFromCommitMessage( | |||||
$api->getCommitMessage($headCommit)); | |||||
/* If this is not a scripted-diff, skip the check. */ | |||||
if (!$script) { | |||||
return self::RESULT_SKIP; | |||||
} | |||||
/* Store the script in a temporary file and make it executable */ | |||||
$tmp = id(new TempFile('script.sh')); | |||||
deadalnix: No. | |||||
Filesystem::writeFile($tmp, $script); | |||||
Filesystem::changePermissions($tmp, 0544); | |||||
$currentBranch = $api->getBranchName(); | |||||
$baseCommit = $api->getBaseCommit(); | |||||
/* Checkout the base commit. */ | |||||
$out = $api->execxLocal('checkout %s', $baseCommit); | |||||
deadalnixUnsubmitted Not Done Inline ActionsYou should check that the repo is clean before doing anything of the kind. deadalnix: You should check that the repo is clean before doing anything of the kind. | |||||
$result = self::RESULT_OKAY; | |||||
/* Apply the script to the base commit from the root directory. */ | |||||
$cmd = '(cd '.$root.' && '.strval($tmp).')'; | |||||
$future = new ExecFuture($cmd); | |||||
list($ret) = $future->resolve(); | |||||
if ($ret != 0) { | |||||
$result = self::RESULT_ERRORS; | |||||
$this->render_to_console($result, | |||||
'Scripted-diff: the script returned an error.'); | |||||
} else { | |||||
/* | |||||
* If the script ran successfully, compare the ouput working tree to the | |||||
* current commit state. | |||||
*/ | |||||
list($ret) = $api->execManualLocal( | |||||
'--no-pager diff --exit-code %s', $headCommit); | |||||
if ($ret != 0) { | |||||
$result = self::RESULT_ERRORS; | |||||
$this->render_to_console($result, | |||||
'Scripted-diff: scripted output does not match the commit content.'); | |||||
} | |||||
} | |||||
$api->execxLocal('reset --hard HEAD'); | |||||
$api->execxLocal('checkout %s', $currentBranch); | |||||
if ($result == self::RESULT_OKAY) { | |||||
$this->render_to_console($result); | |||||
} | |||||
return $result; | |||||
} | |||||
} |
No.