The branch, master on karma.git has been updated via 002a63c12dc1eadb3885d9fc5c6b97cf3863913a (commit) via f3d11575dc77ab1cc7eda290a4366122b923b1c1 (commit) via 51ca66d43a28b1c50cfd4e994712bc577e440e52 (commit) via c358027fd70d57b60f12b620dc78f6fe7c384aec (commit) from 8d595325d65b7de86651483a1705a0ee2a4b4bd5 (commit)
http://git.php.net/?p=karma.git;a=log;h=002a63c12dc1eadb3885d9fc5c6b97cf3863913a;hp=8d595325d65b7de86651483a1705a0ee2a4b4bd5 Summary of changes: hooks/pre-receive | 29 +++++++++----- lib/Git.php | 25 ++++++++++++ lib/Git/PushInformation.php | 86 +++++++++++++++++++++++++++++++++++++++++++ lib/Git/ReceiveHook.php | 43 +++++++++------------ 4 files changed, 148 insertions(+), 35 deletions(-) create mode 100644 lib/Git.php create mode 100644 lib/Git/PushInformation.php -- Log ---------------------------------------- commit 002a63c12dc1eadb3885d9fc5c6b97cf3863913a Author: David Soria Parra <d...@php.net> Date: Fri Mar 2 03:06:30 2012 +0100 Require access to all the repository in case we do a forced push A forced push can happen when you delete a tag or rewrite commits. We allow this, but only if you have access to the root of the repository. diff --git a/hooks/pre-receive b/hooks/pre-receive index 46195a4..48da31b 100755 --- a/hooks/pre-receive +++ b/hooks/pre-receive @@ -11,11 +11,15 @@ namespace Karma; const KARMA_FILE = '/git/checkout/SVNROOT/global_avail'; const REPOSITORY_PATH = '/git/repositories'; +const LIB_PATH = '/git/checkout/karma/lib'; -set_include_path('/git/checkout/karma/lib' . +set_include_path( + getenv('KARMA_LIB_PATH') ?: LIB_PATH . PATH_SEPARATOR . get_include_path()); +include 'Git.php'; +include 'Git/PushInformation.php'; include 'Git/ReceiveHook.php'; function deny($reason) @@ -107,16 +111,19 @@ if ($hook->isKarmaIgnored()) { accept("No karma check necessary. Thank you for your contribution.\n"); } -$requested_paths = $hook->getReceivedPaths(); +$repo_name = $hook->getRepositoryName(); +$pi = new \Git\PushInformation($hook); +$req_paths = ($pi->isForced()) ? [''] : $hook->getReceivedPaths(); +var_dump($pi->isForced()); -if (empty($requested_paths)) { +if (empty($req_paths)) { deny("We cannot figure out what you comitted!"); } -$prefix = sprintf('%s/', $hook->getRepositoryName()); +$prefix = sprintf('%s/', $repo_name); $avail_lines = $hook->getKarmaFile(); -$requested_paths = array_map(function ($x) use ($prefix) { return $prefix . $x;}, $requested_paths); -$unavail_paths = get_unavail_paths($user, $requested_paths, $avail_lines); +$req_paths = array_map(function ($x) use ($prefix) { return $prefix . $x;}, $req_paths); +$unavail_paths = get_unavail_paths($user, $req_paths, $avail_lines); if (!empty($unavail_paths)) { deny(sprintf( diff --git a/lib/Git/PushInformation.php b/lib/Git/PushInformation.php new file mode 100644 index 0000000..edf73dc --- /dev/null +++ b/lib/Git/PushInformation.php @@ -0,0 +1,86 @@ +<?php +namespace Git; + +class PushInformation +{ + const GIT_EXECUTABLE = 'git'; + + private $karmaFile; + private $repositoryBasePath; + + private $hook = null; + private $repourl = null; + + public function __construct(ReceiveHook $hook) + { + $this->repourl = \Git::getRepositoryPath(); + $this->hook = $hook; + } + + /** + * Returns the common ancestor revision for two given revisions + * + * Returns false if no sha1 was returned. Throws an exception if calling + * git fails. + * + * @return boolean + */ + protected function mergeBase($oldrev, $newrev) + { + $baserev = exec(sprintf('%s --git-dir=%s merge-base %s %s', + \Git::GIT_EXECUTABLE, + $this->repourl, + escapeshellarg($oldrev), + escapeshellarg($newrev)), $output, $retval); + + $baserev = trim($baserev); + + if (0 !== $retval) { + throw new \Exception('Failed to call git'); + } + + if (40 != strlen($baserev)) { + return false; + } + + return $baserev; + } + + /** + * Returns true if merging $newrev would be fast forward + * + * @return boolean + */ + public function isFastForward() + { + $result = $this->hook->mapInput( + function ($oldrev, $newrev) { + if ($oldrev == \Git::NULLREV) { + return true; + } + return $oldrev == $this->mergeBase($oldrev, $newrev); + }); + + return array_reduce($result, function($a, $b) { return $a && $b; }, true); + } + + /** + * Returns true if updating the refs would fail if push is not forced. + * + * @return boolean + */ + public function isForced() + { + $result = $this->hook->mapInput( + function($oldrev, $newrev) { + if ($oldrev == \Git::NULLREV) { + return false; + } else if ($newrev == \Git::NULLREV) { + return true; + } + return $newrev == $this->mergeBase($oldrev, $newrev); + }); + + return array_reduce($result, function($a, $b) { return $a || $b; }, false); + } +} diff --git a/lib/Git/ReceiveHook.php b/lib/Git/ReceiveHook.php index e17d055..b51a5f4 100644 --- a/lib/Git/ReceiveHook.php +++ b/lib/Git/ReceiveHook.php @@ -42,6 +42,15 @@ class ReceiveHook return ''; } + public function mapInput(callable $fn) { + $result = []; + foreach($this->hookInput() as $input) { + $result[] = $fn($input['old'], $input['new']); + } + + return $result; + } + /** * Parses the input from git. * @@ -100,12 +109,12 @@ class ReceiveHook sprintf("%s --git-dir=%s for-each-ref --format='%%(refname)' 'refs/heads/*'", \Git::GIT_EXECUTABLE, $repourl), $output); /* do we have heads? otherwise it's a new repo! */ - $heads = implode(' ', $output); if (count($output) > 0) { $not = array_map( function($x) { return sprintf('--not %s', escapeshellarg($x)); - }, $heads); + }, $output); + $not = implode(' ', $not); } exec( sprintf('%s --git-dir=%s log --name-only --pretty=format:"" %s %s', Thank you for your contribution. -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php