#!/usr/bin/env php
<?php

/**
 * @param string $command
 * @param boolean $expectsEmptyOutput
 * @param string|NULL $errorMessage
 * @return array
 */
function commandOrFail($command, $expectsEmptyOutput = FALSE, $errorMessage = NULL) {
	$code = 0;
	$output = array();
	exec($command, $output, $code);
	if (0 < $code || (TRUE === $expectsEmptyOutput && 0 < count($output))) {
		$message = $errorMessage ? ' ! ' . $errorMessage : ' ! Command failed! ' . $command;
		if (TRUE === $expectsEmptyOutput) {
			$message .= PHP_EOL;
			$message .= ' ! No output was expected from command but output occurred:';
			$message .= implode(PHP_EOL, $output);
		}
		exitWithMessage($message, (TRUE === $expectsEmptyOutput && 0 === $code) ? 1 : $code);
	}
	return $output;
}

/**
 * @param string $message
 * @param integer $code
 * @return void
 */
function exitWithMessage($message, $code = 0) {
	echo $message;
	echo PHP_EOL;
	exit($code);
}

/**
 * @param string $message
 * @param string $mark
 */
function message($message, $mark = '✓') {
	echo sprintf(' %s ' . $message, $mark);
	echo PHP_EOL;
}

// Declare variables used by script below
$repository = pathinfo(trim(shell_exec('pwd')), PATHINFO_FILENAME);
$repositoryAddress = sprintf('https://github.com/FluidTYPO3/%s.git', $repository);
$delay = 10;

if (!file_exists('composer.lock')) {
    exitWithMessage('Please run "composer install" before you begin, to ensure you have all release utilities installed in the right versions');
}

message('Starting staging of ' . $repository, '·');
echo ' · ' . sprintf('Delaying for %s seconds. If you wish to abort, NOW is the time to press CTRL+C: ', $delay);
while (0 < $delay && -- $delay) {
	echo $delay . '..';
	sleep(1);
}
echo PHP_EOL;
message('Okay to proceed');

// Step 1: Confirm a clean working directory or fail.
commandOrFail('git status -s', TRUE, 'Working director is NOT CLEAN');
message('Working directory is clean!');

// Step 2: Checkout staging and development and pull changes
message('Pulling development and staging branches from ' . $repository, '·');
commandOrFail('git checkout staging -q', TRUE, 'Failed to check out staging branch');
commandOrFail('git pull ' . $repositoryAddress . ' staging -q');
commandOrFail('git checkout development -q', TRUE);
commandOrFail('git pull ' . $repositoryAddress . ' development -q');
message('Development and staging branches pulled');

// Step 3: Confirm differences exists between `development` and `staging` branches or fail w/ suggestion to do `release` next.
$diff = commandOrFail('git diff staging...development');
if (0 === count($diff)) {
	exitWithMessage(' x Branches development and staging are identical - nothing to do. Did you want to release instead of stage?', 1);
}
message('Development and staging branches are different, good!');

// Step 4: Check out `staging` branch or fail.
commandOrFail('git checkout staging -q');
message('Branch "staging" was checked out');

// Step 5: Merge branch `development` into `staging` and force-generate a merge commit or fail on conflicts.
commandOrFail('git merge --no-ff -s recursive -X theirs development');
message('Branch "development" was merged into "staging" with no fast forwarding using "recursive" strategy favoring "their" branch');

// Step 6: Run unit tests if they are present
commandOrFail('rm composer.lock && composer install -q', FALSE, 'Composer install failed! Please address the issue and retry');
if (file_exists('phpunit.xml.dist')) {
    commandOrFail('./vendor/bin/phpunit');
    message('Unit tests executed successfully');
} else {
    message('Package does not appear to contain unit tests (no phpunit.xml.dist present)');
}

// Step 7: Push the result directly to upstream repository
commandOrFail('git push ' . $repositoryAddress . ' staging -q');
commandOrFail('git fetch origin -q');
message('The merged "staging" branch was pushed to ' . $repositoryAddress);

// Step 8: Check out development again
commandOrFail('git checkout development -q');
message('You are now back on branch "development"');

// Step 9: Report success
message('The repository was staged!');
echo ' · Please allow the CI environment to perform tests. View the results on this URL:' . PHP_EOL;
echo sprintf(' · https://travis-ci.org/FluidTYPO3/%s/builds' . PHP_EOL, $repository);