Skip to content

Instantly share code, notes, and snippets.

@commana
Created February 24, 2012 18:23
Show Gist options
  • Save commana/1902690 to your computer and use it in GitHub Desktop.
Save commana/1902690 to your computer and use it in GitHub Desktop.
Git pre-receive hook with PHP_CodeSniffer support
#!/usr/bin/env ruby
incoming = []
$stdin.each_line do |line|
segments = line.split(" ")
incoming.push({
"old" => segments[0],
"new" => segments[1],
"ref" => segments[2]
})
end
changes = []
incoming.each do |entry|
if entry["new"].match(/0+/) then
next
end
segments = `git diff-tree -r #{entry["new"]}`.split(" ")
changes.push({
"hash" => segments[4],
"mode" => segments[5],
"file" => segments[6]
})
end
def with_changes(changes)
changes.each do |change|
type = `git cat-file -t #{change["hash"]}`.strip
if type != "blob": next end
content = `git cat-file blob #{change["hash"]}`
yield change, content
if $?.to_i != 0 then
exit 1
end
end
end
def run_program(cmd, content)
output = ""
IO.popen(cmd + " 2>&1", "w+") do |p|
p.puts content
p.close_write
output = p.read
end
output
end
with_changes(changes) do |change, content|
puts run_program("php -l", content).gsub(/ -/, " #{change["file"]}")
end
with_changes(changes) do |change, content|
path = File.expand_path(File.dirname(__FILE__))
puts run_program(path + "/pre-receive.phpcs --standard=eStudy #{change["file"]}", content)
end
puts "FIN!"
exit 1
#!/usr/bin/php
<?php
/**
* A commit hook for Git.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Jack Bates <ms419@freezone.co.uk>
* @author Greg Sherwood <gsherwood@squiz.net>
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
* @version CVS: $Id: phpcs-svn-pre-commit,v 1.5 2009/01/14 02:44:18 squiz Exp $
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) {
include_once dirname(__FILE__).'/../CodeSniffer/CLI.php';
} else {
include_once 'PHP/CodeSniffer/CLI.php';
}
/**
* A class to process command line options.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Christoph Thelen <christoph.thelen@mni.thm.de>
* @author Jack Bates <ms419@freezone.co.uk>
* @author Greg Sherwood <gsherwood@squiz.net>
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
* @version Release: @package_version@
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
class PHP_CodeSniffer_Git_Hook extends PHP_CodeSniffer_CLI
{
/**
* Get a list of default values for all possible command line arguments.
*
* @return array
*/
public function getDefaults()
{
$defaults = parent::getDefaults();
$defaults['svnArgs'] = array();
return $defaults;
}//end getDefaults()
/**
* Processes an unknown command line argument.
*
* All unkown args are sent to SVN commands.
*
* @param string $arg The command line argument.
* @param int $pos The position of the argument on the command line.
* @param array $values An array of values determined from CLI args.
*
* @return array The updated CLI values.
* @see getCommandLineValues()
*/
public function processUnknownArgument($arg, $pos, $values)
{
$values['svnArgs'][] = $arg;
return $values;
}//end processUnknownArgument()
/**
* Runs PHP_CodeSniffer over files are directories.
*
* @param array $values An array of values determined from CLI args.
*
* @return int The number of error and warning messages shown.
* @see getCommandLineValues()
*/
public function process($values=array())
{
if (empty($values) === true) {
$values = parent::getCommandLineValues();
}
$values['standard'] = $this->validateStandard($values['standard']);
if (PHP_CodeSniffer::isInstalledStandard($values['standard']) === false) {
// They didn't select a valid coding standard, so help them
// out by letting them know which standards are installed.
echo 'ERROR: the "'.$values['standard'].'" coding standard is not installed. ';
$this->printInstalledStandards();
exit(2);
}
$phpcs = new PHP_CodeSniffer($values['verbosity'], $values['tabWidth']);
// Set file extensions if they were specified. Otherwise,
// let PHP_CodeSniffer decide on the defaults.
if (empty($values['extensions']) === false) {
$phpcs->setAllowedFileExtensions($values['extensions']);
}
// Set ignore patterns if they were specified.
if (empty($values['ignored']) === false) {
$phpcs->setIgnorePatterns($values['ignored']);
}
// Initialize PHP_CodeSniffer listeners but don't process any files.
$phpcs->process(array(), $values['standard'], $values['sniffs']);
$handle = fopen("php://stdin", 'r');
if ($handle === false) {
echo 'ERROR: Could not read stdin.'.PHP_EOL.PHP_EOL;
exit(2);
}
$contents = stream_get_contents($handle);
fclose($handle);
$path = array_shift($values['svnArgs']);
$phpcs->processFile($path, $contents);
return parent::printErrorReport(
$phpcs,
$values['reports'],
$values['showSources'],
$values['reportFile'],
$values['reportWidth']
);
}//end process()
/**
* Prints out the usage information for this script.
*
* @return void
*/
public function printUsage()
{
parent::printUsage();
echo PHP_EOL;
echo ' Each additional argument is passed to the `svnlook changed ...`'.PHP_EOL;
echo ' and `svnlook cat ...` commands. The report is printed on standard output,'.PHP_EOL;
echo ' however Subversion displays only standard error to the user, so in a'.PHP_EOL;
echo ' pre-commit hook, this script should be invoked as follows:'.PHP_EOL;
echo PHP_EOL;
echo ' '.basename($_SERVER['argv'][0]).' ... "$REPOS" -t "$TXN" >&2 || exit 1'.PHP_EOL;
}//end printUsage()
}//end class
$phpcs = new PHP_CodeSniffer_Git_Hook();
$phpcs->checkRequirements();
$numErrors = $phpcs->process();
if ($numErrors !== 0) {
exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment