I want to use a pre-commit hook to check my codefiles before commit them to git. For checking I will use Phing (a PHP build tool).
Here is my pre_commit_hook (MacOS):
#!/bin/sh
echo "Checking files before commit!"
phing -f pre_commit_build.xml || exit 1
And here is the build file:
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyApplication" default="main" basedir=".">
<fileset id="php_project_files" dir="app">
<include name="*.php" />
<include name="**/*.php" />
</fileset>
<target name="main">
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Pre_Commit_Build |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<phingcall target="check_file_names" />
<phingcall target="check_syntax" />
<phingcall target="check_coding_guideline" />
<phingcall target="unit_test" />
</target>
...
<target name="check_file_names">
<property name="failure" value="0" />
<adhoc-task name="check_filename"><![CDATA[
class CheckFileName extends Task {
/** Any filesets of files that should be appended. */
private $filesets = array();
/**
* Nested creator, adds a set of files (nested <fileset> attribute).
* This is for when you don't care what order files get appended.
* @return FileSet
*/
function createFileSet() {
$num = array_push($this->filesets, new FileSet());
return $this->filesets[$num-1];
}
function main() {
// append any files in filesets
foreach($this->filesets as $fs) {
try {
$files = $fs->getDirectoryScanner($this->project)->getIncludedFiles();
foreach ($files as $file) {
if (preg_match('/^[a-z0-9-._]+$/', $file)) {
$this->log("Checked: " . $file);
} else {
$this->log("Error: " . $file . " : Allowed are only a-z 0-9 . - _", Project::MSG_ERR);
$this->project->setProperty('failure', '1');
}
}
} catch (BuildException $be) {
$this->log($be->getMessage(), Project::MSG_WARN);
}
}
}
}
]]></adhoc-task>
<echo message="+------------------------------------------+"/>
<echo message="| |"/>
<echo message="| Check PHP Filenames |"/>
<echo message="| |"/>
<echo message="+------------------------------------------+"/>
<check_filename>
<fileset refid="php_project_files" />
</check_filename>
<echo message="Failure ${failure}" />
...
<target name="check_syntax">
<phplint level="verbose" haltonfailure="false">
<fileset refid="php_project_files" />
</phplint>
</target>
...
</project>
Currently git starts the build process and ALL files of the folder 'app' will be checked (not only those I want to commit). After the process although there will found some fails (i.e. violation of coding guideline) the build process finished and the files will be committed (but they haven't to in this case).
Here are my questions:
How can I tell Phing to use only those files which I want to commit. Or: How can I transfer the information about the files to commit from git to Phing?
How can I "collect" the fails in the targets of the build process (i.e. wrong filenames or violation of a coding guideline) and control, if the build process has to fail.
If one or more target fails, how can I send a return value (1) to git, so that git stops the commit?
How can I define in an adhoc-task that it fails (I have tried it with the property ${failure}?
Thanks a lot for your support!
Stefan
About "only what I want to commit":
In our commit hook, we checkout the files to a temporary staging area and examine those. That's the only way to verify only the staged changes. (Also think of
git add -p
).Return value: Just let your build fail. phing exists with a non-0 status code.