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

Reply via email to