aboutsummaryrefslogtreecommitdiffstats
path: root/git-tools
diff options
context:
space:
mode:
authorMaat <maat-pub@mageia.biz>2012-06-03 21:23:14 +0200
committerMaat <maat-pub@mageia.biz>2012-06-03 21:23:14 +0200
commita06a38ae692551dc1c0416b835ce9924b3d9f7f5 (patch)
tree1bb2c2b3d8d56668585513890afc1d641cead0b1 /git-tools
parent2db884ac2e5122be1db0582b76bf7204783a0c0d (diff)
parent19a47dfbbc4265e33c14d6679b5693d80120db4b (diff)
downloadforums-a06a38ae692551dc1c0416b835ce9924b3d9f7f5.tar
forums-a06a38ae692551dc1c0416b835ce9924b3d9f7f5.tar.gz
forums-a06a38ae692551dc1c0416b835ce9924b3d9f7f5.tar.bz2
forums-a06a38ae692551dc1c0416b835ce9924b3d9f7f5.tar.xz
forums-a06a38ae692551dc1c0416b835ce9924b3d9f7f5.zip
Merging with upstream 3.0.11
Diffstat (limited to 'git-tools')
-rwxr-xr-xgit-tools/hooks/commit-msg143
-rwxr-xr-xgit-tools/hooks/pre-commit65
-rwxr-xr-xgit-tools/hooks/prepare-commit-msg4
-rwxr-xr-xgit-tools/merge.php175
-rwxr-xr-xgit-tools/setup_github_network.php248
5 files changed, 606 insertions, 29 deletions
diff --git a/git-tools/hooks/commit-msg b/git-tools/hooks/commit-msg
index a6777ff9c9..b156d276df 100755
--- a/git-tools/hooks/commit-msg
+++ b/git-tools/hooks/commit-msg
@@ -11,14 +11,30 @@
#
# ln -s ../../git-tools/hooks/commit-msg \\
# .git/hooks/commit-msg
+#
+# You can configure whether invalid commit messages abort commits:
+#
+# git config phpbb.hooks.commit-msg.fatal true (abort)
+# git config phpbb.hooks.commit-msg.fatal false (warn only, do not abort)
+#
+# The default is to warn only.
+#
+# Warning/error messages use color by default if the output is a terminal
+# ("output" here is normally standard error when you run git commit).
+# To force or disable the use of color:
+#
+# git config phpbb.hooks.commit-msg.color true (force color output)
+# git config phpbb.hooks.commit-msg.color false (disable color output)
config_ns="phpbb.hooks.commit-msg";
-if [ "$(git config --bool $config_ns.fatal)" = "false" ]
+if [ "$(git config --bool $config_ns.fatal)" = "true" ]
then
- fatal=0;
-else
fatal=1;
+ severity=Error;
+else
+ fatal=0;
+ severity=Warning;
fi
debug_level=$(git config --int $config_ns.debug || echo 0);
@@ -47,20 +63,86 @@ debug()
quit()
{
- if [ $1 -gt 0 ] && [ $1 -ne $ERR_UNKNOWN ] && [ $fatal -eq 0 ]
+ if [ $1 -eq 0 ] || [ $1 -eq $ERR_UNKNOWN ]
then
+ # success
+ exit 0;
+ elif [ $fatal -eq 0 ]
+ then
+ # problems found but fatal is false
+ complain 'Please run `git commit --amend` and fix the problems mentioned.' 1>&2
exit 0;
else
+ complain "Aborting commit." 1>&2
exit $1;
fi
}
-msg=$(grep -nE '.{81,}' "$1");
+use_color()
+{
+ if [ -z "$use_color_cached" ]
+ then
+ case $(git config --bool $config_ns.color)
+ in
+ false)
+ use_color_cached=1
+ ;;
+ true)
+ use_color_cached=0
+ ;;
+ *)
+ # tty detection in shell:
+ # http://hwi.ath.cx/jsh/list/shext/isatty.sh.html
+ tty 0>/dev/stdout >/dev/null 2>&1
+ use_color_cached=$?
+ ;;
+ esac
+ fi
+ # return value is the flag inverted -
+ # if return value is 0, this means use color
+ return $use_color_cached
+}
+
+complain()
+{
+ if use_color
+ then
+ # Careful: our argument may include arguments to echo like -n
+ # ANSI color codes:
+ # http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html
+ printf "\033[31m\033[1m"
+ if [ "$1" = "-n" ]
+ then
+ echo "$@"
+ printf "\033[0m"
+ else
+ # This will print one trailing space.
+ # Not sure how to avoid this at the moment.
+ echo "$@" $(printf "\033[0m")
+ fi
+ else
+ echo "$@"
+ fi
+}
+
+# Check for empty commit message
+if ! grep -qv '^#' "$1"
+then
+ # Commit message is empty (or contains only comments).
+ # Let git handle this.
+ # It will abort with a message like so:
+ #
+ # Aborting commit due to empty commit message.
+ exit 0
+fi
+
+msg=$(grep -v '^#' "$1" |grep -nE '.{81,}')
if [ $? -eq 0 ]
then
- echo "The following lines are greater than 80 characters long:\n" >&2;
- echo $msg >&2;
+ complain "The following lines are greater than 80 characters long:" >&2;
+ complain >&2
+ complain "$msg" >&2;
quit $ERR_LENGTH;
fi
@@ -107,7 +189,19 @@ do
case $expect in
"header")
err=$ERR_HEADER;
- echo "$line" | grep -Eq "^\[(ticket/[0-9]+|feature/$branch_regex|task/$branch_regex)\] [A-Z].+$"
+ echo "$line" | grep -Eq "^\[(ticket/[0-9]+|feature/$branch_regex|task/$branch_regex)\] .+$"
+ result=$?
+ if ! echo "$line" | grep -Eq "^\[(ticket/[0-9]+|feature/$branch_regex|task/$branch_regex)\] [A-Z].+$"
+ then
+ # Don't be too strict.
+ # Commits may be temporary, intended to be squashed later.
+ # Just issue a warning here.
+ complain "$severity: heading should be a sentence beginning with a capital letter." 1>&2
+ complain "You entered:" 1>&2
+ complain "$line" 1>&2
+ fi
+ # restore exit code
+ (exit $result)
;;
"empty")
err=$ERR_EMPTY;
@@ -128,11 +222,15 @@ do
# Should not end up here
false
;;
+ "possibly-eof")
+ # Allow empty and/or comment lines at the end
+ ! tail -n +"$i" "$1" |grep -qvE '^($|#)'
+ ;;
"comment")
echo "$line" | grep -Eq "^#";
;;
*)
- echo "Unrecognised token $expect" >&2;
+ complain "Unrecognised token $expect" >&2;
quit $err;
;;
esac
@@ -188,7 +286,7 @@ do
in_description=1;
;;
"footer")
- expecting="footer eof";
+ expecting="footer possibly-eof";
if [ "$tickets" = "" ]
then
tickets="$line";
@@ -199,8 +297,11 @@ do
"comment")
# Comments should expect the same thing again
;;
+ "possibly-eof")
+ expecting="eof";
+ ;;
*)
- echo "Unrecognised token $expect" >&2;
+ complain "Unrecognised token $expect" >&2;
quit 254;
;;
esac
@@ -214,11 +315,11 @@ do
else
# None of the expected line formats matched
# Guess we'll call it a day here then
- echo "Syntax error on line $i:" >&2;
- echo ">> $line" >&2;
- echo -n "Expecting: " >&2;
- echo "$expecting" | sed 's/ /, /g' >&2;
- exit $err;
+ complain "Syntax error on line $i:" >&2;
+ complain ">> $line" >&2;
+ complain -n "Expecting: " >&2;
+ complain "$expecting" | sed 's/ /, /g' >&2;
+ quit $err;
fi
i=$(( $i + 1 ));
@@ -227,7 +328,7 @@ done
# If EOF is expected exit cleanly
echo "$expecting" | grep -q "eof" || (
# Unexpected EOF, error
- echo "Unexpected EOF encountered" >&2;
+ complain "Unexpected EOF encountered" >&2;
quit $ERR_EOF;
) && (
# Do post scan checks
@@ -238,8 +339,8 @@ echo "$expecting" | grep -q "eof" || (
if [ ! -z "$dupes" ]
then
- echo "The following tickets are repeated:" >&2;
- echo "$dupes" | sed 's/ /\n/g;s/^/* /g' >&2;
+ complain "The following tickets are repeated:" >&2;
+ complain "$dupes" | sed 's/ /\n/g;s/^/* /g' >&2;
quit $ERR_FOOTER;
fi
fi
@@ -247,8 +348,8 @@ echo "$expecting" | grep -q "eof" || (
if [ $ticket -gt 0 ]
then
echo "$tickets" | grep -Eq "\bPHPBB3-$ticket\b" || (
- echo "Ticket ID [$ticket] of branch missing from list of tickets:" >&2;
- echo "$tickets" | sed 's/ /\n/g;s/^/* /g' >&2;
+ complain "Ticket ID [$ticket] of branch missing from list of tickets:" >&2;
+ complain "$tickets" | sed 's/ /\n/g;s/^/* /g' >&2;
quit $ERR_FOOTER;
) || exit $?;
fi
diff --git a/git-tools/hooks/pre-commit b/git-tools/hooks/pre-commit
index 4d03359773..03babe47cd 100755
--- a/git-tools/hooks/pre-commit
+++ b/git-tools/hooks/pre-commit
@@ -12,8 +12,17 @@
# ln -s ../../git-tools/hooks/pre-commit \\
# .git/hooks/pre-commit
-# NOTE: this is run through /usr/bin/env
-PHP_BIN=php
+if [ -z "$PHP_BIN" ]
+then
+ PHP_BIN=php
+fi
+
+if [ "$(echo -e test)" = test ]
+then
+ echo_e="echo -e"
+else
+ echo_e="echo"
+fi
# necessary check for initial commit
if git rev-parse --verify HEAD >/dev/null 2>&1
@@ -27,7 +36,7 @@ fi
error=0
errors=""
-if ! which $PHP_BIN >/dev/null 2>&1
+if ! which "$PHP_BIN" >/dev/null 2>&1
then
echo "PHP Syntax check failed:"
echo "PHP binary does not exist or is not in path: $PHP_BIN"
@@ -64,7 +73,13 @@ do
# check the staged file content for syntax errors
# using php -l (lint)
- result=$(git cat-file -p $sha | /usr/bin/env $PHP_BIN -l 2>/dev/null)
+ # note: if display_errors=stderr in php.ini,
+ # parse errors are printed on stderr; otherwise
+ # they are printed on stdout.
+ # we filter everything other than parse errors
+ # with a grep below, therefore it should be safe
+ # to combine stdout and stderr in all circumstances
+ result=$(git cat-file -p $sha | "$PHP_BIN" -l 2>&1)
if [ $? -ne 0 ]
then
error=1
@@ -76,7 +91,45 @@ unset IFS
if [ $error -eq 1 ]
then
- echo -e "PHP Syntax check failed:";
- echo -e "$errors" | grep "^Parse error:"
+ echo "PHP Syntax check failed:"
+ # php "display errors" (display_errors php.ini value)
+ # and "log errors" (log_errors php.ini value).
+ # these are independent settings - see main/main.c in php source.
+ # the "log errors" setting produces output which
+ # starts with "PHP Parse error:"; the "display errors"
+ # setting produces output starting with "Parse error:".
+ # if both are turned on php dumps the parse error twice.
+ # therefore here we try to grep for one version and
+ # if that yields no results grep for the other version.
+ #
+ # other fun php facts:
+ #
+ # 1. in cli, display_errors and log_errors have different
+ # destinations by default. display_errors prints to
+ # standard output and log_errors prints to standard error.
+ # whether these destinations make sense is left
+ # as an exercise for the reader.
+ # 2. as mentioned above, with all output turned on
+ # php will print parse errors twice, one time on stdout
+ # and one time on stderr.
+ # 3. it is possible to set both display_errors and log_errors
+ # to off. if this is done php will print the text
+ # "Errors parsing <file>" but will not say what
+ # the errors are. useful behavior, this.
+ # 4. on my system display_errors defaults to on and
+ # log_errors defaults to off, therefore providing
+ # by default one copy of messages. your mileage may vary.
+ # 5. by setting display_errors=stderr and log_errors=on,
+ # both sets of messages will be printed on stderr.
+ # 6. php-cgi binary, given display_errors=stderr and
+ # log_errors=on, still prints both sets of messages
+ # on stderr, but formats one set as an html fragment.
+ # 7. your entry here? ;)
+ $echo_e "$errors" | grep "^Parse error:"
+ if [ $? -ne 0 ]
+ then
+ # match failed
+ $echo_e "$errors" | grep "^PHP Parse error:"
+ fi
exit 1
fi
diff --git a/git-tools/hooks/prepare-commit-msg b/git-tools/hooks/prepare-commit-msg
index 2bf25e58a4..11d2b6b2f2 100755
--- a/git-tools/hooks/prepare-commit-msg
+++ b/git-tools/hooks/prepare-commit-msg
@@ -35,8 +35,8 @@ then
# Branch is prefixed with 'ticket/', append ticket ID to message
if [ "$branch" != "${branch##ticket/}" ];
then
- tail="\n\nPHPBB3-${branch##ticket/}";
+ tail="$(printf "\n\nPHPBB3-${branch##ticket/}")";
fi
- echo "[$branch]$tail $(cat "$1")" > "$1"
+ echo "[$branch] $tail$(cat "$1")" > "$1"
fi
diff --git a/git-tools/merge.php b/git-tools/merge.php
new file mode 100755
index 0000000000..034bd2032c
--- /dev/null
+++ b/git-tools/merge.php
@@ -0,0 +1,175 @@
+#!/usr/bin/env php
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+function show_usage()
+{
+ $filename = basename(__FILE__);
+
+ echo "$filename merges a github pull request.\n";
+ echo "\n";
+
+ echo "Usage: [php] $filename -p pull_request_id [OPTIONS]\n";
+ echo "\n";
+
+ echo "Options:\n";
+ echo " -p pull_request_id The pull request id to be merged (mandatory)\n";
+ echo " -r remote Remote of upstream, defaults to 'upstream' (optional)\n";
+ echo " -d Outputs the commands instead of running them (optional)\n";
+ echo " -h This help text\n";
+
+ exit(2);
+}
+
+// Handle arguments
+$opts = getopt('p:r:dh');
+
+if (empty($opts) || isset($opts['h']))
+{
+ show_usage();
+}
+
+$pull_id = get_arg($opts, 'p', '');
+$remote = get_arg($opts, 'r', 'upstream');
+$dry_run = !get_arg($opts, 'd', true);
+
+try
+{
+ exit(work($pull_id, $remote));
+}
+catch (RuntimeException $e)
+{
+ echo $e->getMessage();
+ exit($e->getCode());
+}
+
+function work($pull_id, $remote)
+{
+ // Get some basic data
+ $pull = get_pull('phpbb', 'phpbb3', $pull_id);
+
+ if (!$pull_id)
+ {
+ show_usage();
+ }
+
+ if ($pull['state'] != 'open')
+ {
+ throw new RuntimeException(sprintf("Error: pull request is closed\n",
+ $target_branch), 5);
+ }
+
+ $pull_user = $pull['head'][0];
+ $pull_branch = $pull['head'][1];
+ $target_branch = $pull['base'][1];
+
+ switch ($target_branch)
+ {
+ case 'develop-olympus':
+ run("git checkout develop-olympus");
+ run("git pull $remote develop-olympus");
+
+ add_remote($pull_user, 'phpbb3');
+ run("git fetch $pull_user");
+ run("git merge --no-ff $pull_user/$pull_branch");
+ run("phpunit");
+
+ run("git checkout develop");
+ run("git pull $remote develop");
+ run("git merge --no-ff develop-olympus");
+ run("phpunit");
+ break;
+
+ case 'develop':
+ run("git checkout develop");
+ run("git pull $remote develop");
+
+ add_remote($pull_user, 'phpbb3');
+ run("git fetch $pull_user");
+ run("git merge --no-ff $pull_user/$pull_branch");
+ run("phpunit");
+ break;
+
+ default:
+ throw new RuntimeException(sprintf("Error: pull request target branch '%s' is not a main branch\n",
+ $target_branch), 5);
+ break;
+ }
+}
+
+function add_remote($username, $repository, $pushable = false)
+{
+ $url = get_repository_url($username, $repository, false);
+ run("git remote add $username $url", true);
+
+ if ($pushable)
+ {
+ $ssh_url = get_repository_url($username, $repository, true);
+ run("git remote set-url --push $username $ssh_url");
+ }
+}
+
+function get_repository_url($username, $repository, $ssh = false)
+{
+ $url_base = ($ssh) ? 'git@github.com:' : 'git://github.com/';
+
+ return $url_base . $username . '/' . $repository . '.git';
+}
+
+function api_request($query)
+{
+ $contents = file_get_contents("http://github.com/api/v2/json/$query");
+
+ if ($contents === false)
+ {
+ throw new RuntimeException("Error: failed to retrieve pull request data\n", 4);
+ }
+
+ return json_decode($contents);
+}
+
+function get_pull($username, $repository, $pull_id)
+{
+ $request = api_request("pulls/$username/$repository/$pull_id");
+
+ $pull = $request->pull;
+
+ $pull_data = array(
+ 'base' => array($pull->base->user->login, $pull->base->ref),
+ 'head' => array($pull->head->user->login, $pull->head->ref),
+ 'state' => $pull->state,
+ );
+
+ return $pull_data;
+}
+
+function get_arg($array, $index, $default)
+{
+ return isset($array[$index]) ? $array[$index] : $default;
+}
+
+function run($cmd, $ignore_fail = false)
+{
+ global $dry_run;
+
+ if (!empty($dry_run))
+ {
+ echo "$cmd\n";
+ }
+ else
+ {
+ passthru(escapeshellcmd($cmd), $status);
+
+ if ($status != 0 && !$ignore_fail)
+ {
+ throw new RuntimeException(sprintf("Error: command '%s' failed with status %s'\n",
+ $cmd, $status), 6);
+ }
+ }
+}
diff --git a/git-tools/setup_github_network.php b/git-tools/setup_github_network.php
new file mode 100755
index 0000000000..5f2e1609a7
--- /dev/null
+++ b/git-tools/setup_github_network.php
@@ -0,0 +1,248 @@
+#!/usr/bin/env php
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+function show_usage()
+{
+ $filename = basename(__FILE__);
+
+ echo "$filename adds repositories of a github network as remotes to a local git repository.\n";
+ echo "\n";
+
+ echo "Usage: [php] $filename -s collaborators|organisation|contributors|network [OPTIONS]\n";
+ echo "\n";
+
+ echo "Scopes:\n";
+ echo " collaborators Repositories of people who have push access to the specified repository\n";
+ echo " contributors Repositories of people who have contributed to the specified repository\n";
+ echo " organisation Repositories of members of the organisation at github\n";
+ echo " network All repositories of the whole github network\n";
+ echo "\n";
+
+ echo "Options:\n";
+ echo " -s scope See description above (mandatory)\n";
+ echo " -u github_username Overwrites the github username (optional)\n";
+ echo " -r repository_name Overwrites the repository name (optional)\n";
+ echo " -m your_github_username Sets up ssh:// instead of git:// for pushable repositories (optional)\n";
+ echo " -d Outputs the commands instead of running them (optional)\n";
+ echo " -h This help text\n";
+
+ exit(1);
+}
+
+// Handle arguments
+$opts = getopt('s:u:r:m:dh');
+
+if (empty($opts) || isset($opts['h']))
+{
+ show_usage();
+}
+
+$scope = get_arg($opts, 's', '');
+$username = get_arg($opts, 'u', 'phpbb');
+$repository = get_arg($opts, 'r', 'phpbb3');
+$developer = get_arg($opts, 'm', '');
+$dry_run = !get_arg($opts, 'd', true);
+run(null, $dry_run);
+exit(work($scope, $username, $repository, $developer));
+
+function work($scope, $username, $repository, $developer)
+{
+ // Get some basic data
+ $network = get_network($username, $repository);
+ $collaborators = get_collaborators($username, $repository);
+
+ if ($network === false || $collaborators === false)
+ {
+ echo "Error: failed to retrieve network or collaborators\n";
+ return 1;
+ }
+
+ switch ($scope)
+ {
+ case 'collaborators':
+ $remotes = array_intersect_key($network, $collaborators);
+ break;
+
+ case 'organisation':
+ $remotes = array_intersect_key($network, get_organisation_members($username));
+ break;
+
+ case 'contributors':
+ $remotes = array_intersect_key($network, get_contributors($username, $repository));
+ break;
+
+ case 'network':
+ $remotes = $network;
+ break;
+
+ default:
+ show_usage();
+ }
+
+ if (file_exists('.git'))
+ {
+ add_remote($username, $repository, isset($collaborators[$developer]));
+ }
+ else
+ {
+ clone_repository($username, $repository, isset($collaborators[$developer]));
+ }
+
+ // Add private security repository for developers
+ if ($username == 'phpbb' && $repository == 'phpbb3' && isset($collaborators[$developer]))
+ {
+ run("git remote add $username-security " . get_repository_url($username, "$repository-security", true));
+ }
+
+ // Skip blessed repository.
+ unset($remotes[$username]);
+
+ foreach ($remotes as $remote)
+ {
+ add_remote($remote['username'], $remote['repository'], $remote['username'] == $developer);
+ }
+
+ run('git remote update');
+}
+
+function clone_repository($username, $repository, $pushable = false)
+{
+ $url = get_repository_url($username, $repository, false);
+ run("git clone $url ./ --origin $username");
+
+ if ($pushable)
+ {
+ $ssh_url = get_repository_url($username, $repository, true);
+ run("git remote set-url --push $username $ssh_url");
+ }
+}
+
+function add_remote($username, $repository, $pushable = false)
+{
+ $url = get_repository_url($username, $repository, false);
+ run("git remote add $username $url");
+
+ if ($pushable)
+ {
+ $ssh_url = get_repository_url($username, $repository, true);
+ run("git remote set-url --push $username $ssh_url");
+ }
+}
+
+function get_repository_url($username, $repository, $ssh = false)
+{
+ $url_base = ($ssh) ? 'git@github.com:' : 'git://github.com/';
+
+ return $url_base . $username . '/' . $repository . '.git';
+}
+
+function api_request($query)
+{
+ $contents = file_get_contents("http://github.com/api/v2/json/$query");
+ if ($contents === false)
+ {
+ return false;
+ }
+ return json_decode($contents);
+}
+
+function get_contributors($username, $repository)
+{
+ $request = api_request("repos/show/$username/$repository/contributors");
+ if ($request === false)
+ {
+ return false;
+ }
+
+ $usernames = array();
+ foreach ($request->contributors as $contributor)
+ {
+ $usernames[$contributor->login] = $contributor->login;
+ }
+
+ return $usernames;
+}
+
+function get_organisation_members($username)
+{
+ $request = api_request("organizations/$username/public_members");
+ if ($request === false)
+ {
+ return false;
+ }
+
+ $usernames = array();
+ foreach ($request->users as $member)
+ {
+ $usernames[$member->login] = $member->login;
+ }
+
+ return $usernames;
+}
+
+function get_collaborators($username, $repository)
+{
+ $request = api_request("repos/show/$username/$repository/collaborators");
+ if ($request === false)
+ {
+ return false;
+ }
+
+ $usernames = array();
+ foreach ($request->collaborators as $collaborator)
+ {
+ $usernames[$collaborator] = $collaborator;
+ }
+
+ return $usernames;
+}
+
+function get_network($username, $repository)
+{
+ $request = api_request("repos/show/$username/$repository/network");
+ if ($request === false)
+ {
+ return false;
+ }
+
+ $usernames = array();
+ foreach ($request->network as $network)
+ {
+ $usernames[$network->owner] = array(
+ 'username' => $network->owner,
+ 'repository' => $network->name,
+ );
+ }
+
+ return $usernames;
+}
+
+function get_arg($array, $index, $default)
+{
+ return isset($array[$index]) ? $array[$index] : $default;
+}
+
+function run($cmd, $dry = false)
+{
+ static $dry_run;
+
+ if (is_null($cmd))
+ {
+ $dry_run = $dry;
+ }
+ else if (!empty($dry_run))
+ {
+ echo "$cmd\n";
+ }
+ else
+ {
+ passthru(escapeshellcmd($cmd));
+ }
+}