The branch PHP_POST_RECEIVE on karma.git has been updated
via 4d61fb520544f543d8c6120fb02548de4bfc2f06 (commit)
via fc047465fda04319c5a14707d7709fff1f2a3f57 (commit)
via b1240df188897323ee2c550d62fcab4a245bec37 (commit)
via fc9c78fe12aa756060684e565adf8fb8a4373120 (commit)
via c388fdc594d5cf8f8f695eef47c179e2e1acc39e (commit)
from 8507e88c7abde403c9bdf1b385d5d4f2b284d1f3 (commit)
http://git.php.net/?p=karma.git;a=log;h=4d61fb520544f543d8c6120fb02548de4bfc2f06;hp=8507e88c7abde403c9bdf1b385d5d4f2b284d1f3
Summary of changes:
hooks/pre-receive | 10 +++-
lib/Git.php | 29 ++++++++++++--
lib/Git/PostReceiveHook.php | 88 +++++++++++++++++--------------------------
lib/Git/PreReceiveHook.php | 67 ++++++++++-----------------------
lib/Git/PushInformation.php | 18 ++-------
lib/Git/ReceiveHook.php | 55 ++++++++++++++++++++++++--
6 files changed, 141 insertions(+), 126 deletions(-)
-- Log ----------------------------------------
commit 4d61fb520544f543d8c6120fb02548de4bfc2f06
Author: Alexander Moskaliov <[email protected]>
Date: Sun Mar 11 13:13:29 2012 +0400
next part of refactoring
diff --git a/lib/Git.php b/lib/Git.php
index ee3e95c..87e5fa9 100644
--- a/lib/Git.php
+++ b/lib/Git.php
@@ -5,6 +5,8 @@ class Git
const GIT_EXECUTABLE = 'git';
const NULLREV = '0000000000000000000000000000000000000000';
+ private static $repositoryPath = null;
+
/**
* Returns the path to the current repository.
*
@@ -15,11 +17,30 @@ class Git
*/
public static function getRepositoryPath()
{
- $path = exec(sprintf('%s rev-parse --git-dir', self::GIT_EXECUTABLE));
- if (!is_dir($path)) {
- return false;
+ if (is_null(self::$repositoryPath)) {
+ $path = exec(sprintf('%s rev-parse --git-dir',
self::GIT_EXECUTABLE));
+ self::$repositoryPath = is_dir($path) ? realpath($path) : false;
}
- return realpath($path);
+ return self::$repositoryPath;
+ }
+
+ /**
+ * Run git shell command and return result
+ *
+ * @param $cmd string
+ * @param $arg string
+ * @param ... string
+ * @return string
+ */
+ public static function gitExec($cmd)
+ {
+ $cmd = self::GIT_EXECUTABLE . " --git-dir=" .
self::getRepositoryPath() . " " . $cmd;
+ $args = func_get_args();
+ array_shift($args);
+ $cmd = vsprintf($cmd, $args);
+ $output = shell_exec($cmd);
+ if ($output === NULL) throw new \Exception('Failed to call git');
+ return $output;
}
}
diff --git a/lib/Git/PostReceiveHook.php b/lib/Git/PostReceiveHook.php
index 0f36aa0..1d5daee 100644
--- a/lib/Git/PostReceiveHook.php
+++ b/lib/Git/PostReceiveHook.php
@@ -92,20 +92,22 @@ class PostReceiveHook extends ReceiveHook
if ($changeType == self::TYPE_UPDATED) {
// check if push was with --force option
- if ($replacedRevisions = $this->getRevisions($newrev . '..' .
$oldrev)) {
+ if ($replacedRevisions =
$this->getRevisions(escapeshellarg($newrev . '..' . $oldrev))) {
$message .= "Discarded revisions: \n" . implode("\n",
$replacedRevisions) . "\n";
}
// git rev-list old..new
- $revisions = $this->getRevisions($oldrev . '..' . $newrev);
+ $revisions = $this->getRevisions(escapeshellarg($oldrev . '..'
. $newrev));
} else {
// for new branch we write log about new commits only
- $revisions = $this->getRevisions($newrev. ' --not ' .
implode(' ', array_diff($this->allBranches, $this->newBranches)));
+ $revisions = $this->getRevisions(
+ escapeshellarg($newrev) . ' --not ' . implode(' ',
$this->escapeArrayShellArgs(array_diff($this->allBranches, $this->newBranches)))
+ );
foreach ($this->updatedBranches as $refname) {
if
($this->isRevExistsInBranches($this->refs[$refname]['old'], [$name])) {
- $this->cacheRevisions($name,
$this->getRevisions($this->refs[$refname]['old'] . '..' . $newrev));
+ $this->cacheRevisions($name,
$this->getRevisions(escapeshellarg($this->refs[$refname]['old'] . '..' .
$newrev)));
}
}
}
@@ -115,9 +117,9 @@ class PostReceiveHook extends ReceiveHook
if (count($revisions)) {
$message .= "--------LOG--------\n";
foreach ($revisions as $revision) {
- $diff = $this->gitExecute(
+ $diff = \Git::gitExec(
'diff-tree --stat --pretty=medium -c %s',
- $revision
+ escapeshellarg($revision)
);
$message .= $diff."\n\n";
@@ -185,7 +187,7 @@ class PostReceiveHook extends ReceiveHook
private function getTagInfo($tag)
{
$info = "Target:\n";
- $info .= $this->gitExecute('diff-tree --stat --pretty=medium -c %s',
$tag);
+ $info .= \Git::gitExec('diff-tree --stat --pretty=medium -c %s',
escapeshellarg($tag));
return $info;
}
@@ -195,14 +197,14 @@ class PostReceiveHook extends ReceiveHook
*/
private function getAnnotatedTagInfo($tag)
{
- $tagInfo = $this->gitExecute('for-each-ref --format="%%(*objectname)
%%(taggername) %%(taggerdate)" %s', $tag);
- list($target, $tagger, $taggerdate) = explode(' ', $tagInfo);
+ $tagInfo = \Git::gitExec('for-each-ref --format="%%(*objectname)
%%(taggername) %%(taggerdate)" %s', escapeshellarg($tag));
+ list($target, $tagger, $taggerDate) = explode(' ', $tagInfo);
$info = "Tagger: " . $tagger . "\n";
- $info .= "Date: " . $taggerdate . "\n";
- $info .= $this->gitExecute("cat-file tag %s | sed -e '1,/^$/d'",
$tag)."\n";
+ $info .= "Date: " . $taggerDate . "\n";
+ $info .= \Git::gitExec("cat-file tag %s | sed -e '1,/^$/d'",
escapeshellarg($tag))."\n";
$info .= "Target:\n";
- $info .= $this->gitExecute('diff-tree --stat --pretty=medium -c %s',
$target);
+ $info .= \Git::gitExec('diff-tree --stat --pretty=medium -c %s',
escapeshellarg($target));
return $info;
}
@@ -212,16 +214,20 @@ class PostReceiveHook extends ReceiveHook
*/
private function isAnnotatedTag($rev)
{
- return trim($this->gitExecute('for-each-ref --format="%%(objecttype)"
%s', $rev)) == 'tag';
+ return trim(\Git::gitExec('for-each-ref --format="%%(objecttype)" %s',
escapeshellarg($rev))) == 'tag';
}
/**
- * @param $revRange string
+ * Get list of revisions for $revRange
+ *
+ * Required already escaped string in $revRange!!!
+ *
+ * @param $revRange string A..B or A ^B C --not D etc.
* @return array
*/
private function getRevisions($revRange)
{
- $output = $this->gitExecute(
+ $output = \Git::gitExec(
'rev-list %s',
$revRange
);
@@ -233,7 +239,7 @@ class PostReceiveHook extends ReceiveHook
private function getCommitInfo($revision)
{
- $raw = $this->gitExecute('rev-list -n 1
--format="%%P%%n%%an%%n%%ae%%n%%aD%%n%%cn%%n%%ce%%n%%cD%%n%%B" %s', $revision);
+ $raw = \Git::gitExec('rev-list -n 1
--format="%%P%%n%%an%%n%%ae%%n%%aD%%n%%cn%%n%%ce%%n%%cD%%n%%B" %s',
escapeshellarg($revision));
$raw = explode("\n", $raw, 9); //8 elements separated by \n, last
element - log message, first(skipped) element - "commit sha"
return [
'parents' => $raw[1], // %P
@@ -279,13 +285,13 @@ class PostReceiveHook extends ReceiveHook
{
$info = $this->getCommitInfo($revision);
- $paths = $this->getChangedPaths($revision);
+ $paths = $this->getChangedPaths(escapeshellarg($revision));
$pathsString = '';
foreach ($paths as $path => $action)
{
$pathsString .= ' ' . $action . ' ' . $path . "\n";
}
- $diff = $this->gitExecute('diff-tree -c -p %s', $revision);
+ $diff = \Git::gitExec('diff-tree -c -p %s',
escapeshellarg($revision));
$mail = new \Mail();
$mail->setSubject($this->emailPrefix . '[commit] ' .
$this->getRepositoryName() . ' ' . implode(' ', array_keys($paths)));
@@ -364,7 +370,7 @@ class PostReceiveHook extends ReceiveHook
* @return bool
*/
private function isRevExistsInBranches($revision, array $branches) {
- return !(bool) $this->gitExecute('rev-list --max-count=1 %s --not %s',
$revision, implode(' ', $branches));
+ return !(bool) \Git::gitExec('rev-list --max-count=1 %s --not %s',
escapeshellarg($revision), implode(' ',
$this->escapeArrayShellArgs($branches)));
}
}
diff --git a/lib/Git/PreReceiveHook.php b/lib/Git/PreReceiveHook.php
index 20672a9..2e93012 100644
--- a/lib/Git/PreReceiveHook.php
+++ b/lib/Git/PreReceiveHook.php
@@ -19,7 +19,7 @@ class PreReceiveHook extends ReceiveHook
*/
public function isKarmaIgnored()
{
- return 'true' === exec(sprintf('%s config karma.ignored',
\Git::GIT_EXECUTABLE));
+ return 'true' === \Git::gitExec('%s config karma.ignored');
}
public function mapInput(callable $fn) {
@@ -68,7 +68,7 @@ class PreReceiveHook extends ReceiveHook
$parsed_input);
/* flattern the array */
- $flattend = array_reduce($paths, 'array_merge', []);
+ $paths = array_reduce($paths, 'array_merge', []);
return array_unique($paths);
diff --git a/lib/Git/PushInformation.php b/lib/Git/PushInformation.php
index edf73dc..4be1c0f 100644
--- a/lib/Git/PushInformation.php
+++ b/lib/Git/PushInformation.php
@@ -3,17 +3,11 @@ 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;
}
@@ -27,17 +21,10 @@ class PushInformation
*/
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 = \Git::gitExec('merge-base %s %s', escapeshellarg($oldrev),
escapeshellarg($newrev));
$baserev = trim($baserev);
- if (0 !== $retval) {
- throw new \Exception('Failed to call git');
- }
if (40 != strlen($baserev)) {
return false;
diff --git a/lib/Git/ReceiveHook.php b/lib/Git/ReceiveHook.php
index 58fe0c3..650a855 100644
--- a/lib/Git/ReceiveHook.php
+++ b/lib/Git/ReceiveHook.php
@@ -13,34 +13,16 @@ abstract class ReceiveHook
const REF_TAG = 1;
private $repositoryName = '';
- protected $repositoryPath = '';
public function __construct($basePath)
{
- $this->repositoryPath = \Git::getRepositoryPath();
- $rel_path = str_replace($basePath, '', $this->repositoryPath);
+ $rel_path = str_replace($basePath, '', \Git::getRepositoryPath());
if (preg_match('@/(.*\.git)$@', $rel_path, $matches)) {
$this->repositoryName = $matches[1];
}
}
/**
- * Run git shell command and return result
- *
- * @param $cmd string
- * @return string
- */
- protected function gitExecute($cmd)
- {
- $cmd = \Git::GIT_EXECUTABLE . " --git-dir=" . $this->repositoryPath .
" " . $cmd;
- $args = func_get_args();
- array_shift($args);
- $cmd = vsprintf($cmd, $args);
- $output = shell_exec($cmd);
- return $output;
- }
-
- /**
* Escape array items by escapeshellarg function
* @param $args
* @return array array with escaped items
@@ -68,12 +50,15 @@ abstract class ReceiveHook
* Return array with changed paths as keys and change type as values
* If commit is merge commit change type will have more than one char
* (for example "MM")
+ *
+ * Required already escaped string in $revRange!!!
+ *
* @param $revRange
* @return array
*/
protected function getChangedPaths($revRange)
{
- $raw = $this->gitExecute('show --name-status --pretty="format:" %s',
$revRange);
+ $raw = \Git::gitExec('show --name-status --pretty="format:" %s',
$revRange);
$paths = [];
if (preg_match_all('/([ACDMRTUXB*]+)\s+([^\n\s]+)/', $raw , $matches,
PREG_SET_ORDER)) {
foreach($matches as $item) {
@@ -91,7 +76,7 @@ abstract class ReceiveHook
*/
protected function getAllBranches()
{
- $branches = explode("\n", $this->gitExecute('for-each-ref
--format="%%(refname)" "refs/heads/*"'));
+ $branches = explode("\n", \Git::gitExec('for-each-ref
--format="%%(refname)" "refs/heads/*"'));
if ($branches[0] == '') $branches = [];
return $branches;
}
commit fc047465fda04319c5a14707d7709fff1f2a3f57
Merge: b1240df fc9c78f
Author: Alexander Moskaliov <[email protected]>
Date: Sun Mar 11 12:02:33 2012 +0400
Merge branch 'master' of git.php.net:/karma into PHP_POST_RECEIVE
* 'master' of git.php.net:/karma:
No comma needed
Require access to all the repository in case we do a forced push
Conflicts:
hooks/post-receive
hooks/pre-receive
lib/Git/PushInformation.php
lib/Git/ReceiveHook.php
diff --cc hooks/pre-receive
index 3370dc4,6a7c29f..c0e838d
--- a/hooks/pre-receive
+++ b/hooks/pre-receive
@@@ -16,8 -18,9 +18,10 @@@ set_include_path
PATH_SEPARATOR .
get_include_path());
+ include 'Git.php';
+ include 'Git/PushInformation.php';
include 'Git/ReceiveHook.php';
+include 'Git/PreReceiveHook.php';
function deny($reason)
{
commit b1240df188897323ee2c550d62fcab4a245bec37
Author: Alexander Moskaliov <[email protected]>
Date: Sun Mar 11 11:40:47 2012 +0400
second part of refactoring
diff --git a/lib/Git/PostReceiveHook.php b/lib/Git/PostReceiveHook.php
index 8250559..0f36aa0 100644
--- a/lib/Git/PostReceiveHook.php
+++ b/lib/Git/PostReceiveHook.php
@@ -34,28 +34,6 @@ class PostReceiveHook extends ReceiveHook
}
/**
- * @param $cmd string
- * @return string
- */
- private function gitExecute($cmd)
- {
- $cmd = \Git::GIT_EXECUTABLE . " --git-dir=" . $this->repositoryPath .
" " . $cmd;
- $args = func_get_args();
- array_shift($args);
- $cmd = vsprintf($cmd, $args);
- $output = shell_exec($cmd);
- return $output;
- }
-
- /**
- * @return array
- */
- private function getAllBranches()
- {
- return explode("\n", $this->gitExecute('for-each-ref
--format="%%(refname)" "refs/heads/*"'));
- }
-
- /**
*
*/
public function process()
@@ -269,24 +247,14 @@ class PostReceiveHook extends ReceiveHook
];
}
- private function getCommitChangedPaths($revision)
- {
- $raw = $this->gitExecute('show --name-status --pretty="format:" %s',
$revision);
- $paths = [];
- if (preg_match_all('/([ACDMRTUXB*]+)\s+([^\n\s]+)/', $raw , $matches,
PREG_SET_ORDER)) {
- foreach($matches as $item) {
- $paths[$item[2]] = $item[1];
- }
- }
- return $paths;
- }
-
/**
* Send mail about commit.
* Subject: [git] [commit] %PROJECT% %PATHS%
* Body:
+ * Commit: %SHA%
* Author: %USER% Thu, 08 Mar 2012 12:39:48
+0000
* Committer: %USER% Thu, 08 Mar 2012
12:39:48 +0000
+ * Parents: %SHA_PARENTS%
*
* Commit: http://git.php.net/?p=%PROJECT_PATH%;a=commitdiff;h=%SHA%
*
@@ -311,7 +279,7 @@ class PostReceiveHook extends ReceiveHook
{
$info = $this->getCommitInfo($revision);
- $paths = $this->getCommitChangedPaths($revision);
+ $paths = $this->getChangedPaths($revision);
$pathsString = '';
foreach ($paths as $path => $action)
{
@@ -335,27 +303,35 @@ class PostReceiveHook extends ReceiveHook
if (strlen($pathsString) < 8192) {
+ // inline changed paths
$message .= "Changed paths:\n" . $pathsString . "\n";
if ((strlen($pathsString) + strlen($diff)) < 8192) {
+ // inline diff
$message .= "Diff:\n" . $diff . "\n";
} else {
+ // diff attach
$diffFile = 'diff_' . $revision . '.txt';
$mail->addTextFile($diffFile, $diff);
if ((strlen($message) + $mail->getFileLength($diffFile)) >
262144) {
+ // diff attach exceeded max size
$mail->dropFile($diffFile);
$message .= 'Diff: <Diff exceeded maximum size>';
}
}
} else {
+ // changed paths attach
$pathsFile = 'paths_' . $revision . '.txt';
$mail->addTextFile($pathsFile, $pathsString);
if ((strlen($message) + $mail->getFileLength($pathsFile)) >
262144) {
+ // changed paths attach exceeded max size
$mail->dropFile($pathsFile);
$message .= 'Changed paths: <changed paths exceeded maximum
size>';
} else {
+ // diff attach
$diffFile = 'diff_' . $revision . '.txt';
$mail->addTextFile($diffFile, $diff);
if ((strlen($message) + $mail->getFileLength($pathsFile) +
$mail->getFileLength($diffFile)) > 262144) {
+ // diff attach exceeded max size
$mail->dropFile($diffFile);
}
}
diff --git a/lib/Git/PreReceiveHook.php b/lib/Git/PreReceiveHook.php
index c1e8e03..20672a9 100644
--- a/lib/Git/PreReceiveHook.php
+++ b/lib/Git/PreReceiveHook.php
@@ -3,7 +3,6 @@ namespace Git;
class PreReceiveHook extends ReceiveHook
{
- const INPUT_PATTERN = '@^([0-9a-f]{40}) ([0-9a-f]{40}) (.+)$@i';
private $karmaFile;
@@ -44,59 +43,33 @@ class PreReceiveHook extends ReceiveHook
return file($this->karmaFile);
}
- /**
- * Returns an array of files that were updated between revision $old and
$new.
- *
- * @param string $old The old revison number.
- * @parma string $new The new revison umber.
- *
- * @return array
- */
- private function getReceivedPathsForRange($old, $new)
- {
- $repourl = \Git::getRepositoryPath();
- $output = [];
-
- /* there is the case where we push a new branch. check only new
commits.
- in case its a brand new repo, no heads will be available. */
- if ($old == \Git::NULLREV) {
- exec(
- 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);
- }
- exec(
- sprintf('%s --git-dir=%s log --name-only --pretty=format:"" %s
%s',
- \Git::GIT_EXECUTABLE, $repourl, $not,
- escapeshellarg($new)), $output);
- } else {
- exec(
- sprintf('%s --git-dir=%s log --name-only --pretty=format:""
%s..%s',
- \Git::GIT_EXECUTABLE, $repourl, escapeshellarg($old),
- escapeshellarg($new)), $output);
- }
- return $output;
- }
-
public function getReceivedPaths()
{
$parsed_input = $this->hookInput();
+ // escaped branches
+ $allBranches =$this->escapeArrayShellArgs($this->getAllBranches());
+
$paths = array_map(
- function ($input) {
- return $this->getReceivedPathsForRange($input['old'],
$input['new']);
+ function ($input) use ($allBranches) {
+ $paths = [];
+
+ if ($input['changetype'] == self::TYPE_CREATED) {
+ $paths =
$this->getChangedPaths(escapeshellarg($input['new']) . ' --not ' . implode(' ',
$allBranches));
+ } elseif ($input['changetype'] == self::TYPE_UPDATED) {
+ $paths =
$this->getChangedPaths(escapeshellarg($input['old'] . '..' . $input['new']));
+ } else {
+ // deleted branch. we also need some paths
+ // to check karma
+ }
+
+ return array_keys($paths);
},
$parsed_input);
- /* remove empty lines, and flattern the array */
+ /* flattern the array */
$flattend = array_reduce($paths, 'array_merge', []);
- $paths = array_filter($flattend);
+
return array_unique($paths);
}
diff --git a/lib/Git/ReceiveHook.php b/lib/Git/ReceiveHook.php
index 420cfe9..58fe0c3 100644
--- a/lib/Git/ReceiveHook.php
+++ b/lib/Git/ReceiveHook.php
@@ -25,6 +25,33 @@ abstract class ReceiveHook
}
/**
+ * Run git shell command and return result
+ *
+ * @param $cmd string
+ * @return string
+ */
+ protected function gitExecute($cmd)
+ {
+ $cmd = \Git::GIT_EXECUTABLE . " --git-dir=" . $this->repositoryPath .
" " . $cmd;
+ $args = func_get_args();
+ array_shift($args);
+ $cmd = vsprintf($cmd, $args);
+ $output = shell_exec($cmd);
+ return $output;
+ }
+
+ /**
+ * Escape array items by escapeshellarg function
+ * @param $args
+ * @return array array with escaped items
+ */
+ protected function escapeArrayShellArgs($args)
+ {
+ return array_map('escapeshellarg', $args);
+ }
+
+
+ /**
* Returns the repository name.
*
* A repository name is the path to the repository without the .git.
@@ -38,14 +65,47 @@ abstract class ReceiveHook
}
/**
+ * Return array with changed paths as keys and change type as values
+ * If commit is merge commit change type will have more than one char
+ * (for example "MM")
+ * @param $revRange
+ * @return array
+ */
+ protected function getChangedPaths($revRange)
+ {
+ $raw = $this->gitExecute('show --name-status --pretty="format:" %s',
$revRange);
+ $paths = [];
+ if (preg_match_all('/([ACDMRTUXB*]+)\s+([^\n\s]+)/', $raw , $matches,
PREG_SET_ORDER)) {
+ foreach($matches as $item) {
+ $paths[$item[2]] = $item[1];
+ }
+ }
+ return $paths;
+ }
+
+
+ /**
+ * Return array with branches names in repository
+ *
+ * @return array
+ */
+ protected function getAllBranches()
+ {
+ $branches = explode("\n", $this->gitExecute('for-each-ref
--format="%%(refname)" "refs/heads/*"'));
+ if ($branches[0] == '') $branches = [];
+ return $branches;
+ }
+
+
+ /**
* Parses the input from git.
*
* Git pipes a list of oldrev, newrev and revname combinations
* to the hook. We parse this input. For more information about
* the input see githooks(5).
*
- * Returns an array with 'old', 'new', 'refname' keys for each ref that
- * will be updated.
+ * Returns an array with 'old', 'new', 'refname', 'changetype', 'reftype'
+ * keys for each ref that will be updated.
* @return array
*/
public function hookInput()
Thank you for your contribution.
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php