Skip to content

Instantly share code, notes, and snippets.

@amenk
Last active January 29, 2021 12:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amenk/1fd8186505a7db3bf42f1a19c8f810c8 to your computer and use it in GitHub Desktop.
Save amenk/1fd8186505a7db3bf42f1a19c8f810c8 to your computer and use it in GitHub Desktop.
Boilerplate Manager RoboFile (for use with robo.li Task Runner)
<?php
use Symfony\Component\Console\Question\ChoiceQuestion;
class RoboFile extends \Robo\Tasks
{
const VERSION_FILE = '.boilerplate-template-version';
var $currentGitVersion = null;
/**
* Applies a template to your project
* @param $type template type, for example laravel
* @param $destination destination folder
*/
public function templateApply($destination, $type = null)
{
$current = $this->getCurrentTemplate($destination);
if ($current) {
$this->say(sprintf('Existing template <info>%s</info> found at version <info>%s</info>', $current['type'], $current['version']));
$recent = $this->getCurrentGitVersion();
if (!$this->isUpgradeAvailable($current, $recent)) {
return;
}
if ($this->confirm(sprintf('Do you want to path the current project status to the newest version which is <info>%s</info>', $recent))) {
$this->templateUpgrade($destination);
return;
} else {
return;
}
}
$this->templateForceInstall($destination, $type);
}
private function getCurrentTemplate($projectDir)
{
$versionFile = $this->getVersionFile($projectDir);
if (!file_exists($versionFile)) {
return false;
}
list($type, $version) = explode('|', trim(file_get_contents($versionFile)));
return compact('type', 'version');
}
private function getVersionFile($dir)
{
return rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . self::VERSION_FILE;
}
private function getCurrentGitVersion()
{
if ($this->currentGitVersion == null) {
$this->taskGitStack()->pull()->run();
$this->currentGitVersion = trim(exec('git describe --tags'));
}
return $this->currentGitVersion;
}
private function isUpgradeAvailable(array $current, $recent)
{
if ($recent === $current['version']) {
$this->say('<info>You are already at the most recent version</info> You can use --force to reapply');
return false;
}
return true;
}
/**
* Tries to upgrades the template in your project folder with the current version
*
* @param $destination project folder
*/
public function templateUpgrade($destination)
{
$recent = $this->getCurrentGitVersion();
$current = $this->getCurrentTemplate($destination);
$this->_exec('git diff ' . escapeshellarg($recent . '..' . $current['version']) . ' ' . escapeshellarg($current['type']) . ' > last.patch');
$patchPath = realpath('last.patch');
$this->_exec('cd ' . escapeshellarg($destination) . ' && git apply --reject -v -p2 ' . $patchPath);
$this->writeVersionFile($current['type'], $destination);
}
private function writeVersionFile($type, $dir)
{
$version = $this->getCurrentGitVersion();
file_put_contents($this->getVersionFile($dir), $type . '|' . $version);
$this->say('Version file written. Please fix conflicts if any, verify and commit everything');
}
/**
* Force installation / replace for the template
*
* @param $type project type
* @param $destination destination folder
*/
public function templateForceInstall($destination, $type = null)
{
$this->getCurrentGitVersion();
if ($type == null) {
$question = new ChoiceQuestion(
'Please select the template to be used',
$this->getTypes(),
0
);
$question->setErrorMessage('Choice is %s is invalid.');
$type = $this->doAsk($question);
}
$this->_copyDir($type, $destination);
$this->writeVersionFile($type, $destination);
}
private function getTypes()
{
$directories = glob(dirname(__FILE__) . '/*', GLOB_ONLYDIR);
$names = [];
foreach ($directories as $directory) {
$names[] = basename($directory);
}
return $names;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment