Skip to content

Commit

Permalink
Renamed to Famelo.Gerrit and added gerrit:update command
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc Neuhaus committed Nov 16, 2012
0 parents commit 7d46c6d
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 0 deletions.
141 changes: 141 additions & 0 deletions Classes/Famelo/Gerrit/Command/GerritCommandController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php
namespace Famelo\Gerrit\Command;

/* *
* This script belongs to the TYPO3 Flow package "Famelo.Gerrit". *
* *
* */

use TYPO3\Flow\Annotations as Flow;

/**
* update command controller for the TYPO3.Gerrit package
*
* @Flow\Scope("singleton")
*/
class GerritCommandController extends \TYPO3\Flow\Cli\CommandController {

/**
* This setups the packages repositories with some stuff helpful for working with gerrit
*
* This command walks through all packages and checks for 2 things:
*
* 1. is there a commit-msg hook to add the Change ID
* 2. is there a remote target to push to gerrit
*
* if either of those misses it adds those.
*
* @return void
*/
public function setupCommand() {
$this->processPackages(FLOW_PATH_PACKAGES);
}

public function processPackages($basePath) {
$paths = scandir($basePath);
foreach ($paths as $path) {
if ($path == '.' || $path == '..') {
continue;
}

if ($path == '.git') {
$this->addGerritRemote($basePath . '/' . $path);
$this->addChangeIdCommitHook($basePath . '/' . $path);
} elseif (is_dir($basePath . '/' . $path)) {
$this->processPackages($basePath . '/' . $path);
}
}
}

public function addChangeIdCommitHook($path) {
if (!file_exists($path . '/hooks/commit-msg')) {
file_put_contents($path . '/hooks/commit-msg', file_get_contents('resource://Famelo.Gerrit/Private/Hooks/commit-msg'));
$this->outputLine('Added commit-msg hook to add ChangeId to: %s', array(realpath($path)));
}
system('chmod +x ' . $path . '/hooks/commit-msg');
}

public function addGerritRemote($path) {
$configTemplate = '
[remote "gerrit"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git://git.typo3.org/FLOW3/Packages/{package}.git
push = HEAD:refs/for/master
';
$config = file_get_contents($path . '/config');
preg_match('/url = git:\/\/git.typo3.org\/FLOW3\/Packages\/(.+).git/', $config, $matches);
if (count($matches) > 0 && !stristr($config, '[remote "gerrit"]')) {
$config .= str_replace('{package}', $matches[1], $configTemplate);
file_put_contents($path . '/config', $config);
$this->outputLine('Added gerrit remote to repository: %s', array(realpath($path)));
}
}


/**
* This command checks for a gerrit.json in the current dir and fetches patches from gerrit
*
* This command will cherrypick all reviews specified in gerrit.json
*
* @return void
*/
public function updateCommand() {
$gerritFile = FLOW_PATH_ROOT . 'gerrit.json';
$typeDirs = scandir(FLOW_PATH_PACKAGES);
$packagePaths = array();
foreach ($typeDirs as $typeDir) {
if (is_dir(FLOW_PATH_PACKAGES . $typeDir) && substr($typeDir, 0, 1) !== '.') {
$typeDir = FLOW_PATH_PACKAGES . $typeDir . '/';
$packageDirs = scandir($typeDir);
foreach ($packageDirs as $packageDir) {
if (is_dir($typeDir . $packageDir) && substr($packageDir, 0, 1) !== '.') {
$packagePaths[$packageDir] = $typeDir . $packageDir;
}
}
}
}
if (file_exists($gerritFile)) {
$packages = json_decode(file_get_contents($gerritFile));
foreach (get_object_vars($packages) as $package => $patches) {
$patches = get_object_vars($patches);
foreach ($patches as $description => $changeId) {
$change = $this->fetchChangeInformation($changeId);
$header = '# Fetching: ' . $change->subject;
echo str_pad('', strlen($header), '#') . chr(10);
echo $header . chr(10);
echo str_pad('', strlen($header), '#') . chr(10);

chdir($packagePaths[$package]);
$command = 'git fetch git://git.typo3.org/' . $change->project . ' ' . $change->currentPatchSet->ref . ' && git cherry-pick FETCH_HEAD';
system($command);
chdir(FLOW_PATH_ROOT);
echo chr(10);
}
}
}
}

public function fetchChangeInformation($changeId) {
$command = 'ssh review.typo3.org -- "gerrit query --current-patch-set --format JSON change:' . $changeId . '"';

$output = $this->executeShellCommand($command);

$parts = explode('{"type":"stats"', $output);
$output = $parts[0];

$data = json_decode($output);
return $data;
}

public function executeShellCommand($command) {
$output = '';
$fp = popen($command, 'r');
while (($line = fgets($fp)) !== FALSE) {
$output .= $line;
}
pclose($fp);
return $output;
}
}

?>
162 changes: 162 additions & 0 deletions Resources/Private/Hooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/bin/bash
# From TYPO3 CI Review 1.0 (09/21/2012)
# original version Gerrit Code Review 2.2.2.1-3-gb2ba1a2
#
# Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
#
# Copyright (coffee) 2012 TYPO3
# Copyright (coffee) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

CHANGE_ID_AFTER=""
COMMIT_MSG_ERROR_FOUND=0
MSG="$1"
ERROR_TEXT=""

# Check for, and add if missing, a unique Change-Id
#
add_ChangeId() {
clean_message=`sed -e '
/^diff --git a\/.*/{
s///
q
}
/^Signed-off-by:/d
/^#/d
' "$MSG" | git stripspace`
if test -z "$clean_message"
then
return
fi

if grep -i '^Change-Id:' "$MSG" >/dev/null
then
return
fi

id=`_gen_ChangeId`
perl -e '
$MSG = shift;
$id = shift;
$CHANGE_ID_AFTER = shift;
undef $/;
open(I, $MSG); $_ = <I>; close I;
s|^diff --git a/.*||ms;
s|^#.*$||mg;
exit unless $_;
@message = split /\n/;
$haveFooter = 0;
$startFooter = @message;
for($line = @message - 1; $line >= 0; $line--) {
$_ = $message[$line];
if (/^[a-zA-Z0-9-]+:/ && !m,^[a-z0-9-]+://,) {
$haveFooter++;
next;
}
next if /^[ []/;
$startFooter = $line if ($haveFooter && /^\r?$/);
last;
}
@footer = @message[$startFooter+1..@message];
@message = @message[0..$startFooter];
push(@footer, "") unless @footer;
for ($line = 0; $line < @footer; $line++) {
$_ = $footer[$line];
next if /^($CHANGE_ID_AFTER):/i;
last;
}
push(@footer, "Change-Id: I$id");
$_ = join("\n", @message, @footer);
open(O, ">$MSG"); print O; close O;
' "$MSG" "$id" "$CHANGE_ID_AFTER"
}
_gen_ChangeIdInput() {
echo "tree `git write-tree`"
if parent=`git rev-parse HEAD^0 2>/dev/null`
then
echo "parent $parent"
fi
echo "author `git var GIT_AUTHOR_IDENT`"
echo "committer `git var GIT_COMMITTER_IDENT`"
echo
printf '%s' "$clean_message"
}
_gen_ChangeId() {
_gen_ChangeIdInput |
git hash-object -t commit --stdin
}


# Check for maximum line length
#
checkForLineLength() {
if egrep -q '^[^#].{74}' "$MSG"
then
COMMIT_MSG_ERROR_FOUND=1
ERROR_TEXT="${ERROR_TEXT}- The maximum line length of 74 characters is exceeded.\n"
fi
}

# Check for existance of a "Resolves: " line.
#
checkForResolves() {
if ! egrep -q '^(Resolves|Fixes): \#[0-9]+$' "$MSG"
then
COMMIT_MSG_ERROR_FOUND=1
ERROR_TEXT="${ERROR_TEXT}- You need at least one 'Resolves|Fixes: #<issue number>' line.\n"
fi
}

# Check for existance of a "Releases: " line.
#
checkForReleases() {
if ! egrep -q '^Releases: [0-9]\.[0-9](, *[0-9]\.[0-9])*$' "$MSG"
then
COMMIT_MSG_ERROR_FOUND=1
ERROR_TEXT="${ERROR_TEXT}- You need a 'Releases:' line. For instance: Releases: 6.0,4.7\n"
fi
}

# Check for existance of the commit type text
#
checkForCommitType() {
if ! egrep -q '\[[^]]+\] .+$' "$MSG"
then
COMMIT_MSG_ERROR_FOUND=1
ERROR_TEXT="${ERROR_TEXT}- Your first line has to contain a commit type like '[BUGFIX]'.\n"
fi
}

checkForLineLength
checkForCommitType
checkForResolves
checkForReleases

# Abort commit on message format errors
if [ $COMMIT_MSG_ERROR_FOUND -eq 1 ]; then
echo -e "\n------------------------------------------------------------------"
echo -e "\n >> Commit aborted <<\n\nYou have errors in your commit message:"
echo -e $ERROR_TEXT
echo -e "\nPlease refer to http://wiki.typo3.org/CommitMessage_Format_(Git)\nfor details on the commit message format."
echo '------------------------------------------------------------------'
fi

add_ChangeId
14 changes: 14 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "famelo/gerrit",
"type": "typo3-flow-package",
"description": null,
"version": null,
"require": {
"typo3/flow": "*"
},
"autoload": {
"psr-0": {
"Famelo\\Gerrit": "Classes"
}
}
}

0 comments on commit 7d46c6d

Please sign in to comment.