public
Last active

A Git pre-commit hook rejecting no-descriptive Phing and Ant build files

  • Download Gist
pre-commit-phing
PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
#!/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;
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.