Created
April 22, 2011 15:39
-
-
Save raphaelstolt/936903 to your computer and use it in GitHub Desktop.
A Git pre-commit hook rejecting no-descriptive Phing and Ant build files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/php | |
<?php | |
define('DEPENDENT_EXTENSION', 'SimpleXML'); | |
if (!extension_loaded(DEPENDENT_EXTENSION)) { | |
$consoleMessage = sprintf( | |
"Skipping build file checks as the '%s' extension isn't available.", | |
DEPENDENT_EXTENSION | |
); | |
echo $consoleMessage . PHP_EOL; | |
exit(0); | |
} | |
define('MIN_TARGET_DESCRIPTION_LENGTH', 10); | |
define('TARGET_DESCRIPTION_ATTRIBUTE', 'description'); | |
define('TARGET_NAME_ATTRIBUTE', 'name'); | |
define('CHECK_DESCRIPTION_LENGTH', true); | |
$possibleBuildFileNames = array( | |
'build.xml.dist', | |
'build.xml-dist', | |
'build-dist.xml', | |
'build.xml', | |
'personal-build.xml' | |
); | |
$violations = getAllBuildFileViolationsOfCommit($possibleBuildFileNames); | |
fireBackPossibleViolationsAndExitAccordingly($violations); | |
function getAllBuildFileViolationsOfCommit(array $possibleBuildFileNames) | |
{ | |
$filesOfCommit = array(); | |
$gitCommand = 'git diff --cached --name-only'; | |
exec($gitCommand, $filesOfCommit, $commandReturnCode); | |
$allViolations = array(); | |
foreach ($filesOfCommit as $file) { | |
if (in_array(basename($file), $possibleBuildFileNames)) { | |
$violations = checkBuildFileForViolations($file); | |
if (count($violations) > 0) { | |
$allViolations[$file] = $violations; | |
} | |
} | |
} | |
return $allViolations; | |
} | |
/** | |
* @param array $allViolations | |
* @return void | |
*/ | |
function fireBackPossibleViolationsAndExitAccordingly(array $allViolations) | |
{ | |
if (count($allViolations) > 0) { | |
foreach ($allViolations as $buildFile => $violations) { | |
$buildFileConsoleMessageHeader = sprintf("Build file '%s':", $buildFile); | |
echo $buildFileConsoleMessageHeader . PHP_EOL; | |
foreach ($violations as $violationMessage) { | |
$buildFileConsoleMessageLine = sprintf(" + %s", $violationMessage); | |
echo $buildFileConsoleMessageLine . PHP_EOL; | |
} | |
} | |
if (count($allViolations) > 1) { | |
$rejectCommitConsoleMessage = sprintf( | |
"Therefore rejecting the commit of build files [ %s ].", | |
implode(', ', array_keys($allViolations)) | |
); | |
} else { | |
$rejectCommitConsoleMessage = sprintf( | |
"Therefore rejecting the commit of build file [ %s ].", | |
implode(', ', array_keys($allViolations)) | |
); | |
} | |
echo $rejectCommitConsoleMessage . PHP_EOL; | |
exit(1); | |
} | |
exit(0); | |
} | |
/** | |
* @param string $buildfile | |
* @return array | |
*/ | |
function checkBuildFileForViolations($buildFile) { | |
if (!file_exists($buildFile)) { | |
return array(); | |
} | |
$buildfileXml = file_get_contents($buildFile); | |
$buildXml = new SimpleXMLElement($buildfileXml); | |
$allBuildTargets = $buildXml->xpath("//target"); | |
$violations = array(); | |
if (count($allBuildTargets) > 0) { | |
$targetsWithNoDescription = $targetsWithTooShortDescription = array(); | |
foreach ($allBuildTargets as $buildTarget) { | |
$actualTragetAttributes = $buildTarget->attributes(); | |
$allUsedTragetAttributes = array(); | |
$actualTargetName = null; | |
foreach ($actualTragetAttributes as $attribute => $value) { | |
$allUsedTragetAttributes[] = $attribute; | |
if ($attribute === TARGET_NAME_ATTRIBUTE) { | |
$actualTargetName = $value; | |
} | |
if (CHECK_DESCRIPTION_LENGTH === true && | |
$attribute === TARGET_DESCRIPTION_ATTRIBUTE && | |
strlen($value) < MIN_TARGET_DESCRIPTION_LENGTH) | |
{ | |
$targetsWithTooShortDescription[] = $actualTargetName; | |
} | |
} | |
if (!in_array(TARGET_DESCRIPTION_ATTRIBUTE, $allUsedTragetAttributes)) { | |
$targetsWithNoDescription[] = $actualTargetName; | |
} | |
} | |
if (count($targetsWithNoDescription) > 0) { | |
if (count($targetsWithNoDescription) > 1) { | |
$violations[] = sprintf( | |
"Build targets [ %s ] don't have mandatory descriptions.", | |
implode(', ', $targetsWithNoDescription) | |
); | |
} else { | |
$violations[] = sprintf( | |
"Build target [ %s ] doesn't have a mandatory description.", | |
implode(', ', $targetsWithNoDescription) | |
); | |
} | |
} | |
if (count($targetsWithTooShortDescription) > 0) { | |
if (count($targetsWithTooShortDescription) > 1) { | |
$violations[] = sprintf( | |
"Build targets [ %s ] don't have an adequate target description length.", | |
implode(', ', $targetsWithTooShortDescription), | |
MIN_TARGET_DESCRIPTION_LENGTH | |
); | |
} else { | |
$violations[] = sprintf( | |
"Build target [ %s ] doesn't have an adequate target description length.", | |
implode(', ', $targetsWithTooShortDescription), | |
MIN_TARGET_DESCRIPTION_LENGTH | |
); | |
} | |
} | |
} | |
return $violations; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment