The branch, master on karma.git has been updated discards 002a63c12dc1eadb3885d9fc5c6b97cf3863913a (commit) via c388fdc594d5cf8f8f695eef47c179e2e1acc39e (commit)
This update added new revisions after undoing existing revisions. That is to say, the old revision is not a strict subset of the new revision. This situation occurs when you --force push a change and generate a repository containing something like this: * -- * -- B -- O -- O -- O (002a63c12dc1eadb3885d9fc5c6b97cf3863913a) \ N -- N -- N (c388fdc594d5cf8f8f695eef47c179e2e1acc39e) When this happens we assume that you've already had alert emails for all of the O revisions, and so we here report only the revisions in the N branch from the common base, B. http://git.php.net/?p=karma.git;a=log;h=c388fdc594d5cf8f8f695eef47c179e2e1acc39e;hp=002a63c12dc1eadb3885d9fc5c6b97cf3863913a Summary of changes: hooks/pre-receive | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) -- Log ---------------------------------------- commit c388fdc594d5cf8f8f695eef47c179e2e1acc39e 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..6a7c29f 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,18 @@ 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(); -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