|
#!/usr/bin/php |
|
<?php |
|
|
|
error_reporting(E_ALL ^ E_STRICT); |
|
ini_set('display_errors', 1); |
|
|
|
define('FLOW_PATH_ROOT', __DIR__ . DIRECTORY_SEPARATOR); |
|
define('FLOW_PATH_PACKAGES', FLOW_PATH_ROOT . 'Packages' . DIRECTORY_SEPARATOR); |
|
|
|
class Gerrit { |
|
|
|
/** |
|
* @var array |
|
*/ |
|
static protected $colors = array( |
|
'green' => '0;32', |
|
'red' => '0;31', |
|
'yellow' => '0;33' |
|
); |
|
|
|
/** |
|
* This command checks for a gerrit.json in the current dir and fetches patches from gerrit |
|
* |
|
* This command will cherry-pick all reviews specified in gerrit.json |
|
* |
|
* @return void |
|
*/ |
|
static public function updateCommand() { |
|
$gerritFile = FLOW_PATH_ROOT . 'gerrit.json'; |
|
$typeDirs = scandir(FLOW_PATH_PACKAGES); |
|
$packagePaths = array('BuildEssentials' => 'Build/BuildEssentials'); |
|
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)); |
|
if (!is_object($packages)) { |
|
echo self::colorize('Could not load gerrit.json! Check for Syntax errors', 'red'); |
|
return; |
|
} |
|
foreach (get_object_vars($packages) as $package => $changes) { |
|
if (!isset($packagePaths[$package])) { |
|
echo self::colorize('The Package ' . $package . ' is not installed', 'red') . PHP_EOL; |
|
continue; |
|
} |
|
chdir($packagePaths[$package]); |
|
$changes = get_object_vars($changes); |
|
$gitLogOutput = self::executeShellCommand('git log -n30'); |
|
foreach ($changes as $description => $changeId) { |
|
$patchSet = NULL; |
|
if (strpos($changeId, ',') !== FALSE) { |
|
list($changeId, $patchSet) = explode(',', $changeId); |
|
} |
|
$change = self::fetchChangeInformation($changeId); |
|
if ($change === FALSE) { |
|
echo self::colorize(sprintf('Could not fetch change information (%u)!', $changeId), 'red') . PHP_EOL; |
|
continue; |
|
} |
|
$header = $package . ': ' . $change->subject; |
|
echo self::colorize($header, 'green') . PHP_EOL; |
|
|
|
if ($change->status == 'MERGED') { |
|
echo self::colorize('This change has been merged upstream.', 'yellow') . PHP_EOL; |
|
} elseif ($change->status == 'ABANDONED') { |
|
echo self::colorize('This change has been abandoned!', 'red') . PHP_EOL; |
|
} |
|
$ref = $change->revisions->{$change->current_revision}->fetch->git->ref; |
|
if ($patchSet !== NULL) { |
|
$explodedRef = explode('/', $ref); |
|
array_pop($explodedRef); |
|
$explodedRef[] = $patchSet; |
|
$ref = implode('/', $explodedRef); |
|
} |
|
$command = 'git fetch --quiet git://review.typo3.org/' . $change->project . ' ' . $ref . ''; |
|
$output = self::executeShellCommand($command); |
|
|
|
$changeIdLine = self::executeShellCommand('git show FETCH_HEAD | grep \'Change-Id\''); |
|
if (self::isAlreadyPicked($changeIdLine, $gitLogOutput)) { |
|
echo self::colorize('Already picked', 'yellow') . PHP_EOL; |
|
} else { |
|
echo $output; |
|
system('git cherry-pick -x --strategy=recursive -X theirs FETCH_HEAD'); |
|
} |
|
|
|
echo PHP_EOL; |
|
} |
|
chdir(FLOW_PATH_ROOT); |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Checks if the change is already picked by looking for the Change-Id |
|
* line in the log. |
|
* |
|
* @param string $changeIdLine |
|
* @param string $gitLogOutput |
|
* @return boolean |
|
*/ |
|
static protected function isAlreadyPicked($changeIdLine, $gitLogOutput) { |
|
return stristr($gitLogOutput, trim($changeIdLine)) !== FALSE; |
|
} |
|
|
|
/** |
|
* @param string $command |
|
* @return string |
|
*/ |
|
static protected function executeShellCommand($command) { |
|
$output = ''; |
|
$fp = popen($command, 'r'); |
|
while (($line = fgets($fp)) !== FALSE) { |
|
$output .= $line; |
|
} |
|
pclose($fp); |
|
return trim($output); |
|
} |
|
|
|
/** |
|
* @param string $text |
|
* @param string $color Allowed values: green, red, yellow |
|
* @return string |
|
*/ |
|
static protected function colorize($text, $color) { |
|
return sprintf("\033[%sm%s\033[0m", self::$colors[$color], $text); |
|
} |
|
|
|
/** |
|
* @param integer $changeId The numeric change id, not the hash |
|
* @return mixed |
|
*/ |
|
static protected function fetchChangeInformation($changeId) { |
|
$output = @file_get_contents('https://review.typo3.org/changes/?q=' . intval($changeId) . '&o=CURRENT_REVISION'); |
|
|
|
if ($output === FALSE) { |
|
return FALSE; |
|
} |
|
|
|
// Remove first line |
|
$output = substr($output, strpos($output, "\n") + 1); |
|
// trim [] |
|
$output = ltrim($output, '['); |
|
$output = rtrim(rtrim($output), ']'); |
|
|
|
$data = json_decode($output); |
|
return $data; |
|
} |
|
|
|
} |
|
|
|
Gerrit::updateCommand(); |
|
|
|
?> |