Last active
December 14, 2015 05:40
-
-
Save troelskn/5037326 to your computer and use it in GitHub Desktop.
Some git-hooks for php development
This file contains 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
#!/bin/sh | |
# /var/git/$REPONAME.git/hooks/ | |
# This script just multiplexes the hook to multiple sub-scripts, since you can only have one hooks/post-receive | |
while read oldrev newrev refname | |
do | |
echo $oldrev $newrev $refname | /usr/share/doc/git-core/contrib/hooks/post-receive-email | |
echo $oldrev $newrev $refname | /home/buildbot/buildbot/scripts/post-receive-hook | |
done |
This file contains 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/env php | |
<?php | |
// /home/buildbot/buildbot/scripts/post-receive-hook | |
require_once(dirname(realpath(__FILE__)).'/../bootstrap.inc.php'); | |
$REPOSITORY = basename(getcwd()); | |
foreach (explode("\n", trim(file_get_contents("php://stdin"))) as $line) { | |
list($OLDREV, $NEWREV, $REFNAME) = explode(" ", $line); | |
$sth = db()->prepare("insert into queue (oldrev, newrev, refname, repository, queued_at, result, build_started_at, build_completed_at, output) values (?, ?, ?, ?, now(), null, null, null, null)"); | |
$sth->execute(array($OLDREV, $NEWREV, $REFNAME, $REPOSITORY)); | |
} |
This file contains 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/env php | |
<?php | |
// /var/git/$REPONAME.git/hooks/pre-receive | |
// Runs various checks on the inbound push and rejects if it isn't found credible | |
// There are some edge cases unhandled, so you may have to disable for some push'es | |
function verbose($str) { | |
// echo $str, "\n"; | |
} | |
function exec_proc($command, $stdin = null) { | |
$descriptorspec = array( | |
0 => array("pipe", "r"), // stdin | |
1 => array("pipe", "w"), // stdout | |
2 => array("pipe", "w") // stderr | |
); | |
$process = proc_open($command, $descriptorspec, $pipes); | |
if (is_resource($process)) { | |
if ($stdin) { | |
fwrite($pipes[0], $stdin); | |
} | |
fclose($pipes[0]); | |
$stdout = stream_get_contents($pipes[1]); | |
fclose($pipes[1]); | |
$stderr = stream_get_contents($pipes[2]); | |
fclose($pipes[2]); | |
$exit_code = proc_close($process); | |
return array($exit_code, $stdout, $stderr); | |
} | |
throw new Exception("Unable to open subprocess"); | |
} | |
function git() { | |
$args = func_get_args(); | |
$command = "git " . implode(" ", array_map('escapeshellarg', $args)); | |
verbose("> {$command}"); | |
return exec_proc($command); | |
} | |
function get_changed_files($base, $commit) { | |
list($code, $stdout, $stderr) = git('diff', '--numstat', '--name-only', '--diff-filter=ACMRTUXB', '--ignore-submodules', "{$base}..{$commit}"); | |
if ($code != 0) { | |
echo $stderr; | |
echo $stdout; | |
throw new Exception("Subprocess exited with error"); | |
} | |
return explode("\n", $stdout); | |
} | |
function get_new_file($filename, $commit) { | |
list($code, $stdout, $stderr) = git('show', "{$commit}:{$filename}"); | |
if ($code != 0) { | |
echo $stderr; | |
echo $stdout; | |
throw new Exception("Subprocess exited with error"); | |
} | |
return $stdout; | |
} | |
function store_file($fname, $contents) { | |
global $tmpdir; | |
if ($tmpdir === null) { | |
$tmpdir = tempnam("/tmp", "php"); | |
unlink($tmpdir); | |
mkdir($tmpdir); | |
} | |
$fullname = $tmpdir.'/'.$fname; | |
if (!is_dir(dirname($fullname))) { | |
mkdir(dirname($fullname), 0777, true); | |
} | |
file_put_contents($fullname, $contents); | |
return $fullname; | |
} | |
function php_lint($filename) { | |
$command = "php -l " . escapeshellarg($filename); | |
verbose("> {$command}"); | |
list($code, $stdout, $stderr) = exec_proc($command); | |
if ($code != 0) { | |
echo trim($stdout), "\n"; | |
} | |
return $code == 0; | |
} | |
function detect_conflict_markers($fname, $contents) { | |
$result = true; | |
$linenum = 0; | |
foreach (explode("\n", $contents) as $line) { | |
$linenum++; | |
if (preg_match('/^(<<<<<<<|>>>>>>>)/', $line)) { | |
echo "Leftover conflict marker found in {$fname} on line {$linenum}\n"; | |
$result = false; | |
} | |
} | |
return $result; | |
} | |
$line = file_get_contents('php://stdin'); | |
list($base, $commit, $ref) = explode(" ", trim($line)); | |
if ($base == "0000000000000000000000000000000000000000") { | |
verbose("Initial push received. Expecting everything to be fine"); | |
exit; | |
} | |
$modified = get_changed_files($base, $commit); | |
$result = true; | |
foreach ($modified as $fname) { | |
$contents = get_new_file($fname, $commit); | |
if (preg_match('/[.]php$/', $fname)) { | |
$filename = store_file($fname, $contents); | |
$result = php_lint($filename) && $result; | |
} | |
$result = detect_conflict_markers($fname, $contents) && $result; | |
} | |
if (isset($tmpdir)) { | |
$command = "rm -rf ".escapeshellarg($tmpdir); | |
exec_proc($command); | |
verbose("> {$command}"); | |
} | |
if (!$result) { | |
echo "Aborting.\n"; | |
exit(1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment