1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-22 14:52:40 +01:00

Add an ArcanistChmodLinter.

Summary: Fixes T3922. Add a linter which complains if files are executable when they shoudn't be.

Test Plan: Tested by modifying the `.arclint` file of the rARC repository and running `arc lint --everything`.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T3922

Differential Revision: https://secure.phabricator.com/D9187
This commit is contained in:
Joshua Spence 2014-05-18 16:57:08 -07:00 committed by epriestley
parent 606380f4bd
commit 904fbe737c
2 changed files with 82 additions and 0 deletions

View file

@ -32,6 +32,7 @@ phutil_register_library_map(array(
'ArcanistCSharpLinter' => 'lint/linter/ArcanistCSharpLinter.php', 'ArcanistCSharpLinter' => 'lint/linter/ArcanistCSharpLinter.php',
'ArcanistCallConduitWorkflow' => 'workflow/ArcanistCallConduitWorkflow.php', 'ArcanistCallConduitWorkflow' => 'workflow/ArcanistCallConduitWorkflow.php',
'ArcanistCapabilityNotSupportedException' => 'workflow/exception/ArcanistCapabilityNotSupportedException.php', 'ArcanistCapabilityNotSupportedException' => 'workflow/exception/ArcanistCapabilityNotSupportedException.php',
'ArcanistChmodLinter' => 'lint/linter/ArcanistChmodLinter.php',
'ArcanistChooseInvalidRevisionException' => 'exception/ArcanistChooseInvalidRevisionException.php', 'ArcanistChooseInvalidRevisionException' => 'exception/ArcanistChooseInvalidRevisionException.php',
'ArcanistChooseNoRevisionsException' => 'exception/ArcanistChooseNoRevisionsException.php', 'ArcanistChooseNoRevisionsException' => 'exception/ArcanistChooseNoRevisionsException.php',
'ArcanistCloseRevisionWorkflow' => 'workflow/ArcanistCloseRevisionWorkflow.php', 'ArcanistCloseRevisionWorkflow' => 'workflow/ArcanistCloseRevisionWorkflow.php',
@ -222,6 +223,7 @@ phutil_register_library_map(array(
'ArcanistCSharpLinter' => 'ArcanistLinter', 'ArcanistCSharpLinter' => 'ArcanistLinter',
'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistCapabilityNotSupportedException' => 'Exception', 'ArcanistCapabilityNotSupportedException' => 'Exception',
'ArcanistChmodLinter' => 'ArcanistLinter',
'ArcanistChooseInvalidRevisionException' => 'Exception', 'ArcanistChooseInvalidRevisionException' => 'Exception',
'ArcanistChooseNoRevisionsException' => 'Exception', 'ArcanistChooseNoRevisionsException' => 'Exception',
'ArcanistCloseRevisionWorkflow' => 'ArcanistBaseWorkflow', 'ArcanistCloseRevisionWorkflow' => 'ArcanistBaseWorkflow',

View file

@ -0,0 +1,80 @@
<?php
/**
* Ensures that files are not executable unless they are either binary or
* contain a shebang.
*/
final class ArcanistChmodLinter extends ArcanistLinter {
const LINT_INVALID_EXECUTABLE = 1;
public function getInfoName() {
return 'Chmod';
}
public function getInfoDescription() {
return pht(
'Checks the permissions on files and ensures that they are not made to '.
'be executable unnecessarily. In particular, a file should not be '.
'executable unless it is either binary or contain a shebang.');
}
public function getLinterName() {
return 'CHMOD';
}
public function getLinterConfigurationName() {
return 'chmod';
}
public function shouldLintBinaryFiles() {
return true;
}
public function getLintNameMap() {
return array(
self::LINT_INVALID_EXECUTABLE => pht('Invalid Executable'),
);
}
public function getLintSeverityMap() {
return array(
self::LINT_INVALID_EXECUTABLE => ArcanistLintSeverity::SEVERITY_WARNING,
);
}
public function lintPath($path) {
if (is_executable($path)) {
if ($this->getEngine()->isBinaryFile($path)) {
// Path is a binary file, which makes it a valid executable.
return;
} else if ($this->getShebang($path)) {
// Path contains a shebang, which makes it a valid executable.
return;
} else {
$this->raiseLintAtPath(
self::LINT_INVALID_EXECUTABLE,
pht(
'Executable files should either be binary or contain a shebang.'));
}
}
}
/**
* Returns the path's shebang.
*
* @param string
* @return string|null
*/
private function getShebang($path) {
$line = head(phutil_split_lines($this->getEngine()->loadData($path), true));
$matches = array();
if (preg_match('/^#!(.*)$/', $line, $matches)) {
return $matches[1];
} else {
return null;
}
}
}