Skip to content

Instantly share code, notes, and snippets.

@raphaelstolt
Created April 22, 2011 15:39
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
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
#!/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