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

Reply via email to