mirror of
https://we.phorge.it/source/arcanist.git
synced 2025-01-10 23:01:04 +01:00
External linters can now specify a version requirement.
Summary: Linters can now use the `version` configuration value to specify the required version of the external binary. The version number may be prefixed with <, <=, >, >=, or = to specify the version comparison operator (default: =). PHP's native `version_compare()` function is used to perform the comparison. Fixes T4954. Test Plan: Tested against a sample of external linters. Reviewers: joshuaspence, epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: Korvin, joshuaspence Projects: #lint Maniphest Tasks: T4954 Differential Revision: https://secure.phabricator.com/D14298
This commit is contained in:
parent
e51e1c3d44
commit
b3ea439f4d
1 changed files with 92 additions and 0 deletions
|
@ -13,6 +13,7 @@ abstract class ArcanistExternalLinter extends ArcanistFutureLinter {
|
|||
private $bin;
|
||||
private $interpreter;
|
||||
private $flags;
|
||||
private $versionRequirement;
|
||||
|
||||
|
||||
/* -( Interpreters, Binaries and Flags )----------------------------------- */
|
||||
|
@ -42,6 +43,16 @@ abstract class ArcanistExternalLinter extends ArcanistFutureLinter {
|
|||
*/
|
||||
abstract public function getInstallInstructions();
|
||||
|
||||
/**
|
||||
* Return a human-readable string describing how to upgrade the linter.
|
||||
*
|
||||
* @return string Human readable upgrade instructions
|
||||
* @task bin
|
||||
*/
|
||||
public function getUpgradeInstructions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true to continue when the external linter exits with an error code.
|
||||
* By default, linters which exit with an error code are assumed to have
|
||||
|
@ -102,6 +113,18 @@ abstract class ArcanistExternalLinter extends ArcanistFutureLinter {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the binary's version requirement.
|
||||
*
|
||||
* @param string Version requirement.
|
||||
* @return this
|
||||
* @task bin
|
||||
*/
|
||||
final public function setVersionRequirement($version) {
|
||||
$this->versionRequirement = trim($version);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the binary or script to execute. This method synthesizes defaults
|
||||
* and configuration. You can override the binary with @{method:setBinary}.
|
||||
|
@ -258,6 +281,64 @@ abstract class ArcanistExternalLinter extends ArcanistFutureLinter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a binary version requirement has been specified, compare the version
|
||||
* of the configured binary to the required version, and if the binary's
|
||||
* version is not supported, throw an exception.
|
||||
*
|
||||
* @param string Version string to check.
|
||||
* @return void
|
||||
*/
|
||||
final protected function checkBinaryVersion($version) {
|
||||
if (!$this->versionRequirement) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$version) {
|
||||
$message = pht(
|
||||
'Linter %s requires %s version %s. Unable to determine the version '.
|
||||
'that you have installed.',
|
||||
get_class($this),
|
||||
$this->getBinary(),
|
||||
$this->versionRequirement);
|
||||
|
||||
$instructions = $this->getUpgradeInstructions();
|
||||
if ($instructions) {
|
||||
$message .= "\n".pht('TO UPGRADE: %s', $instructions);
|
||||
}
|
||||
|
||||
throw new ArcanistMissingLinterException($message);
|
||||
}
|
||||
|
||||
$operator = '==';
|
||||
$compare_to = $this->versionRequirement;
|
||||
|
||||
$matches = null;
|
||||
if (preg_match('/^([<>]=?|=)\s*(.*)$/', $compare_to, $matches)) {
|
||||
$operator = $matches[1];
|
||||
$compare_to = $matches[2];
|
||||
if ($operator === '=') {
|
||||
$operator = '==';
|
||||
}
|
||||
}
|
||||
|
||||
if (!version_compare($version, $compare_to, $operator)) {
|
||||
$message = pht(
|
||||
'Linter %s requires %s version %s. You have version %s.',
|
||||
get_class($this),
|
||||
$this->getBinary(),
|
||||
$this->versionRequirement,
|
||||
$version);
|
||||
|
||||
$instructions = $this->getUpgradeInstructions();
|
||||
if ($instructions) {
|
||||
$message .= "\n".pht('TO UPGRADE: %s', $instructions);
|
||||
}
|
||||
|
||||
throw new ArcanistMissingLinterException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the composed executable command, including the interpreter and binary
|
||||
* but without flags or paths. This can be used to execute `--version`
|
||||
|
@ -308,6 +389,7 @@ abstract class ArcanistExternalLinter extends ArcanistFutureLinter {
|
|||
$version = $this->getVersion();
|
||||
|
||||
if ($version) {
|
||||
$this->checkBinaryVersion($version);
|
||||
return $version.'-'.json_encode($this->getCommandFlags());
|
||||
} else {
|
||||
// Either we failed to parse the version number or the `getVersion`
|
||||
|
@ -395,6 +477,13 @@ abstract class ArcanistExternalLinter extends ArcanistFutureLinter {
|
|||
'Provide a list of additional flags to pass to the linter on the '.
|
||||
'command line.'),
|
||||
),
|
||||
'version' => array(
|
||||
'type' => 'optional string',
|
||||
'help' => pht(
|
||||
'Specify a version requirement for the binary. The version number '.
|
||||
'may be prefixed with <, <=, >, >=, or = to specify the version '.
|
||||
'comparison operator (default: =).'),
|
||||
),
|
||||
);
|
||||
|
||||
if ($this->shouldUseInterpreter()) {
|
||||
|
@ -456,6 +545,9 @@ abstract class ArcanistExternalLinter extends ArcanistFutureLinter {
|
|||
case 'flags':
|
||||
$this->setFlags($value);
|
||||
return;
|
||||
case 'version':
|
||||
$this->setVersionRequirement($value);
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::setLinterConfigurationValue($key, $value);
|
||||
|
|
Loading…
Reference in a new issue