From 8ec92749c2b380d9890fe4d89004944ac60d6a06 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 6 May 2015 23:40:07 +0200 Subject: [PATCH 001/214] Updated README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c827801..76190b1 100644 --- a/README.md +++ b/README.md @@ -230,3 +230,6 @@ All log commands are using a grep-filter (specified as optional argument) |----------------------------|---------------------------------------------------------------------------| | ct user:rebuildsshconfig | Rebuild SSH config from ct repository (/vagrant/provision/sshconfig) | +## Credits + +Thanks to my colleagues at [cron IT GmbH](http://www.cron.eu/) and Ingo Pfennigstorf for testing and some usefull ideas. From 2a1d0b5b85d90a0119fa427ff46e502034e20c13 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 7 May 2015 00:07:59 +0200 Subject: [PATCH 002/214] Cleanup --- .../Console/Builder/AbstractCommandBuilder.php | 15 +++++++++++++-- .../Console/Builder/SelfCommandBuilder.php | 5 +++-- .../Console/Command/Apache/TraceCommand.php | 1 + .../Console/Command/Common/SelfUpdateCommand.php | 4 ---- .../Console/Command/Docker/AbstractCommand.php | 12 ++++++++++++ 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php index 106fefe..6aad59a 100644 --- a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php @@ -28,9 +28,20 @@ class AbstractCommandBuilder implements CommandBuilderInterface { // Constants // ########################################## + /** + * Redirect STDOUT and STDERR to /dev/null (no output) + */ const OUTPUT_REDIRECT_NULL = ' &> /dev/null'; + + /** + * Redirect STDERR to STDOUT + */ const OUTPUT_REDIRECT_ALL_STDOUT = ' 2>&1'; - const OUTPUT_REDIRECT_NO_STDERR = ' 2> /dev/null'; + + /** + * Redirect STDERR to /dev/null (no error output) + */ + const OUTPUT_REDIRECT_NO_STDERR = ' 2> /dev/null'; // ########################################## // Attributs @@ -55,7 +66,7 @@ class AbstractCommandBuilder implements CommandBuilderInterface { * * @var null|string */ - protected $outputRedirect = null; + protected $outputRedirect; /** * Command pipe diff --git a/src/app/CliTools/Console/Builder/SelfCommandBuilder.php b/src/app/CliTools/Console/Builder/SelfCommandBuilder.php index e872498..af78702 100644 --- a/src/app/CliTools/Console/Builder/SelfCommandBuilder.php +++ b/src/app/CliTools/Console/Builder/SelfCommandBuilder.php @@ -22,7 +22,6 @@ class SelfCommandBuilder extends CommandBuilder { - /** * Initalized command */ @@ -31,10 +30,12 @@ protected function initialize() { $arguments = $_SERVER['argv']; + // Check if command is run inside PHAR if (\Phar::running()) { - // running as phar + // PHAR version $this->setCommand(array_shift($arguments)); } elseif (!empty($_SERVER['_'])) { + // Plain PHP version if ($_SERVER['argv'][0] !== $_SERVER['_']) { $this->setCommand($_SERVER['_']); $this->addArgument(reset($arguments)); diff --git a/src/app/CliTools/Console/Command/Apache/TraceCommand.php b/src/app/CliTools/Console/Command/Apache/TraceCommand.php index 4faf2e8..89fbd9f 100644 --- a/src/app/CliTools/Console/Command/Apache/TraceCommand.php +++ b/src/app/CliTools/Console/Command/Apache/TraceCommand.php @@ -35,6 +35,7 @@ class TraceCommand extends \CliTools\Console\Command\AbstractTraceCommand { protected function configure() { $this->setName('apache:trace') ->setDescription('Debug Apache processes with strace'); + parent::configure(); } diff --git a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php index 2368acb..9141871 100644 --- a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php +++ b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php @@ -54,9 +54,5 @@ public function execute(InputInterface $input, OutputInterface $output) { } $updateService->update(); - - - - } } diff --git a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php index 6e70126..74424d0 100644 --- a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php @@ -68,13 +68,17 @@ protected function getDockerEnv($containerName, $envName) { return false; } + // Search updir for docker-compose.yml $path = $this->getDockerPath(); if (!empty($path)) { + // Genrate full docker container name $dockerContainerName = \CliTools\Utility\DockerUtility::getDockerInstanceName($containerName, 1, $path); + // Switch to directory of docker-compose.yml PhpUtility::chdir($path); + // Get docker confguration (fetched directly from docker) $conf = \CliTools\Utility\DockerUtility::getDockerConfiguration($dockerContainerName); if (empty($conf)) { @@ -108,11 +112,14 @@ protected function executeDockerExec($containerName, CommandBuilderInterface $co return 1; } + // Search updir for docker-compose.yml $path = $this->getDockerPath(); if (!empty($path)) { + // Genrate full docker container name $dockerContainerName = \CliTools\Utility\DockerUtility::getDockerInstanceName($containerName, 1, $path); + // Switch to directory of docker-compose.yml PhpUtility::chdir($path); $this->output->writeln('Executing "' . $command->getCommand() . '" in docker container "' . $dockerContainerName . '" ...'); @@ -137,10 +144,13 @@ protected function executeDockerExec($containerName, CommandBuilderInterface $co * @return int|null|void */ protected function executeDockerCompose(CommandBuilderInterface $command = null) { + // Search updir for docker-compose.yml $path = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); if (!empty($path)) { $this->output->writeln('Found docker directory: ' . $path . ''); + + // Switch to directory of docker-compose.yml PhpUtility::chdir($path); $command->setCommand('docker-compose'); @@ -163,9 +173,11 @@ protected function executeDockerCompose(CommandBuilderInterface $command = null) * @return int|null|void */ protected function executeDockerComposeRun($containerName, CommandBuilderInterface $command) { + // Search updir for docker-compose.yml $path = $this->getDockerPath(); if (!empty($path)) { + // Switch to directory of docker-compose.yml PhpUtility::chdir($path); $this->output->writeln('Executing "' . $command->getCommand() . '" in docker container "' . $containerName . '" ...'); From dabcc7ac1b62d1b7e6512aeb342de2e564e3800e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 7 May 2015 20:30:37 +0200 Subject: [PATCH 003/214] Added selfupdate from github Fixes #19 --- .../Command/Common/SelfUpdateCommand.php | 13 +- .../CliTools/Service/SelfUpdateService.php | 164 +++++++++++++++--- src/app/CliTools/Utility/PhpUtility.php | 35 +++- src/config.ini | 9 +- 4 files changed, 194 insertions(+), 27 deletions(-) diff --git a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php index 9141871..388c814 100644 --- a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php +++ b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php @@ -21,6 +21,7 @@ */ use CliTools\Service\SelfUpdateService; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -32,7 +33,13 @@ class SelfUpdateCommand extends \CliTools\Console\Command\AbstractCommand { protected function configure() { $this->setName('self-update') ->setAliases(array('selfupdate')) - ->setDescription('Self update of CliTools Command'); + ->setDescription('Self update of CliTools Command') + ->addOption( + 'force', + 'f', + InputOption::VALUE_NONE, + 'Force update' + ); } /** @@ -44,6 +51,8 @@ protected function configure() { * @return int|null|void */ public function execute(InputInterface $input, OutputInterface $output) { + $force = (bool)$input->getOption('force'); + $updateService = new SelfUpdateService($this->getApplication(), $output); // Check if we need root rights @@ -53,6 +62,6 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->elevateProcess($input, $output); } - $updateService->update(); + $updateService->update($force); } } diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index c3d89e9..1b8bdb0 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -31,6 +31,27 @@ class SelfUpdateService { */ protected $updateUrl; + /** + * Version + * + * @var null|string + */ + protected $updateVersion; + + /** + * Changelog + * + * @var null|string + */ + protected $updateChangelog; + + /** + * Update github url + * + * @var null|string + */ + protected $githubReleaseUrl; + /** * Path to current clitools command * @@ -92,29 +113,88 @@ public function isElevationNeeded() { /** * Update clitools command + * + * @param boolean $force Force update */ - public function update() { - $this->updateUrl = $this->application->getConfigValue('config', 'self_update_url', null); + public function update($force = false) { + $this->githubReleaseUrl = $this->application->getConfigValue('config', 'self_update_github', null); + + if (!empty($this->githubReleaseUrl)) { + $this->fetchLatestReleaseFromGithub(); + } else { + throw new \RuntimeException('GitHub Release URL not set'); + } + + if ($this->checkIfUpdateNeeded($force)) { + // Update needed + $this->doUpdate(); + } + } + + /** + * Check if update is needed + * + * @param boolean $force Force update + * + * @return bool + */ + protected function checkIfUpdateNeeded($force) { + $ret = false; + + $this->output->write('Checking version... '); + + // Check if version is equal + if ($this->updateVersion !== CLITOOLS_COMMAND_VERSION) { + $this->output->write('new version "' . $this->updateVersion . '" found'); + $ret = true; + } else { + $this->output->write('already up to date'); + } + + // Check if update is forced + if ($force) { + $this->output->write(' [forced]'); + $ret = true; + } + + $this->output->writeln(''); + + return $ret; + } + /** + * Do update + */ + protected function doUpdate() { if (empty($this->updateUrl)) { - throw new \RuntimeException('Self-Update url is not set'); + throw new \RuntimeException('Self-Update url is not found'); } $this->output->writeln('Update URL: ' . $this->updateUrl . ''); - $this->output->writeln('Download new clitools command version...'); + $this->output->write('Downloading.'); $this->downloadUpdate(); + $this->output->writeln(' done'); try { + // Test update $versionString = $this->testUpdate(); - $this->output->writeln('Deploy update...'); + // Deploy update + $this->output->writeln('Deploying update... '); $this->deployUpdate(); + // Show version $this->output->writeln(''); $this->output->writeln('Updated to:'); $this->output->writeln(' ' . $versionString); $this->output->writeln(''); + + // Show changelog + if (!empty($this->updateChangelog)) { + $this->showChangelog(); + } + } catch (\Exception $e) { $this->output->writeln('Update failed'); } @@ -122,6 +202,50 @@ public function update() { $this->cleanup(); } + /** + * Fetch latest release from github api + */ + protected function fetchLatestReleaseFromGithub() { + $this->output->write('Getting informations from GitHub... '); + + $data = \CliTools\Utility\PhpUtility::curlFetch($this->githubReleaseUrl); + $data = json_decode($data, true); + + if (!empty($data)) { + $this->updateVersion = trim($data['tag_name']); + $this->updateChangelog = $data['body']; + + foreach ($data['assets'] as $asset) { + if ($asset['name'] === 'clitools.phar') { + $this->updateUrl = $asset['browser_download_url']; + } + } + } + + $this->output->writeln('done'); + } + + /** + * Show changelog + */ + protected function showChangelog() { + + $message = $this->updateChangelog; + + // Pad lines + $message = explode("\n", $message); + $message = array_map(function($line) { + return ' ' . $line; + }, $message); + $message = implode("\n", $message); + + $message = preg_replace('/`([^`]+)`/', '\1', $message); + + $this->output->writeln('Changelog:'); + $this->output->writeln($message); + $this->output->writeln(''); + } + /** * Get current file informations= */ @@ -152,23 +276,23 @@ protected function collectInformations() { * Download file */ protected function downloadUpdate() { - $curlHandle = curl_init(); - curl_setopt($curlHandle, CURLOPT_URL, $this->updateUrl); - curl_setopt($curlHandle, CURLOPT_VERBOSE, 0); - curl_setopt($curlHandle, CURLOPT_HEADER, 0); - curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, 1); - curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 2); - curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, 1); - - $curlData = curl_exec($curlHandle); - if (curl_errno($curlHandle) || empty($curlData)) { - throw new \RuntimeException('Could not download update: ' . curl_error($curlHandle)); - } - curl_close($curlHandle); + $output = $this->output; + + // Progress counter + $progress = function($downloadTotal, $downoadProgress) use ($output) { + static $counter = 0; + + if($counter % 30 === 0) { + $output->write('.'); + } + + $counter++; + }; + + $data = \CliTools\Utility\PhpUtility::curlFetch($this->updateUrl, $progress); $tmpFile = tempnam(sys_get_temp_dir(), 'ct'); - file_put_contents($tmpFile, $curlData); + file_put_contents($tmpFile, $data); $this->cliToolsUpdatePath = $tmpFile; } diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index 97ede9b..ff15411 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -29,7 +29,7 @@ class PhpUtility { * @throws \RuntimeException */ public static function chdir($path) { - if (!chdir($path)) { + if (!is_dir($path) && !chdir($path)) { throw new \RuntimeException('Could not change working directory to "' . $path . '"'); } } @@ -45,4 +45,37 @@ public static function unlink($path) { throw new \RuntimeException('Could not change working directory to "' . $path . '"'); } } + + /** + * Fetch content from url using curl + * + * @param string $url Url + * @param callable $progress Progress callback + * + * @return mixed + */ + public static function curlFetch($url, callable $progress = null) { + $curlHandle = curl_init(); + curl_setopt($curlHandle, CURLOPT_URL, $url); + curl_setopt($curlHandle, CURLOPT_VERBOSE, 0); + curl_setopt($curlHandle, CURLOPT_HEADER, 0); + curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, 1); + curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($curlHandle, CURLOPT_USERAGENT, 'CliTools ' . CLITOOLS_COMMAND_VERSION . '(https://github.com/mblaschke/vagrant-clitools)'); + + if($progress) { + curl_setopt($curlHandle, CURLOPT_NOPROGRESS, false); + curl_setopt($curlHandle, CURLOPT_PROGRESSFUNCTION, $progress); + } + + $ret = curl_exec($curlHandle); + if (curl_errno($curlHandle) || empty($ret)) { + throw new \RuntimeException('Could not fetch url "' . $url . '", error: ' . curl_error($curlHandle)); + } + curl_close($curlHandle); + + return $ret; + } } diff --git a/src/config.ini b/src/config.ini index 4409b59..0d9a901 100644 --- a/src/config.ini +++ b/src/config.ini @@ -1,8 +1,8 @@ [config] -ssh_conf_path = "/opt/conf/ssh" -www_base_path = "/var/www" -domain_dev[] = "dev" -self_update_url = "https://www.achenar.net/clicommand/clitools.phar" +ssh_conf_path = "/opt/conf/ssh" +www_base_path = "/var/www" +domain_dev[] = "dev" +self_update_github = "https://api.github.com/repos/mblaschke/vagrant-clitools/releases/latest" [db] dsn = "mysql:host=localhost" @@ -34,6 +34,7 @@ typo3[] = "/^sys_log$/i" typo3[] = "/^sys_history$/i" typo3[] = "/^tx_extbase_cache.*/i" + [commands] ; load following classes class[] = "CliTools\Console\Command\Common\SelfUpdateCommand" From f29641df4bd3da7377de10266864b1f720d09c03 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 7 May 2015 22:42:13 +0200 Subject: [PATCH 004/214] Improved selfupdate from github Fixes #19 --- src/app/CliTools/Service/SelfUpdateService.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index 1b8bdb0..632a4e6 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -212,6 +212,17 @@ protected function fetchLatestReleaseFromGithub() { $data = json_decode($data, true); if (!empty($data)) { + // Check release + if (!empty($data['draft']) || !empty($data['prerelease'])) { + throw new \RuntimeException('Fetched release of GitHub was not valid (either draft or prerelease)'); + } + + // Check for required tag_name + if (empty($data['tag_name'])) { + throw new \RuntimeException('Fetched release of GitHub was not valid (tag_name is empty)'); + } + + // Get basic informations $this->updateVersion = trim($data['tag_name']); $this->updateChangelog = $data['body']; From 270ad5400c925029cb537711c380889c041112fb Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 8 May 2015 18:05:24 +0200 Subject: [PATCH 005/214] Version bump 1.10.0 --- CHANGELOG.md | 5 +++++ src/command.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0cd95b..c342c40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CliTools Changelog ================== +1.10.0 - Upcoming +------------------ +- Added GitHub based `self-update` +- Fixed some issues + 1.9.0 - 2015-05-06 ------------------ - Added `mysql:backup` (with --filter=typo3, support for plain sql, gzip, bzip2, lzma compression) diff --git a/src/command.php b/src/command.php index a70c438..2f71a6a 100644 --- a/src/command.php +++ b/src/command.php @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -define('CLITOOLS_COMMAND_VERSION', '1.9.0'); +define('CLITOOLS_COMMAND_VERSION', '1.10.0'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From d2794e19e01689086786d9ab71c71fc47e052c98 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 8 May 2015 18:05:34 +0200 Subject: [PATCH 006/214] Improved self update service --- .../CliTools/Service/SelfUpdateService.php | 100 ++++++++++++------ src/config.ini | 2 +- 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index 632a4e6..4f8f117 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -141,14 +141,14 @@ public function update($force = false) { protected function checkIfUpdateNeeded($force) { $ret = false; - $this->output->write('Checking version... '); + $this->output->write('Checking version... '); // Check if version is equal if ($this->updateVersion !== CLITOOLS_COMMAND_VERSION) { - $this->output->write('new version "' . $this->updateVersion . '" found'); + $this->output->write('new version "' . $this->updateVersion . '" found'); $ret = true; } else { - $this->output->write('already up to date'); + $this->output->write('already up to date'); } // Check if update is forced @@ -170,31 +170,41 @@ protected function doUpdate() { throw new \RuntimeException('Self-Update url is not found'); } - $this->output->writeln('Update URL: ' . $this->updateUrl . ''); + try { + // ############## + // Download + // ############## - $this->output->write('Downloading.'); - $this->downloadUpdate(); - $this->output->writeln(' done'); + $this->output->writeln('Update URL: ' . $this->updateUrl . ''); - try { - // Test update - $versionString = $this->testUpdate(); + $this->output->write('Downloading.'); + $this->downloadUpdate(); + $this->output->writeln(' done'); - // Deploy update + // ############## + // Test + // ############## + $this->testUpdate(); + + // ############## + // Deploy + // ############## $this->output->writeln('Deploying update... '); $this->deployUpdate(); - // Show version + // ############## + // Summary + // ############## + + // Version $this->output->writeln(''); - $this->output->writeln('Updated to:'); - $this->output->writeln(' ' . $versionString); + $this->output->writeln('Updated from Version ' . CLITOOLS_COMMAND_VERSION . ' to ' . $this->updateVersion . ''); $this->output->writeln(''); - // Show changelog + // Changelog if (!empty($this->updateChangelog)) { $this->showChangelog(); } - } catch (\Exception $e) { $this->output->writeln('Update failed'); } @@ -208,32 +218,48 @@ protected function doUpdate() { protected function fetchLatestReleaseFromGithub() { $this->output->write('Getting informations from GitHub... '); - $data = \CliTools\Utility\PhpUtility::curlFetch($this->githubReleaseUrl); - $data = json_decode($data, true); + $releaseList = \CliTools\Utility\PhpUtility::curlFetch($this->githubReleaseUrl); + $releaseList = json_decode($releaseList, true); - if (!empty($data)) { - // Check release - if (!empty($data['draft']) || !empty($data['prerelease'])) { - throw new \RuntimeException('Fetched release of GitHub was not valid (either draft or prerelease)'); - } + $releaseFound = false; - // Check for required tag_name - if (empty($data['tag_name'])) { - throw new \RuntimeException('Fetched release of GitHub was not valid (tag_name is empty)'); - } + if (!empty($releaseList)) { + foreach ($releaseList as $release) { + // Check release + if (!empty($release['draft']) || !empty($release['prerelease'])) { + // no valid release + continue; + } - // Get basic informations - $this->updateVersion = trim($data['tag_name']); - $this->updateChangelog = $data['body']; + // Check for required tag_name + if (empty($release['tag_name'])) { + // no valid release (requires version tag) + continue; + } + + // Get basic informations + $this->updateVersion = trim($release['tag_name']); + $this->updateChangelog = $release['body']; + + foreach ($release['assets'] as $asset) { + if ($asset['name'] === 'clitools.phar') { + $this->updateUrl = $asset['browser_download_url']; + } + } - foreach ($data['assets'] as $asset) { - if ($asset['name'] === 'clitools.phar') { - $this->updateUrl = $asset['browser_download_url']; + if (!empty($this->updateVersion) && !empty($this->updateUrl)) { + // valid version found + break; } } } - $this->output->writeln('done'); + if (!empty($this->updateUrl)) { + $this->output->writeln('done'); + } else { + $this->output->writeln('failed'); + throw new \RuntimeException('Could not fetch new version - maybe GitHub API is down or other error occurred'); + } } /** @@ -346,7 +372,7 @@ protected function deployUpdate() { } /** - * Test update and show version + * Test update and try to get version * * @return string */ @@ -363,5 +389,9 @@ protected function testUpdate() { * Cleanup */ protected function cleanup() { + // Remove old update file if set and exists + if ($this->cliToolsUpdatePath && file_exists($this->cliToolsUpdatePath)) { + unlink($this->cliToolsUpdatePath); + } } } diff --git a/src/config.ini b/src/config.ini index 0d9a901..d8ef9aa 100644 --- a/src/config.ini +++ b/src/config.ini @@ -2,7 +2,7 @@ ssh_conf_path = "/opt/conf/ssh" www_base_path = "/var/www" domain_dev[] = "dev" -self_update_github = "https://api.github.com/repos/mblaschke/vagrant-clitools/releases/latest" +self_update_github = "https://api.github.com/repos/mblaschke/vagrant-clitools/releases" [db] dsn = "mysql:host=localhost" From 997805813f29ebf1085eda6f52a5212d21c9e704 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 12:44:16 +0200 Subject: [PATCH 007/214] Cleanup --- src/app/CliTools/Console/Command/Docker/CliCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Docker/CliCommand.php b/src/app/CliTools/Console/Command/Docker/CliCommand.php index 79f455b..5bfd522 100644 --- a/src/app/CliTools/Console/Command/Docker/CliCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CliCommand.php @@ -20,9 +20,9 @@ * along with this program. If not, see . */ +use CliTools\Console\Builder\RemoteCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\RemoteCommandBuilder; class CliCommand extends AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { From 8c1c65c6f59e52e0b1582639f16b1ac8a86be9af Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 12:44:35 +0200 Subject: [PATCH 008/214] Refactored directroty tree searching for file --- src/app/CliTools/Utility/DockerUtility.php | 25 ++--------------- src/app/CliTools/Utility/UnixUtility.php | 31 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/app/CliTools/Utility/DockerUtility.php b/src/app/CliTools/Utility/DockerUtility.php index 57d22f0..4cc55a0 100644 --- a/src/app/CliTools/Utility/DockerUtility.php +++ b/src/app/CliTools/Utility/DockerUtility.php @@ -73,27 +73,7 @@ public static function getDockerConfiguration($container) { * @return bool|string */ public static function searchDockerDirectoryRecursive($path = null) { - $ret = false; - - // Set path to current path (if not specified) - if ($path === null) { - $path = getcwd(); - } - - if (!empty($path) && $path !== '/') { - // Check if current path is docker directory - if (self::isDockerDirectory($path)) { - // Docker found - $ret = $path; - } else { - // go up in directory - $path .= '/../'; - $path = realpath($path); - $ret = self::searchDockerDirectoryRecursive($path); - } - } - - return $ret; + return UnixUtility::findFileInDirectortyTree('docker-compose.yml', $path) } /** @@ -109,8 +89,7 @@ public static function isDockerDirectory($path = null) { } $dockerFileList = array( - 'docker-compose.yml', - 'fig.yml', + 'docker-compose.yml' ); foreach ($dockerFileList as $dockerFile) { diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index 1abd1fa..a3571fc 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -256,4 +256,35 @@ public static function checkExecutable($command) { return false; } + + /** + * Search directory upwards for a file + * + * @param string $file Filename + * @param string $path Path + * @return boolean|string + */ + public static function findFileInDirectortyTree($file, $path = null) { + $ret = false; + + // Set path to current path (if not specified) + if ($path === null) { + $path = getcwd(); + } + + if (!empty($path) && $path !== '/') { + // Check if file exists in path + if (file_exists($file)) { + // Docker found + $ret = $path; + } else { + // go up in directory + $path .= '/../'; + $path = realpath($path); + $ret = self::searchUpDirForFile($path); + } + } + + return $ret; + } } From 86b63603c8d437a7eae0978e9d31516c6c01209e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 12:44:52 +0200 Subject: [PATCH 009/214] Added make (auto search in directory tree) --- CHANGELOG.md | 1 + README.md | 4 + .../Console/Command/Common/MakeCommand.php | 73 +++++++++++++++++++ src/config.ini | 1 + 4 files changed, 79 insertions(+) create mode 100644 src/app/CliTools/Console/Command/Common/MakeCommand.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c342c40..bea8612 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CliTools Changelog 1.10.0 - Upcoming ------------------ - Added GitHub based `self-update` +- Added `make` (auto search for Makefile in tree) - Fixed some issues 1.9.0 - 2015-05-06 diff --git a/README.md b/README.md index 76190b1..7b88eaf 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,9 @@ wget -O"$HOME/.clitools.ini" https://raw.githubusercontent.com/mblaschke/vagrant Now you can use following aliases (some aliases requires clitools 1.8.0!): ```bash +# Shortcut for auto-tree-searching make +alias make='ct make' + # Shortcut for docker-compose (autosearch docker-compose.yml in up-dir, you don't have to be in directory with docker-compose.yml) alias dcc='ct docker:compose' @@ -117,6 +120,7 @@ ignore[] = "CliTools\Console\Command\System\RebootCommand" |----------------------------|---------------------------------------------------------------------------| | ct self-update | Update ct command (download new version) | | ct update | Updates all system components, ssh configuration, ct command update etc. | +| ct make | Search for "Makefile" in tree and start "make" in this directory | ### System commands diff --git a/src/app/CliTools/Console/Command/Common/MakeCommand.php b/src/app/CliTools/Console/Command/Common/MakeCommand.php new file mode 100644 index 0000000..e101958 --- /dev/null +++ b/src/app/CliTools/Console/Command/Common/MakeCommand.php @@ -0,0 +1,73 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Utility\UnixUtility; +use CliTools\Utility\PhpUtility; +use CliTools\Console\Builder\CommandBuilder; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class MakeCommand extends \CliTools\Console\Command\AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { + + /** + * Configure command + */ + protected function configure() { + $this->setName('make') + ->setDescription('Search Makefile updir and start makefile'); + } + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + */ + public function execute(InputInterface $input, OutputInterface $output) { + $paramList = $this->getFullParameterList(); + $path = UnixUtility::findFileInDirectortyTree('Makefile'); + + if (!empty($path)) { + $this->output->writeln('Found Makefile directory: ' . $path . ''); + + // Switch to directory of docker-compose.yml + PhpUtility::chdir($path); + + $command = new CommandBuilder('make'); + + if (!empty($paramList)) { + $command->setArgumentList($paramList); + } + + $command->executeInteractive(); + } else { + $this->output->writeln('No Makefile found in tree'); + + return 1; + } + + return 0; + } +} diff --git a/src/config.ini b/src/config.ini index d8ef9aa..94bf2dd 100644 --- a/src/config.ini +++ b/src/config.ini @@ -38,6 +38,7 @@ typo3[] = "/^tx_extbase_cache.*/i" [commands] ; load following classes class[] = "CliTools\Console\Command\Common\SelfUpdateCommand" +class[] = "CliTools\Console\Command\Common\MakeCommand" class[] = "CliTools\Console\Command\TYPO3\BeUserCommand" class[] = "CliTools\Console\Command\TYPO3\InstallerCommand" From b7c2b125166ff21ea8fec117154fa4cdb9f71367 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 12:48:22 +0200 Subject: [PATCH 010/214] Fixed fatal error --- src/app/CliTools/Utility/DockerUtility.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Utility/DockerUtility.php b/src/app/CliTools/Utility/DockerUtility.php index 4cc55a0..0b66316 100644 --- a/src/app/CliTools/Utility/DockerUtility.php +++ b/src/app/CliTools/Utility/DockerUtility.php @@ -73,7 +73,7 @@ public static function getDockerConfiguration($container) { * @return bool|string */ public static function searchDockerDirectoryRecursive($path = null) { - return UnixUtility::findFileInDirectortyTree('docker-compose.yml', $path) + return UnixUtility::findFileInDirectortyTree('docker-compose.yml', $path); } /** From 712c98b19306c372d8d18f7a4cfd7a42540eb6dc Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 12:51:23 +0200 Subject: [PATCH 011/214] Fixed fatal error, again --- src/app/CliTools/Utility/UnixUtility.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index a3571fc..016b8cb 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -281,7 +281,7 @@ public static function findFileInDirectortyTree($file, $path = null) { // go up in directory $path .= '/../'; $path = realpath($path); - $ret = self::searchUpDirForFile($path); + $ret = self::findFileInDirectortyTree($path); } } From b289735a7927af0b67ab955b14f6322e56e1c529 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 12:55:49 +0200 Subject: [PATCH 012/214] Cleanup --- src/app/CliTools/Console/Command/Common/MakeCommand.php | 1 - src/app/CliTools/Service/SelfUpdateService.php | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Common/MakeCommand.php b/src/app/CliTools/Console/Command/Common/MakeCommand.php index e101958..4d7c1f0 100644 --- a/src/app/CliTools/Console/Command/Common/MakeCommand.php +++ b/src/app/CliTools/Console/Command/Common/MakeCommand.php @@ -23,7 +23,6 @@ use CliTools\Utility\UnixUtility; use CliTools\Utility\PhpUtility; use CliTools\Console\Builder\CommandBuilder; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index 4f8f117..9eb8748 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -221,8 +221,6 @@ protected function fetchLatestReleaseFromGithub() { $releaseList = \CliTools\Utility\PhpUtility::curlFetch($this->githubReleaseUrl); $releaseList = json_decode($releaseList, true); - $releaseFound = false; - if (!empty($releaseList)) { foreach ($releaseList as $release) { // Check release From 803e4dd0c0d375d5beec67cd4c64ccee9a780621 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 15:09:48 +0200 Subject: [PATCH 013/214] Fixed fatal error for chdir --- src/app/CliTools/Utility/PhpUtility.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index ff15411..c606ef6 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -29,7 +29,7 @@ class PhpUtility { * @throws \RuntimeException */ public static function chdir($path) { - if (!is_dir($path) && !chdir($path)) { + if (!is_dir($path) || !chdir($path)) { throw new \RuntimeException('Could not change working directory to "' . $path . '"'); } } From 148afbda14b0da9d7e6acbea49a65bad353cdcf4 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 15:10:05 +0200 Subject: [PATCH 014/214] Fixed findFileInDirectortyTree --- src/app/CliTools/Utility/UnixUtility.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index 016b8cb..4fb265e 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -274,14 +274,14 @@ public static function findFileInDirectortyTree($file, $path = null) { if (!empty($path) && $path !== '/') { // Check if file exists in path - if (file_exists($file)) { - // Docker found + if (file_exists($path . '/' . $file)) { + // File found $ret = $path; } else { // go up in directory $path .= '/../'; $path = realpath($path); - $ret = self::findFileInDirectortyTree($path); + $ret = self::findFileInDirectortyTree($file, $path); } } From 364f7f0f94dbe19493450614b8ddd51e04cc895f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 15:12:22 +0200 Subject: [PATCH 015/214] Added php:composer --- CHANGELOG.md | 1 + README.md | 1 + .../Console/Command/Php/ComposeCommand.php | 72 +++++++++++++++++++ src/config.ini | 1 + 4 files changed, 75 insertions(+) create mode 100644 src/app/CliTools/Console/Command/Php/ComposeCommand.php diff --git a/CHANGELOG.md b/CHANGELOG.md index bea8612..ec85091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ CliTools Changelog ------------------ - Added GitHub based `self-update` - Added `make` (auto search for Makefile in tree) +- Added `php:compose` (auto search for compose.yml in tree) - Fixed some issues 1.9.0 - 2015-05-06 diff --git a/README.md b/README.md index 7b88eaf..0401c16 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,7 @@ All log commands are using a grep-filter (specified as optional argument) |----------------------------|---------------------------------------------------------------------------| | ct php:trace | Trace syscalls from one or all PHP processes (strace) | | | __ct php:trace --all__ -> Trace all php processes immediately | +| ct php:compose | Search for "composer.yml" in tree and start "composer" in this directory | ### Samba commands diff --git a/src/app/CliTools/Console/Command/Php/ComposeCommand.php b/src/app/CliTools/Console/Command/Php/ComposeCommand.php new file mode 100644 index 0000000..045ec95 --- /dev/null +++ b/src/app/CliTools/Console/Command/Php/ComposeCommand.php @@ -0,0 +1,72 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Utility\UnixUtility; +use CliTools\Utility\PhpUtility; +use CliTools\Console\Builder\CommandBuilder; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ComposeCommand extends \CliTools\Console\Command\AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { + + /** + * Configure command + */ + protected function configure() { + $this->setName('php:compose') + ->setDescription('Search composer.json updir and start composer'); + } + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + */ + public function execute(InputInterface $input, OutputInterface $output) { + $paramList = $this->getFullParameterList(); + $path = UnixUtility::findFileInDirectortyTree('composer.json'); + + if (!empty($path)) { + $this->output->writeln('Found composer.json directory: ' . $path . ''); + + // Switch to directory of docker-compose.yml + PhpUtility::chdir($path); + + $command = new CommandBuilder('composer'); + + if (!empty($paramList)) { + $command->setArgumentList($paramList); + } + + $command->executeInteractive(); + } else { + $this->output->writeln('No composer.json found in tree'); + + return 1; + } + + return 0; + } +} diff --git a/src/config.ini b/src/config.ini index 94bf2dd..0f99594 100644 --- a/src/config.ini +++ b/src/config.ini @@ -68,6 +68,7 @@ class[] = "CliTools\Console\Command\Mysql\DropCommand" class[] = "CliTools\Console\Command\Php\TraceCommand" class[] = "CliTools\Console\Command\Php\RestartCommand" +class[] = "CliTools\Console\Command\Php\ComposeCommand" class[] = "CliTools\Console\Command\Samba\RestartCommand" From a40c75d95afa4a147323e1b6dade396b24b531cf Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 15:14:32 +0200 Subject: [PATCH 016/214] Renamed php:compose to php:composer --- CHANGELOG.md | 2 +- README.md | 2 +- .../Command/Php/{ComposeCommand.php => ComposerCommand.php} | 4 ++-- src/config.ini | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename src/app/CliTools/Console/Command/Php/{ComposeCommand.php => ComposerCommand.php} (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec85091..568fbfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ CliTools Changelog ------------------ - Added GitHub based `self-update` - Added `make` (auto search for Makefile in tree) -- Added `php:compose` (auto search for compose.yml in tree) +- Added `php:composer` (auto search for compose.yml in tree) - Fixed some issues 1.9.0 - 2015-05-06 diff --git a/README.md b/README.md index 0401c16..ca35d3f 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ All log commands are using a grep-filter (specified as optional argument) |----------------------------|---------------------------------------------------------------------------| | ct php:trace | Trace syscalls from one or all PHP processes (strace) | | | __ct php:trace --all__ -> Trace all php processes immediately | -| ct php:compose | Search for "composer.yml" in tree and start "composer" in this directory | +| ct php:composer | Search for "composer.yml" in tree and start "composer" in this directory | ### Samba commands diff --git a/src/app/CliTools/Console/Command/Php/ComposeCommand.php b/src/app/CliTools/Console/Command/Php/ComposerCommand.php similarity index 92% rename from src/app/CliTools/Console/Command/Php/ComposeCommand.php rename to src/app/CliTools/Console/Command/Php/ComposerCommand.php index 045ec95..0503f0f 100644 --- a/src/app/CliTools/Console/Command/Php/ComposeCommand.php +++ b/src/app/CliTools/Console/Command/Php/ComposerCommand.php @@ -26,13 +26,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ComposeCommand extends \CliTools\Console\Command\AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { +class ComposerCommand extends \CliTools\Console\Command\AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { /** * Configure command */ protected function configure() { - $this->setName('php:compose') + $this->setName('php:composer') ->setDescription('Search composer.json updir and start composer'); } diff --git a/src/config.ini b/src/config.ini index 0f99594..57ca3fb 100644 --- a/src/config.ini +++ b/src/config.ini @@ -68,7 +68,7 @@ class[] = "CliTools\Console\Command\Mysql\DropCommand" class[] = "CliTools\Console\Command\Php\TraceCommand" class[] = "CliTools\Console\Command\Php\RestartCommand" -class[] = "CliTools\Console\Command\Php\ComposeCommand" +class[] = "CliTools\Console\Command\Php\ComposerCommand" class[] = "CliTools\Console\Command\Samba\RestartCommand" From 61a2458a8593295164e4a907c05b4f7db3b2db43 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 15:15:54 +0200 Subject: [PATCH 017/214] Updated readme, fixed typo in changelog --- CHANGELOG.md | 2 +- README.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 568fbfc..0d49097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ CliTools Changelog ------------------ - Added GitHub based `self-update` - Added `make` (auto search for Makefile in tree) -- Added `php:composer` (auto search for compose.yml in tree) +- Added `php:composer` (auto search for composer.yml in tree) - Fixed some issues 1.9.0 - 2015-05-06 diff --git a/README.md b/README.md index ca35d3f..aa3f05b 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,9 @@ Now you can use following aliases (some aliases requires clitools 1.8.0!): # Shortcut for auto-tree-searching make alias make='ct make' +# Shortcut for auto-tree-searching make +alias composer='ct php:composer' + # Shortcut for docker-compose (autosearch docker-compose.yml in up-dir, you don't have to be in directory with docker-compose.yml) alias dcc='ct docker:compose' From 6872582e8549a587bde40b3b7faa63d4c0ffa335 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 15:28:17 +0200 Subject: [PATCH 018/214] Improved and fixed command parser --- .../Console/Builder/AbstractCommandBuilder.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php index 6aad59a..132e75b 100644 --- a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php @@ -314,10 +314,20 @@ public function setOutputRedirectToFile($filename) { * @return $this */ public function parse($str) { - list($command, $attributs) = explode(' ', $str, 2); + $parsedCmd = explode(' ', $str, 2); - $this->setCommand($command); - $this->setArgumentList(array($attributs), false); + // Check required command + if (empty($parsedCmd[0])) { + throw new \RuntimeException('Command is empty'); + } + + // Set command (first value) + $this->setCommand($parsedCmd[0]); + + // Set arguments (second values) + if (!empty($parsedCmd[1])) { + $this->setArgumentList(array($parsedCmd[1]), false); + } return $this; } From 62b7cdf6ccbb08a917f8d3f8e0467ea8c1975761 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 9 May 2015 15:28:31 +0200 Subject: [PATCH 019/214] Added configurable composer command --- src/app/CliTools/Console/Command/Php/ComposerCommand.php | 5 ++++- src/config.ini | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Php/ComposerCommand.php b/src/app/CliTools/Console/Command/Php/ComposerCommand.php index 0503f0f..7f6c23a 100644 --- a/src/app/CliTools/Console/Command/Php/ComposerCommand.php +++ b/src/app/CliTools/Console/Command/Php/ComposerCommand.php @@ -45,6 +45,8 @@ protected function configure() { * @return int|null|void */ public function execute(InputInterface $input, OutputInterface $output) { + $composerCmd = $this->getApplication()->getConfigValue('bin', 'composer'); + $paramList = $this->getFullParameterList(); $path = UnixUtility::findFileInDirectortyTree('composer.json'); @@ -54,7 +56,8 @@ public function execute(InputInterface $input, OutputInterface $output) { // Switch to directory of docker-compose.yml PhpUtility::chdir($path); - $command = new CommandBuilder('composer'); + $command = new CommandBuilder(); + $command->parse($composerCmd); if (!empty($paramList)) { $command->setArgumentList($paramList); diff --git a/src/config.ini b/src/config.ini index 57ca3fb..7db4904 100644 --- a/src/config.ini +++ b/src/config.ini @@ -10,6 +10,9 @@ username = "root" password = "" debug_log_dir = "/tmp/" +[bin] +composer = "composer" + [syscheck] enabled = 1 wall = 1 From 908df4fe4f48dd4822ad8c5ded95ce2cc4ae49ff Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sun, 10 May 2015 20:41:58 +0200 Subject: [PATCH 020/214] Tried to fix exit code handling if process is signaled --- src/app/CliTools/Console/Shell/Executor.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/app/CliTools/Console/Shell/Executor.php b/src/app/CliTools/Console/Shell/Executor.php index 93d0903..a9a0615 100644 --- a/src/app/CliTools/Console/Shell/Executor.php +++ b/src/app/CliTools/Console/Shell/Executor.php @@ -193,9 +193,18 @@ public function execInteractive() { $process = proc_open($this->command->build(), $descriptorSpec, $pipes); if (is_resource($process)) { - $this->returnCode = proc_close($process); - if ($this->strictMode && $this->returnCode !== 0) { + do { + usleep(50 * 1000); + $status = proc_get_status($process); + } while (is_array($status) && $status['running'] === true); + + $this->returnCode = $status['exitcode']; + + if ($status['signaled'] === true && $status['exitcode'] === -1) { + // user may hit CTRL+C + ConsoleUtility::getOutput()->writeln('Processed stopped by signal'); + } elseif ($this->strictMode && $this->returnCode !== 0) { throw $this->generateException('Process ' . $this->command->getCommand() . ' did not finished successfully'); } } else { From a0c30d514fab169686736b10a3b0d6b7a516c183 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 11 May 2015 18:57:09 +0200 Subject: [PATCH 021/214] Improved sanitizeSqlTable and -Database --- src/app/CliTools/Database/DatabaseConnection.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/CliTools/Database/DatabaseConnection.php b/src/app/CliTools/Database/DatabaseConnection.php index 883a21e..b182fbc 100644 --- a/src/app/CliTools/Database/DatabaseConnection.php +++ b/src/app/CliTools/Database/DatabaseConnection.php @@ -487,7 +487,7 @@ public static function sanitizeSqlField($field) { * @return string */ public static function sanitizeSqlTable($table) { - return preg_replace('/[^_a-zA-Z0-9]/', '', $table); + return '`' . preg_replace('/[^_a-zA-Z0-9]/', '', $table) . '`'; } /** @@ -498,6 +498,6 @@ public static function sanitizeSqlTable($table) { * @return string */ public static function sanitizeSqlDatabase($database) { - return preg_replace('/[^_a-zA-Z0-9]/', '', $database); + return '`' . preg_replace('/[^_a-zA-Z0-9]/', '', $database) . '`'; } } From cbf39431b40e335b85581e80a59a60ba5bbc538a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 11 May 2015 19:00:31 +0200 Subject: [PATCH 022/214] Added mysq:convert --- CHANGELOG.md | 1 + README.md | 7 + .../Console/Command/Mysql/ConvertCommand.php | 136 ++++++++++++++++++ src/config.ini | 2 + 4 files changed, 146 insertions(+) create mode 100644 src/app/CliTools/Console/Command/Mysql/ConvertCommand.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d49097..f0f42df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ CliTools Changelog - Added GitHub based `self-update` - Added `make` (auto search for Makefile in tree) - Added `php:composer` (auto search for composer.yml in tree) +- Added `mysql:convert` for automatic changing charset and collation of one database - Fixed some issues 1.9.0 - 2015-05-06 diff --git a/README.md b/README.md index aa3f05b..eeff256 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,13 @@ All log commands are using a grep-filter (specified as optional argument) | | Dump file can be plaintext, gziped, bzip2 or lzma compressed | | | and will automatically detected | | | __ct mysql:restore typo3 dump.sql.bz2__ | +| ct mysql:convert | Convert character set and collation of a database | +| | __ct mysql:convert typo3__ -> Convert typo3 into UTF-8 with utf8_general_ci | +| | __ct mysql:convert typo3 --charset=latin1__ -> Convert typo3 into LATIN-1 | +| | __ct mysql:convert typo3 --collation=utf8_unicode_ci__ -> Convert typo3 into UTF-8 with utf8_unicode_ci | +| | __ct mysql:convert typo3 --stdout__ -> Print sql statements to stdout | + + ### PHP commands diff --git a/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php new file mode 100644 index 0000000..fafbd02 --- /dev/null +++ b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php @@ -0,0 +1,136 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Database\DatabaseConnection; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ConvertCommand extends \CliTools\Console\Command\AbstractCommand { + + /** + * Configure command + */ + protected function configure() { + $this->setName('mysql:convert') + ->setDescription('Convert charset/collation of a database') + ->addArgument( + 'database', + InputArgument::REQUIRED, + 'Database name' + ) + ->addOption( + 'charset', + null, + InputOption::VALUE_REQUIRED, + 'Charset (default: utf8)' + ) + ->addOption( + 'collation', + null, + InputOption::VALUE_REQUIRED, + 'Collation (default: utf8_general_ci)' + ) + ->addOption( + 'stdout', + null, + InputOption::VALUE_NONE, + 'Only print sql statements, do not execute it' + ); + } + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + */ + public function execute(InputInterface $input, OutputInterface $output) { + $charset = 'utf8'; + $collation = 'utf8_general_ci'; + $stdout = false; + + $database = $input->getArgument('database'); + + if ($input->getOption('charset')) { + $charset = (string)$input->getOption('charset'); + } + + if ($input->getOption('collation')) { + $collation = (string)$input->getOption('collation'); + } + + if ($input->getOption('stdout')) { + $stdout = true; + } + + // ################## + // Alter database + // ################## + + $query = 'ALTER DATABASE %s CHARACTER SET %s COLLATE %s'; + $query = sprintf($query, + DatabaseConnection::sanitizeSqlDatabase($database), + DatabaseConnection::quote($charset), + DatabaseConnection::quote($collation) + ); + + if (!$stdout) { + // Execute + $output->writeln('Converting database ' . $database . ''); + DatabaseConnection::exec($query); + } else { + // Show only + $output->writeln($query . ';'); + } + + // ################## + // Alter tables + // ################## + $tableList = DatabaseConnection::tableList($database); + + foreach ($tableList as $table) { + // Build statement + $query = 'ALTER TABLE %s.%s CONVERT TO CHARACTER SET %s COLLATE %s'; + $query = sprintf($query, + DatabaseConnection::sanitizeSqlDatabase($database), + DatabaseConnection::sanitizeSqlTable($table), + DatabaseConnection::quote($charset), + DatabaseConnection::quote($collation) + ); + + if (!$stdout) { + // Execute + $output->writeln('Converting table ' . $table . ''); + DatabaseConnection::exec($query); + } else { + // Show only + $output->writeln($query . ';'); + } + } + + return 0; + } +} diff --git a/src/config.ini b/src/config.ini index 7db4904..38629cd 100644 --- a/src/config.ini +++ b/src/config.ini @@ -50,6 +50,7 @@ class[] = "CliTools\Console\Command\TYPO3\DomainCommand" class[] = "CliTools\Console\Command\TYPO3\SchedulerCommand" class[] = "CliTools\Console\Command\TYPO3\ListCommand" class[] = "CliTools\Console\Command\TYPO3\CleanupCommand" +class[] = "CliTools\Console\Command\TYPO3\SyncCommand" class[] = "CliTools\Console\Command\Log\ApacheCommand" class[] = "CliTools\Console\Command\Log\PhpCommand" @@ -68,6 +69,7 @@ class[] = "CliTools\Console\Command\Mysql\RestartCommand" class[] = "CliTools\Console\Command\Mysql\DebugCommand" class[] = "CliTools\Console\Command\Mysql\SlowLogCommand" class[] = "CliTools\Console\Command\Mysql\DropCommand" +class[] = "CliTools\Console\Command\Mysql\ConvertCommand" class[] = "CliTools\Console\Command\Php\TraceCommand" class[] = "CliTools\Console\Command\Php\RestartCommand" From 95cd4b2513a0a5cd3f8cf8421640f95385f075f2 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 12 May 2015 18:06:30 +0200 Subject: [PATCH 023/214] Fixed detection of *.bz2 --- src/app/CliTools/Console/Command/Mysql/BackupCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index 033581e..8ee021e 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -82,6 +82,7 @@ public function execute(InputInterface $input, OutputInterface $output) { switch ($fileExt) { case 'bz': + case 'bz2': case 'bzip2': $output->writeln('Using BZIP2 compression'); $commandCompressor = new CommandBuilder('bzip2'); From bf2f2d30910c06298ba002ffc004e82f5bda85a9 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 12 May 2015 18:06:50 +0200 Subject: [PATCH 024/214] Added PhpUtility::mkdir --- src/app/CliTools/Utility/PhpUtility.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index c606ef6..0fbd852 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -34,6 +34,27 @@ public static function chdir($path) { } } + /** + * Create new directory + * + * @param string $path Directory + * @param integer $mode Perms + * @param boolean $recursive Creation of nested directories + * @param resource $context Context + * @throws \RuntimeException + */ + public static function mkdir($path, $mode = 0777, $recursive = false, $context = null) { + if ($context !== null) { + $res = mkdir($path, $mode, $recursive, $context); + } else { + $res = mkdir($path, $mode, $recursive); + } + + if (!$res) { + throw new \RuntimeException('Could not create directory "' . $path . '"'); + } + } + /** * Remove file * From 09cdcbe5ed60deb800d54393873515344f01c24e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 12 May 2015 18:07:01 +0200 Subject: [PATCH 025/214] Updated symfony --- src/composer.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/composer.lock b/src/composer.lock index fd5c2cf..bdabee5 100644 --- a/src/composer.lock +++ b/src/composer.lock @@ -1,7 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "hash": "4585abd5cf3956b5044b2156049a1fe9", @@ -48,17 +48,17 @@ }, { "name": "symfony/class-loader", - "version": "v2.6.6", + "version": "v2.6.7", "target-dir": "Symfony/Component/ClassLoader", "source": { "type": "git", "url": "https://github.com/symfony/ClassLoader.git", - "reference": "861765b3e5f32979de5bd19ad2577cbb830a29d5" + "reference": "695134c9b39559297fa5d1dcff6a9054bb56facb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ClassLoader/zipball/861765b3e5f32979de5bd19ad2577cbb830a29d5", - "reference": "861765b3e5f32979de5bd19ad2577cbb830a29d5", + "url": "https://api.github.com/repos/symfony/ClassLoader/zipball/695134c9b39559297fa5d1dcff6a9054bb56facb", + "reference": "695134c9b39559297fa5d1dcff6a9054bb56facb", "shasum": "" }, "require": { @@ -84,32 +84,32 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony ClassLoader Component", - "homepage": "http://symfony.com", - "time": "2015-03-27 10:19:51" + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" }, { "name": "symfony/console", - "version": "v2.6.6", + "version": "v2.6.7", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667" + "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/5b91dc4ed5eb08553f57f6df04c4730a73992667", - "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667", + "url": "https://api.github.com/repos/symfony/Console/zipball/ebc5679854aa24ed7d65062e9e3ab0b18a917272", + "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272", "shasum": "" }, "require": { @@ -142,18 +142,18 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Console Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:54:10" + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" } ], "packages-dev": [], From 04e426dc4ec2dbc9ffd44d963da786d1b07f1123 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 12 May 2015 18:07:19 +0200 Subject: [PATCH 026/214] Added *.lz --- src/app/CliTools/Console/Command/Mysql/BackupCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index 8ee021e..03ddd6a 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -95,6 +95,7 @@ public function execute(InputInterface $input, OutputInterface $output) { break; case 'lzma': + case 'lz': case 'xz': $output->writeln('Using LZMA compression'); $commandCompressor = new CommandBuilder('xz'); From ebae6bbb2807dc87ec8c16db67f0935fa1b150c1 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 12 May 2015 18:11:18 +0200 Subject: [PATCH 027/214] Added sync [WIP] --- .../Console/Command/Common/SyncCommand.php | 256 ++++++++++++++++++ src/config.ini | 2 +- 2 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 src/app/CliTools/Console/Command/Common/SyncCommand.php diff --git a/src/app/CliTools/Console/Command/Common/SyncCommand.php b/src/app/CliTools/Console/Command/Common/SyncCommand.php new file mode 100644 index 0000000..3aafc1f --- /dev/null +++ b/src/app/CliTools/Console/Command/Common/SyncCommand.php @@ -0,0 +1,256 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Utility\PhpUtility; +use CliTools\Utility\UnixUtility; +use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Builder\SelfCommandBuilder; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class SyncCommand extends \CliTools\Console\Command\AbstractCommand { + + /** + * Project working path + * + * @var string|boolean|null + */ + protected $workingPath; + + /** + * Temporary storage dir + * + * @var + */ + protected $tempDir; + + /** + * Sync configuration + * + * @var array + */ + protected $config = array(); + + /** + * Configure command + */ + protected function configure() { + $this->setName('sync') + ->setDescription('Sync project') +// ->addOption( +// 'sync', +// null, +// InputOption::VALUE_NONE, +// 'Sync project from live server' +// ) + ->addOption( + 'backup', + null, + InputOption::VALUE_NONE, + 'Backup project to shared server' + ) + ->addOption( + 'restore', + null, + InputOption::VALUE_NONE, + 'Restore project from shared server' + ); + } + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + * @throws \Exception + */ + public function execute(InputInterface $input, OutputInterface $output) { + $this->workingPath = UnixUtility::findFileInDirectortyTree('clisync.ini'); + + if (empty($this->workingPath)) { + $this->output->writeln('No clisync.ini found in tree'); + return 1; + } + + $this->output->writeln('Found clisync.ini directory: ' . $this->workingPath . ''); + + $this->readConfiguration(); + $this->startup(); + + try { + if ($input->getOption('backup')) { + $this->backupTask(); + } elseif ($input->getOption('restore')) { + $this->restoreTask(); + } + } catch (\Exception $e) { + $this->cleanup(); + throw $e; + } + + $this->cleanup(); + } + + /** + * Read and validate configuration + */ + protected function readConfiguration() { + $this->config = parse_ini_file($this->workingPath . '/clisync.ini', true); + } + + /** + * Startup task + */ + protected function startup() { + $this->tempDir = '/tmp/.clisync-'.getmypid(); + $this->clearTempDir(); + PhpUtility::mkdir($this->tempDir, 0777, true); + PhpUtility::mkdir($this->tempDir . '/mysql/', 0777, true); + } + + /** + * Cleanup task + */ + protected function cleanup() { + $this->clearTempDir(); + } + + /** + * Clear temp. storage directory if exists + */ + protected function clearTempDir() { + // Remove storage dir + if (!empty($this->tempDir) && is_dir($this->tempDir)) { + $command = new CommandBuilder('rm', '-rf'); + $command->addArgumentSeparator() + ->addArgument($this->tempDir); + $command->executeInteractive(); + } + } + + /** + * Backup task + */ + protected function backupTask() { + // ################## + // Backup dirs + // ################## + $source = $this->workingPath; + $target = $this->config["shared"]["server"] . '/data/'; + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); + + // ################## + // Backup dirs + // ################## + foreach ($this->config["shared"]["database"] as $database) { + // dump database + $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; + + $mysqldump = new SelfCommandBuilder(); + $mysqldump->addArgumentTemplate('mysql:backup %s %s', $database, $dumpFile); + + if (!empty($this->config['shared']['database-filter'])) { + $mysqldump->addArgumentTemplate('--filter=%s', $this->config['shared']['database-filter']); + } + + $mysqldump->executeInteractive(); + } + + // ################## + // Backup mysql dump + // ################## + $source = $this->tempDir; + $target = $this->config["shared"]["server"] . '/dump/'; + $command = $this->createShareRsyncCommand($source, $target, false); + $command->executeInteractive(); + } + + /** + * Restore task + */ + protected function restoreTask() { + // ################## + // Restore dirs + // ################## + $source = $this->config["shared"]["server"] . '/data/'; + $target = $this->workingPath; + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); + + // ################## + // Restore mysql dump + // ################## + $source = $this->config["shared"]["server"] . '/dump/'; + $target = $this->tempDir; + $command = $this->createShareRsyncCommand($source, $target, false); + $command->executeInteractive(); + + $iterator = new \DirectoryIterator($this->tempDir . '/mysql'); + foreach ($iterator as $item) { + // skip dot + if ($item->isDot()) { + continue; + } + + list($database) = explode('.', $item->getFilename(), 2); + + if (!empty($database)) { + $mysqldump = new SelfCommandBuilder(); + $mysqldump->addArgumentTemplate('mysql:restore %s %s', $database, $item->getPathname()); + $mysqldump->executeInteractive(); + } + } + } + + /** + * Create rsync command for share sync + * + * @return CommandBuilder + */ + protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { + $this->output->writeln('Sync from ' . $source . ' to ' . $target . ''); + + $command = new CommandBuilder('rsync', '-rlptD --delete-after'); + + // Set include and exclude + if ($useExcludeInclude) { + foreach ($this->config["shared"]["directory"] as $directory) { + $command->addArgumentTemplate('--include=%s', $directory); + } + $command->addArgumentTemplate('--exclude=%s', '*'); + } + + $source = rtrim($source, '/') . '/'; + $target = rtrim($target, '/') . '/'; + + // Set source and target + $command->addArgument($source) + ->addArgument($target); + + return $command; + } + +} diff --git a/src/config.ini b/src/config.ini index 38629cd..5eba951 100644 --- a/src/config.ini +++ b/src/config.ini @@ -42,6 +42,7 @@ typo3[] = "/^tx_extbase_cache.*/i" ; load following classes class[] = "CliTools\Console\Command\Common\SelfUpdateCommand" class[] = "CliTools\Console\Command\Common\MakeCommand" +class[] = "CliTools\Console\Command\Common\SyncCommand" class[] = "CliTools\Console\Command\TYPO3\BeUserCommand" class[] = "CliTools\Console\Command\TYPO3\InstallerCommand" @@ -50,7 +51,6 @@ class[] = "CliTools\Console\Command\TYPO3\DomainCommand" class[] = "CliTools\Console\Command\TYPO3\SchedulerCommand" class[] = "CliTools\Console\Command\TYPO3\ListCommand" class[] = "CliTools\Console\Command\TYPO3\CleanupCommand" -class[] = "CliTools\Console\Command\TYPO3\SyncCommand" class[] = "CliTools\Console\Command\Log\ApacheCommand" class[] = "CliTools\Console\Command\Log\PhpCommand" From a1dbc4620172f91d8180fb254a76b6b5e29dc663 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 12 May 2015 18:14:55 +0200 Subject: [PATCH 028/214] Improved sync [WIP] --- src/app/CliTools/Console/Command/Common/SyncCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/CliTools/Console/Command/Common/SyncCommand.php b/src/app/CliTools/Console/Command/Common/SyncCommand.php index 3aafc1f..9b6d999 100644 --- a/src/app/CliTools/Console/Command/Common/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Common/SyncCommand.php @@ -166,6 +166,8 @@ protected function backupTask() { // Backup dirs // ################## foreach ($this->config["shared"]["database"] as $database) { + $this->output->writeln('Dumping database ' . $database . ''); + // dump database $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; @@ -218,6 +220,8 @@ protected function restoreTask() { list($database) = explode('.', $item->getFilename(), 2); if (!empty($database)) { + $this->output->writeln('Restoring database ' . $database . ''); + $mysqldump = new SelfCommandBuilder(); $mysqldump->addArgumentTemplate('mysql:restore %s %s', $database, $item->getPathname()); $mysqldump->executeInteractive(); From 6c64c478f0c1a3ef155ba3536ed20ca0ac1f041a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 13 May 2015 19:04:26 +0200 Subject: [PATCH 029/214] Added fileGetContents and filePutContents --- src/app/CliTools/Utility/PhpUtility.php | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index 0fbd852..2c1388a 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -22,6 +22,32 @@ class PhpUtility { + /** + * Get content of file + * + * @param string $file Filename + * @return string + */ + public static function fileGetContents($file) { + if (!is_file($file) || !is_readable($file)) { + throw new \RuntimeException('Could not read "' . $file . '"'); + } + + return file_get_contents($file); + } + + /** + * Get content of file + * + * @param string $file Filename + * @param string $content Content + */ + public static function filePutContents($file, $content) { + if (!file_put_contents($file, $content)) { + throw new \RuntimeException('Could not write "' . $file . '"'); + } + } + /** * Change current working directory * From 36105df5c8bd3853f4be7e9fc75cec1a1a124469 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 13 May 2015 19:04:35 +0200 Subject: [PATCH 030/214] Added yaml parser --- src/composer.json | 3 ++- src/composer.lock | 52 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/composer.json b/src/composer.json index 4d2d5ce..86021d1 100644 --- a/src/composer.json +++ b/src/composer.json @@ -5,6 +5,7 @@ "require": { "symfony/console": "2.*", "symfony/class-loader": "2.*", - "jamiebicknell/Growl-GNTP": "dev-master" + "jamiebicknell/Growl-GNTP": "dev-master", + "symfony/yaml": "^2.6" } } diff --git a/src/composer.lock b/src/composer.lock index bdabee5..10bec02 100644 --- a/src/composer.lock +++ b/src/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "4585abd5cf3956b5044b2156049a1fe9", + "hash": "b7a124516b0d6433c4b6613c55aa1504", "packages": [ { "name": "jamiebicknell/Growl-GNTP", @@ -154,6 +154,56 @@ "description": "Symfony Console Component", "homepage": "https://symfony.com", "time": "2015-05-02 15:18:45" + }, + { + "name": "symfony/yaml", + "version": "v2.6.7", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" } ], "packages-dev": [], From a6024b4fbf6b726aa0bec0f07fd97c4c0f71ca9b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 13 May 2015 19:04:52 +0200 Subject: [PATCH 031/214] Moved sync task to sync:backup and sync:restore --- .../Console/Command/Common/SyncCommand.php | 260 ------------------ .../Console/Command/Sync/AbstractCommand.php | 166 +++++++++++ .../Console/Command/Sync/BackupCommand.php | 78 ++++++ .../Console/Command/Sync/RestoreCommand.php | 74 +++++ .../Console/Command/TYPO3/DomainCommand.php | 2 +- src/config.ini | 4 +- 6 files changed, 322 insertions(+), 262 deletions(-) delete mode 100644 src/app/CliTools/Console/Command/Common/SyncCommand.php create mode 100644 src/app/CliTools/Console/Command/Sync/AbstractCommand.php create mode 100644 src/app/CliTools/Console/Command/Sync/BackupCommand.php create mode 100644 src/app/CliTools/Console/Command/Sync/RestoreCommand.php diff --git a/src/app/CliTools/Console/Command/Common/SyncCommand.php b/src/app/CliTools/Console/Command/Common/SyncCommand.php deleted file mode 100644 index 9b6d999..0000000 --- a/src/app/CliTools/Console/Command/Common/SyncCommand.php +++ /dev/null @@ -1,260 +0,0 @@ - - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -use CliTools\Utility\PhpUtility; -use CliTools\Utility\UnixUtility; -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\SelfCommandBuilder; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class SyncCommand extends \CliTools\Console\Command\AbstractCommand { - - /** - * Project working path - * - * @var string|boolean|null - */ - protected $workingPath; - - /** - * Temporary storage dir - * - * @var - */ - protected $tempDir; - - /** - * Sync configuration - * - * @var array - */ - protected $config = array(); - - /** - * Configure command - */ - protected function configure() { - $this->setName('sync') - ->setDescription('Sync project') -// ->addOption( -// 'sync', -// null, -// InputOption::VALUE_NONE, -// 'Sync project from live server' -// ) - ->addOption( - 'backup', - null, - InputOption::VALUE_NONE, - 'Backup project to shared server' - ) - ->addOption( - 'restore', - null, - InputOption::VALUE_NONE, - 'Restore project from shared server' - ); - } - - /** - * Execute command - * - * @param InputInterface $input Input instance - * @param OutputInterface $output Output instance - * - * @return int|null|void - * @throws \Exception - */ - public function execute(InputInterface $input, OutputInterface $output) { - $this->workingPath = UnixUtility::findFileInDirectortyTree('clisync.ini'); - - if (empty($this->workingPath)) { - $this->output->writeln('No clisync.ini found in tree'); - return 1; - } - - $this->output->writeln('Found clisync.ini directory: ' . $this->workingPath . ''); - - $this->readConfiguration(); - $this->startup(); - - try { - if ($input->getOption('backup')) { - $this->backupTask(); - } elseif ($input->getOption('restore')) { - $this->restoreTask(); - } - } catch (\Exception $e) { - $this->cleanup(); - throw $e; - } - - $this->cleanup(); - } - - /** - * Read and validate configuration - */ - protected function readConfiguration() { - $this->config = parse_ini_file($this->workingPath . '/clisync.ini', true); - } - - /** - * Startup task - */ - protected function startup() { - $this->tempDir = '/tmp/.clisync-'.getmypid(); - $this->clearTempDir(); - PhpUtility::mkdir($this->tempDir, 0777, true); - PhpUtility::mkdir($this->tempDir . '/mysql/', 0777, true); - } - - /** - * Cleanup task - */ - protected function cleanup() { - $this->clearTempDir(); - } - - /** - * Clear temp. storage directory if exists - */ - protected function clearTempDir() { - // Remove storage dir - if (!empty($this->tempDir) && is_dir($this->tempDir)) { - $command = new CommandBuilder('rm', '-rf'); - $command->addArgumentSeparator() - ->addArgument($this->tempDir); - $command->executeInteractive(); - } - } - - /** - * Backup task - */ - protected function backupTask() { - // ################## - // Backup dirs - // ################## - $source = $this->workingPath; - $target = $this->config["shared"]["server"] . '/data/'; - $command = $this->createShareRsyncCommand($source, $target, true); - $command->executeInteractive(); - - // ################## - // Backup dirs - // ################## - foreach ($this->config["shared"]["database"] as $database) { - $this->output->writeln('Dumping database ' . $database . ''); - - // dump database - $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; - - $mysqldump = new SelfCommandBuilder(); - $mysqldump->addArgumentTemplate('mysql:backup %s %s', $database, $dumpFile); - - if (!empty($this->config['shared']['database-filter'])) { - $mysqldump->addArgumentTemplate('--filter=%s', $this->config['shared']['database-filter']); - } - - $mysqldump->executeInteractive(); - } - - // ################## - // Backup mysql dump - // ################## - $source = $this->tempDir; - $target = $this->config["shared"]["server"] . '/dump/'; - $command = $this->createShareRsyncCommand($source, $target, false); - $command->executeInteractive(); - } - - /** - * Restore task - */ - protected function restoreTask() { - // ################## - // Restore dirs - // ################## - $source = $this->config["shared"]["server"] . '/data/'; - $target = $this->workingPath; - $command = $this->createShareRsyncCommand($source, $target, true); - $command->executeInteractive(); - - // ################## - // Restore mysql dump - // ################## - $source = $this->config["shared"]["server"] . '/dump/'; - $target = $this->tempDir; - $command = $this->createShareRsyncCommand($source, $target, false); - $command->executeInteractive(); - - $iterator = new \DirectoryIterator($this->tempDir . '/mysql'); - foreach ($iterator as $item) { - // skip dot - if ($item->isDot()) { - continue; - } - - list($database) = explode('.', $item->getFilename(), 2); - - if (!empty($database)) { - $this->output->writeln('Restoring database ' . $database . ''); - - $mysqldump = new SelfCommandBuilder(); - $mysqldump->addArgumentTemplate('mysql:restore %s %s', $database, $item->getPathname()); - $mysqldump->executeInteractive(); - } - } - } - - /** - * Create rsync command for share sync - * - * @return CommandBuilder - */ - protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { - $this->output->writeln('Sync from ' . $source . ' to ' . $target . ''); - - $command = new CommandBuilder('rsync', '-rlptD --delete-after'); - - // Set include and exclude - if ($useExcludeInclude) { - foreach ($this->config["shared"]["directory"] as $directory) { - $command->addArgumentTemplate('--include=%s', $directory); - } - $command->addArgumentTemplate('--exclude=%s', '*'); - } - - $source = rtrim($source, '/') . '/'; - $target = rtrim($target, '/') . '/'; - - // Set source and target - $command->addArgument($source) - ->addArgument($target); - - return $command; - } - -} diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php new file mode 100644 index 0000000..543df2f --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -0,0 +1,166 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Utility\PhpUtility; +use CliTools\Utility\UnixUtility; +use CliTools\Console\Builder\CommandBuilder; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Yaml\Yaml; + +abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand { + + const CONFIG_FILE = 'clisync.yml'; + const PATH_DUMP = '/dump/'; + const PATH_DATA = '/data/'; + + /** + * Project working path + * + * @var string|boolean|null + */ + protected $workingPath; + + /** + * Temporary storage dir + * + * @var string|null + */ + protected $tempDir; + + /** + * Sync configuration + * + * @var array + */ + protected $config = array(); + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + * @throws \Exception + */ + public function execute(InputInterface $input, OutputInterface $output) { + $this->workingPath = UnixUtility::findFileInDirectortyTree(self::CONFIG_FILE); + + if (empty($this->workingPath)) { + $this->output->writeln('No ' . self::CONFIG_FILE . ' found in tree'); + return 1; + } + + $this->output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); + + $this->readConfiguration(); + $this->startup(); + + try { + $this->runTask(); + } catch (\Exception $e) { + $this->cleanup(); + throw $e; + } + + $this->cleanup(); + } + + /** + * Read and validate configuration + */ + protected function readConfiguration() { + $confFile = $this->workingPath . '/' . self::CONFIG_FILE; + $conf = Yaml::parse(PhpUtility::fileGetContents($confFile)); + + if (!empty($conf)) { + $this->config = new \ArrayObject(); + $this->config->setFlags(\ArrayObject::STD_PROP_LIST|\ArrayObject::ARRAY_AS_PROPS); + $this->config->exchangeArray($conf); + } else { + throw new \RuntimeException('Could not parse "' . $confFile . '"'); + } + } + + /** + * Startup task + */ + protected function startup() { + $this->tempDir = '/tmp/.clisync-'.getmypid(); + $this->clearTempDir(); + PhpUtility::mkdir($this->tempDir, 0777, true); + PhpUtility::mkdir($this->tempDir . '/mysql/', 0777, true); + } + + /** + * Cleanup task + */ + protected function cleanup() { + $this->clearTempDir(); + } + + /** + * Clear temp. storage directory if exists + */ + protected function clearTempDir() { + // Remove storage dir + if (!empty($this->tempDir) && is_dir($this->tempDir)) { + $command = new CommandBuilder('rm', '-rf'); + $command->addArgumentSeparator() + ->addArgument($this->tempDir); + $command->executeInteractive(); + } + } + + /** + * Create rsync command for share sync + * + * @return CommandBuilder + */ + protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { + $this->output->writeln('Sync from ' . $source . ' to ' . $target . ''); + + $command = new CommandBuilder('rsync', '-rlptD --delete-after'); + + if (!empty($this->config->share['rsync']['directory'])) { + $rsyncFilter = $this->tempDir . '/.rsync-filelist'; + + $filterContent = $this->config->share['rsync']['directory']; + $filterContent = implode("\n", $filterContent); + + PhpUtility::filePutContents($rsyncFilter, $filterContent); + $command->addArgumentTemplate('--files-from=%s', $rsyncFilter); + } + + // Paths should have leading / to prevent sync issues + $source = rtrim($source, '/') . '/'; + $target = rtrim($target, '/') . '/'; + + // Set source and target + $command->addArgument($source) + ->addArgument($target); + + return $command; + } + +} diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php new file mode 100644 index 0000000..85bed39 --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -0,0 +1,78 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Console\Builder\SelfCommandBuilder; + +class BackupCommand extends \CliTools\Console\Command\Sync\AbstractCommand { + + /** + * Configure command + */ + protected function configure() { + $this->setName('sync:backup') + ->setDescription('Backup project files'); + } + + /** + * Backup task + */ + protected function runTask() { + // ################## + // Backup dirs + // ################## + $source = $this->workingPath; + $target = $this->config->share['rsync']['server'] . self::PATH_DATA; + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); + + // ################## + // Backup databases + // ################## + if (!empty($this->config->share['mysql']) && !empty($this->config->share['mysql']['database'])) { + foreach ($this->config->share['mysql']['database'] as $database) { + $this->output->writeln('Dumping database ' . $database . ''); + + // dump database + $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; + + $mysqldump = new SelfCommandBuilder(); + $mysqldump->addArgumentTemplate('mysql:backup %s %s', $database, $dumpFile); + + if (!empty($this->config->share['mysql']['filter'])) { + $mysqldump->addArgumentTemplate('--filter=%s', $this->config->share['mysql']['filter']); + } + + $mysqldump->executeInteractive(); + } + + // ################## + // Backup mysql dump + // ################## + $source = $this->tempDir; + $target = $this->config->share['rsync']['server'] . self::PATH_DUMP; + $command = $this->createShareRsyncCommand($source, $target, false); + $command->executeInteractive(); + } + + } + +} diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php new file mode 100644 index 0000000..a331c90 --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -0,0 +1,74 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Console\Builder\SelfCommandBuilder; + +class RestoreCommand extends \CliTools\Console\Command\Sync\AbstractCommand { + + /** + * Configure command + */ + protected function configure() { + $this->setName('sync:restore') + ->setDescription('Restore project files'); + } + + /** + * Restore task + */ + protected function runTask() { + // ################## + // Restore dirs + // ################## + $source = $this->config->share['rsync']['server'] . self::PATH_DUMP; + $target = $this->workingPath; + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); + + // ################## + // Restore mysql dump + // ################## + $source = $this->config->share['rsync']['server'] . self::PATH_DUMP; + $target = $this->tempDir; + $command = $this->createShareRsyncCommand($source, $target, false); + $command->executeInteractive(); + + $iterator = new \DirectoryIterator($this->tempDir . '/mysql'); + foreach ($iterator as $item) { + // skip dot + if ($item->isDot()) { + continue; + } + + list($database) = explode('.', $item->getFilename(), 2); + + if (!empty($database)) { + $this->output->writeln('Restoring database ' . $database . ''); + + $mysqldump = new SelfCommandBuilder(); + $mysqldump->addArgumentTemplate('mysql:restore %s %s', $database, $item->getPathname()); + $mysqldump->executeInteractive(); + } + } + } + +} diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index 63b8a80..ae99bd4 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -120,7 +120,7 @@ protected function setupDevelopmentDomainsForDatabase($database) { // ################## $isMultiSite = false; - $query = 'SELECT uid + $query = 'SELECT uid FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.pages WHERE is_siteroot = 1 AND deleted = 0'; diff --git a/src/config.ini b/src/config.ini index 5eba951..bbade97 100644 --- a/src/config.ini +++ b/src/config.ini @@ -42,7 +42,9 @@ typo3[] = "/^tx_extbase_cache.*/i" ; load following classes class[] = "CliTools\Console\Command\Common\SelfUpdateCommand" class[] = "CliTools\Console\Command\Common\MakeCommand" -class[] = "CliTools\Console\Command\Common\SyncCommand" + +class[] = "CliTools\Console\Command\Sync\BackupCommand" +class[] = "CliTools\Console\Command\Sync\RestoreCommand" class[] = "CliTools\Console\Command\TYPO3\BeUserCommand" class[] = "CliTools\Console\Command\TYPO3\InstallerCommand" From ceabf4254faa6de01e6d22d56164eb793d55e93c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 13 May 2015 19:08:45 +0200 Subject: [PATCH 032/214] Added filter output --- src/app/CliTools/Console/Command/Mysql/BackupCommand.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index 03ddd6a..d352ef7 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -142,6 +142,8 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat throw new \RuntimeException('MySQL dump filters "' . $filter . '" not available"'); } + $this->output->writeln('Using filter "' . $filter . '"'); + // Get filtered tables $tableList = DatabaseConnection::tableList($database); From 67ed16077dcb82af8258158e845b99d3e20a9c4b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 13 May 2015 19:08:53 +0200 Subject: [PATCH 033/214] Cleanup --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 2 +- src/app/CliTools/Console/Command/Sync/BackupCommand.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 543df2f..c082a80 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -142,7 +142,7 @@ protected function createShareRsyncCommand($source, $target, $useExcludeInclude $command = new CommandBuilder('rsync', '-rlptD --delete-after'); - if (!empty($this->config->share['rsync']['directory'])) { + if ($useExcludeInclude && !empty($this->config->share['rsync']['directory'])) { $rsyncFilter = $this->tempDir . '/.rsync-filelist'; $filterContent = $this->config->share['rsync']['directory']; diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 85bed39..6feafdf 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -39,8 +39,8 @@ protected function runTask() { // ################## // Backup dirs // ################## - $source = $this->workingPath; - $target = $this->config->share['rsync']['server'] . self::PATH_DATA; + $source = $this->workingPath; + $target = $this->config->share['rsync']['server'] . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); From ca3c3b32a494c6511421ad6e53b02f1af8d68513 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 12:07:06 +0200 Subject: [PATCH 034/214] Added sync:init --- .../Console/Command/Sync/InitCommand.php | 91 +++++++++++++++++++ src/config.ini | 1 + 2 files changed, 92 insertions(+) create mode 100644 src/app/CliTools/Console/Command/Sync/InitCommand.php diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php new file mode 100644 index 0000000..478c2fc --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -0,0 +1,91 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Utility\PhpUtility; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class InitCommand extends \CliTools\Console\Command\AbstractCommand { + + /** + * Configure command + */ + protected function configure() { + $this->setName('sync:init') + ->setDescription('Create example clisync.yml'); + } + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + * @throws \Exception + */ + public function execute(InputInterface $input, OutputInterface $output) { + $cliSyncFilePath = getcwd() . '/' . AbstractCommand::CONFIG_FILE; + + if (file_exists($cliSyncFilePath)) { + $this->output->writeln('Configuration file ' . AbstractCommand::CONFIG_FILE . ' already exists'); + return 1; + } + + $content = '# Example clisync configuration file + + +# Shared server for backup and restore sync +share: + + rsync: + # target directory or server via ssh (eg. backup-server:/backup/projectname) + target: "/tmp/foo/" + + # List of directories for backup + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + # List of excludes (eg. specific files) + exclude: + # no avi files + - "/example/**/*.avi" + # no mp4 files + - "/example/**/*.mp4" + + mysql: + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 + + # List of databases for backup + database: + - typo3 +'; + + PhpUtility::filePutContents($cliSyncFilePath, $content); + + $this->output->writeln('Successfully created ' . AbstractCommand::CONFIG_FILE . ' '); + } + +} diff --git a/src/config.ini b/src/config.ini index bbade97..59a6210 100644 --- a/src/config.ini +++ b/src/config.ini @@ -43,6 +43,7 @@ typo3[] = "/^tx_extbase_cache.*/i" class[] = "CliTools\Console\Command\Common\SelfUpdateCommand" class[] = "CliTools\Console\Command\Common\MakeCommand" +class[] = "CliTools\Console\Command\Sync\InitCommand" class[] = "CliTools\Console\Command\Sync\BackupCommand" class[] = "CliTools\Console\Command\Sync\RestoreCommand" From 23e1bc951fa27c938f6bcc20c143e0a57012a166 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 12:07:21 +0200 Subject: [PATCH 035/214] Fixed wrong exception in filePutContents --- src/app/CliTools/Utility/PhpUtility.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index 2c1388a..4547e47 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -43,7 +43,7 @@ public static function fileGetContents($file) { * @param string $content Content */ public static function filePutContents($file, $content) { - if (!file_put_contents($file, $content)) { + if (file_put_contents($file, $content) === false) { throw new \RuntimeException('Could not write "' . $file . '"'); } } From 04446908e6f920d2447a69f827e078f6966d10d6 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 12:07:33 +0200 Subject: [PATCH 036/214] Added finisher callbacks --- src/app/CliTools/Console/Shell/Executor.php | 39 ++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Shell/Executor.php b/src/app/CliTools/Console/Shell/Executor.php index a9a0615..c8b4e2f 100644 --- a/src/app/CliTools/Console/Shell/Executor.php +++ b/src/app/CliTools/Console/Shell/Executor.php @@ -21,7 +21,6 @@ */ use CliTools\Exception\CommandExecutionException; -use CliTools\Console\Builder\CommandBuilder; use CliTools\Console\Builder\CommandBuilderInterface; use CliTools\Utility\ConsoleUtility; @@ -64,6 +63,13 @@ class Executor { */ protected $strictMode = true; + /** + * Finisher callback list + * + * @var array + */ + protected $finishers = array(); + // ########################################## // Methods // ########################################## @@ -152,6 +158,15 @@ public function setStrictMode($strictMode) { return $this; } + /** + * Clear state + */ + public function clear() { + $this->output = null; + $this->returnCode = null; + $this->finishers = array(); + } + /** * Execute command @@ -166,6 +181,8 @@ public function execute() { exec($this->command->build(), $this->output, $this->returnCode); + $this->runFinishers(); + if ($this->strictMode && $this->returnCode !== 0) { throw $this->generateException('Process ' . $this->command->getCommand() . ' did not finished successfully'); } @@ -201,6 +218,8 @@ public function execInteractive() { $this->returnCode = $status['exitcode']; + $this->runFinishers(); + if ($status['signaled'] === true && $status['exitcode'] === -1) { // user may hit CTRL+C ConsoleUtility::getOutput()->writeln('Processed stopped by signal'); @@ -252,4 +271,22 @@ protected function generateException($msg) { return $e; } + + /** + * Add finisher callback (will run after command execution) + * + * @param callable $callback + */ + public function addFinisherCallback(callable $callback) { + $this->finishers[] = $callback; + } + + /** + * Run finisher commands + */ + public function runFinishers() { + foreach ($this->finishers as $call) { + $call($this); + } + } } From c42e08067a02e87a19e6bf633db6de1c732e1b84 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 12:07:51 +0200 Subject: [PATCH 037/214] Improved sync:backup and sync:restore --- .../Console/Command/Sync/AbstractCommand.php | 54 +++++++++++++++++-- .../Console/Command/Sync/BackupCommand.php | 4 +- .../Console/Command/Sync/RestoreCommand.php | 4 +- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index c082a80..4b92042 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -143,13 +143,16 @@ protected function createShareRsyncCommand($source, $target, $useExcludeInclude $command = new CommandBuilder('rsync', '-rlptD --delete-after'); if ($useExcludeInclude && !empty($this->config->share['rsync']['directory'])) { - $rsyncFilter = $this->tempDir . '/.rsync-filelist'; - $filterContent = $this->config->share['rsync']['directory']; - $filterContent = implode("\n", $filterContent); + // Add file list (external file with --files-from option) + if (!empty($this->config->share['rsync']['directory'])) { + $this->rsyncAddFileList($command, $this->config->share['rsync']['directory']); + } - PhpUtility::filePutContents($rsyncFilter, $filterContent); - $command->addArgumentTemplate('--files-from=%s', $rsyncFilter); + // Add exclude (external file with --exclude-from option) + if (!empty($this->config->share['rsync']['exclude'])) { + $this->rsyncAddExcludeList($command, $this->config->share['rsync']['exclude']); + } } // Paths should have leading / to prevent sync issues @@ -160,7 +163,48 @@ protected function createShareRsyncCommand($source, $target, $useExcludeInclude $command->addArgument($source) ->addArgument($target); + + // Register teardown + return $command; } + /** + * Add file (pattern) list to rsync command + * + * @param CommandBuilder $command Rsync Command + * @param array $list List of files + */ + protected function rsyncAddFileList(CommandBuilder $command, $list) { + $rsyncFilter = $this->tempDir . '/.rsync-filelist'; + + PhpUtility::filePutContents($rsyncFilter, implode("\n", $list)); + + $command->addArgumentTemplate('--files-from=%s', $rsyncFilter); + + // cleanup rsync file + $command->getExecutor()->addFinisherCallback(function () use ($rsyncFilter) { + unlink($rsyncFilter); + }); + + } + + /** + * Add exclude (pattern) list to rsync command + * + * @param CommandBuilder $command Rsync Command + * @param array $list List of excludes + */ + protected function rsyncAddExcludeList(CommandBuilder $command, $list) { + $rsyncFilter = $this->tempDir . '/.rsync-exclude'; + + PhpUtility::filePutContents($rsyncFilter, implode("\n", $list)); + + $command->addArgumentTemplate('--exclude-from=%s', $rsyncFilter); + + // cleanup rsync file + $command->getExecutor()->addFinisherCallback(function () use ($rsyncFilter) { + unlink($rsyncFilter); + }); + } } diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 6feafdf..4da514f 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -40,7 +40,7 @@ protected function runTask() { // Backup dirs // ################## $source = $this->workingPath; - $target = $this->config->share['rsync']['server'] . self::PATH_DATA; + $target = $this->config->share['rsync']['target'] . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); @@ -68,7 +68,7 @@ protected function runTask() { // Backup mysql dump // ################## $source = $this->tempDir; - $target = $this->config->share['rsync']['server'] . self::PATH_DUMP; + $target = $this->config->share['rsync']['target'] . self::PATH_DUMP; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index a331c90..ffd355f 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -39,7 +39,7 @@ protected function runTask() { // ################## // Restore dirs // ################## - $source = $this->config->share['rsync']['server'] . self::PATH_DUMP; + $source = $this->config->share['rsync']['target'] . self::PATH_DUMP; $target = $this->workingPath; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); @@ -47,7 +47,7 @@ protected function runTask() { // ################## // Restore mysql dump // ################## - $source = $this->config->share['rsync']['server'] . self::PATH_DUMP; + $source = $this->config->share['rsync']['target'] . self::PATH_DUMP; $target = $this->tempDir; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); From c714f0d828441087b63677a60ee0b55ae5bb4d2b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 12:07:59 +0200 Subject: [PATCH 038/214] Updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0f42df..3e46bc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ CliTools Changelog - Added `make` (auto search for Makefile in tree) - Added `php:composer` (auto search for composer.yml in tree) - Added `mysql:convert` for automatic changing charset and collation of one database +- Added `sync:backup` for backup to a shared server (reads clisync.yml) +- Added `sync:restore` for restore from a shared server (reads clisync.yml) - Fixed some issues 1.9.0 - 2015-05-06 From 97e92b31c660d898e3a91fb0dd9747054076b1fe Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 13:10:50 +0200 Subject: [PATCH 039/214] Added argument validation --- .../Builder/AbstractCommandBuilder.php | 60 +++++++++++++++++-- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php index 132e75b..af762b7 100644 --- a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php @@ -185,7 +185,8 @@ public function addArgumentSeparator() { * @return $this */ public function setArgumentList(array $args) { - $this->argumentList = $args; + $this->clearArguments(); + $this->appendArgumentsToList($args); return $this; } @@ -222,8 +223,8 @@ public function addArgument($arg) { /** * Set argument with template * - * @param string $arg Argument sprintf - * @param string $params Argument parameters + * @param string $arg Argument sprintf + * @param string $params... Argument parameters * * @return $this */ @@ -243,6 +244,8 @@ public function addArgumentTemplate($arg, $params) { * @return $this */ public function addArgumentTemplateList($arg, array $params) { + $this->validateArgumentValue($arg); + $params = array_map('escapeshellarg', $params); $this->argumentList[] = vsprintf($arg, $params); return $this; @@ -256,12 +259,45 @@ public function addArgumentTemplateList($arg, array $params) { * @return $this */ public function addArgumentList(array $arg, $escape = true) { + $this->appendArgumentsToList($arg, $escape); + return $this; + } + + /** + * Append one argument to list + * + * @param array $arg Arguments + * @param boolean $escape Enable argument escaping + * + * @return $this + */ + protected function appendArgumentToList($arg, $escape = true) { + $this->validateArgumentValue($arg); + if ($escape) { - $arg = array_map('escapeshellarg', $arg); + $arg = escapeshellarg($arg); } - $this->argumentList = array_merge($this->argumentList, $arg); - return $this; + $this->argumentList[] = $arg; + } + + /** + * Append multiple arguments to list + * + * @param array $args Arguments + * @param boolean $escape Enable argument escaping + * + * @return $this + */ + protected function appendArgumentsToList($args, $escape = true) { + // Validate each argument value + array_walk($args, array($this, 'validateArgumentValue')); + + if ($escape) { + $args = array_map('escapeshellarg', $args); + } + + $this->argumentList = array_merge($this->argumentList, $args); } /** @@ -487,6 +523,18 @@ public function executeInteractive() { return $this->getExecutor()->execInteractive(); } + /** + * Validate argument value + * + * @param mixed $value Value + * @throws \RuntimeException + */ + protected function validateArgumentValue($value) { + if (strlen($value) === 0) { + throw new \RuntimeException('Argument value cannot be empty'); + } + } + // ########################################## // Magic methods // ########################################## From 35cc6cf8a816de446400aefedb52d429fe114e35 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 13:14:06 +0200 Subject: [PATCH 040/214] Added sync commands to README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index eeff256..fa11b5a 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,13 @@ All log commands are using a grep-filter (specified as optional argument) | | __ct mysql:convert typo3 --collation=utf8_unicode_ci__ -> Convert typo3 into UTF-8 with utf8_unicode_ci | | | __ct mysql:convert typo3 --stdout__ -> Print sql statements to stdout | +### Sync commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct sync:init | Create example clisync.yml in current working directory | +| ct sync:backup | Search for clisync.yml in tree and start backup to shared server | +| ct sync:restore | Search for clisync.yml in tree and start restore from shared server | ### PHP commands From 6ed279b793a1200d71d6e53ae4845640dfb36f1c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 14:12:31 +0200 Subject: [PATCH 041/214] Cleanup --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 4b92042..1b2a5b1 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -146,7 +146,7 @@ protected function createShareRsyncCommand($source, $target, $useExcludeInclude // Add file list (external file with --files-from option) if (!empty($this->config->share['rsync']['directory'])) { - $this->rsyncAddFileList($command, $this->config->share['rsync']['directory']); + $this->rsyncAddFileList($command, $this->config->share['rsync']['directory']); } // Add exclude (external file with --exclude-from option) @@ -163,9 +163,6 @@ protected function createShareRsyncCommand($source, $target, $useExcludeInclude $command->addArgument($source) ->addArgument($target); - - // Register teardown - return $command; } From 254086387db5fcdf6113fffb9ef6a294f48cb44a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 14:12:57 +0200 Subject: [PATCH 042/214] Added sync:sync (need better name) --- .../Console/Command/Sync/SyncCommand.php | 166 ++++++++++++++++++ src/config.ini | 1 + 2 files changed, 167 insertions(+) create mode 100644 src/app/CliTools/Console/Command/Sync/SyncCommand.php diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/SyncCommand.php new file mode 100644 index 0000000..9d6286e --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/SyncCommand.php @@ -0,0 +1,166 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Builder\SelfCommandBuilder; +use CliTools\Console\Builder\CommandBuilderInterface; + +class BackupCommand extends \CliTools\Console\Command\Sync\AbstractCommand { + + /** + * Configure command + */ + protected function configure() { + $this->setName('sync:sync') + ->setDescription('Sync from live server'); + } + + /** + * Backup task + */ + protected function runTask() { + // Sync files with rsync to local storage + if (!empty($this->config->sync['rsync'])) { + $this->runTaskRsync(); + } + + // Sync database to local server + if (!empty($this->config->sync['mysql']) && !empty($this->config->sync['mysql']['database'])) { + $this->runTaskDatabase(); + } + } + /** + * Sync files with rsync + */ + protected function runTaskRsync() { + // ################## + // Restore dirs + // ################## + $source = $this->config->sync['rsync']['source']; + $target = $this->workingPath; + $command = $this->createSyncRsyncCommand($source, $target, true); + + $command->executeInteractive(); + } + + /** + * Sync database + */ + protected function runTaskDatabase() { + // ################## + // Sync databases + // ################## + $mysqlConf = $this->config->sync['mysql']; + + $mysqlDumpTemplate = new CommandBuilder('mysqldump'); + $mysqlDumpTemplate->addArgumentTemplate('-u%s', $mysqlConf['username']) + ->addArgumentTemplate('-p%s', $mysqlConf['password']) + ->addArgumentTemplate('-h%s', $mysqlConf['host']) + ->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + + $sshConnectionTemplate = new CommandBuilder('ssh'); + $sshConnectionTemplate->addArgument($this->config->sync['ssh']); + + foreach ($mysqlConf['database'] as $databaseConf) { + list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); + + $dumpFile = $this->tempDir . '/' . $localDatabase . '.sql.bz2'; + + // ########## + // Dump from server + // ########## + $this->output->writeln('Fetching foreign database ' . $foreignDatabase . ''); + + $mysqldump = clone $mysqlDumpTemplate; + $mysqldump->addArgument($foreignDatabase); + + $command = $this->wrapCommand($mysqldump); + + $command->setOutputRedirectToFile($dumpFile); + + $command->executeInteractive(); + + // ########## + // Restore local + // ########## + $this->output->writeln('Restoring database ' . $localDatabase . ''); + + $mysqldump = new SelfCommandBuilder(); + $mysqldump->addArgumentTemplate('mysql:restore %s %s', $localDatabase, $dumpFile); + $mysqldump->executeInteractive(); + } + } + + /** + * Wrap command with ssh if needed + * + * @param CommandBuilderInterface $command + * @return CommandBuilderInterface + */ + protected function wrapCommand(CommandBuilderInterface $command) { + // Wrap in ssh if available + if (!empty($this->config->sync['ssh'])) { + $sshCommand = new CommandBuilder('ssh'); + $sshCommand->addArgument($this->config->sync['ssh']) + ->append($command, true); + + $command = $sshCommand; + } + + return $command; + } + + /** + * Create rsync command for share sync + * + * @return CommandBuilder + */ + protected function createSyncRsyncCommand($source, $target, $useExcludeInclude = false) { + $this->output->writeln('Sync from ' . $source . ' to ' . $target . ''); + + $command = new CommandBuilder('rsync', '-rlptD --delete-after'); + + if ($useExcludeInclude && !empty($this->config->share['rsync']['directory'])) { + + // Add file list (external file with --files-from option) + if (!empty($this->config->sync['rsync']['directory'])) { + $this->rsyncAddFileList($command, $this->config->sync['rsync']['directory']); + } + + // Add exclude (external file with --exclude-from option) + if (!empty($this->config->sync['rsync']['exclude'])) { + $this->rsyncAddExcludeList($command, $this->config->sync['rsync']['exclude']); + } + } + + // Paths should have leading / to prevent sync issues + $source = rtrim($source, '/') . '/'; + $target = rtrim($target, '/') . '/'; + + // Set source and target + $command->addArgument($source) + ->addArgument($target); + + return $command; + } + +} diff --git a/src/config.ini b/src/config.ini index 59a6210..ec562ee 100644 --- a/src/config.ini +++ b/src/config.ini @@ -44,6 +44,7 @@ class[] = "CliTools\Console\Command\Common\SelfUpdateCommand" class[] = "CliTools\Console\Command\Common\MakeCommand" class[] = "CliTools\Console\Command\Sync\InitCommand" +class[] = "CliTools\Console\Command\Sync\SyncCommand" class[] = "CliTools\Console\Command\Sync\BackupCommand" class[] = "CliTools\Console\Command\Sync\RestoreCommand" From 06f7a8b97f4ca9391c0e260242e94691eb243965 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 14:24:25 +0200 Subject: [PATCH 043/214] Cleanup --- .../Console/Command/Sync/AbstractCommand.php | 45 ++++++++++++++----- .../Console/Command/Sync/SyncCommand.php | 40 +++++++---------- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 1b2a5b1..fb2fdb6 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -138,21 +138,44 @@ protected function clearTempDir() { * @return CommandBuilder */ protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { + // File list + $filelist = null; + if (!empty($this->config->share['rsync']['directory'])) { + $filelist = $this->config->share['rsync']['directory']; + } + + // Exclude list + $exclude = null; + if (!empty($this->config->share['rsync']['exclude'])) { + $exclude = $this->config->share['rsync']['exclude']; + } + + return $this->createRsyncCommand($source, $target, $filelist, $exclude); + } + + /** + * Create rsync command for share sync + * + * @param string $source Source directory + * @param string $target Target directory + * @param array|null $filelist List of files (patterns) + * @param array|null $exclude List of excludes (patterns) + * + * @return CommandBuilder + */ + protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { $this->output->writeln('Sync from ' . $source . ' to ' . $target . ''); $command = new CommandBuilder('rsync', '-rlptD --delete-after'); - if ($useExcludeInclude && !empty($this->config->share['rsync']['directory'])) { - - // Add file list (external file with --files-from option) - if (!empty($this->config->share['rsync']['directory'])) { - $this->rsyncAddFileList($command, $this->config->share['rsync']['directory']); - } + // Add file list (external file with --files-from option) + if (!empty($filelist)) { + $this->rsyncAddFileList($command, $filelist); + } - // Add exclude (external file with --exclude-from option) - if (!empty($this->config->share['rsync']['exclude'])) { - $this->rsyncAddExcludeList($command, $this->config->share['rsync']['exclude']); - } + // Add exclude (external file with --exclude-from option) + if (!empty($exclude)) { + $this->rsyncAddExcludeList($command, $exclude); } // Paths should have leading / to prevent sync issues @@ -172,7 +195,7 @@ protected function createShareRsyncCommand($source, $target, $useExcludeInclude * @param CommandBuilder $command Rsync Command * @param array $list List of files */ - protected function rsyncAddFileList(CommandBuilder $command, $list) { + protected function rsyncAddFileList(CommandBuilder $command, array $list) { $rsyncFilter = $this->tempDir . '/.rsync-filelist'; PhpUtility::filePutContents($rsyncFilter, implode("\n", $list)); diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/SyncCommand.php index 9d6286e..48ec51d 100644 --- a/src/app/CliTools/Console/Command/Sync/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/SyncCommand.php @@ -57,7 +57,7 @@ protected function runTaskRsync() { // ################## $source = $this->config->sync['rsync']['source']; $target = $this->workingPath; - $command = $this->createSyncRsyncCommand($source, $target, true); + $command = $this->createRsyncCommand($source, $target); $command->executeInteractive(); } @@ -132,35 +132,25 @@ protected function wrapCommand(CommandBuilderInterface $command) { /** * Create rsync command for share sync * + * @param string $source Source directory + * @param string $target Target directory + * @param array|null $filelist List of files (patterns) + * @param array|null $exclude List of excludes (patterns) + * * @return CommandBuilder */ - protected function createSyncRsyncCommand($source, $target, $useExcludeInclude = false) { - $this->output->writeln('Sync from ' . $source . ' to ' . $target . ''); - - $command = new CommandBuilder('rsync', '-rlptD --delete-after'); - - if ($useExcludeInclude && !empty($this->config->share['rsync']['directory'])) { - - // Add file list (external file with --files-from option) - if (!empty($this->config->sync['rsync']['directory'])) { - $this->rsyncAddFileList($command, $this->config->sync['rsync']['directory']); - } - - // Add exclude (external file with --exclude-from option) - if (!empty($this->config->sync['rsync']['exclude'])) { - $this->rsyncAddExcludeList($command, $this->config->sync['rsync']['exclude']); - } + protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { + // Add file list (external file with --files-from option) + if (!$filelist && !empty($this->config->sync['rsync']['directory'])) { + $filelist = $this->config->sync['rsync']['directory']; } - // Paths should have leading / to prevent sync issues - $source = rtrim($source, '/') . '/'; - $target = rtrim($target, '/') . '/'; - - // Set source and target - $command->addArgument($source) - ->addArgument($target); + // Add exclude (external file with --exclude-from option) + if (!$exclude && !empty($this->config->sync['rsync']['exclude'])) { + $exclude = $this->config->sync['rsync']['exclude']; + } - return $command; + return parent::createRsyncCommand($source, $target, $filelist, $exclude); } } From ee10063ca76c7f4debfe2d114e0a203a17dc02f0 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 15:08:27 +0200 Subject: [PATCH 044/214] Added clearOutputRedirect and clearPipes --- .../Builder/AbstractCommandBuilder.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php index af762b7..1e3cd4e 100644 --- a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php @@ -341,6 +341,16 @@ public function setOutputRedirectToFile($filename) { return $this; } + /** + * Clear output redirect + * + * @return $this + */ + public function clearOutputRedirect() { + $this->outputRedirect = null; + return $this; + } + /** * Parse command and attributs from exec line * @@ -435,6 +445,15 @@ public function setPipeList(array $pipeList) { return $this; } + /** + * Clear pipe list + * + * @return $this + */ + public function clearPipes() { + $this->pipeList = array(); + return $this; + } /** * Add pipe command From b28d11b2757f4db29eb327c67474f19fab5fda7c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 15:08:49 +0200 Subject: [PATCH 045/214] Added generalized mysql table filter --- .../Console/Command/Mysql/BackupCommand.php | 14 ++---- src/app/CliTools/Utility/FilterUtility.php | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 src/app/CliTools/Utility/FilterUtility.php diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index d352ef7..f691864 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -23,6 +23,7 @@ use CliTools\Database\DatabaseConnection; use CliTools\Console\Builder\CommandBuilder; use CliTools\Console\Builder\CommandBuilderInterface; +use CliTools\Utility\FilterUtility; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; @@ -146,16 +147,7 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat // Get filtered tables $tableList = DatabaseConnection::tableList($database); - - $tableListFiltered = array(); - foreach ($tableList as $table) { - foreach ($filterList as $filter) { - if (preg_match($filter, $table)) { - continue 2; - } - } - $tableListFiltered[] = $table; - } + $tableList = FilterUtility::mysqlTableFilter($tableList, $filterList); // Dump only structure $commandStructure = clone $command; @@ -165,7 +157,7 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat $commandData = clone $command; $commandData ->addArgument('--no-create-info') - ->addArgumentList($tableListFiltered); + ->addArgumentList($tableList); // Combine both commands to one $command = new \CliTools\Console\Builder\OutputCombineCommandBuilder(); diff --git a/src/app/CliTools/Utility/FilterUtility.php b/src/app/CliTools/Utility/FilterUtility.php new file mode 100644 index 0000000..e90ed0b --- /dev/null +++ b/src/app/CliTools/Utility/FilterUtility.php @@ -0,0 +1,48 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +class FilterUtility { + + /** + * Filter mysql table list by filter + * + * @param array $tables List of tables + * @param array $filter List of filters + * + * @return array + */ + public static function mysqlTableFilter(array $tables, array $filters) { + $ret = array(); + + foreach ($tables as $table) { + foreach ($filters as $filter) { + if (preg_match($filter, $table)) { + continue 2; + } + } + $ret[] = $table; + } + + return $ret; + } + +} From 3db24b53ce674cf5f07a4dbb6a4520d88b5a782d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 15:09:01 +0200 Subject: [PATCH 046/214] Added support for mysql filter --- .../Console/Command/Sync/SyncCommand.php | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/SyncCommand.php index 48ec51d..a74cf51 100644 --- a/src/app/CliTools/Console/Command/Sync/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/SyncCommand.php @@ -20,6 +20,7 @@ * along with this program. If not, see . */ +use CliTools\Utility\FilterUtility; use CliTools\Console\Builder\CommandBuilder; use CliTools\Console\Builder\SelfCommandBuilder; use CliTools\Console\Builder\CommandBuilderInterface; @@ -45,6 +46,7 @@ protected function runTask() { // Sync database to local server if (!empty($this->config->sync['mysql']) && !empty($this->config->sync['mysql']['database'])) { + // Full mysql transfer $this->runTaskDatabase(); } } @@ -93,8 +95,11 @@ protected function runTaskDatabase() { $mysqldump = clone $mysqlDumpTemplate; $mysqldump->addArgument($foreignDatabase); - $command = $this->wrapCommand($mysqldump); + if ($this->config->sync['mysql']['filter']) { + $mysqldump = $this->addFilterArguments($mysqldump, $foreignDatabase, $this->config->sync['mysql']['filter']); + } + $command = $this->wrapCommand($mysqldump); $command->setOutputRedirectToFile($dumpFile); $command->executeInteractive(); @@ -153,4 +158,58 @@ protected function createRsyncCommand($source, $target, array $filelist = null, return parent::createRsyncCommand($source, $target, $filelist, $exclude); } + /** + * Add filter to command + * + * @param CommandBuilderInterface $command Command + * @param string $database Database + * @param string $filter Filter name + * + * @return CommandBuilderInterface + */ + protected function addFilterArguments(CommandBuilderInterface $commandDump, $database, $filter) { + $command = $commandDump; + + // get filter + $filterList = $this->getApplication()->getConfigValue('mysql-backup-filter', $filter); + + if (empty($filterList)) { + throw new \RuntimeException('MySQL dump filters "' . $filter . '" not available"'); + } + + $this->output->writeln('Using filter "' . $filter . '"'); + + // Get table list + $tableListDumper = clone $commandDump; + $tableListDumper->setCommand('mysql') + ->addArgument('--skip-column-names') + ->addArgumentTemplate('-e %s', 'show tables;') + ->clearOutputRedirect() + ->clearPipes(); + + $tableListDumper = $this->wrapCommand($tableListDumper); + $tableList = $tableListDumper->execute()->getOutput(); + + // Filter table list + $tableList = FilterUtility::mysqlTableFilter($tableList, $filterList); + + // Dump only structure + $commandStructure = clone $command; + $commandStructure->addArgument('--no-data'); + + // Dump only data (only filtered tables) + $commandData = clone $command; + $commandData + ->addArgument('--no-create-info') + ->addArgumentList($tableList); + + // Combine both commands to one + $command = new \CliTools\Console\Builder\OutputCombineCommandBuilder(); + $command + ->addCommandForCombinedOutput($commandStructure) + ->addCommandForCombinedOutput($commandData); + + return $command; + } + } From 8a46ed2c62026b6174557e6975e05fa351e0a2cf Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 17:51:49 +0200 Subject: [PATCH 047/214] Added example of clisync.yml --- Documentation/Examples/clisync.yml | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Documentation/Examples/clisync.yml diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml new file mode 100644 index 0000000..4db4e40 --- /dev/null +++ b/Documentation/Examples/clisync.yml @@ -0,0 +1,64 @@ +####################################### +# Sync from server (eg. live server) +####################################### +sync: + # ssh server host or name (see .ssh/config) + ssh: live-server + + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + source: "live-server:/var/www/website/htdocs" + + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + mysql: + # mysql connection + host: localhost + username: typo3 + password: loremipsum + + mysqldump: + option: "--single-transaction" + + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 + + # List of databases for sync (local:foreign or o) + database: + - typo3:website_live + - other_database + +####################################### +# Shared server (sharing between developers) +####################################### +share: + + rsync: + # target directory or server via ssh (eg. backup-server:/backup/projectname) + target: "/tmp/foo/" + + # List of directories for backup + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + # List of excludes (eg. specific files) + exclude: + # no avi files + - "/example/**/*.avi" + # no mp4 files + - "/example/**/*.mp4" + + mysql: + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 + + # List of databases for backup + database: + - typo3 From 4b074a9d8495e66349fddea4423e8aebca3511b1 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 17:51:59 +0200 Subject: [PATCH 048/214] Improved sync --- .../Console/Command/Sync/SyncCommand.php | 50 +++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/SyncCommand.php index a74cf51..c623053 100644 --- a/src/app/CliTools/Console/Command/Sync/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/SyncCommand.php @@ -22,6 +22,7 @@ use CliTools\Utility\FilterUtility; use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Builder\RemoteCommandBuilder; use CliTools\Console\Builder\SelfCommandBuilder; use CliTools\Console\Builder\CommandBuilderInterface; @@ -73,17 +74,35 @@ protected function runTaskDatabase() { // ################## $mysqlConf = $this->config->sync['mysql']; - $mysqlDumpTemplate = new CommandBuilder('mysqldump'); - $mysqlDumpTemplate->addArgumentTemplate('-u%s', $mysqlConf['username']) - ->addArgumentTemplate('-p%s', $mysqlConf['password']) - ->addArgumentTemplate('-h%s', $mysqlConf['host']) - ->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + $mysqlTemplate = new RemoteCommandBuilder('mysql'); + $mysqlTemplate + ->addArgumentTemplate('-u%s', $mysqlConf['username']) + ->addArgumentTemplate('-p%s', $mysqlConf['password']) + ->addArgumentTemplate('-h%s', $mysqlConf['host']); + + $mysqlDumpTemplate = clone $mysqlTemplate; + $mysqlDumpTemplate + ->setCommand('mysqldump') + ->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + + if (!empty($mysqlConf['mysqldump']['option'])) { + $mysqlDumpTemplate->addArgumentRaw($mysqlConf['mysqldump']['option']); + } $sshConnectionTemplate = new CommandBuilder('ssh'); $sshConnectionTemplate->addArgument($this->config->sync['ssh']); foreach ($mysqlConf['database'] as $databaseConf) { - list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); + if (strpos($databaseConf, ':') !== false) { + list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); + } else { + $localDatabase = $databaseConf; + $foreignDatabase = $databaseConf; + } + + // make sure we don't have any leading whitespaces + $localDatabase = trim($localDatabase); + $foreignDatabase = trim($foreignDatabase); $dumpFile = $this->tempDir . '/' . $localDatabase . '.sql.bz2'; @@ -96,7 +115,10 @@ protected function runTaskDatabase() { $mysqldump->addArgument($foreignDatabase); if ($this->config->sync['mysql']['filter']) { - $mysqldump = $this->addFilterArguments($mysqldump, $foreignDatabase, $this->config->sync['mysql']['filter']); + $mysql = clone $mysqlTemplate; + $mysql->addArgument($foreignDatabase); + + $mysqldump = $this->addFilterArguments($mysqldump, $mysql, $this->config->sync['mysql']['filter']); } $command = $this->wrapCommand($mysqldump); @@ -124,7 +146,7 @@ protected function runTaskDatabase() { protected function wrapCommand(CommandBuilderInterface $command) { // Wrap in ssh if available if (!empty($this->config->sync['ssh'])) { - $sshCommand = new CommandBuilder('ssh'); + $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); $sshCommand->addArgument($this->config->sync['ssh']) ->append($command, true); @@ -161,13 +183,13 @@ protected function createRsyncCommand($source, $target, array $filelist = null, /** * Add filter to command * - * @param CommandBuilderInterface $command Command - * @param string $database Database - * @param string $filter Filter name + * @param CommandBuilderInterface $command Command + * @param CommandBuilderInterface $mysqlCommand Database + * @param string $filter Filter name * * @return CommandBuilderInterface */ - protected function addFilterArguments(CommandBuilderInterface $commandDump, $database, $filter) { + protected function addFilterArguments(CommandBuilderInterface $commandDump, CommandBuilderInterface $mysqlCommand, $filter) { $command = $commandDump; // get filter @@ -179,8 +201,8 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat $this->output->writeln('Using filter "' . $filter . '"'); - // Get table list - $tableListDumper = clone $commandDump; + // Get table list (from cloned mysqldump command) + $tableListDumper = clone $mysqlCommand; $tableListDumper->setCommand('mysql') ->addArgument('--skip-column-names') ->addArgumentTemplate('-e %s', 'show tables;') From fc5888dd5142538d6e051c754edde24e8c356f2a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 18:08:50 +0200 Subject: [PATCH 049/214] Cleanup example clisync.yml --- Documentation/Examples/clisync.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 4db4e40..03bcd53 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -18,7 +18,7 @@ sync: mysql: # mysql connection - host: localhost + host: localhost username: typo3 password: loremipsum @@ -28,7 +28,7 @@ sync: # MySQL filter for typo3 (eg. no caching tables) filter: typo3 - # List of databases for sync (local:foreign or o) + # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) database: - typo3:website_live - other_database From f96805e3a209bf44c576a139c4c80fffd6a81cd7 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 18:23:01 +0200 Subject: [PATCH 050/214] Refactoring --- .../Console/Command/Sync/AbstractCommand.php | 75 ++++++++++++------- .../Command/Sync/AbstractShareCommand.php | 53 +++++++++++++ .../Command/Sync/AbstractSyncCommand.php | 32 ++++++++ .../Console/Command/Sync/BackupCommand.php | 20 ++--- .../Console/Command/Sync/RestoreCommand.php | 10 +-- .../Console/Command/Sync/SyncCommand.php | 32 ++++---- 6 files changed, 162 insertions(+), 60 deletions(-) create mode 100644 src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php create mode 100644 src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index fb2fdb6..b76a796 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -23,6 +23,7 @@ use CliTools\Utility\PhpUtility; use CliTools\Utility\UnixUtility; use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Builder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Yaml\Yaml; @@ -33,6 +34,13 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand const PATH_DUMP = '/dump/'; const PATH_DATA = '/data/'; + /** + * Config area + * + * @var string + */ + protected $confArea; + /** * Project working path * @@ -90,13 +98,16 @@ public function execute(InputInterface $input, OutputInterface $output) { * Read and validate configuration */ protected function readConfiguration() { + + if (empty($this->confArea)) { + throw new \RuntimeException('Config area not set, cannot continue'); + } + $confFile = $this->workingPath . '/' . self::CONFIG_FILE; $conf = Yaml::parse(PhpUtility::fileGetContents($confFile)); if (!empty($conf)) { - $this->config = new \ArrayObject(); - $this->config->setFlags(\ArrayObject::STD_PROP_LIST|\ArrayObject::ARRAY_AS_PROPS); - $this->config->exchangeArray($conf); + $this->config = $conf[$this->confArea]; } else { throw new \RuntimeException('Could not parse "' . $confFile . '"'); } @@ -133,28 +144,7 @@ protected function clearTempDir() { } /** - * Create rsync command for share sync - * - * @return CommandBuilder - */ - protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { - // File list - $filelist = null; - if (!empty($this->config->share['rsync']['directory'])) { - $filelist = $this->config->share['rsync']['directory']; - } - - // Exclude list - $exclude = null; - if (!empty($this->config->share['rsync']['exclude'])) { - $exclude = $this->config->share['rsync']['exclude']; - } - - return $this->createRsyncCommand($source, $target, $filelist, $exclude); - } - - /** - * Create rsync command for share sync + * Create rsync command for sync * * @param string $source Source directory * @param string $target Target directory @@ -227,4 +217,39 @@ protected function rsyncAddExcludeList(CommandBuilder $command, $list) { unlink($rsyncFilter); }); } + + /** + * Create mysql backup command + * + * @param string $database Database name + * @param string $dumpFile MySQL dump file + * + * @return SelfCommandBuilder + */ + protected function createMysqlRestoreCommand($database, $dumpFile) { + $command = new SelfCommandBuilder(); + $command->addArgumentTemplate('mysql:restore %s %s', $database, $dumpFile); + return $command; + } + + /** + * Create mysql backup command + * + * @param string $database Database name + * @param string $dumpFile MySQL dump file + * @param null|string $filter Filter name + * + * @return SelfCommandBuilder + */ + protected function createMysqlBackupCommand($database, $dumpFile, $filter = null) { + $command = new SelfCommandBuilder(); + $command->addArgumentTemplate('mysql:backup %s %s', $database, $dumpFile); + + if ($filter !== null) { + $command->addArgumentTemplate('--filter=%s', $filter); + } + + return $command; + } + } diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php new file mode 100644 index 0000000..c780794 --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -0,0 +1,53 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\AbstractCommand { + + /** + * Config area + * + * @var string + */ + protected $confArea = 'share'; + + /** + * Create rsync command for share sync + * + * @return CommandBuilder + */ + protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { + // File list + $filelist = null; + if (!empty($this->config['rsync']['directory'])) { + $filelist = $this->config['rsync']['directory']; + } + + // Exclude list + $exclude = null; + if (!empty($this->config['rsync']['exclude'])) { + $exclude = $this->config['rsync']['exclude']; + } + + return $this->createRsyncCommand($source, $target, $filelist, $exclude); + } + +} diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php new file mode 100644 index 0000000..079511a --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -0,0 +1,32 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +abstract class AbstractSyncCommand extends \CliTools\Console\Command\Sync\AbstractCommand { + + /** + * Config area + * + * @var string + */ + protected $confArea = 'sync'; + +} diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 4da514f..d7d3e2e 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -22,7 +22,7 @@ use CliTools\Console\Builder\SelfCommandBuilder; -class BackupCommand extends \CliTools\Console\Command\Sync\AbstractCommand { +class BackupCommand extends \CliTools\Console\Command\Sync\AbstractShareCommand { /** * Configure command @@ -40,35 +40,31 @@ protected function runTask() { // Backup dirs // ################## $source = $this->workingPath; - $target = $this->config->share['rsync']['target'] . self::PATH_DATA; + $target = $this->config['rsync']['target'] . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); // ################## // Backup databases // ################## - if (!empty($this->config->share['mysql']) && !empty($this->config->share['mysql']['database'])) { - foreach ($this->config->share['mysql']['database'] as $database) { + if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { + foreach ($this->config['mysql']['database'] as $database) { $this->output->writeln('Dumping database ' . $database . ''); // dump database $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; - $mysqldump = new SelfCommandBuilder(); - $mysqldump->addArgumentTemplate('mysql:backup %s %s', $database, $dumpFile); + $dumpFilter = $this->config['mysql']['filter'] ? $this->config['mysql']['filter'] : null; - if (!empty($this->config->share['mysql']['filter'])) { - $mysqldump->addArgumentTemplate('--filter=%s', $this->config->share['mysql']['filter']); - } - - $mysqldump->executeInteractive(); + $this->createMysqlBackupCommand($database, $dumpFile, $dumpFilter) + ->executeInteractive(); } // ################## // Backup mysql dump // ################## $source = $this->tempDir; - $target = $this->config->share['rsync']['target'] . self::PATH_DUMP; + $target = $this->config['rsync']['target'] . self::PATH_DUMP; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index ffd355f..737b9cc 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -22,7 +22,7 @@ use CliTools\Console\Builder\SelfCommandBuilder; -class RestoreCommand extends \CliTools\Console\Command\Sync\AbstractCommand { +class RestoreCommand extends \CliTools\Console\Command\Sync\AbstractShareCommand { /** * Configure command @@ -39,7 +39,7 @@ protected function runTask() { // ################## // Restore dirs // ################## - $source = $this->config->share['rsync']['target'] . self::PATH_DUMP; + $source = $this->config['rsync']['target'] . self::PATH_DUMP; $target = $this->workingPath; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); @@ -47,7 +47,7 @@ protected function runTask() { // ################## // Restore mysql dump // ################## - $source = $this->config->share['rsync']['target'] . self::PATH_DUMP; + $source = $this->config['rsync']['target'] . self::PATH_DUMP; $target = $this->tempDir; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); @@ -64,9 +64,7 @@ protected function runTask() { if (!empty($database)) { $this->output->writeln('Restoring database ' . $database . ''); - $mysqldump = new SelfCommandBuilder(); - $mysqldump->addArgumentTemplate('mysql:restore %s %s', $database, $item->getPathname()); - $mysqldump->executeInteractive(); + $this->createMysqlRestoreCommand($database, $item->getPathname())->executeInteractive(); } } } diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/SyncCommand.php index c623053..2ab8821 100644 --- a/src/app/CliTools/Console/Command/Sync/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/SyncCommand.php @@ -26,7 +26,7 @@ use CliTools\Console\Builder\SelfCommandBuilder; use CliTools\Console\Builder\CommandBuilderInterface; -class BackupCommand extends \CliTools\Console\Command\Sync\AbstractCommand { +class BackupCommand extends \CliTools\Console\Command\Sync\AbstractSyncCommand { /** * Configure command @@ -41,12 +41,12 @@ protected function configure() { */ protected function runTask() { // Sync files with rsync to local storage - if (!empty($this->config->sync['rsync'])) { + if (!empty($this->config['rsync'])) { $this->runTaskRsync(); } // Sync database to local server - if (!empty($this->config->sync['mysql']) && !empty($this->config->sync['mysql']['database'])) { + if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { // Full mysql transfer $this->runTaskDatabase(); } @@ -58,7 +58,7 @@ protected function runTaskRsync() { // ################## // Restore dirs // ################## - $source = $this->config->sync['rsync']['source']; + $source = $this->config['rsync']['source']; $target = $this->workingPath; $command = $this->createRsyncCommand($source, $target); @@ -72,7 +72,7 @@ protected function runTaskDatabase() { // ################## // Sync databases // ################## - $mysqlConf = $this->config->sync['mysql']; + $mysqlConf = $this->config['mysql']; $mysqlTemplate = new RemoteCommandBuilder('mysql'); $mysqlTemplate @@ -90,7 +90,7 @@ protected function runTaskDatabase() { } $sshConnectionTemplate = new CommandBuilder('ssh'); - $sshConnectionTemplate->addArgument($this->config->sync['ssh']); + $sshConnectionTemplate->addArgument($this->config['ssh']); foreach ($mysqlConf['database'] as $databaseConf) { if (strpos($databaseConf, ':') !== false) { @@ -114,11 +114,11 @@ protected function runTaskDatabase() { $mysqldump = clone $mysqlDumpTemplate; $mysqldump->addArgument($foreignDatabase); - if ($this->config->sync['mysql']['filter']) { + if ($this->config['mysql']['filter']) { $mysql = clone $mysqlTemplate; $mysql->addArgument($foreignDatabase); - $mysqldump = $this->addFilterArguments($mysqldump, $mysql, $this->config->sync['mysql']['filter']); + $mysqldump = $this->addFilterArguments($mysqldump, $mysql, $this->config['mysql']['filter']); } $command = $this->wrapCommand($mysqldump); @@ -131,9 +131,7 @@ protected function runTaskDatabase() { // ########## $this->output->writeln('Restoring database ' . $localDatabase . ''); - $mysqldump = new SelfCommandBuilder(); - $mysqldump->addArgumentTemplate('mysql:restore %s %s', $localDatabase, $dumpFile); - $mysqldump->executeInteractive(); + $this->createMysqlRestoreCommand($localDatabase, $dumpFile)->executeInteractive(); } } @@ -145,9 +143,9 @@ protected function runTaskDatabase() { */ protected function wrapCommand(CommandBuilderInterface $command) { // Wrap in ssh if available - if (!empty($this->config->sync['ssh'])) { + if (!empty($this->config['ssh'])) { $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); - $sshCommand->addArgument($this->config->sync['ssh']) + $sshCommand->addArgument($this->config['ssh']) ->append($command, true); $command = $sshCommand; @@ -168,13 +166,13 @@ protected function wrapCommand(CommandBuilderInterface $command) { */ protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { // Add file list (external file with --files-from option) - if (!$filelist && !empty($this->config->sync['rsync']['directory'])) { - $filelist = $this->config->sync['rsync']['directory']; + if (!$filelist && !empty($this->config['rsync']['directory'])) { + $filelist = $this->config['rsync']['directory']; } // Add exclude (external file with --exclude-from option) - if (!$exclude && !empty($this->config->sync['rsync']['exclude'])) { - $exclude = $this->config->sync['rsync']['exclude']; + if (!$exclude && !empty($this->config['rsync']['exclude'])) { + $exclude = $this->config['rsync']['exclude']; } return parent::createRsyncCommand($source, $target, $filelist, $exclude); From c924ded4042ab8be02145ba027a9a9179fe27b0f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 18:30:59 +0200 Subject: [PATCH 051/214] Refactoring --- .../Console/Command/Sync/SyncCommand.php | 92 ++++++++++++------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/SyncCommand.php index 2ab8821..241a6b8 100644 --- a/src/app/CliTools/Console/Command/Sync/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/SyncCommand.php @@ -74,24 +74,6 @@ protected function runTaskDatabase() { // ################## $mysqlConf = $this->config['mysql']; - $mysqlTemplate = new RemoteCommandBuilder('mysql'); - $mysqlTemplate - ->addArgumentTemplate('-u%s', $mysqlConf['username']) - ->addArgumentTemplate('-p%s', $mysqlConf['password']) - ->addArgumentTemplate('-h%s', $mysqlConf['host']); - - $mysqlDumpTemplate = clone $mysqlTemplate; - $mysqlDumpTemplate - ->setCommand('mysqldump') - ->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); - - if (!empty($mysqlConf['mysqldump']['option'])) { - $mysqlDumpTemplate->addArgumentRaw($mysqlConf['mysqldump']['option']); - } - - $sshConnectionTemplate = new CommandBuilder('ssh'); - $sshConnectionTemplate->addArgument($this->config['ssh']); - foreach ($mysqlConf['database'] as $databaseConf) { if (strpos($databaseConf, ':') !== false) { list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); @@ -111,14 +93,10 @@ protected function runTaskDatabase() { // ########## $this->output->writeln('Fetching foreign database ' . $foreignDatabase . ''); - $mysqldump = clone $mysqlDumpTemplate; - $mysqldump->addArgument($foreignDatabase); + $mysqldump = $this->createMySqlDumpCommand($foreignDatabase); if ($this->config['mysql']['filter']) { - $mysql = clone $mysqlTemplate; - $mysql->addArgument($foreignDatabase); - - $mysqldump = $this->addFilterArguments($mysqldump, $mysql, $this->config['mysql']['filter']); + $mysqldump = $this->addFilterArguments($mysqldump, $foreignDatabase, $this->config['mysql']['filter']); } $command = $this->wrapCommand($mysqldump); @@ -135,6 +113,54 @@ protected function runTaskDatabase() { } } + /** + * Create new mysql command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createMySqlCommand($database = null) { + $command = new RemoteCommandBuilder('mysql'); + $command + ->addArgument('--skip-column-names') + ->addArgumentTemplate('-u%s', $this->config['mysql']['username']) + ->addArgumentTemplate('-p%s', $this->config['mysql']['password']) + ->addArgumentTemplate('-h%s', $this->config['mysql']['host']); + + if ($database !== null) { + $command->addArgument($database); + } + + return $command; + } + + /** + * Create new mysql command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createMySqlDumpCommand($database = null) { + $command = new RemoteCommandBuilder('mysqldump'); + $command + ->addArgumentTemplate('-u%s', $this->config['mysql']['username']) + ->addArgumentTemplate('-p%s', $this->config['mysql']['password']) + ->addArgumentTemplate('-h%s', $this->config['mysql']['host']) + ->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + + if (!empty($this->config['mysqldump']['option'])) { + $command->addArgumentRaw($this->config['mysqldump']['option']); + } + + if ($database !== null) { + $command->addArgument($database); + } + + return $command; + } + /** * Wrap command with ssh if needed * @@ -142,7 +168,7 @@ protected function runTaskDatabase() { * @return CommandBuilderInterface */ protected function wrapCommand(CommandBuilderInterface $command) { - // Wrap in ssh if available + // Wrap in ssh if needed if (!empty($this->config['ssh'])) { $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); $sshCommand->addArgument($this->config['ssh']) @@ -181,13 +207,13 @@ protected function createRsyncCommand($source, $target, array $filelist = null, /** * Add filter to command * - * @param CommandBuilderInterface $command Command - * @param CommandBuilderInterface $mysqlCommand Database - * @param string $filter Filter name + * @param CommandBuilderInterface $command Command + * @param string $database Database + * @param string $filter Filter name * * @return CommandBuilderInterface */ - protected function addFilterArguments(CommandBuilderInterface $commandDump, CommandBuilderInterface $mysqlCommand, $filter) { + protected function addFilterArguments(CommandBuilderInterface $commandDump, $database, $filter) { $command = $commandDump; // get filter @@ -200,12 +226,8 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, Comm $this->output->writeln('Using filter "' . $filter . '"'); // Get table list (from cloned mysqldump command) - $tableListDumper = clone $mysqlCommand; - $tableListDumper->setCommand('mysql') - ->addArgument('--skip-column-names') - ->addArgumentTemplate('-e %s', 'show tables;') - ->clearOutputRedirect() - ->clearPipes(); + $tableListDumper = $this->createMySqlCommand($database); + $tableListDumper->addArgumentTemplate('-e %s', 'show tables;'); $tableListDumper = $this->wrapCommand($tableListDumper); $tableList = $tableListDumper->execute()->getOutput(); From e467a38f564beab1c8cb63a52089af5b5b87ba6b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 18:34:28 +0200 Subject: [PATCH 052/214] Cleanup and refactoring --- .../Command/Sync/AbstractShareCommand.php | 12 ++++-- .../Console/Command/Sync/BackupCommand.php | 4 +- .../Console/Command/Sync/InitCommand.php | 40 ++++++++++++++++++- .../Console/Command/Sync/RestoreCommand.php | 4 +- .../Console/Command/Sync/SyncCommand.php | 12 +++--- 5 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index c780794..8ebf9b3 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -20,6 +20,8 @@ * along with this program. If not, see . */ +use CliTools\Console\Builder\CommandBuilderInterface; + abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\AbstractCommand { /** @@ -32,18 +34,22 @@ abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\Abstr /** * Create rsync command for share sync * - * @return CommandBuilder + * @param string $source Rsync Source + * @param string $target Rsync target + * @param boolean $useExcludeInclude Use file/exclude lists + * + * @return CommandBuilderInterface */ protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { // File list $filelist = null; - if (!empty($this->config['rsync']['directory'])) { + if ($useExcludeInclude && !empty($this->config['rsync']['directory'])) { $filelist = $this->config['rsync']['directory']; } // Exclude list $exclude = null; - if (!empty($this->config['rsync']['exclude'])) { + if ($useExcludeInclude && !empty($this->config['rsync']['exclude'])) { $exclude = $this->config['rsync']['exclude']; } diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index d7d3e2e..cf317a1 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -20,9 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\SelfCommandBuilder; - -class BackupCommand extends \CliTools\Console\Command\Sync\AbstractShareCommand { +class BackupCommand extends AbstractShareCommand { /** * Configure command diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 478c2fc..8a7f69d 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -54,7 +54,44 @@ public function execute(InputInterface $input, OutputInterface $output) { $content = '# Example clisync configuration file -# Shared server for backup and restore sync +####################################### +# Sync from server (eg. live server) +####################################### +sync: + # ssh server host or name (see .ssh/config) + ssh: live-server + + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + source: "live-server:/var/www/website/htdocs" + + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + mysql: + # mysql connection + host: localhost + username: typo3 + password: loremipsum + + mysqldump: + option: "--single-transaction" + + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 + + # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) + database: + - typo3:website_live + - other_database + +####################################### +# Shared server (sharing between developers) +####################################### share: rsync: @@ -81,6 +118,7 @@ public function execute(InputInterface $input, OutputInterface $output) { # List of databases for backup database: - typo3 + '; PhpUtility::filePutContents($cliSyncFilePath, $content); diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 737b9cc..702ffd6 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -20,9 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\SelfCommandBuilder; - -class RestoreCommand extends \CliTools\Console\Command\Sync\AbstractShareCommand { +class RestoreCommand extends AbstractShareCommand { /** * Configure command diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/SyncCommand.php index 241a6b8..620340d 100644 --- a/src/app/CliTools/Console/Command/Sync/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/SyncCommand.php @@ -23,10 +23,10 @@ use CliTools\Utility\FilterUtility; use CliTools\Console\Builder\CommandBuilder; use CliTools\Console\Builder\RemoteCommandBuilder; -use CliTools\Console\Builder\SelfCommandBuilder; +use CliTools\Console\Builder\OutputCombineCommandBuilder; use CliTools\Console\Builder\CommandBuilderInterface; -class BackupCommand extends \CliTools\Console\Command\Sync\AbstractSyncCommand { +class SyncCommand extends AbstractSyncCommand { /** * Configure command @@ -207,9 +207,9 @@ protected function createRsyncCommand($source, $target, array $filelist = null, /** * Add filter to command * - * @param CommandBuilderInterface $command Command - * @param string $database Database - * @param string $filter Filter name + * @param CommandBuilderInterface $commandDump Command + * @param string $database Database + * @param string $filter Filter name * * @return CommandBuilderInterface */ @@ -246,7 +246,7 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat ->addArgumentList($tableList); // Combine both commands to one - $command = new \CliTools\Console\Builder\OutputCombineCommandBuilder(); + $command = new OutputCombineCommandBuilder(); $command ->addCommandForCombinedOutput($commandStructure) ->addCommandForCombinedOutput($commandData); From c8d480eb091706936c268c42b799aa5e423ec1d8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 20:47:44 +0200 Subject: [PATCH 053/214] Refactoring, renamed sync:sync to sync:server --- Documentation/Examples/clisync.yml | 59 +++++++++------- .../Console/Command/Sync/AbstractCommand.php | 2 +- .../Command/Sync/AbstractSyncCommand.php | 2 +- .../Console/Command/Sync/InitCommand.php | 70 +++++++++++-------- .../{SyncCommand.php => ServerCommand.php} | 45 +++++++++++- src/config.ini | 2 +- 6 files changed, 120 insertions(+), 60 deletions(-) rename src/app/CliTools/Console/Command/Sync/{SyncCommand.php => ServerCommand.php} (85%) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 03bcd53..8173694 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -2,36 +2,47 @@ # Sync from server (eg. live server) ####################################### sync: - # ssh server host or name (see .ssh/config) - ssh: live-server - # rsync for some directories - rsync: - # server and source directory (server host or name - see .ssh/config) - source: "live-server:/var/www/website/htdocs" + ################## + # Global config + ################## + _: + mysql: + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 - # directory list/patterns - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" + # specific mysqldump settings + mysqldump: + option: "--single-transaction" - mysql: - # mysql connection - host: localhost - username: typo3 - password: loremipsum + ################## + # Config "production" + ################## + production: + # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) + ssh: live-server - mysqldump: - option: "--single-transaction" + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + source: "live-server:/var/www/website/htdocs" - # MySQL filter for typo3 (eg. no caching tables) - filter: typo3 + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" - # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) - database: - - typo3:website_live - - other_database + mysql: + # mysql connection + host: localhost + username: typo3 + password: loremipsum + + # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) + database: + - typo3:website_live + - other_database ####################################### # Shared server (sharing between developers) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index b76a796..5bb86b3 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -154,7 +154,7 @@ protected function clearTempDir() { * @return CommandBuilder */ protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { - $this->output->writeln('Sync from ' . $source . ' to ' . $target . ''); + $this->output->writeln('Rsync from ' . $source . ' to ' . $target . ''); $command = new CommandBuilder('rsync', '-rlptD --delete-after'); diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index 079511a..4c22eda 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -27,6 +27,6 @@ abstract class AbstractSyncCommand extends \CliTools\Console\Command\Sync\Abstra * * @var string */ - protected $confArea = 'sync'; + protected $confArea = 'server'; } diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 8a7f69d..5fe5d48 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -53,41 +53,51 @@ public function execute(InputInterface $input, OutputInterface $output) { $content = '# Example clisync configuration file - ####################################### # Sync from server (eg. live server) ####################################### sync: - # ssh server host or name (see .ssh/config) - ssh: live-server - - # rsync for some directories - rsync: - # server and source directory (server host or name - see .ssh/config) - source: "live-server:/var/www/website/htdocs" - - # directory list/patterns - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - mysql: - # mysql connection - host: localhost - username: typo3 - password: loremipsum - - mysqldump: - option: "--single-transaction" - - # MySQL filter for typo3 (eg. no caching tables) - filter: typo3 - - # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) - database: - - typo3:website_live - - other_database + ################## + # Global config + ################## + _: + mysql: + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 + + # specific mysqldump settings + mysqldump: + option: "--single-transaction" + + ################## + # Config "production" + ################## + production: + # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) + ssh: live-server + + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + source: "live-server:/var/www/website/htdocs" + + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + mysql: + # mysql connection + host: localhost + username: typo3 + password: loremipsum + + # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) + database: + - typo3:website_live + - other_database ####################################### # Shared server (sharing between developers) diff --git a/src/app/CliTools/Console/Command/Sync/SyncCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php similarity index 85% rename from src/app/CliTools/Console/Command/Sync/SyncCommand.php rename to src/app/CliTools/Console/Command/Sync/ServerCommand.php index 620340d..82ddbf7 100644 --- a/src/app/CliTools/Console/Command/Sync/SyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -25,15 +25,54 @@ use CliTools\Console\Builder\RemoteCommandBuilder; use CliTools\Console\Builder\OutputCombineCommandBuilder; use CliTools\Console\Builder\CommandBuilderInterface; +use Symfony\Component\Console\Input\InputArgument; -class SyncCommand extends AbstractSyncCommand { +class ServerCommand extends AbstractSyncCommand { + + /** + * Server configuration name + * @var string + */ + protected $serverName; /** * Configure command */ protected function configure() { - $this->setName('sync:sync') - ->setDescription('Sync from live server'); + $this + ->setName('sync:server') + ->setDescription('Sync files and database from server') + ->addArgument( + 'server', + InputArgument::REQUIRED, + 'Configuration name for server' + ); + } + + + /** + * Read and validate configuration + */ + protected function readConfiguration() { + parent::readConfiguration(); + + $this->serverName = $this->input->getArgument('server'); + + if (empty($this->serverName) || $this->serverName === '_' || empty($this->config[$this->serverName])) { + throw new \RuntimeException('No valid configuration found for server "' . $this->serverName . '"'); + } + + // Use server specific configuration + $this->output->writeln('Syncing from "' . $this->serverName . '" server'); + + $fullConfig = $this->config; + + if (!empty($fullConfig['_'])) { + // Merge global config with specific config + $this->config = array_replace_recursive($fullConfig['_'], $this->config[$this->serverName]); + } else { + $this->config = $this->config[$this->serverName]; + } } /** diff --git a/src/config.ini b/src/config.ini index ec562ee..fd34450 100644 --- a/src/config.ini +++ b/src/config.ini @@ -44,7 +44,7 @@ class[] = "CliTools\Console\Command\Common\SelfUpdateCommand" class[] = "CliTools\Console\Command\Common\MakeCommand" class[] = "CliTools\Console\Command\Sync\InitCommand" -class[] = "CliTools\Console\Command\Sync\SyncCommand" +class[] = "CliTools\Console\Command\Sync\ServerCommand" class[] = "CliTools\Console\Command\Sync\BackupCommand" class[] = "CliTools\Console\Command\Sync\RestoreCommand" From 5f6ea07e7502838e435581c29c07ac3197b15f90 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 20:54:22 +0200 Subject: [PATCH 054/214] Renamed shell command builder --- src/app/CliTools/Console/Command/AbstractCommand.php | 4 ++-- src/app/CliTools/Console/Command/AbstractTraceCommand.php | 2 +- .../CliTools/Console/Command/Apache/RestartCommand.php | 2 +- src/app/CliTools/Console/Command/Common/MakeCommand.php | 2 +- .../CliTools/Console/Command/Docker/AbstractCommand.php | 4 ++-- src/app/CliTools/Console/Command/Docker/CliCommand.php | 2 +- .../CliTools/Console/Command/Docker/ComposeCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/CreateCommand.php | 4 ++-- src/app/CliTools/Console/Command/Docker/ExecCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/IftopCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/MysqlCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/RootCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/ShellCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/SniffCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/UpCommand.php | 2 +- .../CliTools/Console/Command/Docker/UpgradeCommand.php | 2 +- src/app/CliTools/Console/Command/Mysql/BackupCommand.php | 6 +++--- src/app/CliTools/Console/Command/Mysql/RestartCommand.php | 2 +- src/app/CliTools/Console/Command/Mysql/RestoreCommand.php | 2 +- src/app/CliTools/Console/Command/Php/ComposerCommand.php | 2 +- src/app/CliTools/Console/Command/Php/RestartCommand.php | 2 +- src/app/CliTools/Console/Command/Samba/RestartCommand.php | 2 +- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 4 ++-- .../Console/Command/Sync/AbstractShareCommand.php | 2 +- src/app/CliTools/Console/Command/Sync/ServerCommand.php | 8 ++++---- .../CliTools/Console/Command/System/CrontaskCommand.php | 2 +- .../CliTools/Console/Command/System/OpenFilesCommand.php | 2 +- src/app/CliTools/Console/Command/System/RebootCommand.php | 2 +- .../CliTools/Console/Command/System/ShutdownCommand.php | 2 +- .../CliTools/Console/Command/System/StartupCommand.php | 4 ++-- src/app/CliTools/Console/Command/System/UpdateCommand.php | 6 +++--- .../CliTools/Console/Command/System/VersionCommand.php | 2 +- .../CliTools/Console/Command/TYPO3/ClearCacheCommand.php | 2 +- .../CliTools/Console/Command/TYPO3/SchedulerCommand.php | 2 +- .../CommandBuilder}/AbstractCommandBuilder.php | 2 +- .../{Builder => Shell/CommandBuilder}/CommandBuilder.php | 2 +- .../CommandBuilder}/CommandBuilderInterface.php | 2 +- .../CommandBuilder}/FullSelfCommandBuilder.php | 2 +- .../CommandBuilder}/OutputCombineCommandBuilder.php | 2 +- .../CommandBuilder}/RemoteCommandBuilder.php | 2 +- .../CommandBuilder}/SelfCommandBuilder.php | 2 +- src/app/CliTools/Console/Shell/Executor.php | 2 +- src/app/CliTools/Exception/CommandExecutionException.php | 4 ++-- src/app/CliTools/Service/SelfUpdateService.php | 2 +- src/app/CliTools/Utility/DockerUtility.php | 2 +- src/app/CliTools/Utility/UnixUtility.php | 2 +- 46 files changed, 59 insertions(+), 59 deletions(-) rename src/app/CliTools/Console/{Builder => Shell/CommandBuilder}/AbstractCommandBuilder.php (99%) rename src/app/CliTools/Console/{Builder => Shell/CommandBuilder}/CommandBuilder.php (94%) rename src/app/CliTools/Console/{Builder => Shell/CommandBuilder}/CommandBuilderInterface.php (99%) rename src/app/CliTools/Console/{Builder => Shell/CommandBuilder}/FullSelfCommandBuilder.php (96%) rename src/app/CliTools/Console/{Builder => Shell/CommandBuilder}/OutputCombineCommandBuilder.php (98%) rename src/app/CliTools/Console/{Builder => Shell/CommandBuilder}/RemoteCommandBuilder.php (94%) rename src/app/CliTools/Console/{Builder => Shell/CommandBuilder}/SelfCommandBuilder.php (96%) diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index 9806e45..f3f319f 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -24,8 +24,8 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\FullSelfCommandBuilder; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\FullSelfCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; abstract class AbstractCommand extends Command { diff --git a/src/app/CliTools/Console/Command/AbstractTraceCommand.php b/src/app/CliTools/Console/Command/AbstractTraceCommand.php index fc545b4..3682763 100644 --- a/src/app/CliTools/Console/Command/AbstractTraceCommand.php +++ b/src/app/CliTools/Console/Command/AbstractTraceCommand.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/app/CliTools/Console/Command/Apache/RestartCommand.php b/src/app/CliTools/Console/Command/Apache/RestartCommand.php index ec1ee82..5b7231e 100644 --- a/src/app/CliTools/Console/Command/Apache/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Apache/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Common/MakeCommand.php b/src/app/CliTools/Console/Command/Common/MakeCommand.php index 4d7c1f0..385c9c7 100644 --- a/src/app/CliTools/Console/Command/Common/MakeCommand.php +++ b/src/app/CliTools/Console/Command/Common/MakeCommand.php @@ -22,7 +22,7 @@ use CliTools\Utility\UnixUtility; use CliTools\Utility\PhpUtility; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php index 74424d0..bd52648 100644 --- a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\CommandBuilderInterface; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; use CliTools\Utility\PhpUtility; abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/CliCommand.php b/src/app/CliTools/Console/Command/Docker/CliCommand.php index 5bfd522..d57ce6d 100644 --- a/src/app/CliTools/Console/Command/Docker/CliCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CliCommand.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php index 6f9c88b..ebd09e5 100644 --- a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class ComposeCommand extends AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index aee7af4..6eb0333 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\SelfCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; use CliTools\Utility\PhpUtility; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; diff --git a/src/app/CliTools/Console/Command/Docker/ExecCommand.php b/src/app/CliTools/Console/Command/Docker/ExecCommand.php index f6547f6..831f32c 100644 --- a/src/app/CliTools/Console/Command/Docker/ExecCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ExecCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; class ExecCommand extends AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { diff --git a/src/app/CliTools/Console/Command/Docker/IftopCommand.php b/src/app/CliTools/Console/Command/Docker/IftopCommand.php index 0c260db..550fdb5 100644 --- a/src/app/CliTools/Console/Command/Docker/IftopCommand.php +++ b/src/app/CliTools/Console/Command/Docker/IftopCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class IftopCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/MysqlCommand.php b/src/app/CliTools/Console/Command/Docker/MysqlCommand.php index 4ba4fcf..c8bd82c 100644 --- a/src/app/CliTools/Console/Command/Docker/MysqlCommand.php +++ b/src/app/CliTools/Console/Command/Docker/MysqlCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; class MysqlCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/RootCommand.php b/src/app/CliTools/Console/Command/Docker/RootCommand.php index a6ab553..04805a1 100644 --- a/src/app/CliTools/Console/Command/Docker/RootCommand.php +++ b/src/app/CliTools/Console/Command/Docker/RootCommand.php @@ -23,7 +23,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; class RootCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/ShellCommand.php b/src/app/CliTools/Console/Command/Docker/ShellCommand.php index 73c6963..1820f1b 100644 --- a/src/app/CliTools/Console/Command/Docker/ShellCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ShellCommand.php @@ -24,7 +24,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; class ShellCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/SniffCommand.php b/src/app/CliTools/Console/Command/Docker/SniffCommand.php index d297f42..4be7893 100644 --- a/src/app/CliTools/Console/Command/Docker/SniffCommand.php +++ b/src/app/CliTools/Console/Command/Docker/SniffCommand.php @@ -24,7 +24,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class SniffCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/UpCommand.php b/src/app/CliTools/Console/Command/Docker/UpCommand.php index 893ab59..969c67d 100644 --- a/src/app/CliTools/Console/Command/Docker/UpCommand.php +++ b/src/app/CliTools/Console/Command/Docker/UpCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class UpCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php b/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php index 612f3e5..f514204 100644 --- a/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php +++ b/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class UpgradeCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index f691864..d33ac5f 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -21,8 +21,8 @@ */ use CliTools\Database\DatabaseConnection; -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\CommandBuilderInterface; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; use CliTools\Utility\FilterUtility; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -160,7 +160,7 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat ->addArgumentList($tableList); // Combine both commands to one - $command = new \CliTools\Console\Builder\OutputCombineCommandBuilder(); + $command = new \CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder(); $command ->addCommandForCombinedOutput($commandStructure) ->addCommandForCombinedOutput($commandData); diff --git a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php index bc2afd8..c530a0e 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index ce79bfe..9f5b6ba 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -24,7 +24,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class RestoreCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Php/ComposerCommand.php b/src/app/CliTools/Console/Command/Php/ComposerCommand.php index 7f6c23a..b585843 100644 --- a/src/app/CliTools/Console/Command/Php/ComposerCommand.php +++ b/src/app/CliTools/Console/Command/Php/ComposerCommand.php @@ -22,7 +22,7 @@ use CliTools\Utility\UnixUtility; use CliTools\Utility\PhpUtility; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/Php/RestartCommand.php b/src/app/CliTools/Console/Command/Php/RestartCommand.php index 7b6b18b..55484e4 100644 --- a/src/app/CliTools/Console/Command/Php/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Php/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Samba/RestartCommand.php b/src/app/CliTools/Console/Command/Samba/RestartCommand.php index a5c62c3..0c64e59 100644 --- a/src/app/CliTools/Console/Command/Samba/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Samba/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 5bb86b3..a80d600 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -22,8 +22,8 @@ use CliTools\Utility\PhpUtility; use CliTools\Utility\UnixUtility; -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\SelfCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Yaml\Yaml; diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index 8ebf9b3..20f46d0 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\CommandBuilderInterface; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 82ddbf7..ccfdb97 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -21,10 +21,10 @@ */ use CliTools\Utility\FilterUtility; -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\RemoteCommandBuilder; -use CliTools\Console\Builder\OutputCombineCommandBuilder; -use CliTools\Console\Builder\CommandBuilderInterface; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; use Symfony\Component\Console\Input\InputArgument; class ServerCommand extends AbstractSyncCommand { diff --git a/src/app/CliTools/Console/Command/System/CrontaskCommand.php b/src/app/CliTools/Console/Command/System/CrontaskCommand.php index f6e0865..7c1e7fa 100644 --- a/src/app/CliTools/Console/Command/System/CrontaskCommand.php +++ b/src/app/CliTools/Console/Command/System/CrontaskCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\UnixUtility; -use CliTools\Console\Builder\SelfCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/System/OpenFilesCommand.php b/src/app/CliTools/Console/Command/System/OpenFilesCommand.php index 999f82e..d09a091 100644 --- a/src/app/CliTools/Console/Command/System/OpenFilesCommand.php +++ b/src/app/CliTools/Console/Command/System/OpenFilesCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\FormatUtility; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/app/CliTools/Console/Command/System/RebootCommand.php b/src/app/CliTools/Console/Command/System/RebootCommand.php index 06c1c1b..e1b474e 100644 --- a/src/app/CliTools/Console/Command/System/RebootCommand.php +++ b/src/app/CliTools/Console/Command/System/RebootCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class RebootCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/System/ShutdownCommand.php b/src/app/CliTools/Console/Command/System/ShutdownCommand.php index 88938ae..1e075b6 100644 --- a/src/app/CliTools/Console/Command/System/ShutdownCommand.php +++ b/src/app/CliTools/Console/Command/System/ShutdownCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; class ShutdownCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/System/StartupCommand.php b/src/app/CliTools/Console/Command/System/StartupCommand.php index cd96e97..9d9b500 100644 --- a/src/app/CliTools/Console/Command/System/StartupCommand.php +++ b/src/app/CliTools/Console/Command/System/StartupCommand.php @@ -21,8 +21,8 @@ */ use CliTools\Database\DatabaseConnection; -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\SelfCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/System/UpdateCommand.php b/src/app/CliTools/Console/Command/System/UpdateCommand.php index 71b0637..a1e6fe1 100644 --- a/src/app/CliTools/Console/Command/System/UpdateCommand.php +++ b/src/app/CliTools/Console/Command/System/UpdateCommand.php @@ -21,8 +21,8 @@ */ use CliTools\Service\SelfUpdateService; -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\SelfCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -86,7 +86,7 @@ protected function userUpdate(InputInterface $input, OutputInterface $output) { $command = new CommandBuilder('git', 'pull'); $command->executeInteractive(); - $command = new \CliTools\Console\Builder\SelfCommandBuilder(); + $command = new \CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder(); $command->addArgument('user:rebuildsshconfig'); $command->executeInteractive(); } catch (\RuntimeException $e) { diff --git a/src/app/CliTools/Console/Command/System/VersionCommand.php b/src/app/CliTools/Console/Command/System/VersionCommand.php index a41a181..1f06ff9 100644 --- a/src/app/CliTools/Console/Command/System/VersionCommand.php +++ b/src/app/CliTools/Console/Command/System/VersionCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Database\DatabaseConnection; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Utility\UnixUtility; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php index b7ec986..3ab8468 100644 --- a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\Typo3Utility; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php b/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php index ceca306..3fa71a7 100644 --- a/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\Typo3Utility; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php similarity index 99% rename from src/app/CliTools/Console/Builder/AbstractCommandBuilder.php rename to src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php index 1e3cd4e..d6827aa 100644 --- a/src/app/CliTools/Console/Builder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php @@ -1,6 +1,6 @@ . */ -use CliTools\Console\Builder\CommandBuilder; -use CliTools\Console\Builder\CommandBuilderInterface; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; class CommandExecutionException extends \RuntimeException { diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index 9eb8748..5d11d47 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -2,7 +2,7 @@ namespace CliTools\Service; -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; /* * CliTools Command diff --git a/src/app/CliTools/Utility/DockerUtility.php b/src/app/CliTools/Utility/DockerUtility.php index 0b66316..ec4e7f0 100644 --- a/src/app/CliTools/Utility/DockerUtility.php +++ b/src/app/CliTools/Utility/DockerUtility.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\Executor; class DockerUtility { diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index 4fb265e..9b63de4 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Builder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; abstract class UnixUtility { From f31ec5b90d1470edc42a260c5d0f26b16f06dafb Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 21:19:16 +0200 Subject: [PATCH 055/214] Updated clisync.yml --- Documentation/Examples/clisync.yml | 7 ++++--- src/app/CliTools/Console/Command/Sync/InitCommand.php | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 8173694..26f64f9 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -20,7 +20,8 @@ sync: ################## production: # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) - ssh: live-server + ssh: + hostname: live-server # rsync for some directories rsync: @@ -50,8 +51,8 @@ sync: share: rsync: - # target directory or server via ssh (eg. backup-server:/backup/projectname) - target: "/tmp/foo/" + # source/target directory or server via ssh (eg. backup-server:/backup/projectname) + source: "/tmp/foo/" # List of directories for backup directory: diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 5fe5d48..0392332 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -75,7 +75,8 @@ public function execute(InputInterface $input, OutputInterface $output) { ################## production: # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) - ssh: live-server + ssh: + hostname: live-server # rsync for some directories rsync: @@ -105,8 +106,8 @@ public function execute(InputInterface $input, OutputInterface $output) { share: rsync: - # target directory or server via ssh (eg. backup-server:/backup/projectname) - target: "/tmp/foo/" + # source/target directory or server via ssh (eg. backup-server:/backup/projectname) + source: "/tmp/foo/" # List of directories for backup directory: From 9e62ab2472cb660a0b4f5092c03bde51eb0f19d8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 21:19:32 +0200 Subject: [PATCH 056/214] Implemented better layout, Added some validation --- .../Console/Command/Sync/AbstractCommand.php | 52 +++++++++++++++++++ .../Command/Sync/AbstractShareCommand.php | 2 + .../Command/Sync/AbstractSyncCommand.php | 29 +++++++++++ .../Console/Command/Sync/BackupCommand.php | 4 +- .../Console/Command/Sync/RestoreCommand.php | 4 +- .../Console/Command/Sync/ServerCommand.php | 6 +-- 6 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index a80d600..bbd4598 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -82,6 +82,9 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); $this->readConfiguration(); + if (!$this->validateConfiguration()) { + exit(1); + } $this->startup(); try { @@ -113,6 +116,55 @@ protected function readConfiguration() { } } + /** + * Validate configuration + * + * @return boolean + */ + protected function validateConfiguration() { + $ret = true; + + $output = $this->output; + + // ################## + // Rsync (required) + // ################## + + // Check for rsync directive + if (empty($this->config['rsync'])) { + $output->writeln('No rsync configuration found'); + $ret = false; + } + + // Check if rsync target exists + if (empty($this->config['rsync']['path'])) { + $output->writeln('No rsync path configuration found'); + $ret = false; + } + + // Check if there are any rsync directories + if (empty($this->config['rsync']['directory'])) { + $output->writeln('No rsync directory configuration found'); + $ret = false; + } + + // ################## + // MySQL (optional) + // ################## + + if (!empty($this->config['mysql'])) { + + // Check if one database is configured + if (empty($this->config['mysql']['database'])) { + $output->writeln('No mysql database configuration found'); + $ret = false; + } + + } + + return $ret; + } + /** * Startup task */ diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index 20f46d0..495d4ea 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -31,6 +31,8 @@ abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\Abstr */ protected $confArea = 'share'; + + /** * Create rsync command for share sync * diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index 4c22eda..e237cfa 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -29,4 +29,33 @@ abstract class AbstractSyncCommand extends \CliTools\Console\Command\Sync\Abstra */ protected $confArea = 'server'; + + /** + * Validate configuration + * + * @return boolean + */ + protected function validateConfiguration() { + $ret = parent::validateConfiguration(); + + $output = $this->output; + + // ################## + // SSH (optional) + // ################## + + if (!empty($this->config['ssh'])) { + + // Check if one database is configured + if (empty($this->config['ssh']['hostname'])) { + $output->writeln('No ssh hostname configuration found'); + $ret = false; + } + + } + + return $ret; + } + + } diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index cf317a1..7de2715 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -38,7 +38,7 @@ protected function runTask() { // Backup dirs // ################## $source = $this->workingPath; - $target = $this->config['rsync']['target'] . self::PATH_DATA; + $target = $this->config['rsync']['path'] . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); @@ -62,7 +62,7 @@ protected function runTask() { // Backup mysql dump // ################## $source = $this->tempDir; - $target = $this->config['rsync']['target'] . self::PATH_DUMP; + $target = $this->config['rsync']['path'] . self::PATH_DUMP; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 702ffd6..7bba379 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -37,7 +37,7 @@ protected function runTask() { // ################## // Restore dirs // ################## - $source = $this->config['rsync']['target'] . self::PATH_DUMP; + $source = $this->config['rsync']['path'] . self::PATH_DUMP; $target = $this->workingPath; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); @@ -45,7 +45,7 @@ protected function runTask() { // ################## // Restore mysql dump // ################## - $source = $this->config['rsync']['target'] . self::PATH_DUMP; + $source = $this->config['rsync']['path'] . self::PATH_DUMP; $target = $this->tempDir; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index ccfdb97..ef1143c 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -97,7 +97,7 @@ protected function runTaskRsync() { // ################## // Restore dirs // ################## - $source = $this->config['rsync']['source']; + $source = $this->config['rsync']['path']; $target = $this->workingPath; $command = $this->createRsyncCommand($source, $target); @@ -208,9 +208,9 @@ protected function createMySqlDumpCommand($database = null) { */ protected function wrapCommand(CommandBuilderInterface $command) { // Wrap in ssh if needed - if (!empty($this->config['ssh'])) { + if (!empty($this->config['ssh']['hostname'])) { $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); - $sshCommand->addArgument($this->config['ssh']) + $sshCommand->addArgument($this->config['ssh']['hostname']) ->append($command, true); $command = $sshCommand; From 799ac0558286d282a0b533b269f4e0ee2beeccc7 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 21:38:33 +0200 Subject: [PATCH 057/214] Updated example --- Documentation/Examples/clisync.yml | 4 ++-- src/app/CliTools/Console/Command/Sync/InitCommand.php | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 26f64f9..5a2eda1 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -13,7 +13,7 @@ sync: # specific mysqldump settings mysqldump: - option: "--single-transaction" + option: "--opt --single-transaction" ################## # Config "production" @@ -36,7 +36,7 @@ sync: mysql: # mysql connection - host: localhost + hostname: localhost username: typo3 password: loremipsum diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 0392332..2f4ff8a 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -68,7 +68,7 @@ public function execute(InputInterface $input, OutputInterface $output) { # specific mysqldump settings mysqldump: - option: "--single-transaction" + option: "--opt --single-transaction" ################## # Config "production" @@ -91,7 +91,7 @@ public function execute(InputInterface $input, OutputInterface $output) { mysql: # mysql connection - host: localhost + hostname: localhost username: typo3 password: loremipsum @@ -129,7 +129,6 @@ public function execute(InputInterface $input, OutputInterface $output) { # List of databases for backup database: - typo3 - '; PhpUtility::filePutContents($cliSyncFilePath, $content); From 7f6cf843bb02fe5472757edf0f2581f282cb8fe8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 21:38:48 +0200 Subject: [PATCH 058/214] Added optional mysql settings, Added batch mode --- .../Console/Command/Mysql/RestoreCommand.php | 4 ++ .../Console/Command/Sync/ServerCommand.php | 48 +++++++++++++++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index 9f5b6ba..91714b5 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -105,19 +105,23 @@ public function execute(InputInterface $input, OutputInterface $output) { switch ($dumpFileType) { case 'application/x-bzip2': + $output->writeln('Using BZIP2 uncompression'); $commandFile->setCommand('bzcat'); break; case 'application/gzip': + $output->writeln('Using GZIP uncompression'); $commandFile->setCommand('gzcat'); break; case 'application/x-lzma': case 'application/x-xz': + $output->writeln('Using LZMA uncompression'); $commandFile->setCommand('xzcat'); break; default: + $output->writeln('Using plaintext (no uncompression)'); $commandFile->setCommand('cat'); break; } diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index ef1143c..648b857 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -162,10 +162,25 @@ protected function runTaskDatabase() { protected function createMySqlCommand($database = null) { $command = new RemoteCommandBuilder('mysql'); $command - ->addArgument('--skip-column-names') - ->addArgumentTemplate('-u%s', $this->config['mysql']['username']) - ->addArgumentTemplate('-p%s', $this->config['mysql']['password']) - ->addArgumentTemplate('-h%s', $this->config['mysql']['host']); + // batch mode + ->addArgument('-B') + // skip column names + ->addArgument('-N'); + + // Add username + if (!empty($this->config['mysql']['username'])) { + $command->addArgumentTemplate('-u%s', $this->config['mysql']['username']); + } + + // Add password + if (!empty($this->config['mysql']['password'])) { + $command->addArgumentTemplate('-p%s', $this->config['mysql']['password']); + } + + // Add hostname + if (!empty($this->config['mysql']['hostname'])) { + $command->addArgumentTemplate('-h%s', $this->config['mysql']['hostname']); + } if ($database !== null) { $command->addArgument($database); @@ -183,16 +198,31 @@ protected function createMySqlCommand($database = null) { */ protected function createMySqlDumpCommand($database = null) { $command = new RemoteCommandBuilder('mysqldump'); - $command - ->addArgumentTemplate('-u%s', $this->config['mysql']['username']) - ->addArgumentTemplate('-p%s', $this->config['mysql']['password']) - ->addArgumentTemplate('-h%s', $this->config['mysql']['host']) - ->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + + // Add username + if (!empty($this->config['mysql']['username'])) { + $command->addArgumentTemplate('-u%s', $this->config['mysql']['username']); + } + + // Add password + if (!empty($this->config['mysql']['password'])) { + $command->addArgumentTemplate('-p%s', $this->config['mysql']['password']); + } + + // Add hostname + if (!empty($this->config['mysql']['hostname'])) { + $command->addArgumentTemplate('-h%s', $this->config['mysql']['hostname']); + } + + // Add custom options if (!empty($this->config['mysqldump']['option'])) { $command->addArgumentRaw($this->config['mysqldump']['option']); } + // Add pipe (bzip2 compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + if ($database !== null) { $command->addArgument($database); } From ea8d7e8be7029f08b30f812ca4451c57cc408118 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 21:46:47 +0200 Subject: [PATCH 059/214] Added rsync output (progress) --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index bbd4598..18009cc 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -208,7 +208,7 @@ protected function clearTempDir() { protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { $this->output->writeln('Rsync from ' . $source . ' to ' . $target . ''); - $command = new CommandBuilder('rsync', '-rlptD --delete-after'); + $command = new CommandBuilder('rsync', '-rlptD --delete-after --progress -h'); // Add file list (external file with --files-from option) if (!empty($filelist)) { From bf5bc214d436d0e35faed10bc7d0966abe735d02 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 21:46:56 +0200 Subject: [PATCH 060/214] Fixed wrong output color --- src/app/CliTools/Console/Command/Mysql/RestoreCommand.php | 6 +++--- src/app/CliTools/Console/Command/Sync/ServerCommand.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index 91714b5..785c904 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -81,18 +81,18 @@ public function execute(InputInterface $input, OutputInterface $output) { if (DatabaseConnection::databaseExists($database)) { // Dropping - $output->writeln('Dropping Database "' . $database . '"...'); + $output->writeln('Dropping Database "' . $database . '"...'); $query = 'DROP DATABASE IF EXISTS ' . DatabaseConnection::sanitizeSqlDatabase($database); DatabaseConnection::exec($query); } // Creating - $output->writeln('Creating Database "' . $database . '"...'); + $output->writeln('Creating Database "' . $database . '"...'); $query = 'CREATE DATABASE ' . DatabaseConnection::sanitizeSqlDatabase($database); DatabaseConnection::exec($query); // Inserting - $output->writeln('Restoring dump into Database "' . $database . '"...'); + $output->writeln('Restoring dump into Database "' . $database . '"...'); putenv('USER=' . DatabaseConnection::getDbUsername()); putenv('MYSQL_PWD=' . DatabaseConnection::getDbPassword()); diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 648b857..1dddd37 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -130,7 +130,7 @@ protected function runTaskDatabase() { // ########## // Dump from server // ########## - $this->output->writeln('Fetching foreign database ' . $foreignDatabase . ''); + $this->output->writeln('Fetching foreign database "' . $foreignDatabase . '"'); $mysqldump = $this->createMySqlDumpCommand($foreignDatabase); @@ -146,7 +146,7 @@ protected function runTaskDatabase() { // ########## // Restore local // ########## - $this->output->writeln('Restoring database ' . $localDatabase . ''); + $this->output->writeln('Restoring database "' . $localDatabase . '"'); $this->createMysqlRestoreCommand($localDatabase, $dumpFile)->executeInteractive(); } From 02aa150a4ff7ddad063fffcceaeed80b14aede26 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 21:49:03 +0200 Subject: [PATCH 061/214] Added sync:server --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e46bc1..5e8fb46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ CliTools Changelog - Added `make` (auto search for Makefile in tree) - Added `php:composer` (auto search for composer.yml in tree) - Added `mysql:convert` for automatic changing charset and collation of one database +- Added `sync:server` for syncing any configured server to your local development system (reads clisync.yml) - Added `sync:backup` for backup to a shared server (reads clisync.yml) - Added `sync:restore` for restore from a shared server (reads clisync.yml) - Fixed some issues From b56c6e7b35b9294180783ad3fa90c2163ebc5db0 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 22:15:56 +0200 Subject: [PATCH 062/214] Removed autoloading, switched to composer autoloading --- Makefile | 3 +++ compile.sh | 3 ++- src/app/bootstrap.php | 30 ------------------------ src/command.php | 2 +- src/composer.json | 7 +++++- src/composer.lock | 53 +------------------------------------------ 6 files changed, 13 insertions(+), 85 deletions(-) delete mode 100644 src/app/bootstrap.php diff --git a/Makefile b/Makefile index 789d5f6..47dcfb8 100644 --- a/Makefile +++ b/Makefile @@ -5,3 +5,6 @@ install: cp clitools.phar /usr/local/bin/ct all: build install + +autoload: + sh -c "cd src ; composer dump-autoload --optimize --no-dev" diff --git a/compile.sh b/compile.sh index a7cef5f..95baac9 100755 --- a/compile.sh +++ b/compile.sh @@ -10,7 +10,8 @@ SCRIPT_DIR=$(dirname $(readlink -f "$0")) OLD_PWD=`pwd` cd "$SCRIPT_DIR/src" -composer install +composer install --no-dev +composer dump-autoload --optimize --no-dev cd "$SCRIPT_DIR/" box.phar build -c build.json diff --git a/src/app/bootstrap.php b/src/app/bootstrap.php deleted file mode 100644 index 8c73e30..0000000 --- a/src/app/bootstrap.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -error_reporting(E_ALL); - -// #################################### -// Autoload -// #################################### - -$loader = new Symfony\Component\ClassLoader\UniversalClassLoader(); -$loader->registerNamespaces(array( - 'CliTools' => __DIR__ - )); -$loader->register(); diff --git a/src/command.php b/src/command.php index 2f71a6a..60288cf 100644 --- a/src/command.php +++ b/src/command.php @@ -19,11 +19,11 @@ * along with this program. If not, see . */ +error_reporting(E_ALL); define('CLITOOLS_COMMAND_VERSION', '1.10.0'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; -require __DIR__ . '/app/bootstrap.php'; $app = new CliTools\Console\Application('CliTools :: Development Console Utility', CLITOOLS_COMMAND_VERSION); diff --git a/src/composer.json b/src/composer.json index 86021d1..c2e61bb 100644 --- a/src/composer.json +++ b/src/composer.json @@ -1,11 +1,16 @@ { + "name": "Clitools", "repositories": [ { "type": "vcs", "url": "https://github.com/jamiebicknell/Growl-GNTP.git" } ], "require": { "symfony/console": "2.*", - "symfony/class-loader": "2.*", "jamiebicknell/Growl-GNTP": "dev-master", "symfony/yaml": "^2.6" + }, + "autoload": { + "psr-0": { + "CliTools": "./app" + } } } diff --git a/src/composer.lock b/src/composer.lock index 10bec02..c39197f 100644 --- a/src/composer.lock +++ b/src/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "b7a124516b0d6433c4b6613c55aa1504", + "hash": "7b023eac532864cff6d957dd51e5999c", "packages": [ { "name": "jamiebicknell/Growl-GNTP", @@ -46,57 +46,6 @@ }, "time": "2014-06-21 19:14:27" }, - { - "name": "symfony/class-loader", - "version": "v2.6.7", - "target-dir": "Symfony/Component/ClassLoader", - "source": { - "type": "git", - "url": "https://github.com/symfony/ClassLoader.git", - "reference": "695134c9b39559297fa5d1dcff6a9054bb56facb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/ClassLoader/zipball/695134c9b39559297fa5d1dcff6a9054bb56facb", - "reference": "695134c9b39559297fa5d1dcff6a9054bb56facb", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/finder": "~2.0,>=2.0.5", - "symfony/phpunit-bridge": "~2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\ClassLoader\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony ClassLoader Component", - "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" - }, { "name": "symfony/console", "version": "v2.6.7", From d2841cc0fa89f9141f8c0d37df4f91ebdc9aeca1 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 22:27:24 +0200 Subject: [PATCH 063/214] Renamed build.json to box.json, Enabled gzip compression --- build.json => box.json | 3 ++- compile.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename build.json => box.json (87%) diff --git a/build.json b/box.json similarity index 87% rename from build.json rename to box.json index 9cdc14b..5a9a2d0 100644 --- a/build.json +++ b/box.json @@ -15,5 +15,6 @@ ], "main": "src/command.php", "output": "clitools.phar", - "stub": true + "stub": true, + "compression": "GZ" } diff --git a/compile.sh b/compile.sh index 95baac9..42c5c64 100755 --- a/compile.sh +++ b/compile.sh @@ -14,6 +14,6 @@ composer install --no-dev composer dump-autoload --optimize --no-dev cd "$SCRIPT_DIR/" -box.phar build -c build.json +box.phar build -c box.json cd "$OLD_PWD" From 663db32564c561430085207852b70bba8f75054e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 22:29:22 +0200 Subject: [PATCH 064/214] Updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e8fb46..48c3c6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,9 @@ CliTools Changelog - Added `sync:server` for syncing any configured server to your local development system (reads clisync.yml) - Added `sync:backup` for backup to a shared server (reads clisync.yml) - Added `sync:restore` for restore from a shared server (reads clisync.yml) +- Refactored some classes - Fixed some issues +- Added gzip compression for PHAR 1.9.0 - 2015-05-06 ------------------ From 26e6de7cd2093df85427f5fd396779bc20ac020d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 22:39:39 +0200 Subject: [PATCH 065/214] Updated clisync.yml indention --- Documentation/Examples/clisync.yml | 52 ++++++++-------- .../Console/Command/Sync/InitCommand.php | 61 ++++++++++--------- 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 5a2eda1..c957417 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -8,42 +8,42 @@ sync: ################## _: mysql: - # MySQL filter for typo3 (eg. no caching tables) - filter: typo3 + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 - # specific mysqldump settings - mysqldump: - option: "--opt --single-transaction" + # specific mysqldump settings + mysqldump: + option: "--opt --single-transaction" ################## # Config "production" ################## production: - # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) - ssh: - hostname: live-server + # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) + ssh: + hostname: live-server - # rsync for some directories - rsync: - # server and source directory (server host or name - see .ssh/config) - source: "live-server:/var/www/website/htdocs" + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + source: "live-server:/var/www/website/htdocs" - # directory list/patterns - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" - mysql: - # mysql connection - hostname: localhost - username: typo3 - password: loremipsum + mysql: + # mysql connection + hostname: localhost + username: typo3 + password: loremipsum - # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) - database: - - typo3:website_live - - other_database + # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) + database: + - typo3:website_live + - other_database ####################################### # Shared server (sharing between developers) diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 2f4ff8a..557ba90 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -63,42 +63,42 @@ public function execute(InputInterface $input, OutputInterface $output) { ################## _: mysql: - # MySQL filter for typo3 (eg. no caching tables) - filter: typo3 + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 - # specific mysqldump settings - mysqldump: - option: "--opt --single-transaction" + # specific mysqldump settings + mysqldump: + option: "--opt --single-transaction" ################## # Config "production" ################## production: - # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) - ssh: - hostname: live-server - - # rsync for some directories - rsync: - # server and source directory (server host or name - see .ssh/config) - source: "live-server:/var/www/website/htdocs" - - # directory list/patterns - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - - mysql: - # mysql connection - hostname: localhost - username: typo3 - password: loremipsum - - # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) - database: - - typo3:website_live - - other_database + # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) + ssh: + hostname: live-server + + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + source: "live-server:/var/www/website/htdocs" + + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + mysql: + # mysql connection + hostname: localhost + username: typo3 + password: loremipsum + + # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) + database: + - typo3:website_live + - other_database ####################################### # Shared server (sharing between developers) @@ -129,6 +129,7 @@ public function execute(InputInterface $input, OutputInterface $output) { # List of databases for backup database: - typo3 + '; PhpUtility::filePutContents($cliSyncFilePath, $content); From b044113c65b86a39e40b4e7cc0d59a061c235a18 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 22:39:50 +0200 Subject: [PATCH 066/214] Added styling for yml files --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 812c991..8b65364 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,3 +6,6 @@ indent_size = 4 [Makefile] indent_style = tab + +[*.yml] +indent_size = 2 From 31168e59e2d99d388afdc88446fd60503522393b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 22:57:38 +0200 Subject: [PATCH 067/214] Only drop database if exists --- src/app/CliTools/Console/Command/Mysql/ClearCommand.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php index bda8cff..3d24497 100644 --- a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php @@ -52,9 +52,11 @@ protected function configure() { public function execute(InputInterface $input, OutputInterface $output) { $database = $input->getArgument('db'); - $output->writeln('Dropping Database "' . $database . '"...'); - $query = 'DROP DATABASE IF EXISTS ' . DatabaseConnection::sanitizeSqlDatabase($database); - DatabaseConnection::exec($query); + if (DatabaseConnection::databaseExists($database)) { + $output->writeln('Dropping Database "' . $database . '"...'); + $query = 'DROP DATABASE ' . DatabaseConnection::sanitizeSqlDatabase($database); + DatabaseConnection::exec($query); + } $output->writeln('Creating Database "' . $database . '"...'); $query = 'CREATE DATABASE ' . DatabaseConnection::sanitizeSqlDatabase($database); From 44a7394531eb88f2a4ba8e96a0e04f3aba06c85f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 22:57:43 +0200 Subject: [PATCH 068/214] Refactoring --- .../Console/Command/Mysql/RestoreCommand.php | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index 785c904..a27ccc7 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -64,20 +64,7 @@ public function execute(InputInterface $input, OutputInterface $output) { return 1; } - // Get mime type from file - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $dumpFileType = finfo_file($finfo, $dumpFile); - finfo_close($finfo); - - if ($dumpFileType === 'application/octet-stream') { - $finfo = finfo_open(); - $dumpFileInfo = finfo_file($finfo, $dumpFile); - finfo_close($finfo); - - if (strpos($dumpFileInfo, 'LZMA compressed data') !== false) { - $dumpFileType = 'application/x-lzma'; - } - } + $dumpFileType = $this->getMimeTypeFromDump($dumpFile); if (DatabaseConnection::databaseExists($database)) { // Dropping @@ -132,4 +119,31 @@ public function execute(InputInterface $input, OutputInterface $output) { return 0; } + + + /** + * Get MIME type from dump file + * + * @param string $dumpFile Path to mysql dump file + * + * @return string + */ + protected function getMimeTypeFromDump($dumpFile) { + // Get mime type from file + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $ret = finfo_file($finfo, $dumpFile); + finfo_close($finfo); + + if ($ret === 'application/octet-stream') { + $finfo = finfo_open(); + $dumpFileInfo = finfo_file($finfo, $dumpFile); + finfo_close($finfo); + + if (strpos($dumpFileInfo, 'LZMA compressed data') !== false) { + $ret = 'application/x-lzma'; + } + } + + return $ret; + } } From 3031c00b13e2e5b067e00b1c1a12d3c3ed83a02d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 14 May 2015 23:00:49 +0200 Subject: [PATCH 069/214] Moved mimtype detection into PhpUtility --- .../Console/Command/Mysql/RestoreCommand.php | 28 ++----------------- src/app/CliTools/Utility/PhpUtility.php | 27 ++++++++++++++++++ 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index a27ccc7..d7b2ef4 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -21,6 +21,7 @@ */ use CliTools\Database\DatabaseConnection; +use CliTools\Utility\PhpUtility; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -64,7 +65,7 @@ public function execute(InputInterface $input, OutputInterface $output) { return 1; } - $dumpFileType = $this->getMimeTypeFromDump($dumpFile); + $dumpFileType = PhpUtility::getMimeType($dumpFile); if (DatabaseConnection::databaseExists($database)) { // Dropping @@ -121,29 +122,4 @@ public function execute(InputInterface $input, OutputInterface $output) { } - /** - * Get MIME type from dump file - * - * @param string $dumpFile Path to mysql dump file - * - * @return string - */ - protected function getMimeTypeFromDump($dumpFile) { - // Get mime type from file - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $ret = finfo_file($finfo, $dumpFile); - finfo_close($finfo); - - if ($ret === 'application/octet-stream') { - $finfo = finfo_open(); - $dumpFileInfo = finfo_file($finfo, $dumpFile); - finfo_close($finfo); - - if (strpos($dumpFileInfo, 'LZMA compressed data') !== false) { - $ret = 'application/x-lzma'; - } - } - - return $ret; - } } diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index 4547e47..183f339 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -125,4 +125,31 @@ public static function curlFetch($url, callable $progress = null) { return $ret; } + + + /** + * Get MIME type for file + * + * @param string $file Path to file + * + * @return string + */ + public static function getMimeType($file) { + // Get mime type from file + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $ret = finfo_file($finfo, $file); + finfo_close($finfo); + + if ($ret === 'application/octet-stream') { + $finfo = finfo_open(); + $dumpFileInfo = finfo_file($finfo, $file); + finfo_close($finfo); + + if (strpos($dumpFileInfo, 'LZMA compressed data') !== false) { + $ret = 'application/x-lzma'; + } + } + + return $ret; + } } From 233a0952a25b3d4d7476e110d4a829c95f22fcbd Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:15:57 +0200 Subject: [PATCH 070/214] Added mysqlIgnoreTableFilter --- src/app/CliTools/Utility/FilterUtility.php | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/app/CliTools/Utility/FilterUtility.php b/src/app/CliTools/Utility/FilterUtility.php index e90ed0b..843f11b 100644 --- a/src/app/CliTools/Utility/FilterUtility.php +++ b/src/app/CliTools/Utility/FilterUtility.php @@ -45,4 +45,32 @@ public static function mysqlTableFilter(array $tables, array $filters) { return $ret; } + /** + * Filter mysql table list by filter + * + * @param array $tables List of tables + * @param array $filter List of filters + * @param string|null $database Database + * + * @return array + */ + public static function mysqlIgnoredTableFilter(array $tables, array $filters, $database = null) { + $ret = array(); + + foreach ($tables as $table) { + foreach ($filters as $filter) { + if (preg_match($filter, $table)) { + + if ($database !== null) { + $ret[] = $database . '.' . $table; + } else { + $ret[] = $table; + } + continue 2; + } + } + } + + return $ret; + } } From b7a2832a3bb9965d3046294f1ce035d39462dd4b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:16:14 +0200 Subject: [PATCH 071/214] Added ping, switchDatabase and databaseList --- .../CliTools/Database/DatabaseConnection.php | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/app/CliTools/Database/DatabaseConnection.php b/src/app/CliTools/Database/DatabaseConnection.php index b182fbc..4d06153 100644 --- a/src/app/CliTools/Database/DatabaseConnection.php +++ b/src/app/CliTools/Database/DatabaseConnection.php @@ -121,6 +121,24 @@ public static function getConnection() { return self::$connection; } + + /** + * Ping server + * + * @return bool + */ + public static function ping() { + ConsoleUtility::verboseWriteln('DB::PING', null); + try { + self::getConnection()->query('SELECT 1'); + } catch (\PDOException $e) { + ConsoleUtility::verboseWriteln('DB::QUERY::EXCEPTION', $e); + throw $e; + } + + return true; + } + /** * Execute SELECT query * @@ -142,6 +160,17 @@ public static function query($query) { return $ret; } + /** + * Switch database + * + * @param string $database Database + * + * @throws \PDOException + */ + public static function switchDatabase($database) { + self::exec('USE ' . self::sanitizeSqlDatabase($database)); + } + /** * Execute INSERT/DELETE/UPDATE query * @@ -358,6 +387,22 @@ public static function databaseExists($database) { return ($ret === 1 ); } + /** + * Return list of databases + * + * @return array + */ + public static function databaseList() { + // Get list of databases + $query = 'SELECT SCHEMA_NAME FROM information_schema.SCHEMATA'; + $ret = DatabaseConnection::getCol($query); + + // Filter mysql specific databases + $ret = array_diff($ret, array('mysql', 'information_schema', 'performance_schema')); + + return $ret; + } + /** * Return list of tables of one database * From 142d91f81423bf71f92048aeb187e55d9be7f593 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:16:27 +0200 Subject: [PATCH 072/214] Updated CommandBuilderInterface --- .../CommandBuilderInterface.php | 117 ++++++++++++++---- 1 file changed, 93 insertions(+), 24 deletions(-) diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php b/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php index 81a5e0e..c2c90dd 100644 --- a/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php +++ b/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php @@ -23,15 +23,7 @@ use CliTools\Console\Shell\Executor; interface CommandBuilderInterface { - - /** - * Construct - */ - public function __construct(); - /** - * Get command - * * @return string */ public function getCommand(); @@ -40,6 +32,7 @@ public function getCommand(); * Set command * * @param string $command + * * @return $this */ public function setCommand($command); @@ -69,6 +62,7 @@ public function addArgumentSeparator(); * Set argument from list * * @param array $args Arguments + * * @return $this */ public function setArgumentList(array $args); @@ -76,34 +70,55 @@ public function setArgumentList(array $args); /** * Set arguments raw (unescaped) * - * @param string $arg... Argument + * @param string $arg ... Argument + * * @return $this */ public function addArgumentRaw($arg); + /** + * Set arguments list raw (unescaped) + * + * @param array $arg ... Argument + * + * @return $this + */ + public function addArgumentListRaw($arg); + /** * Set arguments * - * @param string $arg... Argument + * @param string $arg ... Argument + * * @return $this */ public function addArgument($arg); /** - * Set argument with template + * Add argument with template * - * @param string $arg Argument sprintf - * @param string $params Argument parameters + * @param string $arg Argument sprintf + * @param string $params ... Argument parameters * * @return $this */ public function addArgumentTemplate($arg, $params); + /** + * Add argument with template multiple times + * + * @param string $arg Argument sprintf + * @param array $paramList Argument parameters + * + * @return $this + */ + public function addArgumentTemplateMultiple($arg, $paramList); + /** * Set argument with template * - * @param string $arg Argument sprintf - * @param array $params Argument parameters + * @param string $arg Argument sprintf + * @param array $params Argument parameters * * @return $this */ @@ -112,12 +127,33 @@ public function addArgumentTemplateList($arg, array $params); /** * Add arguments list * - * @param array $arg Argument + * @param array $arg Argument * @param boolean $escape Escape shell arguments + * * @return $this */ public function addArgumentList(array $arg, $escape = true); + /** + * Append one argument to list + * + * @param array $arg Arguments + * @param boolean $escape Enable argument escaping + * + * @return $this + */ + public function appendArgumentToList($arg, $escape = true); + + /** + * Append multiple arguments to list + * + * @param array $args Arguments + * @param boolean $escape Enable argument escaping + * + * @return $this + */ + public function appendArgumentsToList($args, $escape = true); + /** * Get arguments list * @@ -136,25 +172,34 @@ public function getOutputRedirect(); * Set output (stdout and/or stderr) redirection * * @param null|string $outputRedirect + * * @return $this */ public function setOutputRedirect($outputRedirect = null); - /** * Redirect command stdout output to file * * @param string $filename Filename + * * @return $this */ public function setOutputRedirectToFile($filename); + /** + * Clear output redirect + * + * @return $this + */ + public function clearOutputRedirect(); + /** * Parse command and attributs from exec line * * WARNING: Not safe! * * @param string $str Command string + * * @return $this */ public function parse($str); @@ -162,8 +207,8 @@ public function parse($str); /** * Append another command builder * - * @param CommandBuilderInterface $command Command builder - * @param boolean $inline Add command as inline string (one big parameter) + * @param CommandBuilderInterface $command Command builder + * @param boolean $inline Add command as inline string (one big parameter) * * @return $this */ @@ -188,15 +233,23 @@ public function getPipeList(); * Set pipe list * * @param array $pipeList + * * @return $this */ public function setPipeList(array $pipeList); + /** + * Clear pipe list + * + * @return $this + */ + public function clearPipes(); /** * Add pipe command * * @param CommandBuilderInterface $command + * * @return $this */ public function addPipeCommand(CommandBuilderInterface $command); @@ -212,29 +265,45 @@ public function build(); /** * Get executor * - * @return Executor + * @return \CliTools\Console\Shell\Executor */ public function getExecutor(); /** * Set executor * - * @param Executor $executor + * @param \CliTools\Console\Shell\Executor $executor */ - public function setExecutor(Executor $executor); + public function setExecutor(\CliTools\Console\Shell\Executor $executor); /** * Execute command * - * @return Executor + * @return \CliTools\Console\Shell\Executor */ public function execute(); /** * Execute command * - * @return Executor + * @return \CliTools\Console\Shell\Executor */ public function executeInteractive(); + /** + * Validate argument value + * + * @param mixed $value Value + * + * @throws \RuntimeException + */ + public function validateArgumentValue($value); + + /** + * To string + * + * @return string + */ + public function __toString(); + } From 9b0e568b128f1ec61508f6e190de83a39179bc42 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:16:42 +0200 Subject: [PATCH 073/214] Refactoring --- .../Console/Command/TYPO3/BeUserCommand.php | 16 ++++------------ .../Console/Command/TYPO3/CleanupCommand.php | 9 +++------ 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php index f1aa756..a36ee13 100644 --- a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php @@ -117,20 +117,12 @@ public function execute(InputInterface $input, OutputInterface $output) { // All databases // ############## - // Get list of databases - $query = 'SELECT SCHEMA_NAME - FROM information_schema.SCHEMATA'; - $databaseList = DatabaseConnection::getCol($query); + $databaseList = DatabaseConnection::databaseList(); $dbFound = false; foreach ($databaseList as $dbName) { - // Skip internal mysql databases - if (in_array(strtolower($dbName), array('mysql', 'information_schema', 'performance_schema'))) { - continue; - } - // Check if database is TYPO3 instance - $query = 'SELECT COUNT(*) as count + $query = 'SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = ' . DatabaseConnection::quote($dbName) . ' AND table_name = \'be_users\''; @@ -206,13 +198,13 @@ protected function setTypo3UserForDatabase($database, $username, $password) { try { // Get uid from current dev user (if already existing) $query = 'SELECT uid - FROM `' . DatabaseConnection::sanitizeSqlDatabase($database) . '`.be_users + FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.be_users WHERE username = ' . DatabaseConnection::quote($username) . ' AND deleted = 0'; $beUserId = DatabaseConnection::getOne($query); // Insert or update user in TYPO3 database - $query = 'INSERT INTO `' . DatabaseConnection::sanitizeSqlDatabase($database) . '`.be_users + $query = 'INSERT INTO ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.be_users (uid, tstamp, crdate, realName, username, password, TSconfig, admin, disable, starttime, endtime) VALUES( ' . DatabaseConnection::quote($beUserId) . ', diff --git a/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php b/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php index 056ee58..9dc95d9 100644 --- a/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php @@ -104,10 +104,7 @@ protected function cleanupTypo3Database($database) { $cleanupTableList = array(); // Check if database is TYPO3 instance - $query = 'SELECT table_name - FROM information_schema.tables - WHERE table_schema = ' . DatabaseConnection::quote($database); - $tableList = DatabaseConnection::getCol($query); + $tableList = DatabaseConnection::tableList($database); foreach ($tableList as $table) { $clearTable = false; @@ -167,10 +164,10 @@ protected function cleanupTypo3Database($database) { $this->output->writeln('Starting cleanup of database ' . $database . '...'); - DatabaseConnection::exec('USE `' . $database . '`'); + DatabaseConnection::switchDatabase(DatabaseConnection::sanitizeSqlDatabase($database)); foreach ($cleanupTableList as $table) { - $query = 'TRUNCATE `' . $table . '`'; + $query = 'TRUNCATE ' . DatabaseConnection::sanitizeSqlTable($table); DatabaseConnection::exec($query); if ($this->output->isVerbose()) { From e376eac35b712822c4d4a99f6f418e4926d3674e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:26:17 +0200 Subject: [PATCH 074/214] Added addArgumentTemplateMultiple --- .../CommandBuilder/AbstractCommandBuilder.php | 18 +++++++++++- .../CommandBuilderInterface.php | 29 ------------------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php index d6827aa..711b82c 100644 --- a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php @@ -221,7 +221,7 @@ public function addArgument($arg) { } /** - * Set argument with template + * Add argument with template * * @param string $arg Argument sprintf * @param string $params... Argument parameters @@ -235,6 +235,22 @@ public function addArgumentTemplate($arg, $params) { return $this->addArgumentTemplateList($arg, $funcArgs); } + /** + * Add argument with template multiple times + * + * @param string $arg Argument sprintf + * @param array $paramList Argument parameters + * + * @return $this + */ + public function addArgumentTemplateMultiple($arg, $paramList) { + foreach ($paramList as $param) { + $this->addArgumentTemplate($arg, $param); + } + + return $this; + } + /** * Set argument with template * diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php b/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php index c2c90dd..d64564b 100644 --- a/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php +++ b/src/app/CliTools/Console/Shell/CommandBuilder/CommandBuilderInterface.php @@ -134,26 +134,6 @@ public function addArgumentTemplateList($arg, array $params); */ public function addArgumentList(array $arg, $escape = true); - /** - * Append one argument to list - * - * @param array $arg Arguments - * @param boolean $escape Enable argument escaping - * - * @return $this - */ - public function appendArgumentToList($arg, $escape = true); - - /** - * Append multiple arguments to list - * - * @param array $args Arguments - * @param boolean $escape Enable argument escaping - * - * @return $this - */ - public function appendArgumentsToList($args, $escape = true); - /** * Get arguments list * @@ -290,15 +270,6 @@ public function execute(); */ public function executeInteractive(); - /** - * Validate argument value - * - * @param mixed $value Value - * - * @throws \RuntimeException - */ - public function validateArgumentValue($value); - /** * To string * From e1142b2cd5e1f568bc53b8cc9eb73963d9b9332e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:26:48 +0200 Subject: [PATCH 075/214] Refactored typo3:domain (will add .vm at the end of each domain now) --- .../Console/Command/TYPO3/DomainCommand.php | 110 ++++-------------- src/config.ini | 2 +- 2 files changed, 21 insertions(+), 91 deletions(-) diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index ae99bd4..7963beb 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -31,7 +31,8 @@ class DomainCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('typo3:domain') + $this + ->setName('typo3:domain') ->setDescription('Add common development domains to database') ->addArgument( 'db', @@ -62,20 +63,11 @@ public function execute(InputInterface $input, OutputInterface $output) { // ############## // All databases // ############## - - // Get list of databases - $query = 'SELECT SCHEMA_NAME - FROM information_schema.SCHEMATA'; - $databaseList = DatabaseConnection::getCol($query); + $databaseList = DatabaseConnection::databaseList(); foreach ($databaseList as $dbName) { - // Skip internal mysql databases - if (in_array(strtolower($dbName), array('mysql', 'information_schema', 'performance_schema'))) { - continue; - } - // Check if database is TYPO3 instance - $query = 'SELECT COUNT(*) as count + $query = 'SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = ' . DatabaseConnection::quote($dbName) . ' AND table_name = \'sys_domain\''; @@ -104,92 +96,30 @@ public function execute(InputInterface $input, OutputInterface $output) { */ protected function setupDevelopmentDomainsForDatabase($database) { - // ################## - // Build domain - // ################## - $domain = null; - - if (preg_match('/^([^_]+)_([^_]+).*/i', $database, $matches)) { - $domain = $matches[2] . '.' . $matches[1]; - } else { - return false; - } - - // ################## - // Check if multi site - // ################## - $isMultiSite = false; - - $query = 'SELECT uid - FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.pages - WHERE is_siteroot = 1 - AND deleted = 0'; - $rootPageSiteList = DatabaseConnection::getCol($query); - - if (count($rootPageSiteList) >= 2) { - $isMultiSite = true; - } + $domain = '.' . $this->getApplication()->getConfigValue('config', 'domain_dev'); + $domainLength = strlen($domain); // ################## - // Disable all other domains + // Fix domains // ################## $query = 'UPDATE ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - SET hidden = 1'; + SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($domain) . ') + WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($domain); DatabaseConnection::exec($query); + // ################## + // Show all domains + // ################## + $query = 'SELECT domainName + FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain + WHERE hidden = 0'; + $domainList = DatabaseConnection::getCol($query); - // Get development domains from config - $tldList = (array)$this->getApplication()->getConfigValue('config', 'domain_dev', array()); - - foreach ($tldList as $tld) { - $fullDomain = $domain . '.' . $tld; - - // ############## - // Loop through root pages - // ############## - foreach ($rootPageSiteList as $rootPageUid) { - $rootPageDomain = $fullDomain; - - // Add rootpage id to domain if TYPO3 instance is multi page - // eg. 123.dev.foobar.dev - if ($isMultiSite) { - $rootPageDomain = $rootPageUid . '.' . $rootPageDomain; - } + $this->output->writeln('Domain list of "' . $database . '":'); - // Check if we have already an entry - $query = 'SELECT uid - FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - WHERE pid = ' . (int)$rootPageUid . ' - AND domainName = ' . DatabaseConnection::quote($rootPageDomain); - $sysDomainId = DatabaseConnection::getOne($query); - - // Add/Update domain - $query = 'INSERT INTO ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - (uid, pid, tstamp, crdate, cruser_id, hidden, domainName, sorting, forced) - VALUES ( - ' . (int)$sysDomainId . ', - ' . (int)$rootPageUid . ', - ' . time() . ', - ' . time() . ', - 1, - 0, - ' . DatabaseConnection::quote($rootPageDomain) . ', - 1, - 1 - ) ON DUPLICATE KEY UPDATE - pid = VALUES(pid), - hidden = VALUES(hidden), - domainName = VALUES(domainName), - sorting = VALUES(sorting), - forced = VALUES(forced)'; - DatabaseConnection::exec($query); - - if ($sysDomainId) { - $this->output->writeln('Domain "' . $rootPageDomain . '" updated to "' . $database . '"'); - } else { - $this->output->writeln('Domain "' . $rootPageDomain . '" added to "' . $database . '"'); - } - } + foreach ($domainList as $domain) { + $this->output->writeln(' '. $domain . ''); } + $this->output->writeln(''); } } diff --git a/src/config.ini b/src/config.ini index fd34450..ba13a1b 100644 --- a/src/config.ini +++ b/src/config.ini @@ -1,7 +1,7 @@ [config] ssh_conf_path = "/opt/conf/ssh" www_base_path = "/var/www" -domain_dev[] = "dev" +domain_dev = "vm" self_update_github = "https://api.github.com/repos/mblaschke/vagrant-clitools/releases" [db] From 2006cdd6a366133e30a363f35627c2bb087fc176 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:27:03 +0200 Subject: [PATCH 076/214] Refactored sync --- .../Console/Command/Sync/AbstractCommand.php | 31 ++++++++---- .../Console/Command/Sync/BackupCommand.php | 12 +++-- .../Console/Command/Sync/RestoreCommand.php | 12 +++-- .../Console/Command/Sync/ServerCommand.php | 48 +++++++++++++------ 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 18009cc..49c760d 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -130,22 +130,17 @@ protected function validateConfiguration() { // Rsync (required) // ################## - // Check for rsync directive - if (empty($this->config['rsync'])) { - $output->writeln('No rsync configuration found'); - $ret = false; - } - // Check if rsync target exists - if (empty($this->config['rsync']['path'])) { + if (!$this->getRsyncPathFromConfig()) { $output->writeln('No rsync path configuration found'); $ret = false; + } else { + $output->writeln('Using rsync path "' . $this->getRsyncPathFromConfig() . '"'); } // Check if there are any rsync directories if (empty($this->config['rsync']['directory'])) { - $output->writeln('No rsync directory configuration found'); - $ret = false; + $output->writeln('No rsync directory configuration found, filesync disabled'); } // ################## @@ -231,6 +226,24 @@ protected function createRsyncCommand($source, $target, array $filelist = null, return $command; } + /** + * Get rsync path from configuration + * + * @return boolean|string + */ + protected function getRsyncPathFromConfig() { + $ret = false; + if (!empty($this->config['rsync']['path'])) { + // Use path from rsync + $ret = $this->config['rsync']['path']; + } elseif(!empty($this->config['ssh']['hostname']) && !empty($this->config['ssh']['path'])) { + // Build path from ssh configuration + $ret = $this->config['ssh']['hostname'] . ':' . $this->config['ssh']['path']; + } + + return $ret; + } + /** * Add file (pattern) list to rsync command * diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 7de2715..0ca5595 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -37,10 +37,12 @@ protected function runTask() { // ################## // Backup dirs // ################## - $source = $this->workingPath; - $target = $this->config['rsync']['path'] . self::PATH_DATA; - $command = $this->createShareRsyncCommand($source, $target, true); - $command->executeInteractive(); + if (!empty($this->config['rsync']['directory'])) { + $source = $this->workingPath; + $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); + } // ################## // Backup databases @@ -62,7 +64,7 @@ protected function runTask() { // Backup mysql dump // ################## $source = $this->tempDir; - $target = $this->config['rsync']['path'] . self::PATH_DUMP; + $target = $this->getRsyncPathFromConfig() . self::PATH_DUMP; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 7bba379..8c298bd 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -37,15 +37,17 @@ protected function runTask() { // ################## // Restore dirs // ################## - $source = $this->config['rsync']['path'] . self::PATH_DUMP; - $target = $this->workingPath; - $command = $this->createShareRsyncCommand($source, $target, true); - $command->executeInteractive(); + if (!empty($this->config['rsync']['directory'])) { + $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; + $target = $this->workingPath; + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); + } // ################## // Restore mysql dump // ################## - $source = $this->config['rsync']['path'] . self::PATH_DUMP; + $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; $target = $this->tempDir; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 1dddd37..513b1bd 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -25,6 +25,7 @@ use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; +use CliTools\Database\DatabaseConnection; use Symfony\Component\Console\Input\InputArgument; class ServerCommand extends AbstractSyncCommand { @@ -33,7 +34,7 @@ class ServerCommand extends AbstractSyncCommand { * Server configuration name * @var string */ - protected $serverName; + protected $contextName; /** * Configure command @@ -43,35 +44,34 @@ protected function configure() { ->setName('sync:server') ->setDescription('Sync files and database from server') ->addArgument( - 'server', + 'context', InputArgument::REQUIRED, 'Configuration name for server' ); } - /** * Read and validate configuration */ protected function readConfiguration() { parent::readConfiguration(); - $this->serverName = $this->input->getArgument('server'); + $this->contextName = $this->input->getArgument('context'); - if (empty($this->serverName) || $this->serverName === '_' || empty($this->config[$this->serverName])) { - throw new \RuntimeException('No valid configuration found for server "' . $this->serverName . '"'); + if (empty($this->contextName) || $this->contextName === '_' || empty($this->config[$this->contextName])) { + throw new \RuntimeException('No valid configuration found for context "' . $this->contextName . '"'); } // Use server specific configuration - $this->output->writeln('Syncing from "' . $this->serverName . '" server'); + $this->output->writeln('Syncing from "' . $this->contextName . '" server'); $fullConfig = $this->config; if (!empty($fullConfig['_'])) { // Merge global config with specific config - $this->config = array_replace_recursive($fullConfig['_'], $this->config[$this->serverName]); + $this->config = array_replace_recursive($fullConfig['_'], $this->config[$this->contextName]); } else { - $this->config = $this->config[$this->serverName]; + $this->config = $this->config[$this->contextName]; } } @@ -79,8 +79,13 @@ protected function readConfiguration() { * Backup task */ protected function runTask() { + // Check database connection + if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { + DatabaseConnection::ping(); + } + // Sync files with rsync to local storage - if (!empty($this->config['rsync'])) { + if (!empty($this->config['rsync']) && !empty($this->config['rsync']['directory'])) { $this->runTaskRsync(); } @@ -97,7 +102,7 @@ protected function runTaskRsync() { // ################## // Restore dirs // ################## - $source = $this->config['rsync']['path']; + $source = $this->getRsyncPathFromConfig(); $target = $this->workingPath; $command = $this->createRsyncCommand($source, $target); @@ -220,7 +225,7 @@ protected function createMySqlDumpCommand($database = null) { $command->addArgumentRaw($this->config['mysqldump']['option']); } - // Add pipe (bzip2 compressed transfer via ssh) + // Add pipe compressor (bzip2 compressed transfer via ssh) $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); if ($database !== null) { @@ -302,17 +307,25 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat $tableList = $tableListDumper->execute()->getOutput(); // Filter table list - $tableList = FilterUtility::mysqlTableFilter($tableList, $filterList); + $ignoredTableList = FilterUtility::mysqlIgnoredTableFilter($tableList, $filterList, $database); // Dump only structure $commandStructure = clone $command; - $commandStructure->addArgument('--no-data'); + $commandStructure + ->addArgument('--no-data') + ->clearPipes(); // Dump only data (only filtered tables) $commandData = clone $command; $commandData ->addArgument('--no-create-info') - ->addArgumentList($tableList); + ->clearPipes(); + + if (!empty($ignoredTableList)) { + $commandData->addArgumentTemplateMultiple('--ignore-table=%s', $ignoredTableList); + } + + $commandPipeList = $command->getPipeList(); // Combine both commands to one $command = new OutputCombineCommandBuilder(); @@ -320,6 +333,11 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat ->addCommandForCombinedOutput($commandStructure) ->addCommandForCombinedOutput($commandData); + // Readd compression pipe + if (!empty($commandPipeList)) { + $command->setPipeList($commandPipeList); + } + return $command; } From 66702f80389766624261b5ff84286e7ca2bfd616 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 20:27:25 +0200 Subject: [PATCH 077/214] Refactored mysql:list and mysql:backup --- .../CliTools/Console/Command/Mysql/BackupCommand.php | 12 +++++++----- .../CliTools/Console/Command/Mysql/ListCommand.php | 10 +--------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index d33ac5f..0dc41d6 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -146,8 +146,8 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat $this->output->writeln('Using filter "' . $filter . '"'); // Get filtered tables - $tableList = DatabaseConnection::tableList($database); - $tableList = FilterUtility::mysqlTableFilter($tableList, $filterList); + $tableList = DatabaseConnection::tableList($database); + $ignoredTableList = FilterUtility::mysqlIgnoredTableFilter($tableList, $filterList, $database); // Dump only structure $commandStructure = clone $command; @@ -155,9 +155,11 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat // Dump only data (only filtered tables) $commandData = clone $command; - $commandData - ->addArgument('--no-create-info') - ->addArgumentList($tableList); + $commandData->addArgument('--no-create-info'); + + if (!empty($ignoredTableList)) { + $commandData->addArgumentTemplateMultiple('--ignore-table=%s', $ignoredTableList); + } // Combine both commands to one $command = new \CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder(); diff --git a/src/app/CliTools/Console/Command/Mysql/ListCommand.php b/src/app/CliTools/Console/Command/Mysql/ListCommand.php index f04351f..043cba1 100644 --- a/src/app/CliTools/Console/Command/Mysql/ListCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ListCommand.php @@ -72,10 +72,7 @@ protected function configure() { public function execute(InputInterface $input, OutputInterface $output) { // Get list of databases - $query = 'SELECT SCHEMA_NAME - FROM information_schema.SCHEMATA'; - $databaseList = DatabaseConnection::getCol($query); - + $databaseList = DatabaseConnection::databaseList(); if (!empty($databaseList)) { // ######################## @@ -84,11 +81,6 @@ public function execute(InputInterface $input, OutputInterface $output) { $databaseRowList = array(); foreach ($databaseList as $database) { - // Skip internal mysql databases - if (in_array(strtolower($database), array('mysql', 'information_schema', 'performance_schema'))) { - continue; - } - // Get all tables $query = 'SELECT COUNT(*) AS count FROM information_schema.tables From 3f405569612be94bca101cb280eacd884ba1afb5 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 21:11:34 +0200 Subject: [PATCH 078/214] Cleanup --- .../Console/Command/Apache/RestartCommand.php | 3 ++- .../Console/Command/Apache/TraceCommand.php | 3 ++- .../Console/Command/Common/MakeCommand.php | 5 ++-- .../Command/Common/SelfUpdateCommand.php | 3 ++- .../Console/Command/Docker/CliCommand.php | 5 ++-- .../Console/Command/Docker/ComposeCommand.php | 5 ++-- .../Console/Command/Docker/CreateCommand.php | 3 ++- .../Console/Command/Docker/ExecCommand.php | 3 ++- .../Console/Command/Docker/IftopCommand.php | 5 ++-- .../Console/Command/Docker/MysqlCommand.php | 3 ++- .../Console/Command/Docker/RootCommand.php | 3 ++- .../Console/Command/Docker/ShellCommand.php | 3 ++- .../Console/Command/Docker/SniffCommand.php | 3 ++- .../Console/Command/Docker/UpCommand.php | 3 ++- .../Console/Command/Docker/UpgradeCommand.php | 3 ++- .../Console/Command/Log/ApacheCommand.php | 3 ++- .../Console/Command/Log/DebugCommand.php | 3 ++- .../Console/Command/Log/MailCommand.php | 3 ++- .../Console/Command/Log/PhpCommand.php | 3 ++- .../Console/Command/Mysql/BackupCommand.php | 14 +++++----- .../Console/Command/Mysql/ClearCommand.php | 3 ++- .../Command/Mysql/ConnectionsCommand.php | 3 ++- .../Console/Command/Mysql/ConvertCommand.php | 3 ++- .../Console/Command/Mysql/DebugCommand.php | 3 ++- .../Console/Command/Mysql/DropCommand.php | 3 ++- .../Console/Command/Mysql/ListCommand.php | 3 ++- .../Console/Command/Mysql/RestartCommand.php | 3 ++- .../Console/Command/Mysql/RestoreCommand.php | 3 ++- .../Console/Command/Mysql/SlowLogCommand.php | 27 ++++++++++--------- .../Console/Command/Php/ComposerCommand.php | 5 ++-- .../Console/Command/Php/RestartCommand.php | 3 ++- .../Console/Command/Php/TraceCommand.php | 3 ++- .../Console/Command/Samba/RestartCommand.php | 3 ++- .../Console/Command/Sync/BackupCommand.php | 5 ++-- .../Console/Command/Sync/InitCommand.php | 5 ++-- .../Console/Command/Sync/RestoreCommand.php | 5 ++-- .../Console/Command/System/BannerCommand.php | 3 ++- .../Command/System/CrontaskCommand.php | 3 ++- .../Console/Command/System/EnvCommand.php | 3 ++- .../Command/System/OpenFilesCommand.php | 3 ++- .../Console/Command/System/RebootCommand.php | 3 ++- .../Command/System/ShutdownCommand.php | 3 ++- .../Console/Command/System/StartupCommand.php | 3 ++- .../Console/Command/System/SwapCommand.php | 3 ++- .../Console/Command/System/UpdateCommand.php | 3 ++- .../Console/Command/System/VersionCommand.php | 3 ++- .../Console/Command/TYPO3/BeUserCommand.php | 3 ++- .../Console/Command/TYPO3/CleanupCommand.php | 3 ++- .../Command/TYPO3/ClearCacheCommand.php | 3 ++- .../Command/TYPO3/InstallerCommand.php | 3 ++- .../Console/Command/TYPO3/ListCommand.php | 3 ++- .../Command/TYPO3/SchedulerCommand.php | 5 ++-- .../Command/User/RebuildSshConfigCommand.php | 3 ++- 53 files changed, 133 insertions(+), 79 deletions(-) diff --git a/src/app/CliTools/Console/Command/Apache/RestartCommand.php b/src/app/CliTools/Console/Command/Apache/RestartCommand.php index 5b7231e..64fe214 100644 --- a/src/app/CliTools/Console/Command/Apache/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Apache/RestartCommand.php @@ -30,7 +30,8 @@ class RestartCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('apache:restart') + $this + ->setName('apache:restart') ->setDescription('Restart Apache'); } diff --git a/src/app/CliTools/Console/Command/Apache/TraceCommand.php b/src/app/CliTools/Console/Command/Apache/TraceCommand.php index 89fbd9f..2330425 100644 --- a/src/app/CliTools/Console/Command/Apache/TraceCommand.php +++ b/src/app/CliTools/Console/Command/Apache/TraceCommand.php @@ -33,7 +33,8 @@ class TraceCommand extends \CliTools\Console\Command\AbstractTraceCommand { * Configure command */ protected function configure() { - $this->setName('apache:trace') + $this + ->setName('apache:trace') ->setDescription('Debug Apache processes with strace'); parent::configure(); diff --git a/src/app/CliTools/Console/Command/Common/MakeCommand.php b/src/app/CliTools/Console/Command/Common/MakeCommand.php index 385c9c7..eb1456b 100644 --- a/src/app/CliTools/Console/Command/Common/MakeCommand.php +++ b/src/app/CliTools/Console/Command/Common/MakeCommand.php @@ -32,8 +32,9 @@ class MakeCommand extends \CliTools\Console\Command\AbstractCommand implements \ * Configure command */ protected function configure() { - $this->setName('make') - ->setDescription('Search Makefile updir and start makefile'); + $this + ->setName('make') + ->setDescription('Search Makefile updir and start makefile'); } /** diff --git a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php index 388c814..a8b30b2 100644 --- a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php +++ b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php @@ -31,7 +31,8 @@ class SelfUpdateCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('self-update') + $this + ->setName('self-update') ->setAliases(array('selfupdate')) ->setDescription('Self update of CliTools Command') ->addOption( diff --git a/src/app/CliTools/Console/Command/Docker/CliCommand.php b/src/app/CliTools/Console/Command/Docker/CliCommand.php index d57ce6d..41e1fb1 100644 --- a/src/app/CliTools/Console/Command/Docker/CliCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CliCommand.php @@ -30,8 +30,9 @@ class CliCommand extends AbstractCommand implements \CliTools\Console\Filter\Any * Configure command */ protected function configure() { - $this->setName('docker:cli') - ->setDescription('Run cli command in docker container (defined by CLI_SCRIPT and CLI_USER as docker environment variable)'); + $this + ->setName('docker:cli') + ->setDescription('Run cli command in docker container (defined by CLI_SCRIPT and CLI_USER as docker environment variable)'); } /** diff --git a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php index ebd09e5..4fe28a6 100644 --- a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php @@ -30,8 +30,9 @@ class ComposeCommand extends AbstractCommand implements \CliTools\Console\Filter * Configure command */ protected function configure() { - $this->setName('docker:compose') - ->setDescription('Run general docker-compose command in docker container'); + $this + ->setName('docker:compose') + ->setDescription('Run general docker-compose command in docker container'); } /** diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index 6eb0333..a98f2af 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -34,7 +34,8 @@ class CreateCommand extends AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:create') + $this + ->setName('docker:create') ->setDescription('Create new docker boilerplate') ->addArgument( 'path', diff --git a/src/app/CliTools/Console/Command/Docker/ExecCommand.php b/src/app/CliTools/Console/Command/Docker/ExecCommand.php index 831f32c..62bd75d 100644 --- a/src/app/CliTools/Console/Command/Docker/ExecCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ExecCommand.php @@ -30,7 +30,8 @@ class ExecCommand extends AbstractCommand implements \CliTools\Console\Filter\An * Configure command */ protected function configure() { - $this->setName('docker:exec') + $this + ->setName('docker:exec') ->setDescription('Run defined command in docker container'); } diff --git a/src/app/CliTools/Console/Command/Docker/IftopCommand.php b/src/app/CliTools/Console/Command/Docker/IftopCommand.php index 550fdb5..29c1ab6 100644 --- a/src/app/CliTools/Console/Command/Docker/IftopCommand.php +++ b/src/app/CliTools/Console/Command/Docker/IftopCommand.php @@ -30,8 +30,9 @@ class IftopCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:iftop') - ->setDescription('Exec iftop for Docker'); + $this + ->setName('docker:iftop') + ->setDescription('Exec iftop for Docker'); } /** diff --git a/src/app/CliTools/Console/Command/Docker/MysqlCommand.php b/src/app/CliTools/Console/Command/Docker/MysqlCommand.php index c8bd82c..408fbf4 100644 --- a/src/app/CliTools/Console/Command/Docker/MysqlCommand.php +++ b/src/app/CliTools/Console/Command/Docker/MysqlCommand.php @@ -30,7 +30,8 @@ class MysqlCommand extends AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:mysql') + $this + ->setName('docker:mysql') ->setDescription('Enter mysql in docker container'); } diff --git a/src/app/CliTools/Console/Command/Docker/RootCommand.php b/src/app/CliTools/Console/Command/Docker/RootCommand.php index 04805a1..b2a1972 100644 --- a/src/app/CliTools/Console/Command/Docker/RootCommand.php +++ b/src/app/CliTools/Console/Command/Docker/RootCommand.php @@ -31,7 +31,8 @@ class RootCommand extends AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:root') + $this + ->setName('docker:root') ->setDescription('Enter shell as root in docker container') ->addArgument( 'container', diff --git a/src/app/CliTools/Console/Command/Docker/ShellCommand.php b/src/app/CliTools/Console/Command/Docker/ShellCommand.php index 1820f1b..be71d40 100644 --- a/src/app/CliTools/Console/Command/Docker/ShellCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ShellCommand.php @@ -32,7 +32,8 @@ class ShellCommand extends AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:shell') + $this + ->setName('docker:shell') ->setDescription('Enter shell in docker container') ->addArgument( 'container', diff --git a/src/app/CliTools/Console/Command/Docker/SniffCommand.php b/src/app/CliTools/Console/Command/Docker/SniffCommand.php index 4be7893..ae32022 100644 --- a/src/app/CliTools/Console/Command/Docker/SniffCommand.php +++ b/src/app/CliTools/Console/Command/Docker/SniffCommand.php @@ -32,7 +32,8 @@ class SniffCommand extends AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:sniff') + $this + ->setName('docker:sniff') ->setDescription('Start network sniffing with docker') ->addArgument( 'protocol', diff --git a/src/app/CliTools/Console/Command/Docker/UpCommand.php b/src/app/CliTools/Console/Command/Docker/UpCommand.php index 969c67d..1fb5609 100644 --- a/src/app/CliTools/Console/Command/Docker/UpCommand.php +++ b/src/app/CliTools/Console/Command/Docker/UpCommand.php @@ -30,7 +30,8 @@ class UpCommand extends AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:up') + $this + ->setName('docker:up') ->setDescription('Start docker container (with fast switching)'); } diff --git a/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php b/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php index f514204..48d462d 100644 --- a/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php +++ b/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php @@ -30,7 +30,8 @@ class UpgradeCommand extends AbstractCommand { * Configure command */ protected function configure() { - $this->setName('docker:upgrade') + $this + ->setName('docker:upgrade') ->setDescription('Upgrade docker version'); } diff --git a/src/app/CliTools/Console/Command/Log/ApacheCommand.php b/src/app/CliTools/Console/Command/Log/ApacheCommand.php index cf4afa8..383e2cb 100644 --- a/src/app/CliTools/Console/Command/Log/ApacheCommand.php +++ b/src/app/CliTools/Console/Command/Log/ApacheCommand.php @@ -30,7 +30,8 @@ class ApacheCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('log:apache') + $this + ->setName('log:apache') ->setAliases(array('apache:log')) ->setDescription('Show up apache log') ->addArgument( diff --git a/src/app/CliTools/Console/Command/Log/DebugCommand.php b/src/app/CliTools/Console/Command/Log/DebugCommand.php index 20f4aeb..796bd26 100644 --- a/src/app/CliTools/Console/Command/Log/DebugCommand.php +++ b/src/app/CliTools/Console/Command/Log/DebugCommand.php @@ -30,7 +30,8 @@ class DebugCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('log:debug') + $this + ->setName('log:debug') ->setAliases(array('debug')) ->setDescription('Show up debugging log') ->addArgument( diff --git a/src/app/CliTools/Console/Command/Log/MailCommand.php b/src/app/CliTools/Console/Command/Log/MailCommand.php index 31b699f..903bde1 100644 --- a/src/app/CliTools/Console/Command/Log/MailCommand.php +++ b/src/app/CliTools/Console/Command/Log/MailCommand.php @@ -30,7 +30,8 @@ class MailCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('log:mail') + $this + ->setName('log:mail') ->setDescription('Show up mail log') ->addArgument( 'grep', diff --git a/src/app/CliTools/Console/Command/Log/PhpCommand.php b/src/app/CliTools/Console/Command/Log/PhpCommand.php index 48536c3..bf13fca 100644 --- a/src/app/CliTools/Console/Command/Log/PhpCommand.php +++ b/src/app/CliTools/Console/Command/Log/PhpCommand.php @@ -30,7 +30,8 @@ class PhpCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('log:php') + $this + ->setName('log:php') ->setAliases(array('php:log')) ->setDescription('Show up php log') ->addArgument( diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index 0dc41d6..b1036a9 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -35,18 +35,20 @@ class BackupCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:backup') - ->setDescription('Backup database') - ->addArgument( + $this + ->setName('mysql:backup') + ->setDescription('Backup database') + ->addArgument( 'db', InputArgument::REQUIRED, 'Database name' - ) - ->addArgument( + ) + ->addArgument( 'file', InputArgument::REQUIRED, 'File (mysql dump)' - )->addOption( + ) + ->addOption( 'filter', 'f', InputOption::VALUE_REQUIRED, diff --git a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php index 3d24497..b6e2a18 100644 --- a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php @@ -31,7 +31,8 @@ class ClearCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:clear') + $this + ->setName('mysql:clear') ->setAliases(array('mysql:create')) ->setDescription('Clear (recreate) database') ->addArgument( diff --git a/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php b/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php index af13c23..eccc41a 100644 --- a/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php @@ -31,7 +31,8 @@ class ConnectionsCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:connections') + $this + ->setName('mysql:connections') ->setDescription('List current connections'); } diff --git a/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php index fafbd02..c9b5932 100644 --- a/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php @@ -32,7 +32,8 @@ class ConvertCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:convert') + $this + ->setName('mysql:convert') ->setDescription('Convert charset/collation of a database') ->addArgument( 'database', diff --git a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php index edb162a..a6cc1a7 100644 --- a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php @@ -31,7 +31,8 @@ class DebugCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:debug') + $this + ->setName('mysql:debug') ->setAliases(array('mysql:querylog')) ->setDescription('Debug mysql connections') ->addArgument( diff --git a/src/app/CliTools/Console/Command/Mysql/DropCommand.php b/src/app/CliTools/Console/Command/Mysql/DropCommand.php index d7f6af8..4d31d48 100644 --- a/src/app/CliTools/Console/Command/Mysql/DropCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/DropCommand.php @@ -31,7 +31,8 @@ class DropCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:drop') + $this + ->setName('mysql:drop') ->setDescription('Drop database') ->addArgument( 'db', diff --git a/src/app/CliTools/Console/Command/Mysql/ListCommand.php b/src/app/CliTools/Console/Command/Mysql/ListCommand.php index 043cba1..8620d34 100644 --- a/src/app/CliTools/Console/Command/Mysql/ListCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ListCommand.php @@ -34,7 +34,8 @@ class ListCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:list') + $this + ->setName('mysql:list') ->setDescription('List all databases') ->addOption( 'sort-name', null, diff --git a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php index c530a0e..f353824 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php @@ -30,7 +30,8 @@ class RestartCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:restart') + $this + ->setName('mysql:restart') ->setDescription('Restart MySQL'); } diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index d7b2ef4..a43c057 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -33,7 +33,8 @@ class RestoreCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:restore') + $this + ->setName('mysql:restore') ->setDescription('Restore database') ->addArgument( 'db', diff --git a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php index 400b26b..02a9926 100644 --- a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php @@ -32,25 +32,26 @@ class SlowLogCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('mysql:slowlog') - ->setDescription('Enable and show slow query log') - ->addArgument( - 'grep', - InputArgument::OPTIONAL, - 'Grep' - ) + $this + ->setName('mysql:slowlog') + ->setDescription('Enable and show slow query log') + ->addArgument( + 'grep', + InputArgument::OPTIONAL, + 'Grep' + ) ->addOption( 'time', 't', InputOption::VALUE_REQUIRED, 'Slow query time (default 1 second)' ) - ->addOption( - 'no-index', - 'i', - InputOption::VALUE_NONE, - 'Enable log queries without indexes log' - ); + ->addOption( + 'no-index', + 'i', + InputOption::VALUE_NONE, + 'Enable log queries without indexes log' + ); } /** diff --git a/src/app/CliTools/Console/Command/Php/ComposerCommand.php b/src/app/CliTools/Console/Command/Php/ComposerCommand.php index b585843..e6ee298 100644 --- a/src/app/CliTools/Console/Command/Php/ComposerCommand.php +++ b/src/app/CliTools/Console/Command/Php/ComposerCommand.php @@ -32,8 +32,9 @@ class ComposerCommand extends \CliTools\Console\Command\AbstractCommand implemen * Configure command */ protected function configure() { - $this->setName('php:composer') - ->setDescription('Search composer.json updir and start composer'); + $this + ->setName('php:composer') + ->setDescription('Search composer.json updir and start composer'); } /** diff --git a/src/app/CliTools/Console/Command/Php/RestartCommand.php b/src/app/CliTools/Console/Command/Php/RestartCommand.php index 55484e4..93e0611 100644 --- a/src/app/CliTools/Console/Command/Php/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Php/RestartCommand.php @@ -30,7 +30,8 @@ class RestartCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('php:restart') + $this + ->setName('php:restart') ->setDescription('Restart PHP FPM'); } diff --git a/src/app/CliTools/Console/Command/Php/TraceCommand.php b/src/app/CliTools/Console/Command/Php/TraceCommand.php index d4477e1..e5b0b92 100644 --- a/src/app/CliTools/Console/Command/Php/TraceCommand.php +++ b/src/app/CliTools/Console/Command/Php/TraceCommand.php @@ -33,7 +33,8 @@ class TraceCommand extends \CliTools\Console\Command\AbstractTraceCommand { * Configure command */ protected function configure() { - $this->setName('php:trace') + $this + ->setName('php:trace') ->setDescription('Debug PHP processes with strace'); parent::configure(); } diff --git a/src/app/CliTools/Console/Command/Samba/RestartCommand.php b/src/app/CliTools/Console/Command/Samba/RestartCommand.php index 0c64e59..059b90e 100644 --- a/src/app/CliTools/Console/Command/Samba/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Samba/RestartCommand.php @@ -30,7 +30,8 @@ class RestartCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('samba:restart') + $this + ->setName('samba:restart') ->setDescription('Restart Samba SMB daemon'); } diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 0ca5595..6f6e986 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -26,8 +26,9 @@ class BackupCommand extends AbstractShareCommand { * Configure command */ protected function configure() { - $this->setName('sync:backup') - ->setDescription('Backup project files'); + $this + ->setName('sync:backup') + ->setDescription('Backup project files'); } /** diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 557ba90..59e0ec6 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -30,8 +30,9 @@ class InitCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('sync:init') - ->setDescription('Create example clisync.yml'); + $this + ->setName('sync:init') + ->setDescription('Create example clisync.yml'); } /** diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 8c298bd..9000a81 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -26,8 +26,9 @@ class RestoreCommand extends AbstractShareCommand { * Configure command */ protected function configure() { - $this->setName('sync:restore') - ->setDescription('Restore project files'); + $this + ->setName('sync:restore') + ->setDescription('Restore project files'); } /** diff --git a/src/app/CliTools/Console/Command/System/BannerCommand.php b/src/app/CliTools/Console/Command/System/BannerCommand.php index bdf498c..93f7027 100644 --- a/src/app/CliTools/Console/Command/System/BannerCommand.php +++ b/src/app/CliTools/Console/Command/System/BannerCommand.php @@ -31,7 +31,8 @@ class BannerCommand extends \CliTools\Console\Command\AbstractCommand implements * Configure command */ protected function configure() { - $this->setName('system:banner') + $this + ->setName('system:banner') ->setDescription('Banner generator for /etc/issue'); } diff --git a/src/app/CliTools/Console/Command/System/CrontaskCommand.php b/src/app/CliTools/Console/Command/System/CrontaskCommand.php index 7c1e7fa..69e6c35 100644 --- a/src/app/CliTools/Console/Command/System/CrontaskCommand.php +++ b/src/app/CliTools/Console/Command/System/CrontaskCommand.php @@ -38,7 +38,8 @@ class CrontaskCommand extends \CliTools\Console\Command\AbstractCommand implemen * Configure command */ protected function configure() { - $this->setName('system:crontask') + $this + ->setName('system:crontask') ->setDescription('System cron task'); } diff --git a/src/app/CliTools/Console/Command/System/EnvCommand.php b/src/app/CliTools/Console/Command/System/EnvCommand.php index cc988dd..af76e5b 100644 --- a/src/app/CliTools/Console/Command/System/EnvCommand.php +++ b/src/app/CliTools/Console/Command/System/EnvCommand.php @@ -30,7 +30,8 @@ class EnvCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('system:env') + $this + ->setName('system:env') ->setDescription('List environment variables'); } diff --git a/src/app/CliTools/Console/Command/System/OpenFilesCommand.php b/src/app/CliTools/Console/Command/System/OpenFilesCommand.php index d09a091..6af3ef0 100644 --- a/src/app/CliTools/Console/Command/System/OpenFilesCommand.php +++ b/src/app/CliTools/Console/Command/System/OpenFilesCommand.php @@ -33,7 +33,8 @@ class OpenFilesCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('system:openfiles') + $this + ->setName('system:openfiles') ->setDescription('List swap usage'); } diff --git a/src/app/CliTools/Console/Command/System/RebootCommand.php b/src/app/CliTools/Console/Command/System/RebootCommand.php index e1b474e..5a1c692 100644 --- a/src/app/CliTools/Console/Command/System/RebootCommand.php +++ b/src/app/CliTools/Console/Command/System/RebootCommand.php @@ -30,7 +30,8 @@ class RebootCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('system:reboot') + $this + ->setName('system:reboot') ->setAliases(array('reboot')) ->setDescription('Reboot system'); } diff --git a/src/app/CliTools/Console/Command/System/ShutdownCommand.php b/src/app/CliTools/Console/Command/System/ShutdownCommand.php index 1e075b6..3eabf33 100644 --- a/src/app/CliTools/Console/Command/System/ShutdownCommand.php +++ b/src/app/CliTools/Console/Command/System/ShutdownCommand.php @@ -30,7 +30,8 @@ class ShutdownCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('system:shutdown') + $this + ->setName('system:shutdown') ->setAliases(array('shutdown')) ->setDescription('Shutdown system'); } diff --git a/src/app/CliTools/Console/Command/System/StartupCommand.php b/src/app/CliTools/Console/Command/System/StartupCommand.php index 9d9b500..367b81b 100644 --- a/src/app/CliTools/Console/Command/System/StartupCommand.php +++ b/src/app/CliTools/Console/Command/System/StartupCommand.php @@ -32,7 +32,8 @@ class StartupCommand extends \CliTools\Console\Command\AbstractCommand implement * Configure command */ protected function configure() { - $this->setName('system:startup') + $this + ->setName('system:startup') ->setDescription('System startup task'); } diff --git a/src/app/CliTools/Console/Command/System/SwapCommand.php b/src/app/CliTools/Console/Command/System/SwapCommand.php index baf24ad..d0db100 100644 --- a/src/app/CliTools/Console/Command/System/SwapCommand.php +++ b/src/app/CliTools/Console/Command/System/SwapCommand.php @@ -33,7 +33,8 @@ class SwapCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('system:swap') + $this + ->setName('system:swap') ->setDescription('List swap usage'); } diff --git a/src/app/CliTools/Console/Command/System/UpdateCommand.php b/src/app/CliTools/Console/Command/System/UpdateCommand.php index a1e6fe1..04a683a 100644 --- a/src/app/CliTools/Console/Command/System/UpdateCommand.php +++ b/src/app/CliTools/Console/Command/System/UpdateCommand.php @@ -32,7 +32,8 @@ class UpdateCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('system:update') + $this + ->setName('system:update') ->setAliases(array('update')) ->setDescription('Update system'); } diff --git a/src/app/CliTools/Console/Command/System/VersionCommand.php b/src/app/CliTools/Console/Command/System/VersionCommand.php index 1f06ff9..d795501 100644 --- a/src/app/CliTools/Console/Command/System/VersionCommand.php +++ b/src/app/CliTools/Console/Command/System/VersionCommand.php @@ -33,7 +33,8 @@ class VersionCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('system:version') + $this + ->setName('system:version') ->setDescription('List common version'); } diff --git a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php index a36ee13..4ab87a6 100644 --- a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php @@ -33,7 +33,8 @@ class BeUserCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('typo3:beuser') + $this + ->setName('typo3:beuser') ->setDescription('Add backend admin user to database') ->addArgument( 'database', diff --git a/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php b/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php index 9dc95d9..c3ed9fc 100644 --- a/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php @@ -31,7 +31,8 @@ class CleanupCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('typo3:cleanup') + $this + ->setName('typo3:cleanup') ->setDescription('Cleanup caches, logs and indexed search') ->addArgument( 'db', diff --git a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php index 3ab8468..79a58a6 100644 --- a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php @@ -32,7 +32,8 @@ class ClearCacheCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('typo3:clearcache') + $this + ->setName('typo3:clearcache') ->setDescription('Clear cache on all (or one specific) TYPO3 instances') ->addArgument( 'path', diff --git a/src/app/CliTools/Console/Command/TYPO3/InstallerCommand.php b/src/app/CliTools/Console/Command/TYPO3/InstallerCommand.php index 3827dd7..c827bfd 100644 --- a/src/app/CliTools/Console/Command/TYPO3/InstallerCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/InstallerCommand.php @@ -32,7 +32,8 @@ class InstallerCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('typo3:installer') + $this + ->setName('typo3:installer') ->setDescription('Enable installer on all (or one specific) TYPO3 instances') ->addArgument( 'path', diff --git a/src/app/CliTools/Console/Command/TYPO3/ListCommand.php b/src/app/CliTools/Console/Command/TYPO3/ListCommand.php index d77a071..9b141aa 100644 --- a/src/app/CliTools/Console/Command/TYPO3/ListCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/ListCommand.php @@ -32,7 +32,8 @@ class ListCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('typo3:list') + $this + ->setName('typo3:list') ->setDescription('List all TYPO3 instances') ->addArgument( 'path', diff --git a/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php b/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php index 3fa71a7..f4e7277 100644 --- a/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php @@ -32,13 +32,14 @@ class SchedulerCommand extends \CliTools\Console\Command\AbstractCommand { * Configure command */ protected function configure() { - $this->setName('typo3:scheduler') + $this + ->setName('typo3:scheduler') ->setDescription('Run scheduler on all (or one specific) TYPO3 instances') ->addArgument( 'path', InputArgument::OPTIONAL, 'Path to TYPO3 instance' - ); +); } /** diff --git a/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php b/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php index 8e9fb84..36cc023 100644 --- a/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php +++ b/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php @@ -29,7 +29,8 @@ class RebuildSshConfigCommand extends \CliTools\Console\Command\AbstractCommand * Configure command */ protected function configure() { - $this->setName('user:rebuildsshconfig') + $this + ->setName('user:rebuildsshconfig') ->setDescription('Rebuild SSH Config for current user'); } From cdd723345d1f52bed8fa9a0149b51ef2ae411d76 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 22:04:44 +0200 Subject: [PATCH 079/214] Added tableExists --- src/app/CliTools/Database/DatabaseConnection.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/app/CliTools/Database/DatabaseConnection.php b/src/app/CliTools/Database/DatabaseConnection.php index 4d06153..ba5457d 100644 --- a/src/app/CliTools/Database/DatabaseConnection.php +++ b/src/app/CliTools/Database/DatabaseConnection.php @@ -417,6 +417,22 @@ public static function tableList($database) { return $ret; } + + /** + * Check if table exists in database + * + * @param string $database Database name + * @param string $table Table name + * @return boolean + */ + public static function tableExists($database, $table) { + $query = 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s'; + $query = sprintf($query, self::quote($database), self::quote($table) ); + $ret = (bool)self::getOne($query); + + return $ret; + } + /** * Begin transaction */ From 30982e10342d72576adf7ee4dd90106d9108127a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 22:04:59 +0200 Subject: [PATCH 080/214] Fixed exception if sys_domain doesn't exists --- .../Console/Command/TYPO3/DomainCommand.php | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index 7963beb..be04203 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -99,27 +99,31 @@ protected function setupDevelopmentDomainsForDatabase($database) { $domain = '.' . $this->getApplication()->getConfigValue('config', 'domain_dev'); $domainLength = strlen($domain); - // ################## - // Fix domains - // ################## - $query = 'UPDATE ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($domain) . ') - WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($domain); - DatabaseConnection::exec($query); - - // ################## - // Show all domains - // ################## - $query = 'SELECT domainName - FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - WHERE hidden = 0'; - $domainList = DatabaseConnection::getCol($query); - - $this->output->writeln('Domain list of "' . $database . '":'); - - foreach ($domainList as $domain) { - $this->output->writeln(' '. $domain . ''); + if (DatabaseConnection::tableExists($database, 'sys_domain')) { + // ################## + // Fix domains + // ################## + $query = 'UPDATE ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain + SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($domain) . ') + WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($domain); + DatabaseConnection::exec($query); + + // ################## + // Show all domains + // ################## + $query = 'SELECT domainName + FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain + WHERE hidden = 0'; + $domainList = DatabaseConnection::getCol($query); + + $this->output->writeln('Domain list of "' . $database . '":'); + + foreach ($domainList as $domain) { + $this->output->writeln(' ' . $domain . ''); + } + $this->output->writeln(''); + } else { + $this->output->writeln('No sys_domain in "' . $database . '" found'); } - $this->output->writeln(''); } } From f5001fea33791e7b92ad41fe4ccf48d794c194b0 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 22:05:04 +0200 Subject: [PATCH 081/214] Cleanup --- src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php | 2 -- src/app/CliTools/Console/Command/Sync/ServerCommand.php | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index 495d4ea..20f46d0 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -31,8 +31,6 @@ abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\Abstr */ protected $confArea = 'share'; - - /** * Create rsync command for share sync * diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 513b1bd..6102d61 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -120,8 +120,10 @@ protected function runTaskDatabase() { foreach ($mysqlConf['database'] as $databaseConf) { if (strpos($databaseConf, ':') !== false) { + // local and foreign database in one string list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); } else { + // database equal $localDatabase = $databaseConf; $foreignDatabase = $databaseConf; } From a0c61f4f2e4a62ed160581ed79619e787bcc7a79 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 22:26:49 +0200 Subject: [PATCH 082/214] Added task section --- Documentation/Examples/clisync.yml | 12 ++++++++++++ .../CliTools/Console/Command/Sync/InitCommand.php | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index c957417..99e4e99 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -74,3 +74,15 @@ share: # List of databases for backup database: - typo3 + +####################################### +# Task configuration +####################################### +task: + + # These commands will be executed after backup, restore and sync + finalize: + # create user "dev" with password "dev" + - 'ct typo3:beuser' + # append toplevel-domain .vm to all domains + - 'ct typo3:domain' diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 59e0ec6..be83595 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -131,6 +131,17 @@ public function execute(InputInterface $input, OutputInterface $output) { database: - typo3 +####################################### +# Task configuration +####################################### +task: + + # These commands will be executed after backup, restore and sync + finalize: + # create user "dev" with password "dev" + - \'ct typo3:beuser\' + # append toplevel-domain .vm to all domains + - \'ct typo3:domain\' '; PhpUtility::filePutContents($cliSyncFilePath, $content); From dfc145a9193d3810634b3d45609c9fb091210211 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 22:27:03 +0200 Subject: [PATCH 083/214] Improved message if no sys_domain is found --- src/app/CliTools/Console/Command/TYPO3/DomainCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index be04203..fd3b59c 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -123,7 +123,7 @@ protected function setupDevelopmentDomainsForDatabase($database) { } $this->output->writeln(''); } else { - $this->output->writeln('No sys_domain in "' . $database . '" found'); + $this->output->writeln('Table "sys_domain" doesn\'t exists in database "' . $database . '"'); } } } From 7c00b030af82405fc5af9344b197a5a906a3c494 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 22:27:17 +0200 Subject: [PATCH 084/214] Added task execution (finalization) --- .../Console/Command/Sync/AbstractCommand.php | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 49c760d..62d875c 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -62,6 +62,13 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand */ protected $config = array(); + /** + * Task configuration + * + * @var array + */ + protected $taskConf = array(); + /** * Execute command * @@ -89,6 +96,7 @@ public function execute(InputInterface $input, OutputInterface $output) { try { $this->runTask(); + $this->runFinalizeTasks(); } catch (\Exception $e) { $this->cleanup(); throw $e; @@ -109,6 +117,12 @@ protected function readConfiguration() { $confFile = $this->workingPath . '/' . self::CONFIG_FILE; $conf = Yaml::parse(PhpUtility::fileGetContents($confFile)); + // store task specific configuration + if (!empty($conf['task'])) { + $this->taskConf = $conf['task']; + } + + // Switch to area configuration if (!empty($conf)) { $this->config = $conf[$this->confArea]; } else { @@ -190,6 +204,19 @@ protected function clearTempDir() { } } + + /** + * Run finalize tasks + */ + protected function runFinalizeTasks() { + foreach ($this->taskConf['finalize'] as $task) { + $command = new CommandBuilder(); + $command + ->parse($task) + ->executeInteractive(); + } + } + /** * Create rsync command for sync * From d5bcc25df8a4c819c1d289a566f38da6a409c4f4 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 15 May 2015 22:42:07 +0200 Subject: [PATCH 085/214] Moved to new repository --- README.md | 2 +- src/config.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa11b5a..8ccb15a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# CliTools for Vagrant VM, Debian and Ubuntu (and others) +# CliTools for Docker, PHP und MySQL development ![latest v1.9.0](https://img.shields.io/badge/latest-v1.9.0-green.svg?style=flat) ![License GPL3](https://img.shields.io/badge/license-GPL3-blue.svg?style=flat) diff --git a/src/config.ini b/src/config.ini index ba13a1b..70091e1 100644 --- a/src/config.ini +++ b/src/config.ini @@ -2,7 +2,7 @@ ssh_conf_path = "/opt/conf/ssh" www_base_path = "/var/www" domain_dev = "vm" -self_update_github = "https://api.github.com/repos/mblaschke/vagrant-clitools/releases" +self_update_github = "https://api.github.com/repos/mblaschke/clitools/releases" [db] dsn = "mysql:host=localhost" From ed11e6d090cf1adb082cfbbcfd4d198402fc7af4 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sun, 17 May 2015 16:19:47 +0200 Subject: [PATCH 086/214] Changed github update, added beta release update --- .../Command/Common/SelfUpdateCommand.php | 10 +++++ .../CliTools/Service/SelfUpdateService.php | 41 ++++++++++++++++++- src/config.ini | 2 +- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php index a8b30b2..f57b37e 100644 --- a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php +++ b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php @@ -40,6 +40,12 @@ protected function configure() { 'f', InputOption::VALUE_NONE, 'Force update' + ) + ->addOption( + 'beta', + null, + InputOption::VALUE_NONE, + 'Allow update to beta releases' ); } @@ -56,6 +62,10 @@ public function execute(InputInterface $input, OutputInterface $output) { $updateService = new SelfUpdateService($this->getApplication(), $output); + if ($input->getOption('beta')) { + $updateService->enablePreVersions(); + } + // Check if we need root rights if (!$this->getApplication()->isRunningAsRoot() && $updateService->isElevationNeeded()) diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index 5d11d47..32213bf 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -23,6 +23,12 @@ */ class SelfUpdateService { + /** + * Github repo url + * + * @var null|string + */ + protected $githubRepo; /** * Update url @@ -83,6 +89,13 @@ class SelfUpdateService { */ protected $application; + /** + * If pre releases should be used + * + * @var bool + */ + protected $updateAllowPreRelease = false; + /** * Constructor * @@ -96,6 +109,16 @@ public function __construct($app, $output) { $this->collectInformations(); } + /** + * Enable prerelease versions (beta) + * + * @return $this + */ + public function enablePreVersions() { + $this->updateAllowPreRelease = true; + return $this; + } + /** * Check if super user rights are required * @@ -117,7 +140,9 @@ public function isElevationNeeded() { * @param boolean $force Force update */ public function update($force = false) { - $this->githubReleaseUrl = $this->application->getConfigValue('config', 'self_update_github', null); + if ($this->githubReleaseUrl !== null) { + + } if (!empty($this->githubReleaseUrl)) { $this->fetchLatestReleaseFromGithub(); @@ -224,11 +249,17 @@ protected function fetchLatestReleaseFromGithub() { if (!empty($releaseList)) { foreach ($releaseList as $release) { // Check release - if (!empty($release['draft']) || !empty($release['prerelease'])) { + if (!empty($release['draft'])) { // no valid release continue; } + // Check for pre release + if (!$this->updateAllowPreRelease && !empty($release['prerelease'])) { + // no pre release allowed + continue; + } + // Check for required tag_name if (empty($release['tag_name'])) { // no valid release (requires version tag) @@ -305,6 +336,12 @@ protected function collectInformations() { $this->cliToolsCommandPerms['perms'] = fileperms($this->cliToolsCommandPath); $this->cliToolsCommandPerms['owner'] = (int)fileowner($this->cliToolsCommandPath); $this->cliToolsCommandPerms['group'] = (int)filegroup($this->cliToolsCommandPath); + + // ################## + // Set github defaults + // ################## + $this->githubRepo = $this->application->getConfigValue('config', 'github_repo', null); + $this->githubReleaseUrl = 'https://api.github.com/repos/' . $this->githubRepo . '/releases'; } /** diff --git a/src/config.ini b/src/config.ini index 70091e1..e3dcd82 100644 --- a/src/config.ini +++ b/src/config.ini @@ -2,7 +2,7 @@ ssh_conf_path = "/opt/conf/ssh" www_base_path = "/var/www" domain_dev = "vm" -self_update_github = "https://api.github.com/repos/mblaschke/clitools/releases" +github_repo = "mblaschke/clitools" [db] dsn = "mysql:host=localhost" From f4b4b8aa187791b0290aaf54a7efebd80a2416b0 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sun, 17 May 2015 16:25:54 +0200 Subject: [PATCH 087/214] Added self-update --fallback Fixes #26 --- .../Command/Common/SelfUpdateCommand.php | 10 ++++++++ .../CliTools/Service/SelfUpdateService.php | 25 +++++++++++++------ src/config.ini | 9 ++++--- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php index f57b37e..8daf646 100644 --- a/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php +++ b/src/app/CliTools/Console/Command/Common/SelfUpdateCommand.php @@ -46,6 +46,12 @@ protected function configure() { null, InputOption::VALUE_NONE, 'Allow update to beta releases' + ) + ->addOption( + 'fallback', + null, + InputOption::VALUE_NONE, + 'Fallback to old update url' ); } @@ -66,6 +72,10 @@ public function execute(InputInterface $input, OutputInterface $output) { $updateService->enablePreVersions(); } + if ($input->getOption('fallback')) { + $updateService->enableUpdateFallback(); + } + // Check if we need root rights if (!$this->getApplication()->isRunningAsRoot() && $updateService->isElevationNeeded()) diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index 32213bf..9e360aa 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -119,6 +119,17 @@ public function enablePreVersions() { return $this; } + /** + * Enable update from old server + * + * @return $this + */ + public function enableUpdateFallback() { + $this->updateUrl = $this->application->getConfigValue('config', 'update_fallback_url', null); + $this->updateVersion = 'fallback'; + return $this; + } + /** * Check if super user rights are required * @@ -140,14 +151,14 @@ public function isElevationNeeded() { * @param boolean $force Force update */ public function update($force = false) { - if ($this->githubReleaseUrl !== null) { - - } - if (!empty($this->githubReleaseUrl)) { - $this->fetchLatestReleaseFromGithub(); - } else { - throw new \RuntimeException('GitHub Release URL not set'); + // Only ask for github if update url is not set + if (!$this->updateUrl) { + if (!empty($this->githubReleaseUrl)) { + $this->fetchLatestReleaseFromGithub(); + } else { + throw new \RuntimeException('GitHub Release URL not set'); + } } if ($this->checkIfUpdateNeeded($force)) { diff --git a/src/config.ini b/src/config.ini index e3dcd82..da28257 100644 --- a/src/config.ini +++ b/src/config.ini @@ -1,8 +1,9 @@ [config] -ssh_conf_path = "/opt/conf/ssh" -www_base_path = "/var/www" -domain_dev = "vm" -github_repo = "mblaschke/clitools" +ssh_conf_path = "/opt/conf/ssh" +www_base_path = "/var/www" +domain_dev = "vm" +github_repo = "mblaschke/clitools" +update_fallback_url = "https://www.achenar.net/clicommand/clitools.phar" [db] dsn = "mysql:host=localhost" From 9bdbbaea5c87a30a7335669d1082b398b411683f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sun, 17 May 2015 17:29:55 +0200 Subject: [PATCH 088/214] Fixed issues with sync --- Documentation/Examples/clisync.yml | 6 +- .../Console/Command/Sync/AbstractCommand.php | 56 +++++++++++++------ .../Command/Sync/AbstractShareCommand.php | 18 ++++++ .../Console/Command/Sync/InitCommand.php | 6 +- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 99e4e99..e4cfe80 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -1,7 +1,7 @@ ####################################### # Sync from server (eg. live server) ####################################### -sync: +server: ################## # Global config @@ -26,7 +26,7 @@ sync: # rsync for some directories rsync: # server and source directory (server host or name - see .ssh/config) - source: "live-server:/var/www/website/htdocs" + path: "live-server:/var/www/website/htdocs" # directory list/patterns directory: @@ -52,7 +52,7 @@ share: rsync: # source/target directory or server via ssh (eg. backup-server:/backup/projectname) - source: "/tmp/foo/" + path: "/tmp/foo/" # List of directories for backup directory: diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 62d875c..966ec27 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -138,37 +138,59 @@ protected function readConfiguration() { protected function validateConfiguration() { $ret = true; - $output = $this->output; + // Rsync (optional) + if (!empty($this->config['rsync'])) { + if (!$this->validateConfigurationRsync()) { + $ret = false; + } + } + + // MySQL (optional) + if (!empty($this->config['mysql'])) { + if (!$this->validateConfigurationMysql()) { + $ret = false; + } + } - // ################## - // Rsync (required) - // ################## + return $ret; + } + + /** + * Validate configuration (rsync) + * + * @return boolean + */ + protected function validateConfigurationRsync() { + $ret = true; // Check if rsync target exists if (!$this->getRsyncPathFromConfig()) { - $output->writeln('No rsync path configuration found'); + $this->output->writeln('No rsync path configuration found'); $ret = false; } else { - $output->writeln('Using rsync path "' . $this->getRsyncPathFromConfig() . '"'); + $this->output->writeln('Using rsync path "' . $this->getRsyncPathFromConfig() . '"'); } // Check if there are any rsync directories if (empty($this->config['rsync']['directory'])) { - $output->writeln('No rsync directory configuration found, filesync disabled'); + $this->output->writeln('No rsync directory configuration found, filesync disabled'); } - // ################## - // MySQL (optional) - // ################## - - if (!empty($this->config['mysql'])) { + return $ret; + } - // Check if one database is configured - if (empty($this->config['mysql']['database'])) { - $output->writeln('No mysql database configuration found'); - $ret = false; - } + /** + * Validate configuration (mysql) + * + * @return boolean + */ + protected function validateConfigurationMysql() { + $ret = true; + // Check if one database is configured + if (empty($this->config['mysql']['database'])) { + $this->output->writeln('No mysql database configuration found'); + $ret = false; } return $ret; diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index 20f46d0..2b38bb5 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -31,6 +31,24 @@ abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\Abstr */ protected $confArea = 'share'; + /** + * Validate configuration + * + * @return boolean + */ + protected function validateConfiguration() { + $ret = parent::validateConfiguration(); + + var_dump($ret); + + // Rsync required for share + $ret = $ret && $this->validateConfigurationRsync(); + + var_dump($ret); + + return $ret; + } + /** * Create rsync command for share sync * diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index be83595..6365392 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -57,7 +57,7 @@ public function execute(InputInterface $input, OutputInterface $output) { ####################################### # Sync from server (eg. live server) ####################################### -sync: +server: ################## # Global config @@ -82,7 +82,7 @@ public function execute(InputInterface $input, OutputInterface $output) { # rsync for some directories rsync: # server and source directory (server host or name - see .ssh/config) - source: "live-server:/var/www/website/htdocs" + path: "live-server:/var/www/website/htdocs" # directory list/patterns directory: @@ -108,7 +108,7 @@ public function execute(InputInterface $input, OutputInterface $output) { rsync: # source/target directory or server via ssh (eg. backup-server:/backup/projectname) - source: "/tmp/foo/" + path: "/tmp/foo/" # List of directories for backup directory: From 27f76dfe564319e69f871053b77738882779f476 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sun, 17 May 2015 18:23:43 +0200 Subject: [PATCH 089/214] Cleanup --- src/app/CliTools/Exception/CommandExecutionException.php | 1 - src/app/CliTools/Utility/FilterUtility.php | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/CliTools/Exception/CommandExecutionException.php b/src/app/CliTools/Exception/CommandExecutionException.php index e548208..6fb1c04 100644 --- a/src/app/CliTools/Exception/CommandExecutionException.php +++ b/src/app/CliTools/Exception/CommandExecutionException.php @@ -20,7 +20,6 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; class CommandExecutionException extends \RuntimeException { diff --git a/src/app/CliTools/Utility/FilterUtility.php b/src/app/CliTools/Utility/FilterUtility.php index 843f11b..09d169e 100644 --- a/src/app/CliTools/Utility/FilterUtility.php +++ b/src/app/CliTools/Utility/FilterUtility.php @@ -25,8 +25,8 @@ class FilterUtility { /** * Filter mysql table list by filter * - * @param array $tables List of tables - * @param array $filter List of filters + * @param array $tables List of tables + * @param array $filters List of filters * * @return array */ @@ -49,7 +49,7 @@ public static function mysqlTableFilter(array $tables, array $filters) { * Filter mysql table list by filter * * @param array $tables List of tables - * @param array $filter List of filters + * @param array $filters List of filters * @param string|null $database Database * * @return array From 870187e7a4ce0da1cf12eb35cbd17b0a0e7884d5 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sun, 17 May 2015 18:24:15 +0200 Subject: [PATCH 090/214] Removed debug --- .../CliTools/Console/Command/Sync/AbstractShareCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index 2b38bb5..8c5f342 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -39,13 +39,9 @@ abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\Abstr protected function validateConfiguration() { $ret = parent::validateConfiguration(); - var_dump($ret); - // Rsync required for share $ret = $ret && $this->validateConfigurationRsync(); - var_dump($ret); - return $ret; } From e6d04d2e07c9e2dae35d3c142f8faeab78fe61ba Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 18 May 2015 22:32:34 +0200 Subject: [PATCH 091/214] Added fileGetContentsArray --- src/app/CliTools/Utility/PhpUtility.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index 183f339..c3cfcbb 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -36,6 +36,21 @@ public static function fileGetContents($file) { return file_get_contents($file); } + /** + * Get content of file (array) + * + * @param string $file Filename + * @return array + */ + public static function fileGetContentsArray($file) { + $content = self::fileGetContents($file); + + $content = str_replace("/r/n", "/n", $content); + $ret = explode("/n", $content); + + return $ret; + } + /** * Get content of file * From e6c702b153ce6b90a275c6b4528bd498f91af3c3 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 18 May 2015 22:34:38 +0200 Subject: [PATCH 092/214] Added --make for docker:create --- CHANGELOG.md | 2 +- README.md | 3 +- .../Console/Command/Docker/CreateCommand.php | 88 ++++++++++++++++++- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48c3c6a..ec654c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ CliTools Changelog ------------------ - Added GitHub based `self-update` - Added `make` (auto search for Makefile in tree) -- Added `php:composer` (auto search for composer.yml in tree) +- Added `php:composer` (auto search for composer.json in tree) - Added `mysql:convert` for automatic changing charset and collation of one database - Added `sync:server` for syncing any configured server to your local development system (reads clisync.yml) - Added `sync:backup` for backup to a shared server (reads clisync.yml) diff --git a/README.md b/README.md index 8ccb15a..2c4e903 100644 --- a/README.md +++ b/README.md @@ -145,8 +145,9 @@ All log commands are using a grep-filter (specified as optional argument) |----------------------------|---------------------------------------------------------------------------| | ct docker:create | Create new docker boilerplate in directory (first argument) | | | __ct docker:create projectname__ -> Create new docker boilerplate instance in directory "projectname" | -| | __ct docker:create projectname --code=git@github.com/foo/bar__ -> Create new docker boilerplate instance in directory "projectname" and custom code repository | +| | __ct docker:create projectname --code=git@github.com/foo/bar__ -> Create new docker boilerplate instance in directory "projectname" and git code repository | | | __ct docker:create projectname --docker=git@github.com/foo/bar__ -> Create new docker boilerplate instance in directory "projectname" and custom docker boilerplate repository | +| | __ct docker:create projectname --code=git@github.com/foo/bar --make=build__ -> Create new docker boilerplate instance in directory "projectname" and git code repository, will run automatic make (Makefile) task "build" after checkout | | ct docker:shell | Jump into a shell inside a docker container (using predefined user defined with CLI_USER in docker env) | | | __ct docker:shell__ -> enter main container | | | __ct docker:shell mysql__ -> enter mysql container | diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index a98f2af..d392730 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -53,6 +53,12 @@ protected function configure() { 'c', InputOption::VALUE_REQUIRED, 'Code repository' + ) + ->addOption( + 'make', + 'm', + InputOption::VALUE_REQUIRED, + 'Makefile command' ); } @@ -65,6 +71,8 @@ protected function configure() { * @return int|null|void */ public function execute(InputInterface $input, OutputInterface $output) { + $currDir = getcwd(); + $path = $input->getArgument('path'); if ($this->input->getOption('docker')) { @@ -75,15 +83,33 @@ public function execute(InputInterface $input, OutputInterface $output) { $boilerplateRepo = $this->getApplication()->getConfigValue('docker', 'boilerplate'); } + // Init docker boilerplate $this->createDockerInstance($path, $boilerplateRepo); + PhpUtility::chdir($currDir); // Init code if ($this->input->getOption('code')) { $this->initCode($path, $input->getOption('code')); + PhpUtility::chdir($currDir); + + // detect document root + $this->initDocumentRoot($path); + PhpUtility::chdir($currDir); + + // Run makefile + if ($this->input->getOption('make')) { + try { + $this->runMakefile($path, $input->getOption('make')); + PhpUtility::chdir($currDir); + } catch (\Exception $e) { + $output->writeln('Make command failed: ' . $e->getMessage() . ''); + } + } } // Start docker + PhpUtility::chdir($currDir); $this->startDockerInstance($path); return 0; @@ -121,7 +147,8 @@ protected function initCode($path, $repo) { // Remove code directory $command = new CommandBuilder('rmdir'); - $command->addArgumentSeparator() + $command + ->addArgumentSeparator() ->addArgument($path) ->executeInteractive(); } @@ -130,6 +157,65 @@ protected function initCode($path, $repo) { $command->executeInteractive(); } + + /** + * Create docker instance from git repository + * + * @param string $path Path + */ + protected function initDocumentRoot($path) { + $codePath = $path . '/code'; + $dockerEnvFile = $path . '/docker-env.yml'; + + $documentRoot = null; + + // try to detect document root + if (is_dir($codePath . '/html')) { + $documentRoot = 'code/html'; + } elseif (is_dir($codePath . '/htdocs')) { + $documentRoot = 'code/htdocs'; + } elseif (is_dir($codePath . '/Web')) { + $documentRoot = 'code/Web'; + } elseif (is_dir($codePath . '/web')) { + $documentRoot = 'code/web'; + } + + if ($documentRoot && is_file($dockerEnvFile) ) { + $dockerEnv = PhpUtility::fileGetContentsArray($dockerEnvFile); + + unset($line); + foreach ($dockerEnv as &$line) { + $line = preg_replace('/^[\s]*DOCUMENT_ROOT[\s]*=code\/?[\s]*$/ms', 'DOCUMENT_ROOT=' . $documentRoot, $line); + } + unset($line); + + $dockerEnv = implode("\n", $dockerEnv); + + PhpUtility::filePutContents($dockerEnvFile, $dockerEnv); + } + } + + /** + * Run make task + * + * @param string $path Path of code + * @param string $makeCommand Makefile command + */ + protected function runMakefile($path, $makeCommand) { + $path .= '/code'; + + $this->output->writeln('Running make with command "' . $makeCommand . '"'); + + PhpUtility::chdir($path); + + // Remove code directory + $command = new CommandBuilder('make'); + $command + ->addArgument($makeCommand) + ->executeInteractive(); + + } + /** * Build and startup docker instance * From bef52e22531bd530b0bdb4bba2e7fc150c3398b9 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 18 May 2015 22:49:22 +0200 Subject: [PATCH 093/214] Cleanup --- src/app/CliTools/Console/Command/Docker/CreateCommand.php | 1 - src/app/CliTools/Utility/PhpUtility.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index d392730..03946a7 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -83,7 +83,6 @@ public function execute(InputInterface $input, OutputInterface $output) { $boilerplateRepo = $this->getApplication()->getConfigValue('docker', 'boilerplate'); } - // Init docker boilerplate $this->createDockerInstance($path, $boilerplateRepo); PhpUtility::chdir($currDir); diff --git a/src/app/CliTools/Utility/PhpUtility.php b/src/app/CliTools/Utility/PhpUtility.php index c3cfcbb..e5656c8 100644 --- a/src/app/CliTools/Utility/PhpUtility.php +++ b/src/app/CliTools/Utility/PhpUtility.php @@ -44,8 +44,8 @@ public static function fileGetContents($file) { */ public static function fileGetContentsArray($file) { $content = self::fileGetContents($file); - $content = str_replace("/r/n", "/n", $content); + $ret = explode("/n", $content); return $ret; From 909b0b306715253c919305b7b57dfc5082ac5f2a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 18 May 2015 22:55:19 +0200 Subject: [PATCH 094/214] Removed docker:upgrade --- .../Console/Command/Docker/UpgradeCommand.php | 55 ------------------- 1 file changed, 55 deletions(-) delete mode 100644 src/app/CliTools/Console/Command/Docker/UpgradeCommand.php diff --git a/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php b/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php deleted file mode 100644 index 48d462d..0000000 --- a/src/app/CliTools/Console/Command/Docker/UpgradeCommand.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; - -class UpgradeCommand extends AbstractCommand { - - /** - * Configure command - */ - protected function configure() { - $this - ->setName('docker:upgrade') - ->setDescription('Upgrade docker version'); - } - - /** - * Execute command - * - * @param InputInterface $input Input instance - * @param OutputInterface $output Output instance - * - * @return int|null|void - */ - public function execute(InputInterface $input, OutputInterface $output) { - $this->elevateProcess($input, $output); - - $command = new CommandBuilder('wget', '-qO- %s', array('https://get.docker.com/')); - $command->addPipeCommand(new CommandBuilder('sh')); - $command->executeInteractive(); - - return 0; - } -} From b337d3831a076df13fd2e1e36bd63e78b174e5e7 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 18 May 2015 23:40:15 +0200 Subject: [PATCH 095/214] Cleanup --- src/app/CliTools/Console/Command/Sync/BackupCommand.php | 4 ++-- src/app/CliTools/Console/Command/Sync/RestoreCommand.php | 2 +- src/app/CliTools/Console/Command/Sync/ServerCommand.php | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 6f6e986..6639d9b 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -38,7 +38,7 @@ protected function runTask() { // ################## // Backup dirs // ################## - if (!empty($this->config['rsync']['directory'])) { + if (!empty($this->config['rsync'])) { $source = $this->workingPath; $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); @@ -48,7 +48,7 @@ protected function runTask() { // ################## // Backup databases // ################## - if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { + if (!empty($this->config['mysql'])) { foreach ($this->config['mysql']['database'] as $database) { $this->output->writeln('Dumping database ' . $database . ''); diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 9000a81..19d428b 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -38,7 +38,7 @@ protected function runTask() { // ################## // Restore dirs // ################## - if (!empty($this->config['rsync']['directory'])) { + if (!empty($this->config['rsync'])) { $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; $target = $this->workingPath; $command = $this->createShareRsyncCommand($source, $target, true); diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 6102d61..fa266c6 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -80,17 +80,17 @@ protected function readConfiguration() { */ protected function runTask() { // Check database connection - if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { + if (!empty($this->config['mysql'])) { DatabaseConnection::ping(); } // Sync files with rsync to local storage - if (!empty($this->config['rsync']) && !empty($this->config['rsync']['directory'])) { + if (!empty($this->config['rsync'])) { $this->runTaskRsync(); } // Sync database to local server - if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { + if (!empty($this->config['mysql'])) { // Full mysql transfer $this->runTaskDatabase(); } From 26d4959b13ee7ebffdedba52c6afa70524e691fb Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 10:48:28 +0200 Subject: [PATCH 096/214] Improved makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 47dcfb8..58f910f 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ +all: autoload build install + build: bash compile.sh install: cp clitools.phar /usr/local/bin/ct -all: build install - autoload: sh -c "cd src ; composer dump-autoload --optimize --no-dev" From 9f43ca63ff6e6083891258bf0974d33c53c6772b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 18:30:06 +0200 Subject: [PATCH 097/214] Added target Fixes #30 --- Documentation/Examples/clisync.yml | 4 ++++ .../Console/Command/Sync/AbstractCommand.php | 19 +++++++++++++++++++ .../Console/Command/Sync/BackupCommand.php | 2 +- .../Console/Command/Sync/RestoreCommand.php | 2 +- .../Console/Command/Sync/ServerCommand.php | 2 +- .../CommandBuilder/AbstractCommandBuilder.php | 2 +- 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index e4cfe80..83178d5 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -27,6 +27,8 @@ server: rsync: # server and source directory (server host or name - see .ssh/config) path: "live-server:/var/www/website/htdocs" + # set target as sub directroy (will be appended to working directory) + #target: "html/" # directory list/patterns directory: @@ -53,6 +55,8 @@ share: rsync: # source/target directory or server via ssh (eg. backup-server:/backup/projectname) path: "/tmp/foo/" + # set target as sub directroy (will be appended to working directory) + #target: "html/" # List of directories for backup directory: diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 966ec27..25b9c7c 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -293,6 +293,25 @@ protected function getRsyncPathFromConfig() { return $ret; } + + /** + * Get rsync working path (with target if set in config) + * + * @return boolean|string + */ + protected function getRsyncWorkingPath() { + $ret = $this->workingPath; + + // remove right / + $ret = rtrim($this->workingPath, '/'); + + if (!empty($this->config['rsync']['target'])) { + $ret .= '/' . $this->config['rsync']['target']; + } + + return $ret; + } + /** * Add file (pattern) list to rsync command * diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 6639d9b..b34e296 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -39,7 +39,7 @@ protected function runTask() { // Backup dirs // ################## if (!empty($this->config['rsync'])) { - $source = $this->workingPath; + $source = $this->getRsyncWorkingPath(); $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 19d428b..23e63bb 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -40,7 +40,7 @@ protected function runTask() { // ################## if (!empty($this->config['rsync'])) { $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; - $target = $this->workingPath; + $target = $this->getRsyncWorkingPath(); $command = $this->createShareRsyncCommand($source, $target, true); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index fa266c6..53d2c4d 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -103,7 +103,7 @@ protected function runTaskRsync() { // Restore dirs // ################## $source = $this->getRsyncPathFromConfig(); - $target = $this->workingPath; + $target = $this->getRsyncWorkingPath(); $command = $this->createRsyncCommand($source, $target); $command->executeInteractive(); diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php index 711b82c..6279754 100644 --- a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php @@ -492,7 +492,7 @@ public function build() { $ret = array(); if (!$this->isExecuteable()) { - throw new \RuntimeException('Command "' . $this->getCommand() . '" is not executable or available'); + throw new \RuntimeException('Command "' . $this->getCommand() . '" is not executable or available, please install it'); } // Add command From aa858b962c1bb04cd3e3b173acf2da818f40527e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 18:30:43 +0200 Subject: [PATCH 098/214] Added autostart of editor, Updated clisync.yml Fixes #30 and Fixes #29 --- .../CliTools/Console/Command/Sync/InitCommand.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 6365392..ba7cce5 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -83,6 +83,8 @@ public function execute(InputInterface $input, OutputInterface $output) { rsync: # server and source directory (server host or name - see .ssh/config) path: "live-server:/var/www/website/htdocs" + # set target as sub directroy (will be appended to working directory) + #target: "html/" # directory list/patterns directory: @@ -109,6 +111,8 @@ public function execute(InputInterface $input, OutputInterface $output) { rsync: # source/target directory or server via ssh (eg. backup-server:/backup/projectname) path: "/tmp/foo/" + # set target as sub directroy (will be appended to working directory + #target: "html/" # List of directories for backup directory: @@ -146,6 +150,17 @@ public function execute(InputInterface $input, OutputInterface $output) { PhpUtility::filePutContents($cliSyncFilePath, $content); + // Start editor with file (if $EDITOR is set) + $editorCmd = getenv('EDITOR'); + if (!empty($editorCmd)) { + $editor = new \CliTools\Console\Shell\CommandBuilder\CommandBuilder(); + $editor + ->parse($editorCmd) + ->addArgument($cliSyncFilePath) + ->executeInteractive(); + } + + $this->output->writeln('Successfully created ' . AbstractCommand::CONFIG_FILE . ' '); } From a08d8b377ca3bf5381a1162cd33907f87c4f197b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 18:30:54 +0200 Subject: [PATCH 099/214] Removed old CommandExecutionUtility --- .../Utility/CommandExecutionUtility.php | 169 ------------------ 1 file changed, 169 deletions(-) delete mode 100644 src/app/CliTools/Utility/CommandExecutionUtility.php diff --git a/src/app/CliTools/Utility/CommandExecutionUtility.php b/src/app/CliTools/Utility/CommandExecutionUtility.php deleted file mode 100644 index 74e5b4b..0000000 --- a/src/app/CliTools/Utility/CommandExecutionUtility.php +++ /dev/null @@ -1,169 +0,0 @@ - - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -use CliTools\Exception\CommandExecutionException; - -/** - * Class CommandExecutionUtility - * - * @package CliTools\Utility - * @deprecated - */ -class CommandExecutionUtility { - - /** - * Build raw command - * - * @param string $command Command - * @param string|null $parameterTemplate Parameter Template - * @param array|null $parameter Parameter List - * - * @return string - */ - public static function buildCommand($command, $parameterTemplate = null, $parameter = null) { - // Escape command - $execCommand = escapeshellcmd($command); - - // Escape args - if ($parameter !== null && is_array($parameter) && count($parameter) >= 1) { - // dynamic paramter - $parameter = array_map('escapeshellarg', $parameter); - - // Just add parameter if template is empty - if ($parameterTemplate === null) { - $parameterTemplate = str_repeat('%s ', count($parameter)); - } - - $execCommand .= ' ' . vsprintf($parameterTemplate, $parameter); - } elseif ($parameterTemplate !== null && $parameter === null) { - // only template specified, use as static parameter - $execCommand .= ' ' . $parameterTemplate; - } - - return $execCommand; - } - - - /** - * Build argument list as string - * - * @param array $parameter Parameter List - * - * @return string - */ - public static function buildArgumentString(array $parameter) { - $parameter = array_map('escapeshellarg', $parameter); - $ret = implode(' ', $parameter); - return $ret; - } - - /** - * Exec raw command - * - * @param string $command Command - * @param string $output Output - * - * @return integer - * @throws CommandExecutionException - */ - public static function execRaw($command, &$output = null) { - ConsoleUtility::verboseWriteln('EXEC::RAW', $command); - - exec($command, $output, $execStatus); - - if ($execStatus !== 0) { - $e = new CommandExecutionException('Process ' . $command . ' did not finished successfully'); - $e->setReturnCode($execStatus); - throw $e; - } - - return $execStatus; - } - - /** - * Exec command - * - * @param string $command Command - * @param string $output Output - * @param string|null $parameterTemplate Parameter Template - * @param array|null $parameter Parameter List - * - * @return integer - * @throws CommandExecutionException - */ - public static function exec($command, &$output, $parameterTemplate, $parameter = null) { - $execCommand = self::buildCommand($command, $parameterTemplate, $parameter); - - ConsoleUtility::verboseWriteln('EXEC::EXEC', $execCommand); - - exec($execCommand, $output, $execStatus); - - if ($execStatus !== 0) { - $e = new CommandExecutionException('Process ' . $execCommand . ' did not finished successfully'); - $e->setReturnCode($execStatus); - throw $e; - } - - return $execStatus; - } - - /** - * Execute command (via passthru) - * - * @param string $command Command - * @param string|null $parameterTemplate Parameter Template - * @param array|null $parameter Parameter List - * - * @return integer - * @throws CommandExecutionException - */ - public static function execInteractive($command, $parameterTemplate = null, $parameter = null) { - $execCommand = self::buildCommand($command, $parameterTemplate, $parameter); - - ConsoleUtility::verboseWriteln('EXEC::INTERACTIVE', $execCommand); - - $descriptorSpec = array( - 0 => array('file', 'php://stdin', 'r'), // stdin is a file that the child will read from - 1 => array('file', 'php://stdout', 'w'), // stdout is a file that the child will write to - 2 => array('file', 'php://stderr', 'w') // stderr is a file that the child will write to - ); - - $process = proc_open($execCommand, $descriptorSpec, $pipes); - - if (is_resource($process)) { - $execStatus = proc_close($process); - $execStatus = pcntl_wexitstatus($execStatus); - - if ($execStatus !== 0) { - $e = new CommandExecutionException('Process ' . $execCommand . ' did not finished successfully [return code: ' . $execStatus . ']'); - $e->setReturnCode($execStatus); - throw $e; - } - } else { - $e = new CommandExecutionException('Process ' . $execCommand . ' could not be started'); - $e->setReturnCode(-1); - throw $e; - } - - return $execStatus; - } -} From 4261bc07c373a81d4837ca39cec1d8437e6a97b4 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 18:35:47 +0200 Subject: [PATCH 100/214] Added transfer compression Fixes #31 --- Documentation/Examples/clisync.yml | 3 +++ .../Console/Command/Sync/InitCommand.php | 3 +++ .../Console/Command/Sync/ServerCommand.php | 19 ++++++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 83178d5..4dc8d35 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -11,6 +11,9 @@ server: # MySQL filter for typo3 (eg. no caching tables) filter: typo3 + # Transfer compression (none if empty, bzip2 or gzip) + compression: bzip2 + # specific mysqldump settings mysqldump: option: "--opt --single-transaction" diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index ba7cce5..7e33e92 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -67,6 +67,9 @@ public function execute(InputInterface $input, OutputInterface $output) { # MySQL filter for typo3 (eg. no caching tables) filter: typo3 + # Transfer compression (none if empty, bzip2 or gzip) + compression: bzip2 + # specific mysqldump settings mysqldump: option: "--opt --single-transaction" diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 53d2c4d..b9c4f09 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -132,7 +132,7 @@ protected function runTaskDatabase() { $localDatabase = trim($localDatabase); $foreignDatabase = trim($foreignDatabase); - $dumpFile = $this->tempDir . '/' . $localDatabase . '.sql.bz2'; + $dumpFile = $this->tempDir . '/' . $localDatabase . '.sql.dump'; // ########## // Dump from server @@ -227,8 +227,21 @@ protected function createMySqlDumpCommand($database = null) { $command->addArgumentRaw($this->config['mysqldump']['option']); } - // Add pipe compressor (bzip2 compressed transfer via ssh) - $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + + if (!empty($this->config['mysql']['compression'])) { + switch($this->config['mysql']['compression']) { + case 'bzip2': + // Add pipe compressor (bzip2 compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + break; + + case 'gzip': + // Add pipe compressor (gzip compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); + break; + } + } + if ($database !== null) { $command->addArgument($database); From 809aa6f79fa80f3d6bc8d42bf238b9c13246e03b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 18:37:06 +0200 Subject: [PATCH 101/214] Fixed gzip dump detection --- src/app/CliTools/Console/Command/Mysql/RestoreCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index a43c057..68653f8 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -99,6 +99,7 @@ public function execute(InputInterface $input, OutputInterface $output) { break; case 'application/gzip': + case 'application/x-gzip': $output->writeln('Using GZIP uncompression'); $commandFile->setCommand('gzcat'); break; From ce9696a02e6a2f7d131dc13ae8e4fe6fa25e29b4 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 18:39:48 +0200 Subject: [PATCH 102/214] Removed forcing of mysql configuration Fixes #33 --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 25b9c7c..63b36b2 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -146,10 +146,13 @@ protected function validateConfiguration() { } // MySQL (optional) - if (!empty($this->config['mysql'])) { + if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { if (!$this->validateConfigurationMysql()) { $ret = false; } + } else { + // No mysql conf set + unset($this->config['mysql']); } return $ret; From c5c6f351d082dc5a44d38151cd51a0c9c8dfd0cc Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 22:29:37 +0200 Subject: [PATCH 103/214] Added config reader --- src/app/CliTools/Reader/ConfigReader.php | 181 +++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/app/CliTools/Reader/ConfigReader.php diff --git a/src/app/CliTools/Reader/ConfigReader.php b/src/app/CliTools/Reader/ConfigReader.php new file mode 100644 index 0000000..38aba84 --- /dev/null +++ b/src/app/CliTools/Reader/ConfigReader.php @@ -0,0 +1,181 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +class ConfigReader implements \ArrayAccess { + + /** + * Data storage + * + * @var array + */ + protected $data = array(); + + /** + * Constructor + * + * @param array $data Data configuration + */ + public function __construct(array $data = null) { + if ($data !== null) { + $this->setData($data); + } + } + + /** + * Set configuration data + * + * @param array $data Data configuration + */ + public function setData(array $data) { + $this->data = $data; + } + + /** + * Get value from specific node (dotted array notation) + * + * @param string $path Path to node (eg. foo.bar.baz) + * @return mixed|null + */ + public function get($path) { + return $this->getNode($path); + } + + /** + * Get array value from specific node (dotted array notation) + * + * @param string $path Path to node (eg. foo.bar.baz) + * @return array|null + */ + public function getArray($path) { + $ret = $this->getNode($path); + + if (!is_array($ret)) { + $ret = array(); + } + + return $ret; + } + + /** + * Set value to specific node (dotted array notation) + * + * @param string $path Path to node (eg. foo.bar.baz) + * @param mixed $value Value to set + */ + public function set($path, $value) { + $node =& $this->getNode($path); + $node = $value; + } + + /** + * Clear value at specific node (dotted array notation) + * + * @param string $path Path to node (eg. foo.bar.baz) + */ + public function clear($path) { + $node =& $this->getNode($path); + $node = null; + } + + /** + * Check if specific node exists + * + * @param string $path Path to node (eg. foo.bar.baz) + * @return bool + */ + public function exists($path) { + return ($this->getNode($path) !== null); + } + + /** + * Get node by reference + * + * @param string $path Path to node (eg. foo.bar.baz) + * @return mixed|null + */ + protected function &getNode($path) { + $pathList = explode('.',$path); + $data = &$this->data; + + foreach ($pathList as $node) { + if (isset($data[$node])) { + $data = &$data[$node]; + } else { + unset($data); + $data = null; + break; + } + } + + if ($data !== null) { + $ret = &$data; + } + + return $ret; + } + + /** + * Array accessor: Set value to offset + * + * @param string $offset Array key + * @param mixed $value Value + */ + public function offsetSet($offset, $value) { + if ($offset === null) { + $this->data[] = $value; + } else { + $this->data[$offset] = $value; + } + } + + /** + * Array accessor: Check if offset exists + * + * @param string $offset Array key + * @return boolean + */ + public function offsetExists($offset) { + return isset($this->data[$offset]); + } + + /** + * Array accessor: Unset offset + * + * @param string $offset Array key + */ + public function offsetUnset($offset) { + unset($this->data[$offset]); + } + + /** + * Array accessor: Get value at offset + * + * @param string $offset Array key + * @return mixed + */ + public function offsetGet($offset) { + return isset($this->data[$offset]) ? $this->data[$offset] : null; + } + +} From a7215adee4eae335ca56cee013d7977d69401836 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 22:29:53 +0200 Subject: [PATCH 104/214] Implemented config reader for sync commands --- .../Console/Command/Sync/AbstractCommand.php | 53 ++++++----- .../Command/Sync/AbstractShareCommand.php | 8 +- .../Command/Sync/AbstractSyncCommand.php | 6 +- .../Console/Command/Sync/BackupCommand.php | 8 +- .../Console/Command/Sync/RestoreCommand.php | 2 +- .../Console/Command/Sync/ServerCommand.php | 87 +++++++++---------- 6 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 63b36b2..494aaf3 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -24,6 +24,7 @@ use CliTools\Utility\UnixUtility; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Reader\ConfigReader; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Yaml\Yaml; @@ -58,14 +59,14 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand /** * Sync configuration * - * @var array + * @var ConfigReaderService */ protected $config = array(); /** * Task configuration * - * @var array + * @var ConfigReaderService */ protected $taskConf = array(); @@ -89,7 +90,9 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); $this->readConfiguration(); + if (!$this->validateConfiguration()) { + $this->output->writeln('Configuration could not be validated'); exit(1); } $this->startup(); @@ -109,6 +112,8 @@ public function execute(InputInterface $input, OutputInterface $output) { * Read and validate configuration */ protected function readConfiguration() { + $this->config = new ConfigReader(); + $this->taskConf = new ConfigReader(); if (empty($this->confArea)) { throw new \RuntimeException('Config area not set, cannot continue'); @@ -119,12 +124,12 @@ protected function readConfiguration() { // store task specific configuration if (!empty($conf['task'])) { - $this->taskConf = $conf['task']; + $this->taskConf->setData($conf['task']); } // Switch to area configuration if (!empty($conf)) { - $this->config = $conf[$this->confArea]; + $this->config->setData($conf[$this->confArea]); } else { throw new \RuntimeException('Could not parse "' . $confFile . '"'); } @@ -139,20 +144,20 @@ protected function validateConfiguration() { $ret = true; // Rsync (optional) - if (!empty($this->config['rsync'])) { + if ($this->config->exists('rsync')) { if (!$this->validateConfigurationRsync()) { $ret = false; } } // MySQL (optional) - if (!empty($this->config['mysql']) && !empty($this->config['mysql']['database'])) { + if ($this->config->exists('mysql.database')) { if (!$this->validateConfigurationMysql()) { $ret = false; } } else { - // No mysql conf set - unset($this->config['mysql']); + // Clear mysql if any options set + $this->config->clear('mysql'); } return $ret; @@ -175,7 +180,7 @@ protected function validateConfigurationRsync() { } // Check if there are any rsync directories - if (empty($this->config['rsync']['directory'])) { + if (!$this->config->exists('rsync.directory')) { $this->output->writeln('No rsync directory configuration found, filesync disabled'); } @@ -188,10 +193,10 @@ protected function validateConfigurationRsync() { * @return boolean */ protected function validateConfigurationMysql() { - $ret = true; + $ret = true; // Check if one database is configured - if (empty($this->config['mysql']['database'])) { + if (!$this->config->exists('mysql.database')) { $this->output->writeln('No mysql database configuration found'); $ret = false; } @@ -234,11 +239,13 @@ protected function clearTempDir() { * Run finalize tasks */ protected function runFinalizeTasks() { - foreach ($this->taskConf['finalize'] as $task) { - $command = new CommandBuilder(); - $command - ->parse($task) - ->executeInteractive(); + if ($this->taskConf->exists('finalize')) { + $this->output->writeln(' ---- Starting FINALIZE TASKS ---- '); + + foreach ($this->taskConf->getArray('finalize') as $task) { + $command = new CommandBuilder(); + $command->parse($task)->executeInteractive(); + } } } @@ -253,7 +260,7 @@ protected function runFinalizeTasks() { * @return CommandBuilder */ protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { - $this->output->writeln('Rsync from ' . $source . ' to ' . $target . ''); + $this->output->writeln('Rsync from ' . $source . ' to ' . $target . ''); $command = new CommandBuilder('rsync', '-rlptD --delete-after --progress -h'); @@ -285,12 +292,12 @@ protected function createRsyncCommand($source, $target, array $filelist = null, */ protected function getRsyncPathFromConfig() { $ret = false; - if (!empty($this->config['rsync']['path'])) { + if ($this->config->exists('rsync.path')) { // Use path from rsync - $ret = $this->config['rsync']['path']; - } elseif(!empty($this->config['ssh']['hostname']) && !empty($this->config['ssh']['path'])) { + $ret = $this->config->get('rsync.path'); + } elseif($this->config->exists('ssh.hostname') && $this->config->exists('ssh.path')) { // Build path from ssh configuration - $ret = $this->config['ssh']['hostname'] . ':' . $this->config['ssh']['path']; + $ret = $this->config->get('ssh.hostname') . ':' . $this->config->get('ssh.path'); } return $ret; @@ -308,8 +315,8 @@ protected function getRsyncWorkingPath() { // remove right / $ret = rtrim($this->workingPath, '/'); - if (!empty($this->config['rsync']['target'])) { - $ret .= '/' . $this->config['rsync']['target']; + if ($this->config->exists('rsync.target')) { + $ret .= '/' . $this->config->get('rsync.target'); } return $ret; diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index 8c5f342..2b28411 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -57,14 +57,14 @@ protected function validateConfiguration() { protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { // File list $filelist = null; - if ($useExcludeInclude && !empty($this->config['rsync']['directory'])) { - $filelist = $this->config['rsync']['directory']; + if ($useExcludeInclude && $this->config->exists('rsync.directory')) { + $filelist = $this->config->get('rsync.directory'); } // Exclude list $exclude = null; - if ($useExcludeInclude && !empty($this->config['rsync']['exclude'])) { - $exclude = $this->config['rsync']['exclude']; + if ($useExcludeInclude && $this->config->exists('rsync.exclude')) { + $exclude = $this->config->get('rsync.exclude'); } return $this->createRsyncCommand($source, $target, $filelist, $exclude); diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index e237cfa..d885716 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -44,14 +44,12 @@ protected function validateConfiguration() { // SSH (optional) // ################## - if (!empty($this->config['ssh'])) { - + if ($this->config->exists('ssh')) { // Check if one database is configured - if (empty($this->config['ssh']['hostname'])) { + if (!$this->config->exists('ssh.hostname')) { $output->writeln('No ssh hostname configuration found'); $ret = false; } - } return $ret; diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index b34e296..2d0953b 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -38,7 +38,7 @@ protected function runTask() { // ################## // Backup dirs // ################## - if (!empty($this->config['rsync'])) { + if ($this->config->exists('rsync')) { $source = $this->getRsyncWorkingPath(); $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); @@ -48,14 +48,14 @@ protected function runTask() { // ################## // Backup databases // ################## - if (!empty($this->config['mysql'])) { - foreach ($this->config['mysql']['database'] as $database) { + if ($this->config->exists('mysql')) { + foreach ($this->config->getArray('mysql.database') as $database) { $this->output->writeln('Dumping database ' . $database . ''); // dump database $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; - $dumpFilter = $this->config['mysql']['filter'] ? $this->config['mysql']['filter'] : null; + $dumpFilter = $this->config->get('mysql.filter'); $this->createMysqlBackupCommand($database, $dumpFile, $dumpFilter) ->executeInteractive(); diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 23e63bb..f42d019 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -38,7 +38,7 @@ protected function runTask() { // ################## // Restore dirs // ################## - if (!empty($this->config['rsync'])) { + if ($this->config->exists('rsync')) { $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; $target = $this->getRsyncWorkingPath(); $command = $this->createShareRsyncCommand($source, $target, true); diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index b9c4f09..fcd8d89 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -65,13 +65,12 @@ protected function readConfiguration() { // Use server specific configuration $this->output->writeln('Syncing from "' . $this->contextName . '" server'); - $fullConfig = $this->config; - - if (!empty($fullConfig['_'])) { + // Jump into section + if ($this->config->exists('_')) { // Merge global config with specific config - $this->config = array_replace_recursive($fullConfig['_'], $this->config[$this->contextName]); + $this->config->setData(array_replace_recursive($this->config->getArray('_'), $this->config->getArray($this->contextName))); } else { - $this->config = $this->config[$this->contextName]; + $this->config->setData($this->config->getArray($this->contextName)); } } @@ -80,18 +79,19 @@ protected function readConfiguration() { */ protected function runTask() { // Check database connection - if (!empty($this->config['mysql'])) { + if ($this->config->exists('mysql')) { DatabaseConnection::ping(); } // Sync files with rsync to local storage - if (!empty($this->config['rsync'])) { + if ($this->config->exists('rsync')) { + $this->output->writeln(' ---- Starting FILE sync ---- '); $this->runTaskRsync(); } // Sync database to local server - if (!empty($this->config['mysql'])) { - // Full mysql transfer + if ($this->config->exists('mysql')) { + $this->output->writeln(' ---- Starting MYSQL sync ---- '); $this->runTaskDatabase(); } } @@ -116,9 +116,7 @@ protected function runTaskDatabase() { // ################## // Sync databases // ################## - $mysqlConf = $this->config['mysql']; - - foreach ($mysqlConf['database'] as $databaseConf) { + foreach ($this->config->getArray('mysql.database') as $databaseConf) { if (strpos($databaseConf, ':') !== false) { // local and foreign database in one string list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); @@ -175,18 +173,18 @@ protected function createMySqlCommand($database = null) { ->addArgument('-N'); // Add username - if (!empty($this->config['mysql']['username'])) { - $command->addArgumentTemplate('-u%s', $this->config['mysql']['username']); + if ($this->config->exists('mysql.username')) { + $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); } // Add password - if (!empty($this->config['mysql']['password'])) { - $command->addArgumentTemplate('-p%s', $this->config['mysql']['password']); + if ($this->config->exists('mysql.password')) { + $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); } // Add hostname - if (!empty($this->config['mysql']['hostname'])) { - $command->addArgumentTemplate('-h%s', $this->config['mysql']['hostname']); + if ($this->config->exists('mysql.hostname')) { + $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); } if ($database !== null) { @@ -206,40 +204,37 @@ protected function createMySqlCommand($database = null) { protected function createMySqlDumpCommand($database = null) { $command = new RemoteCommandBuilder('mysqldump'); - // Add username - if (!empty($this->config['mysql']['username'])) { - $command->addArgumentTemplate('-u%s', $this->config['mysql']['username']); + if ($this->config->exists('mysql.username')) { + $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); } // Add password - if (!empty($this->config['mysql']['password'])) { - $command->addArgumentTemplate('-p%s', $this->config['mysql']['password']); + if ($this->config->exists('mysql.password')) { + $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); } // Add hostname - if (!empty($this->config['mysql']['hostname'])) { - $command->addArgumentTemplate('-h%s', $this->config['mysql']['hostname']); + if ($this->config->exists('mysql.hostname')) { + $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); } // Add custom options - if (!empty($this->config['mysqldump']['option'])) { - $command->addArgumentRaw($this->config['mysqldump']['option']); + if ($this->config->exists('mysqldump.option')) { + $command->addArgumentRaw($this->config->get('mysqldump.option')); } - - if (!empty($this->config['mysql']['compression'])) { - switch($this->config['mysql']['compression']) { - case 'bzip2': - // Add pipe compressor (bzip2 compressed transfer via ssh) - $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); - break; - - case 'gzip': - // Add pipe compressor (gzip compressed transfer via ssh) - $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); - break; - } + // Transfer compression + switch($this->config->get('mysql.compression')) { + case 'bzip2': + // Add pipe compressor (bzip2 compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + break; + + case 'gzip': + // Add pipe compressor (gzip compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); + break; } @@ -258,9 +253,9 @@ protected function createMySqlDumpCommand($database = null) { */ protected function wrapCommand(CommandBuilderInterface $command) { // Wrap in ssh if needed - if (!empty($this->config['ssh']['hostname'])) { + if ($this->config->exists('ssh.hostname')) { $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); - $sshCommand->addArgument($this->config['ssh']['hostname']) + $sshCommand->addArgument($this->config->get('ssh.hostname')) ->append($command, true); $command = $sshCommand; @@ -281,13 +276,13 @@ protected function wrapCommand(CommandBuilderInterface $command) { */ protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { // Add file list (external file with --files-from option) - if (!$filelist && !empty($this->config['rsync']['directory'])) { - $filelist = $this->config['rsync']['directory']; + if (!$filelist && $this->config->exists('rsync.directory')) { + $filelist = $this->config->get('rsync.directory'); } // Add exclude (external file with --exclude-from option) - if (!$exclude && !empty($this->config['rsync']['exclude'])) { - $exclude = $this->config['rsync']['exclude']; + if (!$exclude && $this->config->exists('rsync.exclude')) { + $exclude = $this->config->exists('rsync.exclude'); } return parent::createRsyncCommand($source, $target, $filelist, $exclude); From f5505ed8e4689df3ea73faf635b9606419c664fb Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 22:41:22 +0200 Subject: [PATCH 105/214] Added sync:server with --rsync and --mysql Fixes #32 --- .../Console/Command/Sync/ServerCommand.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index fcd8d89..b7a7049 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -26,6 +26,7 @@ use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; use CliTools\Database\DatabaseConnection; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; class ServerCommand extends AbstractSyncCommand { @@ -47,6 +48,18 @@ protected function configure() { 'context', InputArgument::REQUIRED, 'Configuration name for server' + ) + ->addOption( + 'mysql', + null, + InputOption::VALUE_NONE, + 'Run only mysql' + ) + ->addOption( + 'rsync', + null, + InputOption::VALUE_NONE, + 'Run only rsync' ); } @@ -65,13 +78,32 @@ protected function readConfiguration() { // Use server specific configuration $this->output->writeln('Syncing from "' . $this->contextName . '" server'); + // ################## // Jump into section + // ################## if ($this->config->exists('_')) { // Merge global config with specific config $this->config->setData(array_replace_recursive($this->config->getArray('_'), $this->config->getArray($this->contextName))); } else { $this->config->setData($this->config->getArray($this->contextName)); } + + // ################## + // Option specific runners + // ################## + + if ($this->input->getOption('mysql') || $this->input->getOption('rsync')) { + // Clear mysql config if mysql isn't active + if (!$this->input->getOption('mysql')) { + $this->config->clear('mysql'); + } + + // Clear rsync config if rsync isn't active + if (!$this->input->getOption('rsync')) { + $this->config->clear('rsync'); + } + } + } /** From 09b82b8b298e2f21710006983ac17247fc87be4b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 23:30:05 +0200 Subject: [PATCH 106/214] Some refactoring --- .../Console/Command/Sync/AbstractCommand.php | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 494aaf3..eb4a26e 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -71,30 +71,45 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand protected $taskConf = array(); /** - * Execute command + * Initializes the command just after the input has been validated. * - * @param InputInterface $input Input instance - * @param OutputInterface $output Output instance + * This is mainly useful when a lot of commands extends one main command + * where some things need to be initialized based on the input arguments and options. * - * @return int|null|void - * @throws \Exception + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * @throws \RuntimeException */ - public function execute(InputInterface $input, OutputInterface $output) { - $this->workingPath = UnixUtility::findFileInDirectortyTree(self::CONFIG_FILE); + protected function initialize(InputInterface $input, OutputInterface $output) { + parent::initialize($input, $output); + + // Find configuration file + $this->workingPath = UnixUtility::findFileInDirectortyTree(self::CONFIG_FILE); if (empty($this->workingPath)) { - $this->output->writeln('No ' . self::CONFIG_FILE . ' found in tree'); - return 1; + throw new \RuntimeException('No ' . self::CONFIG_FILE . ' found in tree'); } + $output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); - $this->output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); - + // Read configuration $this->readConfiguration(); + // Validate configuration if (!$this->validateConfiguration()) { - $this->output->writeln('Configuration could not be validated'); - exit(1); + throw new \RuntimeException('Configuration could not be validated'); } + } + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + * @throws \Exception + */ + public function execute(InputInterface $input, OutputInterface $output) { $this->startup(); try { From 3000516030aabac688094cfb6afbcc3b9f96375f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 19 May 2015 23:30:14 +0200 Subject: [PATCH 107/214] Added sync:server to README --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c4e903..8e52e2a 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,10 @@ All log commands are using a grep-filter (specified as optional argument) | ct sync:init | Create example clisync.yml in current working directory | | ct sync:backup | Search for clisync.yml in tree and start backup to shared server | | ct sync:restore | Search for clisync.yml in tree and start restore from shared server | - +| ct sync:server | Search for clisync.yml in tree and start server synchronization (eg. from live or preview to local development instance | +| | __ct sync:server production__ -> Use "production" configuration and start sync | +| | __ct sync:server preview --rsync__ -> Use "preview" configuration and start only rsync | +| | __ct sync:server staging --mysql__ -> Use "staging" configuration and start only mysql sync | ### PHP commands From 6180e0bd8ddfbc79b202371055bd56af7186641c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 10:01:29 +0200 Subject: [PATCH 108/214] Added editor command builder --- .../CommandBuilder/EditorCommandBuilder.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/app/CliTools/Console/Shell/CommandBuilder/EditorCommandBuilder.php diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/EditorCommandBuilder.php b/src/app/CliTools/Console/Shell/CommandBuilder/EditorCommandBuilder.php new file mode 100644 index 0000000..33c3fe1 --- /dev/null +++ b/src/app/CliTools/Console/Shell/CommandBuilder/EditorCommandBuilder.php @@ -0,0 +1,41 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +class EditorCommandBuilder extends CommandBuilder { + + /** + * Initalized command + * + * @throws \RuntimeException + */ + protected function initialize() { + parent::initialize(); + + $editorCmd = getenv('EDITOR'); + + if (empty($editorCmd)) { + throw new \RuntimeException('No $EDITOR environment variable set'); + } + + $this->parse($editorCmd); + } +} From 041afb6428a6cf4075b6b0d2b8c2b1dd7816859c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 10:01:36 +0200 Subject: [PATCH 109/214] Added finish message list --- .../Console/Command/AbstractCommand.php | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index f3f319f..bc007ba 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -29,6 +29,13 @@ abstract class AbstractCommand extends Command { + /** + * Message list (will be shown at the end) + * + * @var array + */ + protected $finishMessageList = array(); + /** * Input * @@ -59,6 +66,40 @@ protected function initialize(InputInterface $input, OutputInterface $output) { ConsoleUtility::initialize($input, $output); } + /** + * Runs the command. + * + * The code to execute is either defined directly with the + * setCode() method or by overriding the execute() method + * in a sub-class. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * + * @return int The command exit code + * + * @throws \Exception + * + * @see setCode() + * @see execute() + * + * @api + */ + public function run(InputInterface $input, OutputInterface $output) { + + try { + $ret = parent::run($input, $output); + } catch (\Exception $e) { + $this->showFinishMessages(); + throw $e; + } + + $this->showFinishMessages(); + + return $ret; + } + + /** * Get full parameter list * @@ -142,4 +183,23 @@ protected function showLog($logList, $input, $output, $grep = null, $optionList return 0; } + + /** + * Add message to finish list + * + * @param string $message Message + */ + protected function addFinishMessage($message) { + $this->output->writeln($message); + $this->messageList[] = $message; + } + + /** + * Show all finish messages + */ + protected function showFinishMessages() { + foreach ($this->finishMessageList as $message) { + $this->output->writeln($message); + } + } } From 55a52b5fe09929fe4ca0901cdde511cfc6cb609c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 12:19:48 +0200 Subject: [PATCH 110/214] Add finish messages --- .../Console/Command/AbstractCommand.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index bc007ba..04101ba 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -89,13 +89,12 @@ public function run(InputInterface $input, OutputInterface $output) { try { $ret = parent::run($input, $output); + $this->showFinishMessages(); } catch (\Exception $e) { $this->showFinishMessages(); throw $e; } - $this->showFinishMessages(); - return $ret; } @@ -191,15 +190,23 @@ protected function showLog($logList, $input, $output, $grep = null, $optionList */ protected function addFinishMessage($message) { $this->output->writeln($message); - $this->messageList[] = $message; + $this->finishMessageList[] = $message; } /** * Show all finish messages */ protected function showFinishMessages() { - foreach ($this->finishMessageList as $message) { - $this->output->writeln($message); + + if (!empty($this->finishMessageList)) { + $this->output->writeln(''); + $this->output->writeln('Replay finish message log:'); + + foreach ($this->finishMessageList as $message) { + $this->output->writeln(' - ' . $message); + } } + + $this->finishMessageList = array(); } } From a1fb7a59f59c1e36724cbb1aafb92fe55b2f2180 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 12:20:03 +0200 Subject: [PATCH 111/214] Refactored editor command (with EditorCommandBuilder) --- src/app/CliTools/Console/Command/Sync/InitCommand.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 7e33e92..43f623c 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -21,6 +21,7 @@ */ use CliTools\Utility\PhpUtility; +use CliTools\Console\Shell\CommandBuilder\EditorCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -154,16 +155,15 @@ public function execute(InputInterface $input, OutputInterface $output) { PhpUtility::filePutContents($cliSyncFilePath, $content); // Start editor with file (if $EDITOR is set) - $editorCmd = getenv('EDITOR'); - if (!empty($editorCmd)) { - $editor = new \CliTools\Console\Shell\CommandBuilder\CommandBuilder(); + try { + $editor = new EditorCommandBuilder(); $editor - ->parse($editorCmd) ->addArgument($cliSyncFilePath) ->executeInteractive(); + } catch (\Exception $e) { + $this->output->writeln('' . $e->getMessage() . ''); } - $this->output->writeln('Successfully created ' . AbstractCommand::CONFIG_FILE . ' '); } From 4228fbd7d09c0423c3940d03471627d532b73af7 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 12:20:58 +0200 Subject: [PATCH 112/214] Added interactive edit of docker-compose.yml and docker-env.yml Also added finish message if make fails Fixes #34 --- .../Console/Command/Docker/CreateCommand.php | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index 03946a7..d885b8f 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -20,9 +20,10 @@ * along with this program. If not, see . */ +use CliTools\Utility\PhpUtility; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; -use CliTools\Utility\PhpUtility; +use CliTools\Console\Shell\CommandBuilder\EditorCommandBuilder; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; @@ -96,13 +97,17 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->initDocumentRoot($path); PhpUtility::chdir($currDir); + // Start interactive editor + $this->startInteractiveEditor($path . '/docker-compose.yml'); + $this->startInteractiveEditor($path . '/docker-env.yml'); + // Run makefile if ($this->input->getOption('make')) { try { $this->runMakefile($path, $input->getOption('make')); PhpUtility::chdir($currDir); } catch (\Exception $e) { - $output->writeln('Make command failed: ' . $e->getMessage() . ''); + $this->addFinishMessage('Make command failed: ' . $e->getMessage() . ''); } } } @@ -114,6 +119,29 @@ public function execute(InputInterface $input, OutputInterface $output) { return 0; } + /** + * Start interactive editor + * + * @param string $path Path to file + */ + protected function startInteractiveEditor($path) { + if (file_exists($path)) { + // Start editor with file (if $EDITOR is set) + try { + $editor = new EditorCommandBuilder(); + + $this->output->writeln('Starting interactive EDITOR for file ' .$path . ''); + sleep(1); + + $editor + ->addArgument($path) + ->executeInteractive(); + } catch (\Exception $e) { + $this->addFinishMessage('' . $e->getMessage() . ''); + } + } + } + /** * Create docker instance from git repository * @@ -204,7 +232,7 @@ protected function runMakefile($path, $makeCommand) { $path .= '/code'; $this->output->writeln('Running make with command "' . $makeCommand . '"'); - + try { PhpUtility::chdir($path); // Remove code directory @@ -212,7 +240,9 @@ protected function runMakefile($path, $makeCommand) { $command ->addArgument($makeCommand) ->executeInteractive(); - + } catch (\Exception $e) { + $this->addFinishMessage('Make command failed: ' . $e->getMessage() . ''); + } } /** @@ -229,4 +259,5 @@ protected function startDockerInstance($path) { $command->addArgument('docker:up'); $command->executeInteractive(); } + } From ed68fb4d76bc82c22de64c0eedce8e02c7cbf00d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 13:36:43 +0200 Subject: [PATCH 113/214] Fixed issue with sync backup/restore if disabled rsync --- src/app/CliTools/Console/Command/Sync/BackupCommand.php | 4 ++-- src/app/CliTools/Console/Command/Sync/RestoreCommand.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 2d0953b..b466316 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -38,7 +38,7 @@ protected function runTask() { // ################## // Backup dirs // ################## - if ($this->config->exists('rsync')) { + if ($this->config->exists('rsync.directory')) { $source = $this->getRsyncWorkingPath(); $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; $command = $this->createShareRsyncCommand($source, $target, true); @@ -48,7 +48,7 @@ protected function runTask() { // ################## // Backup databases // ################## - if ($this->config->exists('mysql')) { + if ($this->config->exists('mysql.database')) { foreach ($this->config->getArray('mysql.database') as $database) { $this->output->writeln('Dumping database ' . $database . ''); diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index f42d019..cb32ba6 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -38,7 +38,7 @@ protected function runTask() { // ################## // Restore dirs // ################## - if ($this->config->exists('rsync')) { + if ($this->config->exists('rsync.directory')) { $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; $target = $this->getRsyncWorkingPath(); $command = $this->createShareRsyncCommand($source, $target, true); From 81be74ec9d0e3e2b3d89d234a20f98e724e3fdc2 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 13:36:51 +0200 Subject: [PATCH 114/214] Set version to 1.9.905 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index 60288cf..32b27c3 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.10.0'); +define('CLITOOLS_COMMAND_VERSION', '1.9.905'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From 1ef7b23eafe923684e0b9c2fc35c687544d1328b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 23:38:43 +0200 Subject: [PATCH 115/214] Added stop exception --- src/app/CliTools/Console/Application.php | 13 ++++++++++ src/app/CliTools/Exception/StopException.php | 27 ++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/app/CliTools/Exception/StopException.php diff --git a/src/app/CliTools/Console/Application.php b/src/app/CliTools/Console/Application.php index 4d3151a..f229277 100644 --- a/src/app/CliTools/Console/Application.php +++ b/src/app/CliTools/Console/Application.php @@ -160,6 +160,9 @@ public function doRun(InputInterface $input, OutputInterface $output) { } else { $ret = parent::doRun($input, $output); } + } catch(\CliTools\Exception\StopException $e) { + $this->callTearDown(); + $ret = (int)$e->getMessage(); } catch (\Exception $e) { $this->callTearDown(); throw $e; @@ -321,4 +324,14 @@ public function getSettingsService() { } return $this->settingsService; } + + /** + * Set process title + * + * @param string $title Title + */ + public function setProcessTitle($title) { + // DECSLPP. + echo "\033]0;" . 'ct: ' . $title . "\033\\"; + } } diff --git a/src/app/CliTools/Exception/StopException.php b/src/app/CliTools/Exception/StopException.php new file mode 100644 index 0000000..e9a5f26 --- /dev/null +++ b/src/app/CliTools/Exception/StopException.php @@ -0,0 +1,27 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; + +class StopException extends \RuntimeException { + +} From 5682c69b37350fe6a5e3a5b43b71b729219d7e0b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 23:39:10 +0200 Subject: [PATCH 116/214] Implemented stop exception instead of exit --- src/app/CliTools/Console/Command/AbstractCommand.php | 2 +- src/app/CliTools/Console/Command/Mysql/DebugCommand.php | 2 +- src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index 04101ba..cd167b2 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -139,7 +139,7 @@ protected function elevateProcess(InputInterface $input, OutputInterface $output } catch (\Exception $e) { // do not display exception here because it's a child process } - exit(0); + throw new \CliTools\Exception\StopException(0); } else { // running as root } diff --git a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php index a6cc1a7..721e987 100644 --- a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php @@ -60,7 +60,7 @@ public function execute(InputInterface $input, OutputInterface $output) { if (!is_dir($debugLogDir)) { if (!mkdir($debugLogDir, 0777, true)) { $output->writeln('Could not create "' . $debugLogDir . '" directory'); - exit(1); + throw new \CliTools\Exception\StopException(1); } } diff --git a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php index 02a9926..4955198 100644 --- a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php @@ -85,7 +85,7 @@ public function execute(InputInterface $input, OutputInterface $output) { if (!is_dir($debugLogDir)) { if (!mkdir($debugLogDir, 0777, true)) { $output->writeln('Could not create "' . $debugLogDir . '" directory'); - exit(1); + throw new \CliTools\Exception\StopException(1); } } From 2ad2392f44bd711f1bf8669692aff644d3f4e089 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 23:56:08 +0200 Subject: [PATCH 117/214] Implemented process title --- .../CliTools/Console/Command/Docker/CreateCommand.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index d885b8f..5251f51 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -130,6 +130,8 @@ protected function startInteractiveEditor($path) { try { $editor = new EditorCommandBuilder(); + $this->getApplication()->setProcessTitle('Edit ' . basename($path)); + $this->output->writeln('Starting interactive EDITOR for file ' .$path . ''); sleep(1); @@ -149,6 +151,8 @@ protected function startInteractiveEditor($path) { * @param string $repo Repository */ protected function createDockerInstance($path, $repo) { + $this->getApplication()->setProcessTitle('Cloning docker'); + $this->output->writeln('Create new docker boilerplate in "' . $path . '"'); $command = new CommandBuilder('git','clone --branch=master --recursive %s %s', array($repo, $path)); @@ -162,6 +166,8 @@ protected function createDockerInstance($path, $repo) { * @param string $repo Repository */ protected function initCode($path, $repo) { + $this->getApplication()->setProcessTitle('Cloning code'); + $path .= '/code'; $this->output->writeln('Initialize new code instance in "' . $path . '"'); @@ -229,6 +235,8 @@ protected function initDocumentRoot($path) { * @param string $makeCommand Makefile command */ protected function runMakefile($path, $makeCommand) { + $this->getApplication()->setProcessTitle('Run make'); + $path .= '/code'; $this->output->writeln('Running make with command "' . $makeCommand . '"'); @@ -251,6 +259,8 @@ protected function runMakefile($path, $makeCommand) { * @param string $path Path */ protected function startDockerInstance($path) { + $this->getApplication()->setProcessTitle('Start docker'); + $this->output->writeln('Building docker containers "' . $path . '"'); PhpUtility::chdir($path); From 66453963220aaa7f70d59f0d44114b3ed9cc690a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 23:56:19 +0200 Subject: [PATCH 118/214] Added pre check if docker is running --- .../Console/Command/Sync/AbstractCommand.php | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index eb4a26e..84b9ddd 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -22,6 +22,7 @@ use CliTools\Utility\PhpUtility; use CliTools\Utility\UnixUtility; +use CliTools\Utility\ConsoleUtility; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; use CliTools\Reader\ConfigReader; @@ -227,6 +228,8 @@ protected function startup() { $this->clearTempDir(); PhpUtility::mkdir($this->tempDir, 0777, true); PhpUtility::mkdir($this->tempDir . '/mysql/', 0777, true); + + $this->checkIfDockerExists(); } /** @@ -249,6 +252,28 @@ protected function clearTempDir() { } } + /** + * Check if docker exists + * + * @throws \CliTools\Exception\StopException + */ + protected function checkIfDockerExists() { + $dockerPath = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); + + if (!empty($dockerPath)) { + $this->output->writeln('Running docker containers:'); + + // Docker instance found + $docker = new CommandBuilder('docker', 'ps'); + $docker->executeInteractive(); + + $answer = ConsoleUtility::questionYesNo('Are these running containers the right one?', 'no'); + + if (!$answer) { + throw new \CliTools\Exception\StopException(1); + } + } + } /** * Run finalize tasks From b8b60fd276b11bf3ba1faf8033dacb252bb872c1 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 23:56:49 +0200 Subject: [PATCH 119/214] Added questionYesNo --- src/app/CliTools/Utility/ConsoleUtility.php | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/app/CliTools/Utility/ConsoleUtility.php b/src/app/CliTools/Utility/ConsoleUtility.php index 1c4dc93..1dad09e 100644 --- a/src/app/CliTools/Utility/ConsoleUtility.php +++ b/src/app/CliTools/Utility/ConsoleUtility.php @@ -20,6 +20,8 @@ * along with this program. If not, see . */ +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -108,4 +110,32 @@ public static function verboseWriteln($area, $line) { self::$output->writeln($line); } } + + /** + * Ask question with yes/no detection + * + * @param string $question Question + * @param string $default Default + * + * @return bool + */ + public static function questionYesNo($message, $default) { + $ret = false; + + while (1) { + $question = new Question(' >>> ' . $message . ' [yes/no] ', $default); + $questionDialog = new QuestionHelper(); + $answer = $questionDialog->ask(self::$input, self::$output, $question); + + if (stripos($answer, 'n') === 0) { + $ret = false; + break; + } elseif (stripos($answer, 'y') === 0) { + $ret = true; + break; + } + } + + return $ret; + } } From aabc5741499fd9853edb020694ae449e06c4a633 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 20 May 2015 23:56:58 +0200 Subject: [PATCH 120/214] Verion bump to 1.9.906 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index 32b27c3..96b1d11 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.905'); +define('CLITOOLS_COMMAND_VERSION', '1.9.906'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From a22b971df77cb97d19766616f1e5385752523205 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 21 May 2015 16:45:56 +0200 Subject: [PATCH 121/214] Fixed badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8e52e2a..eff7e8a 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ ![latest v1.9.0](https://img.shields.io/badge/latest-v1.9.0-green.svg?style=flat) ![License GPL3](https://img.shields.io/badge/license-GPL3-blue.svg?style=flat) -[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/mblaschke/vagrant-clitools.svg)](http://isitmaintained.com/project/mblaschke/vagrant-clitools "Average time to resolve an issue") -[![Percentage of issues still open](http://isitmaintained.com/badge/open/mblaschke/vagrant-clitools.svg)](http://isitmaintained.com/project/mblaschke/vagrant-clitools "Percentage of issues still open") +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/mblaschke/clitools.svg)](http://isitmaintained.com/project/mblaschke/clitools "Average time to resolve an issue") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/mblaschke/clitools.svg)](http://isitmaintained.com/project/mblaschke/clitools "Percentage of issues still open") [![SensioLabsInsight](https://insight.sensiolabs.com/projects/9f12f125-3623-4b9d-b01b-07090f91e416/big.png)](https://insight.sensiolabs.com/projects/9f12f125-3623-4b9d-b01b-07090f91e416) From ab8bf494ebe885300bfdd8e8c3e70467ed6284e9 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 21 May 2015 20:53:47 +0200 Subject: [PATCH 122/214] Added insert method --- .../CliTools/Database/DatabaseConnection.php | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/app/CliTools/Database/DatabaseConnection.php b/src/app/CliTools/Database/DatabaseConnection.php index ba5457d..b674d83 100644 --- a/src/app/CliTools/Database/DatabaseConnection.php +++ b/src/app/CliTools/Database/DatabaseConnection.php @@ -192,6 +192,29 @@ public static function exec($query) { return $ret; } + + /** + * Generate and execute INSERT query + * + * @param string $table Table name + * @param array $values Values + * + * @return int + * @throws \PDOException + */ + public static function insert($table, $values) { + $fieldList = array_keys($values); + + $valueList = array(); + foreach ($values as $value) { + $valueList[] = self::quote($value); + } + + $query = 'INSERT INTO %s (%s) VALUES (%s)'; + $query = sprintf($query, $table, implode(',',$fieldList), implode(',',$valueList)); + self::exec($query); + } + /** * Quote * From 973230b721452db510ca7febcecbb7f1d490cf29 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 21 May 2015 22:05:58 +0200 Subject: [PATCH 123/214] Added more workflow stuff in typo3:domain --- CHANGELOG.md | 3 + README.md | 4 + .../Console/Command/TYPO3/DomainCommand.php | 119 ++++++++++++++---- 3 files changed, 104 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec654c4..c70ca8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ CliTools Changelog - Added `sync:server` for syncing any configured server to your local development system (reads clisync.yml) - Added `sync:backup` for backup to a shared server (reads clisync.yml) - Added `sync:restore` for restore from a shared server (reads clisync.yml) +- Added `typo3:domain --list` for only list the domains of one or all databases +- Added `typo3:domain --remove=domain/pattern` for domain cleanup (eg. vagrant share) +- Added `typo3:domain --duplication=suffix` for domain duplication - Refactored some classes - Fixed some issues - Added gzip compression for PHAR diff --git a/README.md b/README.md index eff7e8a..05d1766 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,10 @@ All log commands are using a grep-filter (specified as optional argument) | ct typo3:cleanup | Cleanup command tables to same some table space | | | __ct typo3:cleanup__ | | | __ct typo3:cleanup typo3__ | +| ct typo3:domain | Add default suffix to all domains (default: .vm) | +| | __ct typo3:domain --list__ Print list of domains and exit | +| | __ct typo3:domain --remove='*.vagrantshare.com'__ Remove all *.vagrantshare.com domains (used by vagrant:share command) | +| | __ct typo3:domain --duplicate='foobar.vagrantshare.com'__ Duplicates all domains and add suffix 'foobar.vagrantshare.com' (used by vagrant:share command) | ### User commands diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index fd3b59c..b0d54db 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -21,6 +21,7 @@ */ use CliTools\Database\DatabaseConnection; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -38,9 +39,26 @@ protected function configure() { 'db', InputArgument::OPTIONAL, 'Database name' + ) + ->addOption( + 'list', + null, + InputOption::VALUE_NONE, + 'List only databases' + ) + ->addOption( + 'remove', + null, + InputOption::VALUE_REQUIRED, + 'Remove domain (with wildcard support)' + ) + ->addOption( + 'duplicate', + null, + InputOption::VALUE_REQUIRED, + 'Add duplication domains (will duplicate all domains in system, eg. for vagrant share)' ); } - /** * Execute command * @@ -74,17 +92,91 @@ public function execute(InputInterface $input, OutputInterface $output) { $isTypo3Database = DatabaseConnection::getOne($query); if ($isTypo3Database) { - $this->setupDevelopmentDomainsForDatabase($dbName); + $this->runTaskForDomain($dbName); } } } else { // ############## // One databases // ############## - $this->setupDevelopmentDomainsForDatabase($dbName); + $this->runTaskForDomain($dbName); + } + } + + /** + * Run tasks for one domain + */ + protected function runTaskForDomain($dbName) { + DatabaseConnection::switchDatabase($dbName); + + if ($this->input->getOption('list')) { + // Show domain list (and skip all other tasks) + $this->showDomainList($dbName); + } else { + // Remove domains (eg. for cleanup) + if ($this->input->getOption('remove')) { + $this->removeDomains($this->input->getOption('remove')); + } + + // Set development domains + $this->manipulateDomains($dbName); + + // Add sharing domains + if ($this->input->getOption('duplicate')) { + $this->addDuplicateDomains($this->input->getOption('duplicate')); + } + + // Show domain list + $this->showDomainList($dbName); } + } + + /** + * Remove domains + */ + protected function removeDomains($pattern) { + $pattern = str_replace('*', '%', $pattern); - return 0; + $query = 'DELETE FROM sys_domain WHERE domainName LIKE %s'; + $query = sprintf($query, DatabaseConnection::quote($pattern)); + DatabaseConnection::exec($query); + } + + + /** + * Add share domains (eg. for vagrantshare) + * + * @param string $suffix Domain suffix + */ + protected function addDuplicateDomains($suffix) { + + $query = 'SELECT * FROM sys_domain'; + $domainList = DatabaseConnection::getAll($query); + + foreach ($domainList as $domain) { + unset($domain['uid']); + + $domain['domainName'] .= '.' . ltrim($suffix, '.'); + + DatabaseConnection::insert('sys_domain', $domain); + } + } + + /** + * Show list of domains + * + * @param string $dbName Domain name + */ + protected function showDomainList($dbName) { + $query = 'SELECT domainName FROM sys_domain ORDER BY domainName ASC'; + $domainList = DatabaseConnection::getCol($query); + + $this->output->writeln('Domain list of "' . $dbName . '":'); + + foreach ($domainList as $domain) { + $this->output->writeln(' ' . $domain . ''); + } + $this->output->writeln(''); } /** @@ -94,7 +186,7 @@ public function execute(InputInterface $input, OutputInterface $output) { * * @return void */ - protected function setupDevelopmentDomainsForDatabase($database) { + protected function manipulateDomains($database) { $domain = '.' . $this->getApplication()->getConfigValue('config', 'domain_dev'); $domainLength = strlen($domain); @@ -107,23 +199,6 @@ protected function setupDevelopmentDomainsForDatabase($database) { SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($domain) . ') WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($domain); DatabaseConnection::exec($query); - - // ################## - // Show all domains - // ################## - $query = 'SELECT domainName - FROM ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - WHERE hidden = 0'; - $domainList = DatabaseConnection::getCol($query); - - $this->output->writeln('Domain list of "' . $database . '":'); - - foreach ($domainList as $domain) { - $this->output->writeln(' ' . $domain . ''); - } - $this->output->writeln(''); - } else { - $this->output->writeln('Table "sys_domain" doesn\'t exists in database "' . $database . '"'); } } } From 5e8a22f3970cd84d8f9018c10fda3e8b5a98854a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 21 May 2015 22:06:52 +0200 Subject: [PATCH 124/214] Added callbacks for executor --- .../Shell/CommandBuilder/AbstractCommandBuilder.php | 5 +++-- src/app/CliTools/Console/Shell/Executor.php | 12 +++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php index 6279754..938d4f4 100644 --- a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php @@ -552,10 +552,11 @@ public function execute() { /** * Execute command * + * @param array $opts Option array * @return Executor */ - public function executeInteractive() { - return $this->getExecutor()->execInteractive(); + public function executeInteractive(array $opts = null) { + return $this->getExecutor()->execInteractive($opts); } /** diff --git a/src/app/CliTools/Console/Shell/Executor.php b/src/app/CliTools/Console/Shell/Executor.php index 2997882..778cf09 100644 --- a/src/app/CliTools/Console/Shell/Executor.php +++ b/src/app/CliTools/Console/Shell/Executor.php @@ -193,10 +193,11 @@ public function execute() { /** * Execute interactive * + * @param array $opts Option array * @return $this * @throws \Exception */ - public function execInteractive() { + public function execInteractive(array $opts = null) { $this->checkCommand(); ConsoleUtility::verboseWriteln('EXEC::INTERACTIVE', $this->command->build()); @@ -211,9 +212,18 @@ public function execInteractive() { if (is_resource($process)) { + if (!empty($opts['startupCallback']) && is_callable($opts['startupCallback'])) { + $opts['startupCallback']($process); + } + do { usleep(50 * 1000); $status = proc_get_status($process); + + if (!empty($opts['runningCallback']) && is_callable($opts['runningCallback'])) { + $opts['runningCallback']($process, $status); + } + } while (is_array($status) && $status['running'] === true); $this->returnCode = $status['exitcode']; From 81850c35985b1f2524639e2a00318a64cdf22c5e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 21 May 2015 22:48:52 +0200 Subject: [PATCH 125/214] Added vagrant:share --- CHANGELOG.md | 1 + README.md | 6 ++ .../Console/Command/Vagrant/ShareCommand.php | 91 +++++++++++++++++++ src/config.ini | 2 + 4 files changed, 100 insertions(+) create mode 100644 src/app/CliTools/Console/Command/Vagrant/ShareCommand.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c70ca8b..0304d18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ CliTools Changelog - Added `typo3:domain --list` for only list the domains of one or all databases - Added `typo3:domain --remove=domain/pattern` for domain cleanup (eg. vagrant share) - Added `typo3:domain --duplication=suffix` for domain duplication +- Added `vagrant:share` with automatic domain setting for TYPO3 projects (ALPHA! not finished!) - Refactored some classes - Fixed some issues - Added gzip compression for PHAR diff --git a/README.md b/README.md index 05d1766..ff98b8a 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,12 @@ All log commands are using a grep-filter (specified as optional argument) | | __ct typo3:domain --remove='*.vagrantshare.com'__ Remove all *.vagrantshare.com domains (used by vagrant:share command) | | | __ct typo3:domain --duplicate='foobar.vagrantshare.com'__ Duplicates all domains and add suffix 'foobar.vagrantshare.com' (used by vagrant:share command) | +### Vagrant commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct vagrant:share | Start sharing (with some workflow stuff) (ALPHA! not finished!) | + ### User commands | Command | Description | diff --git a/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php new file mode 100644 index 0000000..6e923cc --- /dev/null +++ b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php @@ -0,0 +1,91 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ShareCommand extends \CliTools\Console\Command\AbstractCommand { + + /** + * Configure command + */ + protected function configure() { + $this + ->setName('vagrant:share') + ->setDescription('Start share for vagrant'); + } + + /** + * Execute command + * + * @param InputInterface $input Input instance + * @param OutputInterface $output Output instance + * + * @return int|null|void + */ + public function execute(InputInterface $input, OutputInterface $output) { + + $runningCallback = function($process, $status) { + static $domainFound = false; + if ($domainFound) { + return; + } + + $pid = $status['pid']; + + exec('pgrep -P ' . (int)$pid . ' | xargs ps -o command=', $output); + + if (!empty($output)) { + foreach ($output as $line) { + if (preg_match('/register\.vagrantshare\.com/', $line)) { + + if (preg_match('/-name ([^\s]+)/', $line, $matches)) { + $domainName = $matches[1]; + + $typo3Domain = new SelfCommandBuilder(); + $typo3Domain + ->addArgument('typo3:domain') + ->addArgument('--remove=*.vagrantshare.com') + ->addArgumentTemplate('--duplicate=%s', $domainName . '.vagrantshare.com') + ->execute(); + + $domainFound = true; + } + } + } + } + + }; + + $opts = array( + 'runningCallback' => $runningCallback, + ); + + $vagrant = new CommandBuilder('vagrant', 'share'); + $vagrant + ->addArgumentRaw('--http 80') + ->addArgumentRaw('--https 443') + ->executeInteractive($opts); + } +} diff --git a/src/config.ini b/src/config.ini index da28257..f2ab0c8 100644 --- a/src/config.ini +++ b/src/config.ini @@ -106,6 +106,8 @@ class[] = "CliTools\Console\Command\System\CrontaskCommand" class[] = "CliTools\Console\Command\User\RebuildSshConfigCommand" +class[] = "CliTools\Console\Command\Vagrant\ShareCommand" + exclude[] = "CliTools\Console\Command\*\RestartCommand" ; exclude this class (example) From b7f99b1a54b6685f8f9aea3166ed9fa598fcc598 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 21 May 2015 22:58:20 +0200 Subject: [PATCH 126/214] Cleanup --- src/app/CliTools/Console/Shell/Executor.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/app/CliTools/Console/Shell/Executor.php b/src/app/CliTools/Console/Shell/Executor.php index 778cf09..6ec7733 100644 --- a/src/app/CliTools/Console/Shell/Executor.php +++ b/src/app/CliTools/Console/Shell/Executor.php @@ -217,15 +217,12 @@ public function execInteractive(array $opts = null) { } do { - usleep(50 * 1000); $status = proc_get_status($process); - - if (!empty($opts['runningCallback']) && is_callable($opts['runningCallback'])) { + if (!empty($status) && !empty($opts['runningCallback']) && is_callable($opts['runningCallback'])) { $opts['runningCallback']($process, $status); } - - } while (is_array($status) && $status['running'] === true); - + usleep(100 * 1000); + } while (!empty($status) && is_array($status) && $status['running'] === true); $this->returnCode = $status['exitcode']; $this->runFinishers(); @@ -296,7 +293,9 @@ public function addFinisherCallback(callable $callback) { */ public function runFinishers() { foreach ($this->finishers as $call) { - $call($this); + if (is_callable($call)) { + $call($this); + } } } } From 20eb7f77db398bf88469373a2ead3c2a71109f3d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 21 May 2015 23:11:35 +0200 Subject: [PATCH 127/214] Improved vagrant share --- .../CliTools/Console/Command/Vagrant/ShareCommand.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php index 6e923cc..57c11bd 100644 --- a/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php +++ b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php @@ -66,7 +66,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $typo3Domain = new SelfCommandBuilder(); $typo3Domain ->addArgument('typo3:domain') - ->addArgument('--remove=*.vagrantshare.com') + ->addArgumentTemplate('--remove=%s', '*.vagrantshare.com') ->addArgumentTemplate('--duplicate=%s', $domainName . '.vagrantshare.com') ->execute(); @@ -75,8 +75,16 @@ public function execute(InputInterface $input, OutputInterface $output) { } } } + }; + $cleanupCallback = function() { + $typo3Domain = new SelfCommandBuilder(); + $typo3Domain + ->addArgument('typo3:domain') + ->addArgumentTemplate('--remove=%s', '*.vagrantshare.com') + ->execute(); }; + $this->getApplication()->registerTearDown($cleanupCallback); $opts = array( 'runningCallback' => $runningCallback, From 6167e3ffc56b3193b59ea995988958a4bfed2b24 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 11:57:35 +0200 Subject: [PATCH 128/214] Improved documentation --- Documentation/COMMANDS.md | 154 +++++++++++++++++++++++ Documentation/INSTALL.md | 121 ++++++++++++++++++ Documentation/USAGE.md | 50 ++++++++ README.md | 259 ++------------------------------------ 4 files changed, 332 insertions(+), 252 deletions(-) create mode 100644 Documentation/COMMANDS.md create mode 100644 Documentation/INSTALL.md create mode 100644 Documentation/USAGE.md diff --git a/Documentation/COMMANDS.md b/Documentation/COMMANDS.md new file mode 100644 index 0000000..4efd56f --- /dev/null +++ b/Documentation/COMMANDS.md @@ -0,0 +1,154 @@ +[<-- Back to main section](../README.md) + +## Commands + +### Special commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct self-update | Update ct command (download new version) | +| ct update | Updates all system components, ssh configuration, ct command update etc. | +| ct make | Search for "Makefile" in tree and start "make" in this directory | + +### System commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct shutdown (alias) | Shutdown system | + +### Log commands + +All log commands are using a grep-filter (specified as optional argument) + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct log:mail | Shows mail logs | + +### Docker commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct docker:create | Create new docker boilerplate in directory (first argument) | +| | __ct docker:create projectname__ -> Create new docker boilerplate instance in directory "projectname" | +| | __ct docker:create projectname --code=git@github.com/foo/bar__ -> Create new docker boilerplate instance in directory "projectname" and git code repository | +| | __ct docker:create projectname --docker=git@github.com/foo/bar__ -> Create new docker boilerplate instance in directory "projectname" and custom docker boilerplate repository | +| | __ct docker:create projectname --code=git@github.com/foo/bar --make=build__ -> Create new docker boilerplate instance in directory "projectname" and git code repository, will run automatic make (Makefile) task "build" after checkout | +| ct docker:shell | Jump into a shell inside a docker container (using predefined user defined with CLI_USER in docker env) | +| | __ct docker:shell__ -> enter main container | +| | __ct docker:shell mysql__ -> enter mysql container | +| | __ct docker:shell --user=www-data -> enter main container as user www-data | +| ct docker:root | Jump into a shell inside a docker container as root user | +| ct docker:mysql | Jump into a mysql client inside a docker container | +| | __ct docker:mysql__ -> execute mysql client inside main container | +| ct docker:sniff | Start network sniffer for various protocols | +| | __ct docker:sniff http__ -> start HTTP sniffing | +| ct docker:exec | Execute command in docker container | +| | __ct docker:exec ps__ -> run 'ps' inside main container | +| ct docker:cli | Execute special cli command in docker container | +| | __ct docker:cli scheduler__ -> run 'scheduler' in TYPO3 CMS | +| ct docker:compose | Execute docker-compose (recursive up-searching for docker-compose.yml) | +| | __ct docker:compose ps__ -> list all running docker-compose containers | + +### MySQL commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct mysql:clear | Clear database (remove all tables in database) | +| | __ct mysql:clear typo3__ | +| ct mysql:connections | Lists all current connections | +| ct mysql:create | Create (and drops if already exists) a database | +| | __ct mysql:create typo3__ | +| ct mysql:debug | Shows mysql debug log (lists all queries) with basic filter support | +| | __ct mysql:debug__ (full log) | +| | __ct mysql:debug tt_content__ (full log) | +| ct mysql:slowlog | Shows mysql slow log | +| | __ct mysql:slowlog__ (show slow queries with 1 sec and more) | +| | __ct mysql:slowlog --time=10__ (show slow queries with 10 sec and more) | +| | __ct mysql:slowlog --no-index__ (show not using index and slow (1sec) queries) | +| ct mysql:drop | Drops a database | +| | __ct mysql:drop typo3__ | +| ct mysql:list | Lists all databases with some statitics | +| ct mysql:restart | Restart MySQL server | +| ct mysql:backup | Backup a database to file | +| | Compression type will be detected from file extension (default plain sql) | +| | __ct mysql:restore typo3 dump.sql__ -> plain sql dump | +| | __ct mysql:restore typo3 dump.sql.gz__ -> gzip'ed sql dump | +| | __ct mysql:restore typo3 dump.sql.bzip2__ -> bzip2'ed sql dump | +| | __ct mysql:restore typo3 dump.sql.xz__ -> xz'ed (lzma'ed) sql dump | +| | __ct mysql:restore typo3 dump.sql --filter=typo3__ -> No TYPO3 cache tables in dump | +| ct mysql:restore | Create (and drops if already exists) a database and restore from a dump | +| | Dump file can be plaintext, gziped, bzip2 or lzma compressed | +| | and will automatically detected | +| | __ct mysql:restore typo3 dump.sql.bz2__ | +| ct mysql:convert | Convert character set and collation of a database | +| | __ct mysql:convert typo3__ -> Convert typo3 into UTF-8 with utf8_general_ci | +| | __ct mysql:convert typo3 --charset=latin1__ -> Convert typo3 into LATIN-1 | +| | __ct mysql:convert typo3 --collation=utf8_unicode_ci__ -> Convert typo3 into UTF-8 with utf8_unicode_ci | +| | __ct mysql:convert typo3 --stdout__ -> Print sql statements to stdout | + +### Sync commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct sync:init | Create example clisync.yml in current working directory | +| ct sync:backup | Search for clisync.yml in tree and start backup to shared server | +| ct sync:restore | Search for clisync.yml in tree and start restore from shared server | +| ct sync:server | Search for clisync.yml in tree and start server synchronization (eg. from live or preview to local development instance | +| | __ct sync:server production__ -> Use "production" configuration and start sync | +| | __ct sync:server preview --rsync__ -> Use "preview" configuration and start only rsync | +| | __ct sync:server staging --mysql__ -> Use "staging" configuration and start only mysql sync | + +### PHP commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct php:trace | Trace syscalls from one or all PHP processes (strace) | +| | __ct php:trace --all__ -> Trace all php processes immediately | +| ct php:composer | Search for "composer.yml" in tree and start "composer" in this directory | + +### Samba commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct samba:restart | Restart Samba server | + + +### System commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct system:env | Lists common environment variables | +| ct system:openfiles | Lists current open files count grouped by process | +| ct system:shutdown | Shutdown system | +| ct system:swap | Show swap usage for running processes | +| ct system:update | Updates all system components, ssh configuration, ct command update etc. | +| ct system:version | Shows version for common packages | + +### TYPO3 commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct typo3:beuser | Injects a dev user (pass dev) to all or one specified TYPO3 database | +| | __ct typo3:beuser__ | +| | __ct typo3:beuser typo3__ | +| ct typo3:cleanup | Cleanup command tables to same some table space | +| | __ct typo3:cleanup__ | +| | __ct typo3:cleanup typo3__ | +| ct typo3:domain | Add default suffix to all domains (default: .vm) | +| | __ct typo3:domain --list__ Print list of domains and exit | +| | __ct typo3:domain --remove='*.vagrantshare.com'__ Remove all *.vagrantshare.com domains (used by vagrant:share command) | +| | __ct typo3:domain --duplicate='foobar.vagrantshare.com'__ Duplicates all domains and add suffix 'foobar.vagrantshare.com' (used by vagrant:share command) | + +### Vagrant commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct vagrant:share | Start sharing (with some workflow stuff) (ALPHA! not finished!) | + +### User commands + +| Command | Description | +|----------------------------|---------------------------------------------------------------------------| +| ct user:rebuildsshconfig | Rebuild SSH config from ct repository (/vagrant/provision/sshconfig) | + + diff --git a/Documentation/INSTALL.md b/Documentation/INSTALL.md new file mode 100644 index 0000000..d0a75d6 --- /dev/null +++ b/Documentation/INSTALL.md @@ -0,0 +1,121 @@ +[<-- Back to main section](../README.md) + +# Installation + +## Requirements + +- PHP 5.5 (CLI) with pcntl module +- Tools + - git + - wget + - multitail + - tshark + - tcpdump + - ngrep + - strace + - lsof + - sudo + - moreutils (ifdata) + - coreutils (grep, sort, uniq, awk, cat, df, ip, cut, lsb_release, wall) + - docker and docker-compose (if you want to use docker) + - mysql (if you want to use mysql) + + +## Install clitools + +```bash +# Download latest tools (or in ~/bin if you have it in $PATH) +wget -O/usr/local/bin/ct https://www.achenar.net/clicommand/clitools.phar + +# Set executable bit +chmod 777 /usr/local/bin/ct + +# Download example config +wget -O"$HOME/.clitools.ini" https://raw.githubusercontent.com/mblaschke/vagrant-development/develop/provision/ansible/roles/clitools/files/clitools.ini +``` + +## Aliases + +Now you can use following aliases (some aliases requires clitools 1.8.0!): + +```bash +# Shortcut for auto-tree-searching make +alias make='ct make' + +# Shortcut for auto-tree-searching make +alias composer='ct php:composer' + +# Shortcut for docker-compose (autosearch docker-compose.yml in up-dir, you don't have to be in directory with docker-compose.yml) +alias dcc='ct docker:compose' + +# Startup docker-container (and shutdown previous one, v1.9.0 and up) +alias dccup='ct docker:up' +alias dccstop='ct docker:compose stop' + +# Enter main docker container (as CLI_USER if available - if not specified then root is used) +alias dcshell='ct docker:shell' +alias dcsh='ct docker:shell' + +# Enter main docker container (as root) +alias dcroot='ct docker:root' + +# Execute predefined cli in docker container +alias dccrun='ct docker:cli' +alias dcrun='ct docker:cli' + +# Execute mysql client in docker container +alias dcsql='ct docker:mysql' +alias dcmysql='ct docker:mysql' +``` + +## Configuration + +CliTools will read /etc/clitools.ini (system wide) and ~/.clitools.ini (personal) for configuration + +The [default configuration](https://github.com/mblaschke/vagrant-clitools/blob/develop/src/config.ini) is inside the phar. + +### Docker specific configuration +```ini +[config] +; ssh_conf_path = "/vagrant/provision/sshconfig/" + +[db] +dsn = "mysql:host=127.0.0.1;port=13306" +username = "root" +password = "dev" +debug_log_dir = "/tmp/debug/" + +[syscheck] +enabled = 1 +wall = 1 +growl = 1 +diskusage = 85 + +[growl] +server = 192.168.56.1 +password = + +[commands] +; not used commands here +ignore[] = "CliTools\Console\Command\Log\ApacheCommand" +ignore[] = "CliTools\Console\Command\Log\PhpCommand" +ignore[] = "CliTools\Console\Command\Log\DebugCommand" +ignore[] = "CliTools\Console\Command\Apache\RestartCommand" +ignore[] = "CliTools\Console\Command\Mysql\RestartCommand" +ignore[] = "CliTools\Console\Command\Php\RestartCommand" +ignore[] = "CliTools\Console\Command\System\UpdateCommand" +ignore[] = "CliTools\Console\Command\System\RebootCommand" +``` + +## Update clitools + +```bash +# Stable channel +ct self-udpate + +## Beta channel +ct self-update --beta + +## Fallback update (if GitHub fails) +ct self-update --fallback +``` diff --git a/Documentation/USAGE.md b/Documentation/USAGE.md new file mode 100644 index 0000000..1a7af5f --- /dev/null +++ b/Documentation/USAGE.md @@ -0,0 +1,50 @@ +[<-- Back to main section](../README.md) + +# Usage + +## SYNC: Project synchronatizon + +With the `sync` commands you can update your local development installation to the current state of your +server installations. Currently filesync (rsync) and database fetching is supported. + +First you need to create a `clisync.yml` in your project directory, the CliTools will provide your an example +of this file by using following command: + + ct sync:init + +If you need special SSH settings (ports, compression, identify...) please use your `~/.ssh/config` file +to such settings. + +You can commit this clisync.yml into your project so other developers can use the sync feature, too. + +### Synchronisation with servers (ct sync:server) + +The synchronisation with your servers is one way only, it just syncs your server installation to your +local installation (CliTools are no deployment tools!). + +In the `clisync.yml` you can specify multiple servers. + +Now you can sync your `production` server to your local installation: + + # Full sync (files and database) + ct sync:server production + + # Only MySQL + ct sync:server production --mysql + + # Only Files + ct sync:server production --files + +## Project sharing (ct sync:backup and ct sync:restore) + +The sharing can be used to share files (assets) and databases between developers. +Please use a common development/storage server with ssh access for each developer for this feature. + + + # Make backup of current state and transfer to share server + ct sync:backup + + # Restore to state from the share server + ct sync:restore + + diff --git a/README.md b/README.md index ff98b8a..89cdbde 100644 --- a/README.md +++ b/README.md @@ -8,263 +8,18 @@ [![SensioLabsInsight](https://insight.sensiolabs.com/projects/9f12f125-3623-4b9d-b01b-07090f91e416/big.png)](https://insight.sensiolabs.com/projects/9f12f125-3623-4b9d-b01b-07090f91e416) -CliTools is a terminal utility for some handy convierence tasks based on Symfony Components (Console). - -Documentation is still WIP :) - -## Requirements - -- PHP 5.5 (CLI) -- Tools - - git - - wget - - multitail - - tshark - - tcpdump - - ngrep - - strace - - lsof - - sudo - - moreutils (ifdata) - - coreutils (grep, sort, uniq, awk, cat, df, ip, cut, lsb_release, wall) - - docker and docker-compose (if you want to use docker) - - mysql (if you want to use mysql) - -## Installation - - -```bash -# Download latest tools (or in ~/bin if you have it in $PATH) -wget -O/usr/local/bin/ct https://www.achenar.net/clicommand/clitools.phar - -# Set executable bit -chmod 777 /usr/local/bin/ct - -# Download example config -wget -O"$HOME/.clitools.ini" https://raw.githubusercontent.com/mblaschke/vagrant-development/develop/provision/ansible/roles/clitools/files/clitools.ini -``` - -Now you can use following aliases (some aliases requires clitools 1.8.0!): - -```bash -# Shortcut for auto-tree-searching make -alias make='ct make' - -# Shortcut for auto-tree-searching make -alias composer='ct php:composer' - -# Shortcut for docker-compose (autosearch docker-compose.yml in up-dir, you don't have to be in directory with docker-compose.yml) -alias dcc='ct docker:compose' - -# Startup docker-container (and shutdown previous one, v1.9.0 and up) -alias dccup='ct docker:up' -alias dccstop='ct docker:compose stop' - -# Enter main docker container (as CLI_USER if available - if not specified then root is used) -alias dcshell='ct docker:shell' -alias dcsh='ct docker:shell' - -# Enter main docker container (as root) -alias dcroot='ct docker:root' - -# Execute predefined cli in docker container -alias dccrun='ct docker:cli' -alias dcrun='ct docker:cli' - -# Execute mysql client in docker container -alias dcsql='ct docker:mysql' -alias dcmysql='ct docker:mysql' -``` - -## Configuration - -CliTools will read /etc/clitools.ini (system wide) and ~/.clitools.ini (personal) for configuration - -The [default configuration](https://github.com/mblaschke/vagrant-clitools/blob/develop/src/config.ini) is inside the phar. - -### Docker specific configuration -```ini -[config] -; ssh_conf_path = "/vagrant/provision/sshconfig/" - -[db] -dsn = "mysql:host=127.0.0.1;port=13306" -username = "root" -password = "dev" -debug_log_dir = "/tmp/debug/" - -[syscheck] -enabled = 1 -wall = 1 -growl = 1 -diskusage = 85 - -[growl] -server = 192.168.56.1 -password = +## Introduction -[commands] -; not used commands here -ignore[] = "CliTools\Console\Command\Log\ApacheCommand" -ignore[] = "CliTools\Console\Command\Log\PhpCommand" -ignore[] = "CliTools\Console\Command\Log\DebugCommand" -ignore[] = "CliTools\Console\Command\Apache\RestartCommand" -ignore[] = "CliTools\Console\Command\Mysql\RestartCommand" -ignore[] = "CliTools\Console\Command\Php\RestartCommand" -ignore[] = "CliTools\Console\Command\System\UpdateCommand" -ignore[] = "CliTools\Console\Command\System\RebootCommand" -``` - -## Commands - -### Special commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct self-update | Update ct command (download new version) | -| ct update | Updates all system components, ssh configuration, ct command update etc. | -| ct make | Search for "Makefile" in tree and start "make" in this directory | - -### System commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct shutdown (alias) | Shutdown system | - -### Log commands - -All log commands are using a grep-filter (specified as optional argument) - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct log:mail | Shows mail logs | - -### Docker commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct docker:create | Create new docker boilerplate in directory (first argument) | -| | __ct docker:create projectname__ -> Create new docker boilerplate instance in directory "projectname" | -| | __ct docker:create projectname --code=git@github.com/foo/bar__ -> Create new docker boilerplate instance in directory "projectname" and git code repository | -| | __ct docker:create projectname --docker=git@github.com/foo/bar__ -> Create new docker boilerplate instance in directory "projectname" and custom docker boilerplate repository | -| | __ct docker:create projectname --code=git@github.com/foo/bar --make=build__ -> Create new docker boilerplate instance in directory "projectname" and git code repository, will run automatic make (Makefile) task "build" after checkout | -| ct docker:shell | Jump into a shell inside a docker container (using predefined user defined with CLI_USER in docker env) | -| | __ct docker:shell__ -> enter main container | -| | __ct docker:shell mysql__ -> enter mysql container | -| | __ct docker:shell --user=www-data -> enter main container as user www-data | -| ct docker:root | Jump into a shell inside a docker container as root user | -| ct docker:mysql | Jump into a mysql client inside a docker container | -| | __ct docker:mysql__ -> execute mysql client inside main container | -| ct docker:sniff | Start network sniffer for various protocols | -| | __ct docker:sniff http__ -> start HTTP sniffing | -| ct docker:exec | Execute command in docker container | -| | __ct docker:exec ps__ -> run 'ps' inside main container | -| ct docker:cli | Execute special cli command in docker container | -| | __ct docker:cli scheduler__ -> run 'scheduler' in TYPO3 CMS | -| ct docker:compose | Execute docker-compose (recursive up-searching for docker-compose.yml) | -| | __ct docker:compose ps__ -> list all running docker-compose containers | - -### MySQL commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct mysql:clear | Clear database (remove all tables in database) | -| | __ct mysql:clear typo3__ | -| ct mysql:connections | Lists all current connections | -| ct mysql:create | Create (and drops if already exists) a database | -| | __ct mysql:create typo3__ | -| ct mysql:debug | Shows mysql debug log (lists all queries) with basic filter support | -| | __ct mysql:debug__ (full log) | -| | __ct mysql:debug tt_content__ (full log) | -| ct mysql:slowlog | Shows mysql slow log | -| | __ct mysql:slowlog__ (show slow queries with 1 sec and more) | -| | __ct mysql:slowlog --time=10__ (show slow queries with 10 sec and more) | -| | __ct mysql:slowlog --no-index__ (show not using index and slow (1sec) queries) | -| ct mysql:drop | Drops a database | -| | __ct mysql:drop typo3__ | -| ct mysql:list | Lists all databases with some statitics | -| ct mysql:restart | Restart MySQL server | -| ct mysql:backup | Backup a database to file | -| | Compression type will be detected from file extension (default plain sql) | -| | __ct mysql:restore typo3 dump.sql__ -> plain sql dump | -| | __ct mysql:restore typo3 dump.sql.gz__ -> gzip'ed sql dump | -| | __ct mysql:restore typo3 dump.sql.bzip2__ -> bzip2'ed sql dump | -| | __ct mysql:restore typo3 dump.sql.xz__ -> xz'ed (lzma'ed) sql dump | -| | __ct mysql:restore typo3 dump.sql --filter=typo3__ -> No TYPO3 cache tables in dump | -| ct mysql:restore | Create (and drops if already exists) a database and restore from a dump | -| | Dump file can be plaintext, gziped, bzip2 or lzma compressed | -| | and will automatically detected | -| | __ct mysql:restore typo3 dump.sql.bz2__ | -| ct mysql:convert | Convert character set and collation of a database | -| | __ct mysql:convert typo3__ -> Convert typo3 into UTF-8 with utf8_general_ci | -| | __ct mysql:convert typo3 --charset=latin1__ -> Convert typo3 into LATIN-1 | -| | __ct mysql:convert typo3 --collation=utf8_unicode_ci__ -> Convert typo3 into UTF-8 with utf8_unicode_ci | -| | __ct mysql:convert typo3 --stdout__ -> Print sql statements to stdout | - -### Sync commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct sync:init | Create example clisync.yml in current working directory | -| ct sync:backup | Search for clisync.yml in tree and start backup to shared server | -| ct sync:restore | Search for clisync.yml in tree and start restore from shared server | -| ct sync:server | Search for clisync.yml in tree and start server synchronization (eg. from live or preview to local development instance | -| | __ct sync:server production__ -> Use "production" configuration and start sync | -| | __ct sync:server preview --rsync__ -> Use "preview" configuration and start only rsync | -| | __ct sync:server staging --mysql__ -> Use "staging" configuration and start only mysql sync | - -### PHP commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct php:trace | Trace syscalls from one or all PHP processes (strace) | -| | __ct php:trace --all__ -> Trace all php processes immediately | -| ct php:composer | Search for "composer.yml" in tree and start "composer" in this directory | - -### Samba commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct samba:restart | Restart Samba server | - - -### System commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct system:env | Lists common environment variables | -| ct system:openfiles | Lists current open files count grouped by process | -| ct system:shutdown | Shutdown system | -| ct system:swap | Show swap usage for running processes | -| ct system:update | Updates all system components, ssh configuration, ct command update etc. | -| ct system:version | Shows version for common packages | - -### TYPO3 commands - -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct typo3:beuser | Injects a dev user (pass dev) to all or one specified TYPO3 database | -| | __ct typo3:beuser__ | -| | __ct typo3:beuser typo3__ | -| ct typo3:cleanup | Cleanup command tables to same some table space | -| | __ct typo3:cleanup__ | -| | __ct typo3:cleanup typo3__ | -| ct typo3:domain | Add default suffix to all domains (default: .vm) | -| | __ct typo3:domain --list__ Print list of domains and exit | -| | __ct typo3:domain --remove='*.vagrantshare.com'__ Remove all *.vagrantshare.com domains (used by vagrant:share command) | -| | __ct typo3:domain --duplicate='foobar.vagrantshare.com'__ Duplicates all domains and add suffix 'foobar.vagrantshare.com' (used by vagrant:share command) | +CliTools is a terminal utility for some handy convierence tasks based on Symfony Components (Console). -### Vagrant commands +## Table of contents -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct vagrant:share | Start sharing (with some workflow stuff) (ALPHA! not finished!) | +- [Installation and requirements](/documentation/INSTALL.md) +- [Usage](/documentation/USAGE.md) +- [Command overview](/documentation/COMMANDS.md) -### User commands +Documentation is still WIP :) -| Command | Description | -|----------------------------|---------------------------------------------------------------------------| -| ct user:rebuildsshconfig | Rebuild SSH config from ct repository (/vagrant/provision/sshconfig) | ## Credits From 706942494d5f5949c1248e87e8e9d8e2424ca30c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 11:58:40 +0200 Subject: [PATCH 129/214] Fixed doc paths --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 89cdbde..aef4dab 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ CliTools is a terminal utility for some handy convierence tasks based on Symfony ## Table of contents -- [Installation and requirements](/documentation/INSTALL.md) -- [Usage](/documentation/USAGE.md) -- [Command overview](/documentation/COMMANDS.md) +- [Installation and requirements](/Documentation/INSTALL.md) +- [Usage](/Documentation/USAGE.md) +- [Command overview](/Documentation/COMMANDS.md) Documentation is still WIP :) From fb0943a9997f3fcc9f973acb3295b0940beb8f71 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 12:00:12 +0200 Subject: [PATCH 130/214] Fixed typo --- Documentation/USAGE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/USAGE.md b/Documentation/USAGE.md index 1a7af5f..081ff17 100644 --- a/Documentation/USAGE.md +++ b/Documentation/USAGE.md @@ -33,7 +33,7 @@ Now you can sync your `production` server to your local installation: ct sync:server production --mysql # Only Files - ct sync:server production --files + ct sync:server production --rsync ## Project sharing (ct sync:backup and ct sync:restore) From 60ee4332d33a13a99d120b999e6bb29118f46333 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 12:17:58 +0200 Subject: [PATCH 131/214] Added highlighting --- Documentation/USAGE.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Documentation/USAGE.md b/Documentation/USAGE.md index 081ff17..2d591cf 100644 --- a/Documentation/USAGE.md +++ b/Documentation/USAGE.md @@ -10,7 +10,9 @@ server installations. Currently filesync (rsync) and database fetching is suppor First you need to create a `clisync.yml` in your project directory, the CliTools will provide your an example of this file by using following command: - ct sync:init +```bash +ct sync:init +``` If you need special SSH settings (ports, compression, identify...) please use your `~/.ssh/config` file to such settings. @@ -26,25 +28,27 @@ In the `clisync.yml` you can specify multiple servers. Now you can sync your `production` server to your local installation: - # Full sync (files and database) - ct sync:server production +```bash +# Full sync (files and database) +ct sync:server production - # Only MySQL - ct sync:server production --mysql +# Only MySQL +ct sync:server production --mysql - # Only Files - ct sync:server production --rsync +# Only Files +ct sync:server production --rsync +``` ## Project sharing (ct sync:backup and ct sync:restore) The sharing can be used to share files (assets) and databases between developers. Please use a common development/storage server with ssh access for each developer for this feature. - +```bash # Make backup of current state and transfer to share server ct sync:backup # Restore to state from the share server ct sync:restore - +``` From fffc0d92d7bf4da9f071d3353d78b9687027c000 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 12:18:48 +0200 Subject: [PATCH 132/214] Fixed indentio --- Documentation/USAGE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/USAGE.md b/Documentation/USAGE.md index 2d591cf..41a9609 100644 --- a/Documentation/USAGE.md +++ b/Documentation/USAGE.md @@ -45,10 +45,10 @@ The sharing can be used to share files (assets) and databases between developers Please use a common development/storage server with ssh access for each developer for this feature. ```bash - # Make backup of current state and transfer to share server - ct sync:backup +# Make backup of current state and transfer to share server +ct sync:backup - # Restore to state from the share server - ct sync:restore +# Restore to state from the share server +ct sync:restore ``` From 052e05f478938156da1feade90fef5a39d7573ec Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 12:37:57 +0200 Subject: [PATCH 133/214] Improved readme usage --- Documentation/USAGE-DOCKER.md | 101 ++++++++++++++++++++++ Documentation/{USAGE.md => USAGE-SYNC.md} | 6 +- README.md | 3 +- 3 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 Documentation/USAGE-DOCKER.md rename Documentation/{USAGE.md => USAGE-SYNC.md} (93%) diff --git a/Documentation/USAGE-DOCKER.md b/Documentation/USAGE-DOCKER.md new file mode 100644 index 0000000..8881a25 --- /dev/null +++ b/Documentation/USAGE-DOCKER.md @@ -0,0 +1,101 @@ +[<-- Back to main section](../README.md) + +# Usage of `docker` + +## Docker creation + +You can easly create new docker instances (from my or a custom docker boilerplate) also with code intalization +and Makefile running. + +```bash +# Startup new docker boilerplate +ct docker:create + +# Startup new custom docker boilerplate +ct docker:create --docker=git... + +# Startup new docker boilerplate with code repository +ct docker:create --code=git... + +# Startup new docker boilerplate with code repository and makefile run +ct docker:create --code=git... --make=build +``` + +## Docker startup + +The `docker:up` command will search the `docker-compose.yml` in the current parent directroy tree and +execute `docker-compose` from this directroy - you don't have to change the current directroy. + +Also the previous docker instance will be shut down to avoid port conflicts. + +```bash +# Startup docker-compose +ct docker:up +``` + +## Custom docker commands + +As `docker:up` the `docker:compose` will search the `docker-compose.yml` and will execute your command +from this directroy. + +```bash +# Stop docker instance +ct docker:compose stop + +# Show docker container status +ct docker:compose ps +``` + +Hint: Use `dcc` as alias for `ct docker:compose` for easy docker-compose usage + +## Docker shell access + +There are many ways to jump into docker containers: + +```bash +# Jump into a root shell +ct docker:root + +# Jump into a root shell in mysql container +ct docker:root mysql + +# Jump into a user shell (defined by CLI_USER as docker env) +ct docker:shell + +# Jump into a root user in mysql container (defined by CLI_USER as docker env) +ct docker:root mysql +``` + +## Docker command execution + +```bash +# Execute command "ps" in "main" container +ct docker:exec ps +``` + +## Docker cli execution + +You can define a common CLI script entrypoint with the environment variable CLI_SCRIPT in your docker containers. +The environment variable will be read by `ct docker:cli` and will be executed - you don't have to jump +into your containers, you can start your CLI_SCRIPTs from the outide. + +```bash +# Execute predefined cli command with argument "help" in "main" container +ct docker:cli help +``` + +## Docker debugging + +If you want to debug a docker application (eg. your webpage inside docker) the `ct docker:sniff` provides you +a network sniffer set for various protocols (eg. http or mysql). + +```bash +# Show basic http traffic +ct docker:sniff http + +# Show full http traffic +ct docker:sniff http --full + +# Show mysql querys by using network sniffer +ct docker:sniff mysql +``` diff --git a/Documentation/USAGE.md b/Documentation/USAGE-SYNC.md similarity index 93% rename from Documentation/USAGE.md rename to Documentation/USAGE-SYNC.md index 41a9609..a2a76dd 100644 --- a/Documentation/USAGE.md +++ b/Documentation/USAGE-SYNC.md @@ -1,8 +1,8 @@ [<-- Back to main section](../README.md) -# Usage +# Usage SYNC -## SYNC: Project synchronatizon +## Init and configuration of `sync` With the `sync` commands you can update your local development installation to the current state of your server installations. Currently filesync (rsync) and database fetching is supported. @@ -19,7 +19,7 @@ to such settings. You can commit this clisync.yml into your project so other developers can use the sync feature, too. -### Synchronisation with servers (ct sync:server) +## Synchronisation with servers (ct sync:server) The synchronisation with your servers is one way only, it just syncs your server installation to your local installation (CliTools are no deployment tools!). diff --git a/README.md b/README.md index aef4dab..fc6b22d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ CliTools is a terminal utility for some handy convierence tasks based on Symfony ## Table of contents - [Installation and requirements](/Documentation/INSTALL.md) -- [Usage](/Documentation/USAGE.md) +- [Usage `docker` commands](/Documentation/USAGE-DOCKER.md) +- [Usage `sync` comands](/Documentation/USAGE-SYNC.md) - [Command overview](/Documentation/COMMANDS.md) Documentation is still WIP :) From e98d93c46948cbd10e0f05a76675b5dbbd5b6461 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 12:56:58 +0200 Subject: [PATCH 134/214] Added mysql and typo3 usage --- Documentation/USAGE-MYSQL.md | 89 ++++++++++++++++++++++++++++++++++++ Documentation/USAGE-SYNC.md | 2 +- Documentation/USAGE-TYPO3.md | 43 +++++++++++++++++ README.md | 6 ++- 4 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 Documentation/USAGE-MYSQL.md create mode 100644 Documentation/USAGE-TYPO3.md diff --git a/Documentation/USAGE-MYSQL.md b/Documentation/USAGE-MYSQL.md new file mode 100644 index 0000000..269e482 --- /dev/null +++ b/Documentation/USAGE-MYSQL.md @@ -0,0 +1,89 @@ +[<-- Back to main section](../README.md) + +# Usage of `ct mysql:...` + +# Common commands + +```bash +# Create database typo3 (recreate and clears database if exists) +ct mysql:create typo3 + +# Drop database typo3 +ct mysql:drop typo3 + +# List databases with statistics +ct mysql:list +``` + +# Debugging + +The `ct mysql:querylog` and `ct mysql:slowlog` provides a convinent way to access the general query log +and the slow log. + +In the query log you can see all queries send and executed by the MySQL database. +The slow query log can be used to see long running queries. + +```bash +# Enable and show query log +ct mysql:querylog + +# Enable and show query log +ct mysql:slowlog + +# Enable and show query log for all queries running longer than 1 sec +ct mysql:slowlog --time=1 + +# Enable and show query log for all queries which don't uses indizes +ct mysql:slowlog --no-index + +``` + +# Backup database +You can easily backup a MySQL database (including compression compressions) and a filter set for tables. + +```bash +# Backup typo3 database (without compression) +ct mysql:backup typo3 dump.sql + +# Backup typo3 database (with gzip) +ct mysql:backup typo3 dump.sql.gz + +# Backup typo3 database (with bzip2) +ct mysql:backup typo3 dump.sql.bz2 + +# Backup typo3 database (with LZMA/xz) +ct mysql:backup typo3 dump.sql.xz +``` + +# Restore database + +Restoring is as easy as backuping a database, the `ct mysql:restore` will drop the database (if exists), +recreate it and restores the dump into the database. With this workflow you also removes all tables which +are not part of the dump file - it's a clean restore of the dump. +Also the compression is automatically detected by file mime type. + +```bash +# Restore typo3 database (auto compression detection) +ct mysql:restore typo3 dump.sql +``` + +# Datbase charset conversion + +```bash +# Convert database to UTF8 +ct mysql:convert typo3 + +# Convert database typo3 to UTF8 and collation utf8_unicode_ci +ct mysql:convert typo3 --collation=utf8_unicode_ci + +# Convert database typo3 to Latin1 +ct mysql:convert typo3 --charset=latin1 + +# Convert database typo3 to Latin1, only show queries +ct mysql:convert typo3 --stdout +``` + + + + + diff --git a/Documentation/USAGE-SYNC.md b/Documentation/USAGE-SYNC.md index a2a76dd..8df281d 100644 --- a/Documentation/USAGE-SYNC.md +++ b/Documentation/USAGE-SYNC.md @@ -1,6 +1,6 @@ [<-- Back to main section](../README.md) -# Usage SYNC +# Usage `ct sync:...` ## Init and configuration of `sync` diff --git a/Documentation/USAGE-TYPO3.md b/Documentation/USAGE-TYPO3.md new file mode 100644 index 0000000..e132f11 --- /dev/null +++ b/Documentation/USAGE-TYPO3.md @@ -0,0 +1,43 @@ +[<-- Back to main section](../README.md) + +# Usage `ct typo3:...` + +## Backend user injection + +The `ct typo3:beuser` can be used for creating a backend user in all or a specific TYPO3 database +(with salted password support). + +Default username: dev +Default password: dev + +```bash +# Create the user in all databases +ct typo3:beuser + +# Create the user in typo3 databases +ct typo3:beuser typo3 + +# Create the user in typo3 databases with plain password (no salted password) +ct typo3:beuser typo3 --plain +``` + +## Automatic domain manipulation + +The `ct typo3:domain` can be used for manipulation of the domain records eg. for matching your +development environment. + +```bash +# Add a .vm at the and of all domains in all databases +ct typo3:domain + +# Add a .vm at the and of all domains in typo3 database +ct typo3:domain typo3 + +# Add a .vm at the and of all domains and remove all *.vagrantshare.com domains (used by vagrant:share) +ct typo3:domain --remove='*.vagrantshare.com' + +# Add a .vm at the and of all domains and duplicate all domains with the suffix .vagrantshare.com (used by vagrant:share) +ct typo3:domain --duplicate='.vagrantshare.com' +``` + + diff --git a/README.md b/README.md index fc6b22d..25974cd 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,10 @@ CliTools is a terminal utility for some handy convierence tasks based on Symfony ## Table of contents - [Installation and requirements](/Documentation/INSTALL.md) -- [Usage `docker` commands](/Documentation/USAGE-DOCKER.md) -- [Usage `sync` comands](/Documentation/USAGE-SYNC.md) +- [Usage `ct docker:...` commands](/Documentation/USAGE-DOCKER.md) +- [Usage `ct sync:...` comands](/Documentation/USAGE-SYNC.md) +- [Usage `ct mysql:...` comands](/Documentation/USAGE-MYSQL.md) +- [Usage `ct typo3:...` comands](/Documentation/USAGE-TYPO3.md) - [Command overview](/Documentation/COMMANDS.md) Documentation is still WIP :) From 8ce9bb979a182ee4dcd1f959636121a4b31daf98 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 15:18:18 +0200 Subject: [PATCH 135/214] Improved docker usage and added php usage documentation --- Documentation/USAGE-DOCKER.md | 4 ++-- Documentation/USAGE-PHP.md | 33 +++++++++++++++++++++++++++++++++ README.md | 3 ++- 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 Documentation/USAGE-PHP.md diff --git a/Documentation/USAGE-DOCKER.md b/Documentation/USAGE-DOCKER.md index 8881a25..4d424d5 100644 --- a/Documentation/USAGE-DOCKER.md +++ b/Documentation/USAGE-DOCKER.md @@ -1,6 +1,6 @@ [<-- Back to main section](../README.md) -# Usage of `docker` +# Usage of `ct docker:...` ## Docker creation @@ -46,7 +46,7 @@ ct docker:compose stop ct docker:compose ps ``` -Hint: Use `dcc` as alias for `ct docker:compose` for easy docker-compose usage +Hint: You can use `alias dcc='ct docker:compose'` for this. ## Docker shell access diff --git a/Documentation/USAGE-PHP.md b/Documentation/USAGE-PHP.md new file mode 100644 index 0000000..911ec67 --- /dev/null +++ b/Documentation/USAGE-PHP.md @@ -0,0 +1,33 @@ +[<-- Back to main section](../README.md) + +# Usage `ct php:...` + +## Composer (auto searching in path tree) + +Because you always need to jump into `composer.json` directroy `ct php:composer` will do this for you + +```bash +# Run composer install task +ct php:composer install + +# Run composer update task +ct php:composer update +``` + +Hint: You can use `alias composer='ct php:composer'` for this. + + +## Sys-Tracing PHP Processes + +Because strace'ing already running processes requires some shell knowledge `ct php:trace` will make this handy for you. + +```bash +# Trace one or all php processes (interactive mode) +ct php:trace + +# Trace all processes immediately +ct php:trace --all +``` + + + diff --git a/README.md b/README.md index 25974cd..33ef4d9 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Introduction -CliTools is a terminal utility for some handy convierence tasks based on Symfony Components (Console). +CliTools is a terminal utility for some handy convierence tasks and is based on Symfony Components (Console). ## Table of contents @@ -19,6 +19,7 @@ CliTools is a terminal utility for some handy convierence tasks based on Symfony - [Usage `ct sync:...` comands](/Documentation/USAGE-SYNC.md) - [Usage `ct mysql:...` comands](/Documentation/USAGE-MYSQL.md) - [Usage `ct typo3:...` comands](/Documentation/USAGE-TYPO3.md) +- [Usage `ct php:...` comands](/Documentation/USAGE-PHP.md) - [Command overview](/Documentation/COMMANDS.md) Documentation is still WIP :) From ba2da8a8b82600af8b0fda61d741a50ca08f64e2 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 22 May 2015 15:21:51 +0200 Subject: [PATCH 136/214] Fixed sniffer violations --- src/app/CliTools/Exception/StopException.php | 2 -- src/app/CliTools/Reader/ConfigReader.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/app/CliTools/Exception/StopException.php b/src/app/CliTools/Exception/StopException.php index e9a5f26..0d565b8 100644 --- a/src/app/CliTools/Exception/StopException.php +++ b/src/app/CliTools/Exception/StopException.php @@ -20,8 +20,6 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; - class StopException extends \RuntimeException { } diff --git a/src/app/CliTools/Reader/ConfigReader.php b/src/app/CliTools/Reader/ConfigReader.php index 38aba84..fda55cd 100644 --- a/src/app/CliTools/Reader/ConfigReader.php +++ b/src/app/CliTools/Reader/ConfigReader.php @@ -2,8 +2,6 @@ namespace CliTools\Reader; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; - /* * CliTools Command * Copyright (C) 2015 Markus Blaschke From 2f611bef8aa09b0b70c315459c0545d7c626d67c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 25 May 2015 23:16:36 +0200 Subject: [PATCH 137/214] Fixed possible issue --- src/app/CliTools/Console/Application.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/CliTools/Console/Application.php b/src/app/CliTools/Console/Application.php index f229277..86a5ac7 100644 --- a/src/app/CliTools/Console/Application.php +++ b/src/app/CliTools/Console/Application.php @@ -179,8 +179,10 @@ public function doRun(InputInterface $input, OutputInterface $output) { protected function initializePosixTrap() { declare(ticks = 1); - $signalHandler = function ($signal) { - $this->callTearDown(); + $me = $this; + + $signalHandler = function ($signal) use($me) { + $me->callTearDown(); // Prevent terminal messup echo "\n"; From 167236b9302fc81a64a1cd7468989a929f6320c4 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 25 May 2015 23:17:02 +0200 Subject: [PATCH 138/214] Implemented all arguments for vagrant share Related #38 --- .../Console/Command/Vagrant/ShareCommand.php | 98 ++++++++++++++++++- 1 file changed, 93 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php index 57c11bd..5cc1287 100644 --- a/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php +++ b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php @@ -23,6 +23,8 @@ use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; class ShareCommand extends \CliTools\Console\Command\AbstractCommand { @@ -33,7 +35,54 @@ class ShareCommand extends \CliTools\Console\Command\AbstractCommand { protected function configure() { $this ->setName('vagrant:share') - ->setDescription('Start share for vagrant'); + ->setDescription('Start share for vagrant') + ->addArgument( + 'name', + InputArgument::OPTIONAL, + 'Specific name for the share' + ) + ->addOption( + 'http', + null, + InputOption::VALUE_REQUIRED, + 'Local HTTP port to forward to' + ) + ->addOption( + 'https', + null, + InputOption::VALUE_REQUIRED, + 'Local HTTPS port to forward to' + ) + ->addOption( + 'name', + null, + InputOption::VALUE_REQUIRED, + 'Specific name for the share' + ) + ->addOption( + 'ssh', + null, + InputOption::VALUE_NONE, + 'Allow \'vagrant connect --ssh\' access' + ) + ->addOption( + 'ssh-no-password', + null, + InputOption::VALUE_NONE, + 'Key won\'t be encrypted with --ssh' + ) + ->addOption( + 'ssh-port', + null, + InputOption::VALUE_REQUIRED, + 'Specific port for SSH when using --ssh' + ) + ->addOption( + '--ssh-once', + null, + InputOption::VALUE_NONE, + 'Allow \'vagrant connect --ssh\' only one time' + ); } /** @@ -91,9 +140,48 @@ public function execute(InputInterface $input, OutputInterface $output) { ); $vagrant = new CommandBuilder('vagrant', 'share'); - $vagrant - ->addArgumentRaw('--http 80') - ->addArgumentRaw('--https 443') - ->executeInteractive($opts); + + // Share name + if ($input->getOption('name')) { + $vagrant->addArgumentTemplate('--name %s', $input->getOption('name')); + } elseif ($input->getArgument('name')) { + $vagrant->addArgumentTemplate('--name %s', $input->getArgument('name')); + } + + + // HTTP port + if ($input->getOption('http')) { + $vagrant->addArgumentTemplate('--http %s', $input->getOption('http')); + } else { + $vagrant->addArgumentTemplate('--http %s', 80); + } + + // HTTPS port + if ($input->getOption('https')) { + $vagrant->addArgumentTemplate('--http %s', $input->getOption('https')); + } else { + $vagrant->addArgumentTemplate('--https %s', 443); + } + + + // SSH stuff + if ($input->getOption('ssh')) { + $vagrant->addArgument('--ssh'); + } + + if ($input->getOption('ssh-no-password')) { + $vagrant->addArgument('--ssh-no-password'); + } + + if ($input->getOption('ssh-port')) { + $vagrant->addArgumentTemplate('--ssh-port %s', $input->getOption('ssh-port')); + } + + if ($input->getOption('ssh-once')) { + $vagrant->addArgument('--ssh-once'); + } + + + $vagrant->executeInteractive($opts); } } From 7ea0bc28b06e113550599f0e7ebec5ae4a2220aa Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 25 May 2015 23:29:56 +0200 Subject: [PATCH 139/214] Cleanup --- src/app/CliTools/Console/Shell/Executor.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/app/CliTools/Console/Shell/Executor.php b/src/app/CliTools/Console/Shell/Executor.php index 6ec7733..02940b1 100644 --- a/src/app/CliTools/Console/Shell/Executor.php +++ b/src/app/CliTools/Console/Shell/Executor.php @@ -211,18 +211,26 @@ public function execInteractive(array $opts = null) { $process = proc_open($this->command->build(), $descriptorSpec, $pipes); if (is_resource($process)) { - if (!empty($opts['startupCallback']) && is_callable($opts['startupCallback'])) { $opts['startupCallback']($process); } do { - $status = proc_get_status($process); - if (!empty($status) && !empty($opts['runningCallback']) && is_callable($opts['runningCallback'])) { - $opts['runningCallback']($process, $status); + if (is_resource($process)) { + $status = proc_get_status($process); + if (!empty($status) && !empty($opts['runningCallback']) && is_callable($opts['runningCallback'])) { + $opts['runningCallback']($process, $status); + } + } else { + break; } usleep(100 * 1000); } while (!empty($status) && is_array($status) && $status['running'] === true); + + if (is_resource($process)) { + proc_close($process); + } + $this->returnCode = $status['exitcode']; $this->runFinishers(); From 7f2b77800c7d69c7b4365c7d37b9341fcaccfae8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 25 May 2015 23:44:57 +0200 Subject: [PATCH 140/214] Remove dev domain from share domain duplications --- .../Console/Command/TYPO3/DomainCommand.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index b0d54db..5768ef8 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -149,6 +149,7 @@ protected function removeDomains($pattern) { * @param string $suffix Domain suffix */ protected function addDuplicateDomains($suffix) { + $devDomain = '.' . $this->getApplication()->getConfigValue('config', 'domain_dev'); $query = 'SELECT * FROM sys_domain'; $domainList = DatabaseConnection::getAll($query); @@ -156,7 +157,15 @@ protected function addDuplicateDomains($suffix) { foreach ($domainList as $domain) { unset($domain['uid']); - $domain['domainName'] .= '.' . ltrim($suffix, '.'); + $domainName = $domain['domainName']; + + // remove development suffix + $domainName = preg_replace('/' . preg_quote($devDomain). '$/', '', $domainName); + + // add share domain + $domainName .= '.' . ltrim($suffix, '.'); + + $domain['domainName'] = $domainName; DatabaseConnection::insert('sys_domain', $domain); } @@ -187,17 +196,16 @@ protected function showDomainList($dbName) { * @return void */ protected function manipulateDomains($database) { - - $domain = '.' . $this->getApplication()->getConfigValue('config', 'domain_dev'); - $domainLength = strlen($domain); + $devDomain = '.' . $this->getApplication()->getConfigValue('config', 'domain_dev'); + $domainLength = strlen($devDomain); if (DatabaseConnection::tableExists($database, 'sys_domain')) { // ################## // Fix domains // ################## $query = 'UPDATE ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($domain) . ') - WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($domain); + SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($devDomain) . ') + WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($devDomain); DatabaseConnection::exec($query); } } From 759a27431c351375658cbb60aa687209e0de6900 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 26 May 2015 22:58:23 +0200 Subject: [PATCH 141/214] Version bump 1.9.907 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index 96b1d11..472634c 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.906'); +define('CLITOOLS_COMMAND_VERSION', '1.9.907'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From 56f7c4062ab6472aec5daf3b2fa76116dcf6733f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 26 May 2015 22:59:00 +0200 Subject: [PATCH 142/214] Fixed docblocks, Added multiple file search for findFileInDirectortyTree --- src/app/CliTools/Utility/UnixUtility.php | 35 ++++++++++++++---------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index 9b63de4..124caa4 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -49,13 +49,13 @@ public static function lsbSystemDescription() { /** * Get CPU Count * - * @return string + * @return integer */ public static function cpuCount() { $command = new CommandBuilder('nproc'); $ret = $command->execute()->getOutputString(); - $ret = trim($ret); + $ret = (int)trim($ret); return $ret; } @@ -63,7 +63,7 @@ public static function cpuCount() { /** * Get Memory Count * - * @return string + * @return integer */ public static function memorySize() { $command = new CommandBuilder('cat', '/proc/meminfo'); @@ -112,7 +112,7 @@ public static function dockerVersion() { /** * Get mount info list * - * @return string + * @return array */ public static function mountInfoList() { $command = new CommandBuilder('df', '-a --type=ext3 --type=ext4 --type vmhgfs --type vboxsf --portability'); @@ -205,12 +205,12 @@ public static function defaultGateway() { * @param string $message Message */ public static function sendWallMessage($message) { - $commandWall = new CommandBuilder('wall'); - $commandWall->setOutputRedirect(CommandBuilder::OUTPUT_REDIRECT_NULL); + $wall = new CommandBuilder('wall'); + $wall->setOutputRedirect(CommandBuilder::OUTPUT_REDIRECT_NULL); $command = new CommandBuilder('echo'); $command->addArgument($message) - ->addPipeCommand($commandWall); + ->addPipeCommand($wall); $command->execute(); } @@ -260,13 +260,15 @@ public static function checkExecutable($command) { /** * Search directory upwards for a file * - * @param string $file Filename - * @param string $path Path + * @param string|array $file Filename + * @param string $path Path * @return boolean|string */ public static function findFileInDirectortyTree($file, $path = null) { $ret = false; + $fileList = (array)$file; + // Set path to current path (if not specified) if ($path === null) { $path = getcwd(); @@ -274,14 +276,19 @@ public static function findFileInDirectortyTree($file, $path = null) { if (!empty($path) && $path !== '/') { // Check if file exists in path - if (file_exists($path . '/' . $file)) { - // File found - $ret = $path; - } else { + foreach ($fileList as $file) { + if (file_exists($path . '/' . $file)) { + // File found + $ret = $path; + break; + } + } + + if ($ret === false) { // go up in directory $path .= '/../'; $path = realpath($path); - $ret = self::findFileInDirectortyTree($file, $path); + $ret = self::findFileInDirectortyTree($fileList, $path); } } From 7789a82ecbd5069a600d744e21c38f7d409e51fc Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 26 May 2015 23:06:58 +0200 Subject: [PATCH 143/214] Up-Path searching now returns file path --- src/app/CliTools/Utility/UnixUtility.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index 124caa4..2ff801c 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -279,7 +279,7 @@ public static function findFileInDirectortyTree($file, $path = null) { foreach ($fileList as $file) { if (file_exists($path . '/' . $file)) { // File found - $ret = $path; + $ret = $path . '/' . $file; break; } } From b5b290562391817b5b61d70b04d627fef1ee98ca Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 26 May 2015 23:08:42 +0200 Subject: [PATCH 144/214] Improved sync conf file detection --- .../Console/Command/Sync/AbstractCommand.php | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 84b9ddd..83620ba 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -50,6 +50,13 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand */ protected $workingPath; + /** + * Project configuration file path + * + * @var string|boolean|null + */ + protected $confFilePath; + /** * Temporary storage dir * @@ -84,12 +91,20 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand protected function initialize(InputInterface $input, OutputInterface $output) { parent::initialize($input, $output); + $confFileList = array( + self::CONFIG_FILE, + '.' . self::CONFIG_FILE, + ); + // Find configuration file - $this->workingPath = UnixUtility::findFileInDirectortyTree(self::CONFIG_FILE); - if (empty($this->workingPath)) { + $this->confFilePath = UnixUtility::findFileInDirectortyTree($confFileList); + if (empty($this->confFilePath)) { throw new \RuntimeException('No ' . self::CONFIG_FILE . ' found in tree'); } + + $this->workingPath = dirname($this->confFilePath); + $output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); // Read configuration @@ -135,8 +150,11 @@ protected function readConfiguration() { throw new \RuntimeException('Config area not set, cannot continue'); } - $confFile = $this->workingPath . '/' . self::CONFIG_FILE; - $conf = Yaml::parse(PhpUtility::fileGetContents($confFile)); + if (!file_exists($this->confFilePath)) { + throw new \RuntimeException('Config file "' . $this->confFilePath . '" not found'); + } + + $conf = Yaml::parse(PhpUtility::fileGetContents($this->confFilePath)); // store task specific configuration if (!empty($conf['task'])) { @@ -147,7 +165,7 @@ protected function readConfiguration() { if (!empty($conf)) { $this->config->setData($conf[$this->confArea]); } else { - throw new \RuntimeException('Could not parse "' . $confFile . '"'); + throw new \RuntimeException('Could not parse "' . $this->confFilePath . '"'); } } From e4b62891cd7ef5c5822fcd2d2b5d0374cfe7e113 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 26 May 2015 23:08:54 +0200 Subject: [PATCH 145/214] Fixed up path searching --- src/app/CliTools/Console/Command/Common/MakeCommand.php | 1 + .../CliTools/Console/Command/Docker/AbstractCommand.php | 9 +++++++-- src/app/CliTools/Console/Command/Docker/UpCommand.php | 6 +++++- src/app/CliTools/Console/Command/Php/ComposerCommand.php | 5 +++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/Common/MakeCommand.php b/src/app/CliTools/Console/Command/Common/MakeCommand.php index eb1456b..9a11e8f 100644 --- a/src/app/CliTools/Console/Command/Common/MakeCommand.php +++ b/src/app/CliTools/Console/Command/Common/MakeCommand.php @@ -50,6 +50,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $path = UnixUtility::findFileInDirectortyTree('Makefile'); if (!empty($path)) { + $path = dirname($path); $this->output->writeln('Found Makefile directory: ' . $path . ''); // Switch to directory of docker-compose.yml diff --git a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php index bd52648..c8e7954 100644 --- a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php @@ -40,8 +40,12 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand */ protected function getDockerPath() { if ($this->dockerPath === null) { - $this->dockerPath = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); - $this->output->writeln('Found docker directory: ' . $this->dockerPath . ''); + $composePath = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); + + if (!empty($composePath)) { + $this->dockerPath = dirname($this->dockerPath); + $this->output->writeln('Found docker directory: ' . $this->dockerPath . ''); + } } return $this->dockerPath; @@ -148,6 +152,7 @@ protected function executeDockerCompose(CommandBuilderInterface $command = null) $path = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); if (!empty($path)) { + $path = dirname($path); $this->output->writeln('Found docker directory: ' . $path . ''); // Switch to directory of docker-compose.yml diff --git a/src/app/CliTools/Console/Command/Docker/UpCommand.php b/src/app/CliTools/Console/Command/Docker/UpCommand.php index 1fb5609..1ffa226 100644 --- a/src/app/CliTools/Console/Command/Docker/UpCommand.php +++ b/src/app/CliTools/Console/Command/Docker/UpCommand.php @@ -45,9 +45,13 @@ protected function configure() { */ public function execute(InputInterface $input, OutputInterface $output) { - $dockerPath = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); + $dockerPath = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); $lastDockerPath = $this->getApplication()->getSettingsService()->get('docker.up.last'); + if (!empty($dockerPath)) { + $dockerPath = dirname($dockerPath); + } + // Stop last docker instance if ($dockerPath && $lastDockerPath) { // Only stop if instance is another one diff --git a/src/app/CliTools/Console/Command/Php/ComposerCommand.php b/src/app/CliTools/Console/Command/Php/ComposerCommand.php index e6ee298..772f210 100644 --- a/src/app/CliTools/Console/Command/Php/ComposerCommand.php +++ b/src/app/CliTools/Console/Command/Php/ComposerCommand.php @@ -49,9 +49,10 @@ public function execute(InputInterface $input, OutputInterface $output) { $composerCmd = $this->getApplication()->getConfigValue('bin', 'composer'); $paramList = $this->getFullParameterList(); - $path = UnixUtility::findFileInDirectortyTree('composer.json'); + $composerJsonPath = UnixUtility::findFileInDirectortyTree('composer.json'); - if (!empty($path)) { + if (!empty($composerJsonPath)) { + $path = dirname($composerJsonPath); $this->output->writeln('Found composer.json directory: ' . $path . ''); // Switch to directory of docker-compose.yml From f501aa20787faef85b22e032f15d6fb11b224cc5 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 26 May 2015 23:09:00 +0200 Subject: [PATCH 146/214] Updated README --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 33ef4d9..98b469f 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,21 @@ ## Introduction -CliTools is a terminal utility for some handy convierence tasks and is based on Symfony Components (Console). +CliTools is a terminal utility for faster development. It should make some daily task very easy. + +CliTools is based on Symfony Components (Console). ## Table of contents - [Installation and requirements](/Documentation/INSTALL.md) - [Usage `ct docker:...` commands](/Documentation/USAGE-DOCKER.md) -- [Usage `ct sync:...` comands](/Documentation/USAGE-SYNC.md) -- [Usage `ct mysql:...` comands](/Documentation/USAGE-MYSQL.md) -- [Usage `ct typo3:...` comands](/Documentation/USAGE-TYPO3.md) -- [Usage `ct php:...` comands](/Documentation/USAGE-PHP.md) +- [Usage `ct sync:...` commands](/Documentation/USAGE-SYNC.md) +- [Usage `ct mysql:...` commands](/Documentation/USAGE-MYSQL.md) +- [Usage `ct typo3:...` commands](/Documentation/USAGE-TYPO3.md) +- [Usage `ct php:...` commands](/Documentation/USAGE-PHP.md) - [Command overview](/Documentation/COMMANDS.md) -Documentation is still WIP :) - - ## Credits -Thanks to my colleagues at [cron IT GmbH](http://www.cron.eu/) and Ingo Pfennigstorf for testing and some usefull ideas. +Thanks to my colleagues at [cron IT GmbH](http://www.cron.eu/), [Ingo Pfennigstorf](https://twitter.com/krautsock) +and [Florian Tatzel](https://twitter.com/panadeedu) for testing and some usefull ideas. From dca20fa872a90d8996f9904f940a774439f70d7d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 27 May 2015 20:48:35 +0200 Subject: [PATCH 147/214] Added typo3:domain --baseurl --- Documentation/COMMANDS.md | 1 + Documentation/USAGE-TYPO3.md | 3 + .../Console/Command/TYPO3/DomainCommand.php | 69 +++++++++++++++---- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/Documentation/COMMANDS.md b/Documentation/COMMANDS.md index 4efd56f..01617b5 100644 --- a/Documentation/COMMANDS.md +++ b/Documentation/COMMANDS.md @@ -135,6 +135,7 @@ All log commands are using a grep-filter (specified as optional argument) | | __ct typo3:cleanup__ | | | __ct typo3:cleanup typo3__ | | ct typo3:domain | Add default suffix to all domains (default: .vm) | +| | __ct typo3:domain --baseurl__ Also update config.baseURL in SetupTS | | | __ct typo3:domain --list__ Print list of domains and exit | | | __ct typo3:domain --remove='*.vagrantshare.com'__ Remove all *.vagrantshare.com domains (used by vagrant:share command) | | | __ct typo3:domain --duplicate='foobar.vagrantshare.com'__ Duplicates all domains and add suffix 'foobar.vagrantshare.com' (used by vagrant:share command) | diff --git a/Documentation/USAGE-TYPO3.md b/Documentation/USAGE-TYPO3.md index e132f11..75d0acc 100644 --- a/Documentation/USAGE-TYPO3.md +++ b/Documentation/USAGE-TYPO3.md @@ -33,6 +33,9 @@ ct typo3:domain # Add a .vm at the and of all domains in typo3 database ct typo3:domain typo3 +# ... and also add config.baseURL to SetupTS +ct typo3:domain typo3 --baseurl + # Add a .vm at the and of all domains and remove all *.vagrantshare.com domains (used by vagrant:share) ct typo3:domain --remove='*.vagrantshare.com' diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index 5768ef8..49a9d3d 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -40,6 +40,12 @@ protected function configure() { InputArgument::OPTIONAL, 'Database name' ) + ->addOption( + 'baseurl', + null, + InputOption::VALUE_NONE, + 'Also set config.baseURL setting' + ) ->addOption( 'list', null, @@ -59,6 +65,7 @@ protected function configure() { 'Add duplication domains (will duplicate all domains in system, eg. for vagrant share)' ); } + /** * Execute command * @@ -119,7 +126,12 @@ protected function runTaskForDomain($dbName) { } // Set development domains - $this->manipulateDomains($dbName); + $this->manipulateDomains(); + + // Add sharing domains + if ($this->input->getOption('baseurl')) { + $this->updateBaseUrlConfig(); + } // Add sharing domains if ($this->input->getOption('duplicate')) { @@ -142,6 +154,41 @@ protected function removeDomains($pattern) { DatabaseConnection::exec($query); } + /** + * Update baseURL config + */ + protected function updateBaseUrlConfig() { + $query = 'SELECT st.uid as template_id, + st.config as template_config, + (SELECT sd.domainName + FROM sys_domain sd + WHERE sd.pid = st.pid + ORDER BY sd.forced DESC, + sd.sorting ASC + LIMIT 1) as domain_name + FROM sys_template st + WHERE st.root = 1 + AND st.deleted = 0 + HAVING domain_name IS NOT NULL'; + $templateIdList = DatabaseConnection::getAll($query); + + foreach ($templateIdList as $row) { + $templateId = $row['template_id']; + $domainName = $row['domain_name']; + $templateConf = $row['template_config']; + + // Remove old baseURL entries (no duplciates) + $templateConf = preg_replace('/^config.baseURL = .*$/m', '', $templateConf); + $templateConf = trim($templateConf); + + // Add new baseURL + $templateConf .= "\n" . 'config.baseURL = http://' . $domainName .'/'; + + $query = 'UPDATE sys_template SET config = %s WHERE uid = %s'; + $query = sprintf($query, DatabaseConnection::quote($templateConf), (int)$templateId); + DatabaseConnection::exec($query); + } + } /** * Add share domains (eg. for vagrantshare) @@ -191,22 +238,18 @@ protected function showDomainList($dbName) { /** * Set development domains for TYPO3 database * - * @param string $database Database - * * @return void */ - protected function manipulateDomains($database) { + protected function manipulateDomains() { $devDomain = '.' . $this->getApplication()->getConfigValue('config', 'domain_dev'); $domainLength = strlen($devDomain); - if (DatabaseConnection::tableExists($database, 'sys_domain')) { - // ################## - // Fix domains - // ################## - $query = 'UPDATE ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.sys_domain - SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($devDomain) . ') - WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($devDomain); - DatabaseConnection::exec($query); - } + // ################## + // Fix domains + // ################## + $query = 'UPDATE sys_domain + SET domainName = CONCAT(domainName, ' . DatabaseConnection::quote($devDomain) . ') + WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . DatabaseConnection::quote($devDomain); + DatabaseConnection::exec($query); } } From f3860890c87eb84d5a62970d62fcf6b282127b49 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 27 May 2015 23:21:41 +0200 Subject: [PATCH 148/214] Improved docker:create --- Documentation/USAGE-DOCKER.md | 10 +++++----- .../CliTools/Console/Command/Docker/CreateCommand.php | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/USAGE-DOCKER.md b/Documentation/USAGE-DOCKER.md index 4d424d5..d8eb717 100644 --- a/Documentation/USAGE-DOCKER.md +++ b/Documentation/USAGE-DOCKER.md @@ -8,17 +8,17 @@ You can easly create new docker instances (from my or a custom docker boilerplat and Makefile running. ```bash -# Startup new docker boilerplate -ct docker:create +# Startup new docker boilerplate into foobar directory +ct docker:create foobar # Startup new custom docker boilerplate -ct docker:create --docker=git... +ct docker:create foobar --docker=git... # Startup new docker boilerplate with code repository -ct docker:create --code=git... +ct docker:create foobar --code=git... # Startup new docker boilerplate with code repository and makefile run -ct docker:create --code=git... --make=build +ct docker:create foobar --code=git... --make=build ``` ## Docker startup diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index 5251f51..d6c0e32 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -97,10 +97,6 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->initDocumentRoot($path); PhpUtility::chdir($currDir); - // Start interactive editor - $this->startInteractiveEditor($path . '/docker-compose.yml'); - $this->startInteractiveEditor($path . '/docker-env.yml'); - // Run makefile if ($this->input->getOption('make')) { try { @@ -112,6 +108,10 @@ public function execute(InputInterface $input, OutputInterface $output) { } } + // Start interactive editor + $this->startInteractiveEditor($path . '/docker-compose.yml'); + $this->startInteractiveEditor($path . '/docker-env.yml'); + // Start docker PhpUtility::chdir($currDir); $this->startDockerInstance($path); From 33f64d853a50a1869ec0644d12745f6b5892733d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 28 May 2015 10:01:46 +0200 Subject: [PATCH 149/214] Updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0304d18..52480bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,9 @@ CliTools Changelog - Added `typo3:domain --list` for only list the domains of one or all databases - Added `typo3:domain --remove=domain/pattern` for domain cleanup (eg. vagrant share) - Added `typo3:domain --duplication=suffix` for domain duplication +- Added `typo3:domain --baseurl` for setting config.baseURL in SetupTS - Added `vagrant:share` with automatic domain setting for TYPO3 projects (ALPHA! not finished!) +- Added docker detection for sync features - Refactored some classes - Fixed some issues - Added gzip compression for PHAR From 053cd6d3698ce92c8011f0cd0bda9f43f5af96af Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 28 May 2015 23:01:11 +0200 Subject: [PATCH 150/214] Added --rsync and --mysql to sync:backup and sync:restore Fixes #36 --- .../Console/Command/Sync/BackupCommand.php | 94 ++++++++++++++----- .../Console/Command/Sync/RestoreCommand.php | 63 +++++++++++-- 2 files changed, 122 insertions(+), 35 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index b466316..07daffd 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -20,6 +20,8 @@ * along with this program. If not, see . */ +use Symfony\Component\Console\Input\InputOption; + class BackupCommand extends AbstractShareCommand { /** @@ -28,48 +30,88 @@ class BackupCommand extends AbstractShareCommand { protected function configure() { $this ->setName('sync:backup') - ->setDescription('Backup project files'); + ->setDescription('Backup project files') + ->addOption( + 'mysql', + null, + InputOption::VALUE_NONE, + 'Run only mysql' + ) + ->addOption( + 'rsync', + null, + InputOption::VALUE_NONE, + 'Run only rsync' + ); } /** * Backup task */ protected function runTask() { + // ################## + // Option specific runners + // ################## + $runRsync = true; + $runMysql = true; + + if ($this->input->getOption('mysql') || $this->input->getOption('rsync')) { + // don't run rsync if not specifiecd + $runRsync = $this->input->getOption('rsync'); + + // don't run mysql if not specifiecd + $runMysql = $this->input->getOption('mysql'); + } + + // ################## // Backup dirs // ################## - if ($this->config->exists('rsync.directory')) { - $source = $this->getRsyncWorkingPath(); - $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; - $command = $this->createShareRsyncCommand($source, $target, true); - $command->executeInteractive(); + if ($runRsync && $this->config->exists('rsync.directory')) { + $this->runTaskRsync(); } // ################## // Backup databases // ################## - if ($this->config->exists('mysql.database')) { - foreach ($this->config->getArray('mysql.database') as $database) { - $this->output->writeln('Dumping database ' . $database . ''); - - // dump database - $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; - - $dumpFilter = $this->config->get('mysql.filter'); - - $this->createMysqlBackupCommand($database, $dumpFile, $dumpFilter) - ->executeInteractive(); - } - - // ################## - // Backup mysql dump - // ################## - $source = $this->tempDir; - $target = $this->getRsyncPathFromConfig() . self::PATH_DUMP; - $command = $this->createShareRsyncCommand($source, $target, false); - $command->executeInteractive(); + if ($runMysql && $this->config->exists('mysql.database')) { + $this->runTaskMysql(); } + } + /** + * Sync files with rsync + */ + protected function runTaskRsync() { + $source = $this->getRsyncWorkingPath(); + $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); } + + /** + * Sync files with mysql + */ + protected function runTaskMysql() { + foreach ($this->config->getArray('mysql.database') as $database) { + $this->output->writeln('Dumping database ' . $database . ''); + + // dump database + $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; + + $dumpFilter = $this->config->get('mysql.filter'); + + $this->createMysqlBackupCommand($database, $dumpFile, $dumpFilter) + ->executeInteractive(); + } + + // ################## + // Backup mysql dump + // ################## + $source = $this->tempDir; + $target = $this->getRsyncPathFromConfig() . self::PATH_DUMP; + $command = $this->createShareRsyncCommand($source, $target, false); + $command->executeInteractive(); + } } diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index cb32ba6..b8bf17a 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -20,6 +20,8 @@ * along with this program. If not, see . */ +use Symfony\Component\Console\Input\InputOption; + class RestoreCommand extends AbstractShareCommand { /** @@ -28,28 +30,72 @@ class RestoreCommand extends AbstractShareCommand { protected function configure() { $this ->setName('sync:restore') - ->setDescription('Restore project files'); + ->setDescription('Restore project files') + ->addOption( + 'mysql', + null, + InputOption::VALUE_NONE, + 'Run only mysql' + ) + ->addOption( + 'rsync', + null, + InputOption::VALUE_NONE, + 'Run only rsync' + ); } /** * Restore task */ protected function runTask() { + // ################## + // Option specific runners + // ################## + $runRsync = true; + $runMysql = true; + + if ($this->input->getOption('mysql') || $this->input->getOption('rsync')) { + // don't run rsync if not specifiecd + $runRsync = $this->input->getOption('rsync'); + + // don't run mysql if not specifiecd + $runMysql = $this->input->getOption('mysql'); + } + + // ################## // Restore dirs // ################## - if ($this->config->exists('rsync.directory')) { - $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; - $target = $this->getRsyncWorkingPath(); - $command = $this->createShareRsyncCommand($source, $target, true); - $command->executeInteractive(); + if ($runRsync && $this->config->exists('rsync.directory')) { + $this->runTaskRsync(); } // ################## // Restore mysql dump // ################## - $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; - $target = $this->tempDir; + if ($runMysql) { + $this->runTaskMysql(); + } + } + + /** + * Sync files with rsync + */ + protected function runTaskRsync() { + $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; + $target = $this->getRsyncWorkingPath(); + $command = $this->createShareRsyncCommand($source, $target, true); + $command->executeInteractive(); + } + + + /** + * Sync files with mysql + */ + protected function runTaskMysql() { + $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; + $target = $this->tempDir; $command = $this->createShareRsyncCommand($source, $target, false); $command->executeInteractive(); @@ -69,5 +115,4 @@ protected function runTask() { } } } - } From a8669a9cbd2978f4de3f43eb806e10e2172c789c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 28 May 2015 23:01:34 +0200 Subject: [PATCH 151/214] Refactored sync:server --rsync and --mysql --- .../Console/Command/Sync/ServerCommand.php | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index b7a7049..863ec43 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -87,46 +87,48 @@ protected function readConfiguration() { } else { $this->config->setData($this->config->getArray($this->contextName)); } + } + /** + * Backup task + */ + protected function runTask() { // ################## // Option specific runners // ################## + $runRsync = true; + $runMysql = true; if ($this->input->getOption('mysql') || $this->input->getOption('rsync')) { - // Clear mysql config if mysql isn't active - if (!$this->input->getOption('mysql')) { - $this->config->clear('mysql'); - } + // don't run rsync if not specifiecd + $runRsync = $this->input->getOption('rsync'); - // Clear rsync config if rsync isn't active - if (!$this->input->getOption('rsync')) { - $this->config->clear('rsync'); - } + // don't run mysql if not specifiecd + $runMysql = $this->input->getOption('mysql'); } - } + // ################## + // Run tasks + // ################## - /** - * Backup task - */ - protected function runTask() { // Check database connection - if ($this->config->exists('mysql')) { + if ($runMysql && $this->config->exists('mysql')) { DatabaseConnection::ping(); } // Sync files with rsync to local storage - if ($this->config->exists('rsync')) { + if ($runRsync && $this->config->exists('rsync')) { $this->output->writeln(' ---- Starting FILE sync ---- '); $this->runTaskRsync(); } // Sync database to local server - if ($this->config->exists('mysql')) { + if ($runMysql && $this->config->exists('mysql')) { $this->output->writeln(' ---- Starting MYSQL sync ---- '); $this->runTaskDatabase(); } } + /** * Sync files with rsync */ From 7e3a445da3037e72ae4a99e8769fea963bd43e3d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 28 May 2015 23:01:39 +0200 Subject: [PATCH 152/214] Fixed typo --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 83620ba..ba1ca95 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -285,7 +285,7 @@ protected function checkIfDockerExists() { $docker = new CommandBuilder('docker', 'ps'); $docker->executeInteractive(); - $answer = ConsoleUtility::questionYesNo('Are these running containers the right one?', 'no'); + $answer = ConsoleUtility::questionYesNo('Are these running containers the right ones?', 'no'); if (!$answer) { throw new \CliTools\Exception\StopException(1); From 7b5399b629b49ef7a00468173c93c5e7c23482ba Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 28 May 2015 23:45:41 +0200 Subject: [PATCH 153/214] Updated readme --- Documentation/COMMANDS.md | 6 ++++++ Documentation/USAGE-SYNC.md | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Documentation/COMMANDS.md b/Documentation/COMMANDS.md index 01617b5..42f3922 100644 --- a/Documentation/COMMANDS.md +++ b/Documentation/COMMANDS.md @@ -92,7 +92,13 @@ All log commands are using a grep-filter (specified as optional argument) |----------------------------|---------------------------------------------------------------------------| | ct sync:init | Create example clisync.yml in current working directory | | ct sync:backup | Search for clisync.yml in tree and start backup to shared server | +| | __ct sync:backup__ -> Backup files and database from share | +| | __ct sync:backup --rsync__ -> Backup only files from share | +| | __ct sync:backup --mysql__ -> Backup only database from share | | ct sync:restore | Search for clisync.yml in tree and start restore from shared server | +| | __ct sync:restore__ -> Restore files and database from share | +| | __ct sync:restore --rsync__ -> Restore only files from share | +| | __ct sync:restore --mysql__ -> Restore only database from share | | ct sync:server | Search for clisync.yml in tree and start server synchronization (eg. from live or preview to local development instance | | | __ct sync:server production__ -> Use "production" configuration and start sync | | | __ct sync:server preview --rsync__ -> Use "preview" configuration and start only rsync | diff --git a/Documentation/USAGE-SYNC.md b/Documentation/USAGE-SYNC.md index 8df281d..abe203b 100644 --- a/Documentation/USAGE-SYNC.md +++ b/Documentation/USAGE-SYNC.md @@ -48,7 +48,20 @@ Please use a common development/storage server with ssh access for each develope # Make backup of current state and transfer to share server ct sync:backup +# ... only MySQL +ct sync:backup --mysql + +# ... only files +ct sync:backup --rsync + # Restore to state from the share server ct sync:restore + +# ... only MySQL +ct sync:restore --mysql + +# ... only files +ct sync:restore --rsync + ``` From e84bfc106736140b164b6ea37e07ff950ed7dda9 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 28 May 2015 23:46:33 +0200 Subject: [PATCH 154/214] Version bump 1.9.908 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index 472634c..ff649df 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.907'); +define('CLITOOLS_COMMAND_VERSION', '1.9.908'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From ce1c878ea78f4f7b75bc8cd8280fa251711f2ecc Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 29 May 2015 17:28:00 +0200 Subject: [PATCH 155/214] Fixed bug with parsed commands --- .../Console/Shell/CommandBuilder/AbstractCommandBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php index 938d4f4..2de9474 100644 --- a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php @@ -388,7 +388,7 @@ public function parse($str) { // Set arguments (second values) if (!empty($parsedCmd[1])) { - $this->setArgumentList(array($parsedCmd[1]), false); + $this->addArgumentRaw($parsedCmd[1]); } return $this; } From a56240e0397b97a53c32be6bc63a98a6a090f101 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 29 May 2015 17:48:56 +0200 Subject: [PATCH 156/214] Added getDsn --- src/app/CliTools/Database/DatabaseConnection.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app/CliTools/Database/DatabaseConnection.php b/src/app/CliTools/Database/DatabaseConnection.php index b674d83..f55bde8 100644 --- a/src/app/CliTools/Database/DatabaseConnection.php +++ b/src/app/CliTools/Database/DatabaseConnection.php @@ -76,6 +76,15 @@ public static function setDsn($dsn, $username = null, $password = null) { self::$connection = null; } + /** + * Get Db DSN + * + * @return string + */ + public static function getDsn() { + return self::$dbDsn; + } + /** * Get Db Username * From 41e476a70e63e3566f20f3d017a6e18339330ea6 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 29 May 2015 17:51:59 +0200 Subject: [PATCH 157/214] Added --host, --port, --user and --password to mysql:* methods Fixes #40 --- .../Console/Command/Docker/SniffCommand.php | 8 ++ .../Console/Command/Mysql/AbstractCommand.php | 100 ++++++++++++++++++ .../Console/Command/Mysql/BackupCommand.php | 13 ++- .../Console/Command/Mysql/ClearCommand.php | 4 +- .../Command/Mysql/ConnectionsCommand.php | 4 +- .../Console/Command/Mysql/ConvertCommand.php | 4 +- .../Console/Command/Mysql/DebugCommand.php | 2 +- .../Console/Command/Mysql/DropCommand.php | 4 +- .../Console/Command/Mysql/ListCommand.php | 4 +- .../Console/Command/Mysql/RestartCommand.php | 2 +- .../Console/Command/Mysql/RestoreCommand.php | 13 ++- .../Console/Command/Mysql/SlowLogCommand.php | 2 +- 12 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 src/app/CliTools/Console/Command/Mysql/AbstractCommand.php diff --git a/src/app/CliTools/Console/Command/Docker/SniffCommand.php b/src/app/CliTools/Console/Command/Docker/SniffCommand.php index ae32022..dd421f4 100644 --- a/src/app/CliTools/Console/Command/Docker/SniffCommand.php +++ b/src/app/CliTools/Console/Command/Docker/SniffCommand.php @@ -45,6 +45,12 @@ protected function configure() { null, InputOption::VALUE_NONE, 'Show full output (if supported by protocol)' + ) + ->addOption( + 'filter', + null, + InputOption::VALUE_NONE, + 'Additonal filter' ); } @@ -199,6 +205,8 @@ public function execute(InputInterface $input, OutputInterface $output) { switch ($command->getCommand()) { case 'tshark': $command->addArgumentTemplate('-i %s', $dockerInterface); + + break; case 'tcpdump': diff --git a/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php b/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php new file mode 100644 index 0000000..2800aee --- /dev/null +++ b/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php @@ -0,0 +1,100 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Database\DatabaseConnection; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand { + + /** + * Configure command + */ + protected function configure() { + $this + ->addOption( + 'host', + null, + InputOption::VALUE_REQUIRED, + 'MySQL host' + ) + ->addOption( + 'port', + null, + InputOption::VALUE_REQUIRED, + 'MySQL port' + ) + ->addOption( + 'user', + 'u', + InputOption::VALUE_REQUIRED, + 'MySQL user' + ) + ->addOption( + 'password', + 'p', + InputOption::VALUE_REQUIRED, + 'MySQL host' + ); + } + + /** + * Initializes the command just after the input has been validated. + * + * This is mainly useful when a lot of commands extends one main command + * where some things need to be initialized based on the input arguments and options. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + */ + protected function initialize(InputInterface $input, OutputInterface $output) { + parent::initialize($input, $output); + + $dsn = null; + $user = null; + $password = null; + + if ($this->input->getOption('host')) { + $host = $this->input->getOption('host'); + $port = 3306; + + if ($this->input->getOption('port')) { + $port = $this->input->getOption('port'); + } + + $dsn = 'mysql:host=' . urlencode($host) . ';port=' . (int)$port; + } + + if ($this->input->getOption('user')) { + $user = $this->input->getOption('user'); + } + + if ($this->input->getOption('password')) { + $password = $this->input->getOption('password'); + } + + if ($user !== null || $password !== null) { + DatabaseConnection::setDsn($dsn, $user, $password); + } + } +} diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index b1036a9..0bda41d 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -29,12 +29,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class BackupCommand extends \CliTools\Console\Command\AbstractCommand { +class BackupCommand extends AbstractCommand { /** * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('mysql:backup') ->setDescription('Backup database') @@ -109,6 +111,15 @@ public function execute(InputInterface $input, OutputInterface $output) { $command = new CommandBuilder('mysqldump','--user=%s %s --single-transaction', array(DatabaseConnection::getDbUsername(), $database)); + // Set server connection details + if ($input->getOption('host')) { + $command->addArgumentTemplate('-h %s', $input->getOption('host')); + } + + if ($input->getOption('port')) { + $command->addArgumentTemplate('-P %s', $input->getOption('port')); + } + if (!empty($filter)) { $command = $this->addFilterArguments($command, $database, $filter); } diff --git a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php index b6e2a18..52dc642 100644 --- a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php @@ -25,12 +25,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ClearCommand extends \CliTools\Console\Command\AbstractCommand { +class ClearCommand extends AbstractCommand { /** * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('mysql:clear') ->setAliases(array('mysql:create')) diff --git a/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php b/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php index eccc41a..318f241 100644 --- a/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ConnectionsCommand.php @@ -25,12 +25,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ConnectionsCommand extends \CliTools\Console\Command\AbstractCommand { +class ConnectionsCommand extends AbstractCommand { /** * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('mysql:connections') ->setDescription('List current connections'); diff --git a/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php index c9b5932..0c4ef55 100644 --- a/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php @@ -26,12 +26,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class ConvertCommand extends \CliTools\Console\Command\AbstractCommand { +class ConvertCommand extends AbstractCommand { /** * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('mysql:convert') ->setDescription('Convert charset/collation of a database') diff --git a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php index 721e987..d449a65 100644 --- a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php @@ -25,7 +25,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class DebugCommand extends \CliTools\Console\Command\AbstractCommand { +class DebugCommand extends AbstractCommand { /** * Configure command diff --git a/src/app/CliTools/Console/Command/Mysql/DropCommand.php b/src/app/CliTools/Console/Command/Mysql/DropCommand.php index 4d31d48..d84b867 100644 --- a/src/app/CliTools/Console/Command/Mysql/DropCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/DropCommand.php @@ -25,12 +25,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class DropCommand extends \CliTools\Console\Command\AbstractCommand { +class DropCommand extends AbstractCommand { /** * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('mysql:drop') ->setDescription('Drop database') diff --git a/src/app/CliTools/Console/Command/Mysql/ListCommand.php b/src/app/CliTools/Console/Command/Mysql/ListCommand.php index 8620d34..5d692be 100644 --- a/src/app/CliTools/Console/Command/Mysql/ListCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ListCommand.php @@ -28,12 +28,14 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class ListCommand extends \CliTools\Console\Command\AbstractCommand { +class ListCommand extends AbstractCommand { /** * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('mysql:list') ->setDescription('List all databases') diff --git a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php index f353824..b3d502a 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php @@ -24,7 +24,7 @@ use Symfony\Component\Console\Output\OutputInterface; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -class RestartCommand extends \CliTools\Console\Command\AbstractCommand { +class RestartCommand extends AbstractCommand { /** * Configure command diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index 68653f8..c4e8d98 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -27,12 +27,14 @@ use Symfony\Component\Console\Output\OutputInterface; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -class RestoreCommand extends \CliTools\Console\Command\AbstractCommand { +class RestoreCommand extends AbstractCommand { /** * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('mysql:restore') ->setDescription('Restore database') @@ -88,6 +90,15 @@ public function execute(InputInterface $input, OutputInterface $output) { $commandMysql = new CommandBuilder('mysql','--user=%s %s --one-database', array(DatabaseConnection::getDbUsername(), $database)); + // Set server connection details + if ($input->getOption('host')) { + $commandMysql->addArgumentTemplate('-h %s', $input->getOption('host')); + } + + if ($input->getOption('port')) { + $commandMysql->addArgumentTemplate('-P %s', $input->getOption('port')); + } + $commandFile = new CommandBuilder(); $commandFile->addArgument($dumpFile); $commandFile->addPipeCommand($commandMysql); diff --git a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php index 4955198..04150d3 100644 --- a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php @@ -26,7 +26,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class SlowLogCommand extends \CliTools\Console\Command\AbstractCommand { +class SlowLogCommand extends AbstractCommand { /** * Configure command From 1e5a3537167040e95f00c957f76f78d0b122ab58 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 29 May 2015 18:08:10 +0200 Subject: [PATCH 158/214] Added possiblity to get whole config without key --- src/app/CliTools/Reader/ConfigReader.php | 54 ++++++++++++++++-------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/app/CliTools/Reader/ConfigReader.php b/src/app/CliTools/Reader/ConfigReader.php index fda55cd..fa4ce16 100644 --- a/src/app/CliTools/Reader/ConfigReader.php +++ b/src/app/CliTools/Reader/ConfigReader.php @@ -52,20 +52,20 @@ public function setData(array $data) { /** * Get value from specific node (dotted array notation) * - * @param string $path Path to node (eg. foo.bar.baz) + * @param string|null $path Path to node (eg. foo.bar.baz) * @return mixed|null */ - public function get($path) { + public function get($path = null) { return $this->getNode($path); } /** * Get array value from specific node (dotted array notation) * - * @param string $path Path to node (eg. foo.bar.baz) + * @param string|null $path Path to node (eg. foo.bar.baz) * @return array|null */ - public function getArray($path) { + public function getArray($path = null) { $ret = $this->getNode($path); if (!is_array($ret)) { @@ -75,6 +75,24 @@ public function getArray($path) { return $ret; } + /** + * Get list of keys from specific node (dotted array notation) + * + * @param string|null $path Path to node (eg. foo.bar.baz) + * @return array|null + */ + public function getList($path = null) { + $ret = $this->getNode($path); + + if (is_array($ret)) { + $ret = array_keys($ret); + } else { + $ret = array(); + } + + return $ret; + } + /** * Set value to specific node (dotted array notation) * @@ -89,9 +107,9 @@ public function set($path, $value) { /** * Clear value at specific node (dotted array notation) * - * @param string $path Path to node (eg. foo.bar.baz) + * @param null|string $path Path to node (eg. foo.bar.baz) */ - public function clear($path) { + public function clear($path = null) { $node =& $this->getNode($path); $node = null; } @@ -99,30 +117,32 @@ public function clear($path) { /** * Check if specific node exists * - * @param string $path Path to node (eg. foo.bar.baz) + * @param null|string $path Path to node (eg. foo.bar.baz) * @return bool */ - public function exists($path) { + public function exists($path = null) { return ($this->getNode($path) !== null); } /** * Get node by reference * - * @param string $path Path to node (eg. foo.bar.baz) + * @param string|null $path Path to node (eg. foo.bar.baz) * @return mixed|null */ protected function &getNode($path) { - $pathList = explode('.',$path); $data = &$this->data; - foreach ($pathList as $node) { - if (isset($data[$node])) { - $data = &$data[$node]; - } else { - unset($data); - $data = null; - break; + if ($path !== null) { + $pathList = explode('.', $path); + foreach ($pathList as $node) { + if (isset($data[$node])) { + $data = &$data[$node]; + } else { + unset($data); + $data = null; + break; + } } } From ab9107bf9fea8c9b85c7d975a99b6ad33e90fb5f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 29 May 2015 18:08:30 +0200 Subject: [PATCH 159/214] Added selector for server context Fixes #39 --- .../Command/Sync/AbstractSyncCommand.php | 33 +++++++++++++++++++ .../Console/Command/Sync/ServerCommand.php | 5 +-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index d885716..f4c1b86 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -20,6 +20,9 @@ * along with this program. If not, see . */ +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Question\ChoiceQuestion; + abstract class AbstractSyncCommand extends \CliTools\Console\Command\Sync\AbstractCommand { /** @@ -55,5 +58,35 @@ protected function validateConfiguration() { return $ret; } + /** + * Get server context from user + */ + protected function getServerContext() { + $ret = null; + + if (!$this->input->getArgument('context')) { + // ######################## + // Ask user for server context + // ######################## + + $serverList = $this->config->getList(); + $serverList = array_diff($serverList, array('_')); + + if (empty($serverList)) { + throw new \RuntimeException('No valid servers found in configuration'); + } + + $question = new ChoiceQuestion('Please choose process for tracing', $serverList); + + $questionDialog = new QuestionHelper(); + + $ret = $questionDialog->ask($this->input, $this->output, $question); + } else { + $ret = $this->input->getArgument('context'); + } + + return $ret; + } + } diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 863ec43..fc947e4 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -29,6 +29,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; + class ServerCommand extends AbstractSyncCommand { /** @@ -46,7 +47,7 @@ protected function configure() { ->setDescription('Sync files and database from server') ->addArgument( 'context', - InputArgument::REQUIRED, + InputArgument::OPTIONAL, 'Configuration name for server' ) ->addOption( @@ -69,7 +70,7 @@ protected function configure() { protected function readConfiguration() { parent::readConfiguration(); - $this->contextName = $this->input->getArgument('context'); + $this->contextName = $this->getServerContext(); if (empty($this->contextName) || $this->contextName === '_' || empty($this->config[$this->contextName])) { throw new \RuntimeException('No valid configuration found for context "' . $this->contextName . '"'); From 207328a7663af85efeb23a70e356e146f4f2bd2f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 30 May 2015 15:10:48 +0200 Subject: [PATCH 160/214] Updated credits --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 98b469f..9b1fa72 100644 --- a/README.md +++ b/README.md @@ -26,5 +26,8 @@ CliTools is based on Symfony Components (Console). ## Credits -Thanks to my colleagues at [cron IT GmbH](http://www.cron.eu/), [Ingo Pfennigstorf](https://twitter.com/krautsock) -and [Florian Tatzel](https://twitter.com/panadeedu) for testing and some usefull ideas. +Thanks for support, ideas and issues ... +- [Ingo Pfennigstorf](https://twitter.com/krautsock) +- [Florian Tatzel](https://twitter.com/PanadeEdu) +- my (old) colleagues at [Lightwerk GmbH](http://www.lightwerk.de/) +- my colleagues at [cron IT GmbH](http://www.cron.eu/) From f39e2763cd4f95b83539d8e250102a58fe3fcc4c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 30 May 2015 15:19:25 +0200 Subject: [PATCH 161/214] Updated credits --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9b1fa72..11b9d2d 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,5 @@ Thanks for support, ideas and issues ... - [Florian Tatzel](https://twitter.com/PanadeEdu) - my (old) colleagues at [Lightwerk GmbH](http://www.lightwerk.de/) - my colleagues at [cron IT GmbH](http://www.cron.eu/) + +Did I forget anyone? Send me a tweet or create pull request! From 9e2a3193df23c21585148f623192d47fa003253e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 30 May 2015 20:23:42 +0200 Subject: [PATCH 162/214] Updated to symfony 2.7 --- CHANGELOG.md | 1 + src/composer.lock | 34 ++++++++++++++++------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52480bf..c9fd8c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ CliTools Changelog - Added `typo3:domain --baseurl` for setting config.baseURL in SetupTS - Added `vagrant:share` with automatic domain setting for TYPO3 projects (ALPHA! not finished!) - Added docker detection for sync features +- Updated to Symfony 2.7 - Refactored some classes - Fixed some issues - Added gzip compression for PHAR diff --git a/src/composer.lock b/src/composer.lock index c39197f..725f601 100644 --- a/src/composer.lock +++ b/src/composer.lock @@ -48,21 +48,20 @@ }, { "name": "symfony/console", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Console", + "version": "v2.7.0", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272" + "reference": "7f0bec04961c61c961df0cb8c2ae88dbfd83f399" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/ebc5679854aa24ed7d65062e9e3ab0b18a917272", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272", + "url": "https://api.github.com/repos/symfony/Console/zipball/7f0bec04961c61c961df0cb8c2ae88dbfd83f399", + "reference": "7f0bec04961c61c961df0cb8c2ae88dbfd83f399", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", @@ -78,11 +77,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Console\\": "" } }, @@ -102,25 +101,24 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-05-29 16:22:24" }, { "name": "symfony/yaml", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Yaml", + "version": "v2.7.0", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + "reference": "4a29a5248aed4fb45f626a7bbbd330291492f5c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/4a29a5248aed4fb45f626a7bbbd330291492f5c3", + "reference": "4a29a5248aed4fb45f626a7bbbd330291492f5c3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -128,11 +126,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Yaml\\": "" } }, @@ -152,7 +150,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-05-02 15:21:08" } ], "packages-dev": [], From e18b1e11ceebc618a18e2a236485d1d7e9652c9b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 30 May 2015 21:28:58 +0200 Subject: [PATCH 163/214] Fixed selection of processes --- src/app/CliTools/Console/Command/AbstractTraceCommand.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/CliTools/Console/Command/AbstractTraceCommand.php b/src/app/CliTools/Console/Command/AbstractTraceCommand.php index 3682763..85be3c0 100644 --- a/src/app/CliTools/Console/Command/AbstractTraceCommand.php +++ b/src/app/CliTools/Console/Command/AbstractTraceCommand.php @@ -104,7 +104,6 @@ public function execute(InputInterface $input, OutputInterface $output) { } } - if (!empty($pid)) { switch ($pid) { case 'all': @@ -157,7 +156,7 @@ protected function buildProcessList() { $currentPid = posix_getpid(); $processList = array( - 'all processes' => 'all', + 'all' => 'all processes', ); $command = new CommandBuilder('ps'); @@ -183,8 +182,8 @@ protected function buildProcessList() { continue; } - $pidList[] = (int)$pid; - $processList[$cmd] = (int)$pid; + $pidList[] = (int)$pid; + $processList[(int)$pid] = $cmd; } return array($pidList, $processList); From 2b8d79c378e8398911c79b3212e90416cb769023 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Sat, 30 May 2015 21:41:28 +0200 Subject: [PATCH 164/214] Improved interactive question handling --- src/app/CliTools/Console/Command/AbstractTraceCommand.php | 3 ++- src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/CliTools/Console/Command/AbstractTraceCommand.php b/src/app/CliTools/Console/Command/AbstractTraceCommand.php index 85be3c0..d7f7e95 100644 --- a/src/app/CliTools/Console/Command/AbstractTraceCommand.php +++ b/src/app/CliTools/Console/Command/AbstractTraceCommand.php @@ -97,7 +97,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $pid = 'all'; } else { $question = new ChoiceQuestion('Please choose process for tracing', $processList); - + $question->setMaxAttempts(1); + $questionDialog = new QuestionHelper(); $pid = $questionDialog->ask($input, $output, $question); diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index f4c1b86..5bb1fb0 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -76,7 +76,9 @@ protected function getServerContext() { throw new \RuntimeException('No valid servers found in configuration'); } - $question = new ChoiceQuestion('Please choose process for tracing', $serverList); + $questionList = array_combine(array_values($serverList), array_values($serverList) ); + $question = new ChoiceQuestion('Please choose process for tracing', $questionList); + $question->setMaxAttempts(1); $questionDialog = new QuestionHelper(); From 006e4e6adb517dc26e02b76517b05ca07098798e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 2 Jun 2015 00:00:23 +0200 Subject: [PATCH 165/214] Added ssh config examples --- Documentation/USAGE-SYNC.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Documentation/USAGE-SYNC.md b/Documentation/USAGE-SYNC.md index abe203b..a56fa7d 100644 --- a/Documentation/USAGE-SYNC.md +++ b/Documentation/USAGE-SYNC.md @@ -65,3 +65,26 @@ ct sync:restore --rsync ``` +## Advanced ssh options + +If you need some advaned ssh options (eg. other ports) use your `~/.ssh/config` configuration file: + + Host project-server + Hostname project-server.example.com + Port 12345 + User root + +If you have a proxy server you can configure it like this: + + Host ssh-proxy + Hostname ssh-proxy.example.com + User foo + + Host project-server + Hostname project-server.example.com + Port 12345 + User root + ProxyCommand ssh ssh-proxy -W %h:%p + + +Now you can use `project-server` as ssh-hostname and your settings will automatically used from your `~/.ssh/config`. From 10bc337c510558f812612a5e3a2da4c5755d8abe Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 2 Jun 2015 00:17:42 +0200 Subject: [PATCH 166/214] Version bump 1.9.909 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index ff649df..e4e6dc6 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.908'); +define('CLITOOLS_COMMAND_VERSION', '1.9.909'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From 67cd670bcd81518aaaff490f93c9a9e50938e1f8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 3 Jun 2015 18:15:20 +0200 Subject: [PATCH 167/214] Fixed regression --- src/app/CliTools/Console/Command/Docker/AbstractCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php index c8e7954..6e6b27b 100644 --- a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php @@ -43,7 +43,7 @@ protected function getDockerPath() { $composePath = \CliTools\Utility\DockerUtility::searchDockerDirectoryRecursive(); if (!empty($composePath)) { - $this->dockerPath = dirname($this->dockerPath); + $this->dockerPath = dirname($composePath); $this->output->writeln('Found docker directory: ' . $this->dockerPath . ''); } } From c6c478608915e941e994b418c442b0f71fd9e5f8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 3 Jun 2015 18:15:34 +0200 Subject: [PATCH 168/214] Fixed text --- src/app/CliTools/Console/Command/Mysql/RestoreCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index c4e8d98..4d5107a 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -105,24 +105,24 @@ public function execute(InputInterface $input, OutputInterface $output) { switch ($dumpFileType) { case 'application/x-bzip2': - $output->writeln('Using BZIP2 uncompression'); + $output->writeln('Using BZIP2 decompression'); $commandFile->setCommand('bzcat'); break; case 'application/gzip': case 'application/x-gzip': - $output->writeln('Using GZIP uncompression'); + $output->writeln('Using GZIP decompression'); $commandFile->setCommand('gzcat'); break; case 'application/x-lzma': case 'application/x-xz': - $output->writeln('Using LZMA uncompression'); + $output->writeln('Using LZMA decompression'); $commandFile->setCommand('xzcat'); break; default: - $output->writeln('Using plaintext (no uncompression)'); + $output->writeln('Using plaintext (no decompression)'); $commandFile->setCommand('cat'); break; } From 41ca99b420b2c37bd0ed9486307af0f4fa8a1df2 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 3 Jun 2015 18:15:49 +0200 Subject: [PATCH 169/214] Improved interactive question --- .../Console/Command/AbstractTraceCommand.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/AbstractTraceCommand.php b/src/app/CliTools/Console/Command/AbstractTraceCommand.php index d7f7e95..ca58dd0 100644 --- a/src/app/CliTools/Console/Command/AbstractTraceCommand.php +++ b/src/app/CliTools/Console/Command/AbstractTraceCommand.php @@ -96,12 +96,17 @@ public function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption('all')) { $pid = 'all'; } else { - $question = new ChoiceQuestion('Please choose process for tracing', $processList); - $question->setMaxAttempts(1); - - $questionDialog = new QuestionHelper(); + try { + $question = new ChoiceQuestion('Please choose process for tracing', $processList); + $question->setMaxAttempts(1); - $pid = $questionDialog->ask($input, $output, $question); + $questionDialog = new QuestionHelper(); + + $pid = $questionDialog->ask($input, $output, $question); + } catch(\InvalidArgumentException $e) { + // Invalid value, just stop here + throw new \CliTools\Exception\StopException(1); + } } } From 946f594befc4520300e431a75e72d4a51c32d28f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Wed, 3 Jun 2015 23:36:20 +0200 Subject: [PATCH 170/214] Improved sync selection --- .../Command/Sync/AbstractSyncCommand.php | 63 +++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index 5bb1fb0..c5b8ee4 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -76,13 +76,66 @@ protected function getServerContext() { throw new \RuntimeException('No valid servers found in configuration'); } - $questionList = array_combine(array_values($serverList), array_values($serverList) ); - $question = new ChoiceQuestion('Please choose process for tracing', $questionList); - $question->setMaxAttempts(1); + $serverOptionList = array(); + + foreach ($serverList as $context) { + $line = array(); + + // hostname + $optPath = $context . '.ssh.hostname'; + if ($this->config->exists($optPath)) { + $line[] = 'host:' . $this->config->get($optPath); + } + + // rsync path + $optPath = $context . '.rsync.path'; + if ($this->config->exists($optPath)) { + $line[] = 'rsync:' . $this->config->get($optPath); + } + + // mysql database list + $optPath = $context . '.mysql.database'; + if ($this->config->exists($optPath)) { + $dbList = $this->config->getArray($optPath); + $foreignDbList = array(); + + foreach ($dbList as $databaseConf) { + if (strpos($databaseConf, ':') !== false) { + // local and foreign database in one string + list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); + $foreignDbList[] = $foreignDatabase; + } else { + // database equal + $foreignDbList[] = $databaseConf; + } + } + + if (!empty($foreignDbList)) { + $line[] .= 'mysql:' . implode(', ', $foreignDbList); + } + } + + if (!empty($line)) { + $line = implode(' ', $line); + } else { + // fallback + $line = $context; + } + + $serverOptionList[$context] = $line; + } + + try { + $question = new ChoiceQuestion('Please choose server context for synchronization', $serverOptionList); + $question->setMaxAttempts(1); - $questionDialog = new QuestionHelper(); + $questionDialog = new QuestionHelper(); - $ret = $questionDialog->ask($this->input, $this->output, $question); + $ret = $questionDialog->ask($this->input, $this->output, $question); + } catch(\InvalidArgumentException $e) { + // Invalid server context, just stop here + throw new \CliTools\Exception\StopException(1); + } } else { $ret = $this->input->getArgument('context'); } From d7a3f4f7f73b9ec796d90638ef2e2c13dfc3f8ea Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 4 Jun 2015 17:17:15 +0200 Subject: [PATCH 171/214] Added Formatter with padding and wrapping --- .../Formatter/OutputFormatterStyle.php | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/app/CliTools/Console/Formatter/OutputFormatterStyle.php diff --git a/src/app/CliTools/Console/Formatter/OutputFormatterStyle.php b/src/app/CliTools/Console/Formatter/OutputFormatterStyle.php new file mode 100644 index 0000000..17024a2 --- /dev/null +++ b/src/app/CliTools/Console/Formatter/OutputFormatterStyle.php @@ -0,0 +1,164 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +class OutputFormatterStyle extends \Symfony\Component\Console\Formatter\OutputFormatterStyle { + + protected static $availableForegroundColors = array( + 'black' => array('set' => 30, 'unset' => 39), + 'red' => array('set' => 31, 'unset' => 39), + 'green' => array('set' => 32, 'unset' => 39), + 'yellow' => array('set' => 33, 'unset' => 39), + 'blue' => array('set' => 34, 'unset' => 39), + 'magenta' => array('set' => 35, 'unset' => 39), + 'cyan' => array('set' => 36, 'unset' => 39), + 'white' => array('set' => 37, 'unset' => 39), + ); + protected static $availableBackgroundColors = array( + 'black' => array('set' => 40, 'unset' => 49), + 'red' => array('set' => 41, 'unset' => 49), + 'green' => array('set' => 42, 'unset' => 49), + 'yellow' => array('set' => 43, 'unset' => 49), + 'blue' => array('set' => 44, 'unset' => 49), + 'magenta' => array('set' => 45, 'unset' => 49), + 'cyan' => array('set' => 46, 'unset' => 49), + 'white' => array('set' => 47, 'unset' => 49), + ); + protected static $availableOptions = array( + 'bold' => array('set' => 1, 'unset' => 22), + 'underscore' => array('set' => 4, 'unset' => 24), + 'blink' => array('set' => 5, 'unset' => 25), + 'reverse' => array('set' => 7, 'unset' => 27), + 'conceal' => array('set' => 8, 'unset' => 28), + ); + + /** + * Padding + * + * @var null|integer + */ + protected $padding; + + /** + * Padding + * + * @var null|integer + */ + protected $paddingOutside; + + /** + * Wrap + * + * @var null|string + */ + protected $wrap; + + /** + * Application + * + * @var \CliTools\Console\Application + */ + protected $application; + + /** + * Set padding + * + * @param integer|string $padding Padding + */ + public function setPadding($padding) { + $this->padding = $padding; + } + + /** + * Set padding + * + * @param integer|string $padding Padding + */ + public function setPaddingOutside($padding) { + $this->paddingOutside = $padding; + } + + /** + * Set application + * + * @param \CliTools\Console\Application $app Application + */ + public function setApplication(\CliTools\Console\Application $app) { + $this->application = $app; + } + + /** + * Set wrap + * + * @param string $wrap Wrap value + */ + public function setWrap($wrap) { + $this->wrap = $wrap; + } + + /** + * Applies the style to a given text. + * + * @param string $text The text to style + * + * @return string + */ + public function apply($text) { + + $ret = $text; + + // ################## + // Padding + // ################## + + if (!empty($this->padding)) { + $ret = $this->padding . $ret; + } + + + // ################## + // Wrap + // ################## + + if (!empty($this->wrap)) { + list($width) = $this->application->getTerminalDimensions(); + + $length = strlen($text); + $wrapLength = (int)($width - $length - 2)/2 * 0.5; + + if ($wrapLength >= 1) { + $ret = str_repeat($this->wrap, $wrapLength) . ' '. $ret . ' ' . str_repeat($this->wrap, $wrapLength); + } + } + + $ret = parent::apply($ret); + + // ################## + // Padding + // ################## + + if (!empty($this->paddingOutside)) { + $ret = $this->paddingOutside . $ret; + } + + return $ret; + } +} From d0f1baf686666e06bbc43d48cf80ce46b4f0cd9b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 4 Jun 2015 17:17:32 +0200 Subject: [PATCH 172/214] Added new styles --- src/app/CliTools/Console/Application.php | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/app/CliTools/Console/Application.php b/src/app/CliTools/Console/Application.php index 86a5ac7..c526750 100644 --- a/src/app/CliTools/Console/Application.php +++ b/src/app/CliTools/Console/Application.php @@ -22,6 +22,7 @@ use CliTools\Database\DatabaseConnection; use CliTools\Service\SettingsService; +use CliTools\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\ArgvInput; @@ -173,6 +174,34 @@ public function doRun(InputInterface $input, OutputInterface $output) { return $ret; } + + /** + * Configures the input and output instances based on the user arguments and options. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + */ + protected function configureIO(InputInterface $input, OutputInterface $output) { + parent::configureIO($input, $output); + + $style = new OutputFormatterStyle(); + $style->setApplication($this); + $style->setWrap('-', '-'); + $output->getFormatter()->setStyle('h1', $style); + + $style = new OutputFormatterStyle(); + $style->setPaddingOutside(' ===> '); + $output->getFormatter()->setStyle('h2', $style); + + $style = new OutputFormatterStyle(); + $style->setPaddingOutside(' - '); + $output->getFormatter()->setStyle('p', $style); + + $style = new OutputFormatterStyle('white', 'red'); + $style->setPadding(' [EE] '); + $output->getFormatter()->setStyle('p-error', $style); + } + /** * Initialize POSIX trap */ From dd70cc2d073e8e76f29bae1439f66307346f3fc9 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 4 Jun 2015 17:22:04 +0200 Subject: [PATCH 173/214] Fixed some styling Fixes #37 --- .../Console/Command/AbstractCommand.php | 4 +- .../Console/Command/AbstractTraceCommand.php | 2 + .../Command/Docker/AbstractCommand.php | 14 ++-- .../Console/Command/Docker/CliCommand.php | 4 +- .../Console/Command/Docker/CreateCommand.php | 17 ++-- .../Console/Command/Docker/ExecCommand.php | 2 +- .../Console/Command/Docker/SniffCommand.php | 77 ++++++++++++++++--- .../Console/Command/Docker/UpCommand.php | 5 +- .../Console/Command/Log/ApacheCommand.php | 1 + .../Console/Command/Log/DebugCommand.php | 1 + .../Console/Command/Log/MailCommand.php | 1 + .../Console/Command/Log/PhpCommand.php | 2 + .../Console/Command/Mysql/AbstractCommand.php | 6 +- .../Console/Command/Mysql/BackupCommand.php | 14 ++-- .../Console/Command/Mysql/ClearCommand.php | 8 +- .../Console/Command/Mysql/ConvertCommand.php | 4 +- .../Console/Command/Mysql/DebugCommand.php | 10 ++- .../Console/Command/Mysql/DropCommand.php | 4 +- .../Console/Command/Mysql/ListCommand.php | 2 +- .../Console/Command/Mysql/RestoreCommand.php | 20 ++--- .../Console/Command/Mysql/SlowLogCommand.php | 16 ++-- .../Console/Command/Sync/AbstractCommand.php | 8 +- .../Command/Sync/AbstractSyncCommand.php | 2 +- .../Console/Command/Sync/BackupCommand.php | 8 ++ .../Console/Command/Sync/InitCommand.php | 4 +- .../Console/Command/Sync/RestoreCommand.php | 10 ++- .../Console/Command/Sync/ServerCommand.php | 20 +++-- .../Command/User/RebuildSshConfigCommand.php | 14 ++-- 28 files changed, 195 insertions(+), 85 deletions(-) diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index cd167b2..d49dfb2 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -163,12 +163,14 @@ protected function showLog($logList, $input, $output, $grep = null, $optionList // check if logfiles are accessable foreach ($logList as $log) { if (!is_readable($log)) { - $output->writeln('Can\'t read ' . $log . ''); + $output->writeln('Can\'t read ' . $log . ''); return 1; } } + $output->writeln('

Reading logfile with multitail

'); + $command = new CommandBuilder('multitail', '--follow-all'); // Add grep diff --git a/src/app/CliTools/Console/Command/AbstractTraceCommand.php b/src/app/CliTools/Console/Command/AbstractTraceCommand.php index ca58dd0..eb79f6c 100644 --- a/src/app/CliTools/Console/Command/AbstractTraceCommand.php +++ b/src/app/CliTools/Console/Command/AbstractTraceCommand.php @@ -90,6 +90,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $command->setOutputRedirect(CommandBuilder::OUTPUT_REDIRECT_ALL_STDOUT); + $output->writeln('

Starting process stracing

'); + if (empty($pid)) { list($pidList, $processList) = $this->buildProcessList(); diff --git a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php index 6e6b27b..594269b 100644 --- a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php @@ -63,12 +63,12 @@ protected function getDockerEnv($containerName, $envName) { $ret = null; if (empty($containerName)) { - $this->output->writeln('No container specified'); + $this->output->writeln('No container specified'); return false; } if (empty($envName)) { - $this->output->writeln('No environment name specified'); + $this->output->writeln('No environment name specified'); return false; } @@ -107,12 +107,12 @@ protected function getDockerEnv($containerName, $envName) { */ protected function executeDockerExec($containerName, CommandBuilderInterface $command) { if (empty($containerName)) { - $this->output->writeln('No container specified'); + $this->output->writeln('No container specified'); return 1; } if (!$command->isExecuteable()) { - $this->output->writeln('No command specified or not executeable'); + $this->output->writeln('No command specified or not executeable'); return 1; } @@ -132,7 +132,7 @@ protected function executeDockerExec($containerName, CommandBuilderInterface $co $dockerCommand->append($command, false); $dockerCommand->executeInteractive(); } else { - $this->output->writeln('No docker-compose.yml found in tree'); + $this->output->writeln('No docker-compose.yml found in tree'); return 1; } @@ -161,7 +161,7 @@ protected function executeDockerCompose(CommandBuilderInterface $command = null) $command->setCommand('docker-compose'); $command->executeInteractive(); } else { - $this->output->writeln('No docker-compose.yml found in tree'); + $this->output->writeln('No docker-compose.yml found in tree'); return 1; } @@ -191,7 +191,7 @@ protected function executeDockerComposeRun($containerName, CommandBuilderInterfa $dockerCommand->append($command, false); $dockerCommand->executeInteractive(); } else { - $this->output->writeln('No docker-compose.yml found in tree'); + $this->output->writeln('No docker-compose.yml found in tree'); return 1; } diff --git a/src/app/CliTools/Console/Command/Docker/CliCommand.php b/src/app/CliTools/Console/Command/Docker/CliCommand.php index 41e1fb1..03e5561 100644 --- a/src/app/CliTools/Console/Command/Docker/CliCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CliCommand.php @@ -59,7 +59,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $cliUser = $this->getDockerEnv($container, 'CLI_USER'); if (empty($cliScript)) { - $output->writeln('Docker container "' . $container . '" doesn\'t have environment variable "CLI_SCRIPT"'); + $output->writeln('Docker container "' . $container . '" doesn\'t have environment variable "CLI_SCRIPT"'); return 1; } @@ -89,7 +89,7 @@ public function execute(InputInterface $input, OutputInterface $output) { break; default: - $output->writeln('CliMethod "' . $cliMethod .'" not defined'); + $output->writeln('CliMethod "' . $cliMethod .'" not defined'); $ret = 1; break; } diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index d6c0e32..89fe8d1 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -84,15 +84,20 @@ public function execute(InputInterface $input, OutputInterface $output) { $boilerplateRepo = $this->getApplication()->getConfigValue('docker', 'boilerplate'); } + $output->writeln('

Creating new docker boilerplate instance in "' . $path . '"

'); + // Init docker boilerplate $this->createDockerInstance($path, $boilerplateRepo); PhpUtility::chdir($currDir); // Init code if ($this->input->getOption('code')) { + + $output->writeln('

Init code repository

'); $this->initCode($path, $input->getOption('code')); PhpUtility::chdir($currDir); + $output->writeln('

Init document root

'); // detect document root $this->initDocumentRoot($path); PhpUtility::chdir($currDir); @@ -100,10 +105,11 @@ public function execute(InputInterface $input, OutputInterface $output) { // Run makefile if ($this->input->getOption('make')) { try { + $output->writeln('

Run Makefile

'); $this->runMakefile($path, $input->getOption('make')); PhpUtility::chdir($currDir); } catch (\Exception $e) { - $this->addFinishMessage('Make command failed: ' . $e->getMessage() . ''); + $this->addFinishMessage('Make command failed: ' . $e->getMessage() . ''); } } } @@ -113,6 +119,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $this->startInteractiveEditor($path . '/docker-env.yml'); // Start docker + $output->writeln('

Build and start docker containers

'); PhpUtility::chdir($currDir); $this->startDockerInstance($path); @@ -132,14 +139,14 @@ protected function startInteractiveEditor($path) { $this->getApplication()->setProcessTitle('Edit ' . basename($path)); - $this->output->writeln('Starting interactive EDITOR for file ' .$path . ''); + $this->output->writeln('

Starting interactive EDITOR for file ' .$path . '

'); sleep(1); $editor ->addArgument($path) ->executeInteractive(); } catch (\Exception $e) { - $this->addFinishMessage('' . $e->getMessage() . ''); + $this->addFinishMessage('' . $e->getMessage() . ''); } } } @@ -153,8 +160,6 @@ protected function startInteractiveEditor($path) { protected function createDockerInstance($path, $repo) { $this->getApplication()->setProcessTitle('Cloning docker'); - $this->output->writeln('Create new docker boilerplate in "' . $path . '"'); - $command = new CommandBuilder('git','clone --branch=master --recursive %s %s', array($repo, $path)); $command->executeInteractive(); } @@ -249,7 +254,7 @@ protected function runMakefile($path, $makeCommand) { ->addArgument($makeCommand) ->executeInteractive(); } catch (\Exception $e) { - $this->addFinishMessage('Make command failed: ' . $e->getMessage() . ''); + $this->addFinishMessage('Make command failed: ' . $e->getMessage() . ''); } } diff --git a/src/app/CliTools/Console/Command/Docker/ExecCommand.php b/src/app/CliTools/Console/Command/Docker/ExecCommand.php index 62bd75d..1a8f684 100644 --- a/src/app/CliTools/Console/Command/Docker/ExecCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ExecCommand.php @@ -54,7 +54,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $ret = $this->executeDockerExec($container, $command); } else { - $output->writeln('No command/parameter specified'); + $output->writeln('No command/parameter specified'); $ret = 1; } diff --git a/src/app/CliTools/Console/Command/Docker/SniffCommand.php b/src/app/CliTools/Console/Command/Docker/SniffCommand.php index dd421f4..95bd9bc 100644 --- a/src/app/CliTools/Console/Command/Docker/SniffCommand.php +++ b/src/app/CliTools/Console/Command/Docker/SniffCommand.php @@ -23,6 +23,8 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Output\OutputInterface; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; @@ -37,7 +39,7 @@ protected function configure() { ->setDescription('Start network sniffing with docker') ->addArgument( 'protocol', - InputArgument::REQUIRED, + InputArgument::OPTIONAL, 'Protocol' ) ->addOption( @@ -67,7 +69,9 @@ public function execute(InputInterface $input, OutputInterface $output) { $dockerInterface = $this->getApplication()->getConfigValue('docker', 'interface'); - $protocol = $input->getArgument('protocol'); + $output->writeln('

Starting network sniffing

'); + + $protocol = $this->getProtocol(); $fullOutput = $input->getOption('full'); $command = new CommandBuilder(); @@ -81,6 +85,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // ARP // ############## case 'arp': + $output->writeln('

Using protocol "arp"

'); $command->setCommand('tshark'); $command->addArgument('arp'); break; @@ -93,6 +98,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // ICMP // ############## case 'icmp': + $output->writeln('

Using protocol "icmp"

'); $command->setCommand('tshark'); $command->addArgument('icmp'); break; @@ -106,6 +112,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // ############## case 'con': case 'tcp': + $output->writeln('

Using protocol "tcp"

'); $command->setCommand('tshark'); $command->addArgumentRaw('-R "tcp.flags.syn==1 && tcp.flags.ack==0"'); break; @@ -118,6 +125,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // HTTP // ############## case 'http': + $output->writeln('

Using protocol "http"

'); $command->setCommand('tshark'); if ($fullOutput) { @@ -131,6 +139,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // SOLR // ############## case 'solr': + $output->writeln('

Using protocol "solr"

'); $command->setCommand('tcpdump'); $command->addArgumentRaw('-nl -s0 -w- port 8983'); @@ -143,6 +152,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // ELASTICSEARCH // ############## case 'elasticsearch': + $output->writeln('

Using protocol "elasticsearch"

'); $command->setCommand('tcpdump'); $command->addArgumentRaw('-A -nn -s 0 \'tcp dst port 9200 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)\''); break; @@ -152,6 +162,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // ############## case 'memcache': case 'memcached': + $output->writeln('

Using protocol "memcache"

'); $command->setCommand('tcpdump'); $command->addArgumentRaw('-s 65535 -A -ttt port 11211| cut -c 9- | grep -i \'^get\|set\''); break; @@ -160,6 +171,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // REDIS // ############## case 'redis': + $output->writeln('

Using protocol "redis"

'); $command->setCommand('tcpdump'); $command->addArgumentRaw('-s 65535 tcp port 6379'); break; @@ -169,6 +181,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // ############## case 'smtp': case 'mail': + $output->writeln('

Using protocol "smtp"

'); $command->setCommand('tshark'); $command->addArgumentRaw('tcp -f "port 25" -R "smtp"'); break; @@ -177,6 +190,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // MYSQL // ############## case 'mysql': + $output->writeln('

Using protocol "mysql"

'); $command->setCommand('tshark'); $command->addArgumentRaw('tcp -d tcp.port==3306,mysql -T fields -e mysql.query "port 3306"'); break; @@ -185,6 +199,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // DNS // ############## case 'dns': + $output->writeln('

Using protocol "dns"

'); $command->setCommand('tshark'); $command->addArgumentRaw('-nn -e ip.src -e dns.qry.name -E separator=" " -T fields port 53'); break; @@ -193,27 +208,28 @@ public function execute(InputInterface $input, OutputInterface $output) { // HELP // ############## default: - $output->writeln('Protocol not supported:'); - $output->writeln(' OSI layer 7: http, solr, elasticsearch, memcache, redis, smtp, mysql, dns'); - $output->writeln(' OSI layer 4: tcp'); - $output->writeln(' OSI layer 3: icmp'); - $output->writeln(' OSI layer 2: arp'); + $output->writeln('Protocol not supported:'); + $output->writeln(' OSI layer 7: http, solr, elasticsearch, memcache, redis, smtp, mysql, dns'); + $output->writeln(' OSI layer 4: tcp'); + $output->writeln(' OSI layer 3: icmp'); + $output->writeln(' OSI layer 2: arp'); return 1; break; } switch ($command->getCommand()) { case 'tshark': + $output->writeln('

Using sniffer "tshark"

'); $command->addArgumentTemplate('-i %s', $dockerInterface); - - break; case 'tcpdump': + $output->writeln('

Using sniffer "tcpdump"

'); $command->addArgumentTemplate('-i %s', $dockerInterface); break; case 'ngrep': + $output->writeln('

Using sniffer "ngrep"

'); $command->addArgumentTemplate('-d %s', $dockerInterface); break; } @@ -222,4 +238,47 @@ public function execute(InputInterface $input, OutputInterface $output) { return 0; } + + + /** + * Get protocol + * + * @return string + */ + protected function getProtocol() { + $ret = null; + + if(!$this->input->getArgument('protocol')) { + $protocolList = array( + 'http' => 'HTTP', + 'solr' => 'Solr', + 'elasticsearch' => 'Elasticsearch', + 'memcache' => 'Memcache', + 'redis' => 'Redis', + 'smtp' => 'SMTP', + 'mysql' => 'MySQL queries', + 'dns' => 'DNS', + 'tcp' => 'TCP', + 'icmp' => 'ICMP', + 'arp' => 'ARP', + ); + + try { + $question = new ChoiceQuestion('Please choose network protocol for sniffing', $protocolList); + $question->setMaxAttempts(1); + + $questionDialog = new QuestionHelper(); + + $ret = $questionDialog->ask($this->input, $this->output, $question); + } catch(\InvalidArgumentException $e) { + // Invalid server context, just stop here + throw new \CliTools\Exception\StopException(1); + } + } else { + $ret = $this->input->getArgument('protocol'); + } + + + return $ret; + } } diff --git a/src/app/CliTools/Console/Command/Docker/UpCommand.php b/src/app/CliTools/Console/Command/Docker/UpCommand.php index 1ffa226..a19637b 100644 --- a/src/app/CliTools/Console/Command/Docker/UpCommand.php +++ b/src/app/CliTools/Console/Command/Docker/UpCommand.php @@ -52,6 +52,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $dockerPath = dirname($dockerPath); } + $output->writeln('

Starting docker containers

'); + // Stop last docker instance if ($dockerPath && $lastDockerPath) { // Only stop if instance is another one @@ -61,6 +63,7 @@ public function execute(InputInterface $input, OutputInterface $output) { } // Start current docker containers + $this->output->writeln('

Start docker containers in "' . $dockerPath . '"

'); $command = new CommandBuilder(null, 'up -d'); $ret = $this->executeDockerCompose($command); @@ -81,7 +84,7 @@ protected function stopContainersFromPrevRun($path) { $currentPath = getcwd(); try { - $this->output->writeln('Trying to stop last running docker container in "' . $path . '"'); + $this->output->writeln('

Trying to stop last running docker container in "' . $path . '"

'); // Jump into last docker dir \CliTools\Utility\PhpUtility::chdir($path); diff --git a/src/app/CliTools/Console/Command/Log/ApacheCommand.php b/src/app/CliTools/Console/Command/Log/ApacheCommand.php index 383e2cb..55aba20 100644 --- a/src/app/CliTools/Console/Command/Log/ApacheCommand.php +++ b/src/app/CliTools/Console/Command/Log/ApacheCommand.php @@ -56,6 +56,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $grep = $input->getArgument('grep'); } + $output->writeln('

Starting apache log tail

'); // Show log $logList = array( diff --git a/src/app/CliTools/Console/Command/Log/DebugCommand.php b/src/app/CliTools/Console/Command/Log/DebugCommand.php index 796bd26..67ed98a 100644 --- a/src/app/CliTools/Console/Command/Log/DebugCommand.php +++ b/src/app/CliTools/Console/Command/Log/DebugCommand.php @@ -56,6 +56,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $grep = $input->getArgument('grep'); } + $output->writeln('

Starting debug log tail

'); // Show log $logList = array( diff --git a/src/app/CliTools/Console/Command/Log/MailCommand.php b/src/app/CliTools/Console/Command/Log/MailCommand.php index 903bde1..778c8d8 100644 --- a/src/app/CliTools/Console/Command/Log/MailCommand.php +++ b/src/app/CliTools/Console/Command/Log/MailCommand.php @@ -55,6 +55,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $grep = $input->getArgument('grep'); } + $output->writeln('

Starting mail log tail

'); // Show log $logList = array( diff --git a/src/app/CliTools/Console/Command/Log/PhpCommand.php b/src/app/CliTools/Console/Command/Log/PhpCommand.php index bf13fca..425d233 100644 --- a/src/app/CliTools/Console/Command/Log/PhpCommand.php +++ b/src/app/CliTools/Console/Command/Log/PhpCommand.php @@ -56,6 +56,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $grep = $input->getArgument('grep'); } + $output->writeln('

Starting php log tail

'); + // Show log $logList = array( '/var/log/php-fpm/dev.error.log', diff --git a/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php b/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php index 2800aee..3389d8b 100644 --- a/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php @@ -74,7 +74,7 @@ protected function initialize(InputInterface $input, OutputInterface $output) { $user = null; $password = null; - if ($this->input->getOption('host')) { + if ($this->input->hasOption('host') && $this->input->getOption('host')) { $host = $this->input->getOption('host'); $port = 3306; @@ -85,11 +85,11 @@ protected function initialize(InputInterface $input, OutputInterface $output) { $dsn = 'mysql:host=' . urlencode($host) . ';port=' . (int)$port; } - if ($this->input->getOption('user')) { + if ($this->input->hasOption('user') && $this->input->getOption('user')) { $user = $this->input->getOption('user'); } - if ($this->input->getOption('password')) { + if ($this->input->hasOption('password') && $this->input->getOption('password')) { $password = $this->input->getOption('password'); } diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index 0bda41d..5254173 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -72,11 +72,13 @@ public function execute(InputInterface $input, OutputInterface $output) { $filter = $input->getOption('filter'); if (!DatabaseConnection::databaseExists($database)) { - $output->writeln('Database "' . $database . '" does not exists'); + $output->writeln('Database "' . $database . '" does not exists'); return 1; } + $output->writeln('

Dumping database "' . $database . '" into file "' . $dumpFile . '"

'); + $fileExt = pathinfo($dumpFile, PATHINFO_EXTENSION); // Inserting @@ -89,20 +91,20 @@ public function execute(InputInterface $input, OutputInterface $output) { case 'bz': case 'bz2': case 'bzip2': - $output->writeln('Using BZIP2 compression'); + $output->writeln('

Using BZIP2 compression

'); $commandCompressor = new CommandBuilder('bzip2'); break; case 'gz': case 'gzip': - $output->writeln('Using GZIP compression'); + $output->writeln('

Using GZIP compression

'); $commandCompressor = new CommandBuilder('gzip'); break; case 'lzma': case 'lz': case 'xz': - $output->writeln('Using LZMA compression'); + $output->writeln('

Using LZMA compression

'); $commandCompressor = new CommandBuilder('xz'); $commandCompressor->addArgument('--compress') ->addArgument('--stdout'); @@ -128,13 +130,13 @@ public function execute(InputInterface $input, OutputInterface $output) { $command->addPipeCommand($commandCompressor); $commandCompressor->setOutputRedirectToFile($dumpFile); } else { - $output->writeln('Using no compression'); + $output->writeln('

Using no compression

'); $command->setOutputRedirectToFile($dumpFile); } $command->executeInteractive(); - $output->writeln('Database "' . $database . '" stored to "' . $dumpFile . '"'); + $output->writeln('

Database "' . $database . '" stored to "' . $dumpFile . '"

'); } /** diff --git a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php index 52dc642..c4db1c2 100644 --- a/src/app/CliTools/Console/Command/Mysql/ClearCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ClearCommand.php @@ -55,17 +55,19 @@ protected function configure() { public function execute(InputInterface $input, OutputInterface $output) { $database = $input->getArgument('db'); + $output->writeln('

Clearing database "' . $database . '"

'); + if (DatabaseConnection::databaseExists($database)) { - $output->writeln('Dropping Database "' . $database . '"...'); + $output->writeln('

Dropping database

'); $query = 'DROP DATABASE ' . DatabaseConnection::sanitizeSqlDatabase($database); DatabaseConnection::exec($query); } - $output->writeln('Creating Database "' . $database . '"...'); + $output->writeln('

Creating database

'); $query = 'CREATE DATABASE ' . DatabaseConnection::sanitizeSqlDatabase($database); DatabaseConnection::exec($query); - $output->writeln('Database "' . $database . '" dropped and recreated'); + $output->writeln('

Database "' . $database . '" recreated

'); return 0; } diff --git a/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php index 0c4ef55..9594872 100644 --- a/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ConvertCommand.php @@ -102,7 +102,7 @@ public function execute(InputInterface $input, OutputInterface $output) { if (!$stdout) { // Execute - $output->writeln('Converting database ' . $database . ''); + $output->writeln('

Converting database ' . $database . '

'); DatabaseConnection::exec($query); } else { // Show only @@ -126,7 +126,7 @@ public function execute(InputInterface $input, OutputInterface $output) { if (!$stdout) { // Execute - $output->writeln('Converting table ' . $table . ''); + $output->writeln('

Converting table ' . $table . '

'); DatabaseConnection::exec($query); } else { // Show only diff --git a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php index d449a65..e72f217 100644 --- a/src/app/CliTools/Console/Command/Mysql/DebugCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/DebugCommand.php @@ -56,10 +56,12 @@ public function execute(InputInterface $input, OutputInterface $output) { $debugLogLocation = $this->getApplication()->getConfigValue('db', 'debug_log_dir'); $debugLogDir = dirname($debugLogLocation); + $output->writeln('

Starting MySQL general query log

'); + // Create directory if not exists if (!is_dir($debugLogDir)) { if (!mkdir($debugLogDir, 0777, true)) { - $output->writeln('Could not create "' . $debugLogDir . '" directory'); + $output->writeln('Could not create "' . $debugLogDir . '" directory'); throw new \CliTools\Exception\StopException(1); } } @@ -78,14 +80,14 @@ public function execute(InputInterface $input, OutputInterface $output) { if (!empty($logFileRow['Value'])) { // Enable general log - $output->writeln('Enabling general log'); + $output->writeln('

Enabling general log

'); $query = 'SET GLOBAL general_log = \'ON\''; DatabaseConnection::exec($query); // Setup teardown cleanup $tearDownFunc = function () use ($output) { // Disable general log - $output->writeln('Disabling general log'); + $output->writeln('

Disabling general log

'); $query = 'SET GLOBAL general_log = \'OFF\''; DatabaseConnection::exec($query); }; @@ -110,7 +112,7 @@ public function execute(InputInterface $input, OutputInterface $output) { return 0; } else { - $output->writeln('MySQL general_log_file not set'); + $output->writeln('MySQL general_log_file not set'); return 1; } diff --git a/src/app/CliTools/Console/Command/Mysql/DropCommand.php b/src/app/CliTools/Console/Command/Mysql/DropCommand.php index d84b867..e2a7015 100644 --- a/src/app/CliTools/Console/Command/Mysql/DropCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/DropCommand.php @@ -54,11 +54,11 @@ protected function configure() { public function execute(InputInterface $input, OutputInterface $output) { $database = $input->getArgument('db'); - $output->writeln('Dropping Database "' . $database . '"...'); + $output->writeln('

Dropping Database "' . $database . '"...

'); $query = 'DROP DATABASE IF EXISTS ' . DatabaseConnection::sanitizeSqlDatabase($database); DatabaseConnection::exec($query); - $output->writeln('Database "' . $database . '" dropped'); + $output->writeln('

Database dropped

'); return 0; } diff --git a/src/app/CliTools/Console/Command/Mysql/ListCommand.php b/src/app/CliTools/Console/Command/Mysql/ListCommand.php index 5d692be..3971b0d 100644 --- a/src/app/CliTools/Console/Command/Mysql/ListCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/ListCommand.php @@ -222,7 +222,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $table->render(); } else { - $output->writeln('No databases found'); + $output->writeln('No databases found'); } return 0; diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index 4d5107a..bd26161 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -63,27 +63,28 @@ public function execute(InputInterface $input, OutputInterface $output) { $dumpFile = $input->getArgument('file'); if (!is_file($dumpFile) || !is_readable($dumpFile)) { - $output->writeln('File is not readable'); + $output->writeln('File is not readable'); return 1; } $dumpFileType = PhpUtility::getMimeType($dumpFile); + $output->writeln('

Restoring dump "' . $dumpFile . '" into database "' . $database . '"

'); + if (DatabaseConnection::databaseExists($database)) { // Dropping - $output->writeln('Dropping Database "' . $database . '"...'); + $output->writeln('

Dropping database

'); $query = 'DROP DATABASE IF EXISTS ' . DatabaseConnection::sanitizeSqlDatabase($database); DatabaseConnection::exec($query); } // Creating - $output->writeln('Creating Database "' . $database . '"...'); + $output->writeln('

Creating database

'); $query = 'CREATE DATABASE ' . DatabaseConnection::sanitizeSqlDatabase($database); DatabaseConnection::exec($query); // Inserting - $output->writeln('Restoring dump into Database "' . $database . '"...'); putenv('USER=' . DatabaseConnection::getDbUsername()); putenv('MYSQL_PWD=' . DatabaseConnection::getDbPassword()); @@ -105,31 +106,32 @@ public function execute(InputInterface $input, OutputInterface $output) { switch ($dumpFileType) { case 'application/x-bzip2': - $output->writeln('Using BZIP2 decompression'); + $output->writeln('

Using BZIP2 decompression

'); $commandFile->setCommand('bzcat'); break; case 'application/gzip': case 'application/x-gzip': - $output->writeln('Using GZIP decompression'); + $output->writeln('

Using GZIP decompression

'); $commandFile->setCommand('gzcat'); break; case 'application/x-lzma': case 'application/x-xz': - $output->writeln('Using LZMA decompression'); + $output->writeln('

Using LZMA decompression

'); $commandFile->setCommand('xzcat'); break; default: - $output->writeln('Using plaintext (no decompression)'); + $output->writeln('

Using plaintext (no decompression)

'); $commandFile->setCommand('cat'); break; } + $output->writeln('

Reading dump

'); $commandFile->executeInteractive(); - $output->writeln('Database "' . $database . '" restored'); + $output->writeln('

Database "' . $database . '" restored

'); return 0; } diff --git a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php index 04150d3..7b09cd1 100644 --- a/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/SlowLogCommand.php @@ -81,10 +81,12 @@ public function execute(InputInterface $input, OutputInterface $output) { $debugLogLocation = $this->getApplication()->getConfigValue('db', 'debug_log_dir'); $debugLogDir = dirname($debugLogLocation); + $output->writeln('

Starting MySQL slow query log

'); + // Create directory if not exists if (!is_dir($debugLogDir)) { if (!mkdir($debugLogDir, 0777, true)) { - $output->writeln('Could not create "' . $debugLogDir . '" directory'); + $output->writeln('Could not create "' . $debugLogDir . '" directory'); throw new \CliTools\Exception\StopException(1); } } @@ -101,22 +103,22 @@ public function execute(InputInterface $input, OutputInterface $output) { if (!empty($logFileRow['Value'])) { // Enable slow log - $output->writeln('Enabling slow log'); + $output->writeln('

Enabling slow log

'); $query = 'SET GLOBAL slow_query_log = \'ON\''; DatabaseConnection::exec($query); // Enable slow log - $output->writeln('Set long_query_time to ' . (int)abs($slowLogQueryTime) . ' seconds'); + $output->writeln('

Set long_query_time to ' . (int)abs($slowLogQueryTime) . ' seconds

'); $query = 'SET GLOBAL long_query_time = ' . (int)abs($slowLogQueryTime); DatabaseConnection::exec($query); // Enable log queries without indexes log if ($logNonIndexedQueries) { - $output->writeln('Enabling logging of queries without using indexes'); + $output->writeln('

Enabling logging of queries without using indexes

'); $query = 'SET GLOBAL log_queries_not_using_indexes = \'ON\''; DatabaseConnection::exec($query); } else { - $output->writeln('Disabling logging of queries without using indexes'); + $output->writeln('

Disabling logging of queries without using indexes

'); $query = 'SET GLOBAL log_queries_not_using_indexes = \'OFF\''; DatabaseConnection::exec($query); } @@ -124,7 +126,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // Setup teardown cleanup $tearDownFunc = function () use ($output, $logNonIndexedQueries) { // Disable general log - $output->writeln('Disable slow log'); + $output->writeln('

Disable slow log

'); $query = 'SET GLOBAL slow_query_log = \'OFF\''; DatabaseConnection::exec($query); @@ -155,7 +157,7 @@ public function execute(InputInterface $input, OutputInterface $output) { return 0; } else { - $output->writeln('MySQL general_log_file not set'); + $output->writeln('MySQL general_log_file not set'); return 1; } diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index ba1ca95..71e021e 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -100,7 +100,7 @@ protected function initialize(InputInterface $input, OutputInterface $output) { // Find configuration file $this->confFilePath = UnixUtility::findFileInDirectortyTree($confFileList); if (empty($this->confFilePath)) { - throw new \RuntimeException('No ' . self::CONFIG_FILE . ' found in tree'); + throw new \RuntimeException('No ' . self::CONFIG_FILE . ' found in tree'); } $this->workingPath = dirname($this->confFilePath); @@ -112,7 +112,7 @@ protected function initialize(InputInterface $input, OutputInterface $output) { // Validate configuration if (!$this->validateConfiguration()) { - throw new \RuntimeException('Configuration could not be validated'); + throw new \RuntimeException('Configuration could not be validated'); } } @@ -207,7 +207,7 @@ protected function validateConfigurationRsync() { // Check if rsync target exists if (!$this->getRsyncPathFromConfig()) { - $this->output->writeln('No rsync path configuration found'); + $this->output->writeln('No rsync path configuration found'); $ret = false; } else { $this->output->writeln('Using rsync path "' . $this->getRsyncPathFromConfig() . '"'); @@ -231,7 +231,7 @@ protected function validateConfigurationMysql() { // Check if one database is configured if (!$this->config->exists('mysql.database')) { - $this->output->writeln('No mysql database configuration found'); + $this->output->writeln('No mysql database configuration found'); $ret = false; } diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index c5b8ee4..2308789 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -50,7 +50,7 @@ protected function validateConfiguration() { if ($this->config->exists('ssh')) { // Check if one database is configured if (!$this->config->exists('ssh.hostname')) { - $output->writeln('No ssh hostname configuration found'); + $output->writeln('No ssh hostname configuration found'); $ret = false; } } diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 07daffd..8d722e0 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -45,6 +45,14 @@ protected function configure() { ); } + /** + * Startup task + */ + protected function startup() { + $this->output->writeln('

Starting share backup

'); + parent::startup(); + } + /** * Backup task */ diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 43f623c..080c110 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -49,7 +49,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $cliSyncFilePath = getcwd() . '/' . AbstractCommand::CONFIG_FILE; if (file_exists($cliSyncFilePath)) { - $this->output->writeln('Configuration file ' . AbstractCommand::CONFIG_FILE . ' already exists'); + $this->output->writeln('Configuration file ' . AbstractCommand::CONFIG_FILE . ' already exists'); return 1; } @@ -161,7 +161,7 @@ public function execute(InputInterface $input, OutputInterface $output) { ->addArgument($cliSyncFilePath) ->executeInteractive(); } catch (\Exception $e) { - $this->output->writeln('' . $e->getMessage() . ''); + $this->output->writeln('' . $e->getMessage() . ''); } $this->output->writeln('Successfully created ' . AbstractCommand::CONFIG_FILE . ' '); diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index b8bf17a..35df4db 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -45,6 +45,14 @@ protected function configure() { ); } + /** + * Startup task + */ + protected function startup() { + $this->output->writeln('

Starting share restore

'); + parent::startup(); + } + /** * Restore task */ @@ -109,7 +117,7 @@ protected function runTaskMysql() { list($database) = explode('.', $item->getFilename(), 2); if (!empty($database)) { - $this->output->writeln('Restoring database ' . $database . ''); + $this->output->writeln('

Restoring database ' . $database . '

'); $this->createMysqlRestoreCommand($database, $item->getPathname())->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index fc947e4..e5bdf5a 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -64,6 +64,14 @@ protected function configure() { ); } + /** + * Startup task + */ + protected function startup() { + $this->output->writeln('

Starting server synchronization

'); + parent::startup(); + } + /** * Read and validate configuration */ @@ -77,7 +85,7 @@ protected function readConfiguration() { } // Use server specific configuration - $this->output->writeln('Syncing from "' . $this->contextName . '" server'); + $this->output->writeln('

Syncing from "' . $this->contextName . '" server

'); // ################## // Jump into section @@ -119,13 +127,13 @@ protected function runTask() { // Sync files with rsync to local storage if ($runRsync && $this->config->exists('rsync')) { - $this->output->writeln(' ---- Starting FILE sync ---- '); + $this->output->writeln('

Starting FILE sync

'); $this->runTaskRsync(); } // Sync database to local server if ($runMysql && $this->config->exists('mysql')) { - $this->output->writeln(' ---- Starting MYSQL sync ---- '); + $this->output->writeln('

Starting MYSQL sync

'); $this->runTaskDatabase(); } } @@ -170,7 +178,7 @@ protected function runTaskDatabase() { // ########## // Dump from server // ########## - $this->output->writeln('Fetching foreign database "' . $foreignDatabase . '"'); + $this->output->writeln('

Fetching foreign database "' . $foreignDatabase . '"

'); $mysqldump = $this->createMySqlDumpCommand($foreignDatabase); @@ -186,7 +194,7 @@ protected function runTaskDatabase() { // ########## // Restore local // ########## - $this->output->writeln('Restoring database "' . $localDatabase . '"'); + $this->output->writeln('

Restoring database "' . $localDatabase . '"

'); $this->createMysqlRestoreCommand($localDatabase, $dumpFile)->executeInteractive(); } @@ -342,7 +350,7 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat throw new \RuntimeException('MySQL dump filters "' . $filter . '" not available"'); } - $this->output->writeln('Using filter "' . $filter . '"'); + $this->output->writeln('

Using filter "' . $filter . '"

'); // Get table list (from cloned mysqldump command) $tableListDumper = $this->createMySqlCommand($database); diff --git a/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php b/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php index 36cc023..8adcf21 100644 --- a/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php +++ b/src/app/CliTools/Console/Command/User/RebuildSshConfigCommand.php @@ -46,7 +46,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $userHome = getenv('HOME'); $userName = getenv('USER'); - $output->writeln('Rebuilding ~/.ssh/config ...'); + $output->writeln('

Rebuilding ~/.ssh/config ...

'); $targetConfFile = $userHome . '/.ssh/config'; $userConfFile = $userHome . '/.ssh/config.user'; @@ -78,13 +78,13 @@ public function execute(InputInterface $input, OutputInterface $output) { $confContent[] = '# from: ' . $defaultUserFile; $confContent[] = file_get_contents($defaultUserFile); - $output->writeln('Using user defaults from ' . $defaultUserFile . ''); + $output->writeln('

Using user defaults from ' . $defaultUserFile . '

'); } elseif (file_exists($defaultFile)) { // System default $confContent[] = '# from: ' . $defaultFile; $confContent[] = file_get_contents($defaultFile); - $output->writeln('Using system defaults from ' . $defaultFile . ''); + $output->writeln('

Using system defaults from ' . $defaultFile . '

'); } else { // No default found, provide at least good defaults $confContent[] = '# from: no config'; @@ -96,7 +96,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $confContent[] = ' ServerAliveInterval 60'; $confContent[] = ' ForwardAgent no'; - $output->writeln('No defaults found, setting internal defaults'); + $output->writeln('

No defaults found, setting internal defaults

'); } $confContent[] = ''; @@ -132,7 +132,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $confContent[] = file_get_contents($filePath); $confContent[] = ''; - $output->writeln('Using ' . $filePath . ''); + $output->writeln('

Using ' . $filePath . '

'); } } @@ -147,7 +147,7 @@ public function execute(InputInterface $input, OutputInterface $output) { if (file_exists($userConfFile)) { $confContent[] = file_get_contents($userConfFile); - $output->writeln('Using ' . $userConfFile . ''); + $output->writeln('

Using ' . $userConfFile . '

'); } $confContent[] = ''; @@ -167,7 +167,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // Write file file_put_contents($targetConfFile, $confContent); - $output->writeln('Finished rebuilding ssh configuration'); + $output->writeln('

Finished rebuilding ssh configuration

'); return 0; } From 49e4deed4aebe234962bf45b221b8d9705f42efd Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 4 Jun 2015 20:56:52 +0200 Subject: [PATCH 174/214] Added tty1 reload on banner update --- .../Command/System/CrontaskCommand.php | 2 ++ .../Console/Command/System/StartupCommand.php | 3 ++ src/app/CliTools/Utility/UnixUtility.php | 31 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/app/CliTools/Console/Command/System/CrontaskCommand.php b/src/app/CliTools/Console/Command/System/CrontaskCommand.php index 69e6c35..72ff0b9 100644 --- a/src/app/CliTools/Console/Command/System/CrontaskCommand.php +++ b/src/app/CliTools/Console/Command/System/CrontaskCommand.php @@ -74,6 +74,8 @@ protected function setupBanner() { file_put_contents('/etc/issue', $outputIssue); file_put_contents('/etc/motd', $output); + + UnixUtility::reloadTtyBanner('tty1'); } /** diff --git a/src/app/CliTools/Console/Command/System/StartupCommand.php b/src/app/CliTools/Console/Command/System/StartupCommand.php index 367b81b..539a291 100644 --- a/src/app/CliTools/Console/Command/System/StartupCommand.php +++ b/src/app/CliTools/Console/Command/System/StartupCommand.php @@ -20,6 +20,7 @@ * along with this program. If not, see . */ +use CliTools\Utility\UnixUtility; use CliTools\Database\DatabaseConnection; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; @@ -65,6 +66,8 @@ protected function setupBanner() { file_put_contents('/etc/issue', $outputIssue); file_put_contents('/etc/motd', $output); + + UnixUtility::reloadTtyBanner('tty1'); } /** diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index 2ff801c..2834e41 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -294,4 +294,35 @@ public static function findFileInDirectortyTree($file, $path = null) { return $ret; } + + /** + * Reload tty + */ + public static function reloadTtyBanner($ttyName) { + // Check if we can reload tty + try { + $who = new CommandBuilder('who'); + $who->addPipeCommand( new CommandBuilder('grep', '%s', array($ttyName))); + $who->execute(); + + // if there is no exception -> there is a logged in user + } catch (\Exception $e) { + // if there is an exception -> there is NO logged in user + + try { + $ps = new CommandBuilder('ps', 'h -o pid,comm,args -C getty'); + $ps->addPipeCommand( new CommandBuilder('grep', '%s', array($ttyName))); + $output = $ps->execute()->getOutput(); + + if (!empty($output)) { + $outputLine = trim(reset($output)); + $outputLineParts = preg_split('/[\s]+/', $outputLine); + list($pid, $cmd) = $outputLineParts; + + posix_kill($pid, SIGHUP); + } + + } catch (\Exception $e) {} + } + } } From d75f9b2e15f3483b95ca463a4176944535e2dcd8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 4 Jun 2015 21:03:52 +0200 Subject: [PATCH 175/214] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9fd8c2..816431a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ CliTools Changelog - Added `typo3:domain --duplication=suffix` for domain duplication - Added `typo3:domain --baseurl` for setting config.baseURL in SetupTS - Added `vagrant:share` with automatic domain setting for TYPO3 projects (ALPHA! not finished!) +- TTY banner now will be reloaded (SIGHUB is send to getty tty1) - Added docker detection for sync features - Updated to Symfony 2.7 - Refactored some classes From c22292a5bc0ac87833701bdd8bc3058c5e94e5bf Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 4 Jun 2015 21:13:06 +0200 Subject: [PATCH 176/214] Version bump 1.9.910 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index e4e6dc6..6dd9ff0 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.909'); +define('CLITOOLS_COMMAND_VERSION', '1.9.910'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From 62ebe7b8081adf175180ea6f9badc4081607ccca Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 5 Jun 2015 16:48:46 +0200 Subject: [PATCH 177/214] Fixed regression --- src/app/CliTools/Console/Command/Sync/ServerCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index e5bdf5a..2070988 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -325,7 +325,7 @@ protected function createRsyncCommand($source, $target, array $filelist = null, // Add exclude (external file with --exclude-from option) if (!$exclude && $this->config->exists('rsync.exclude')) { - $exclude = $this->config->exists('rsync.exclude'); + $exclude = $this->config->get('rsync.exclude'); } return parent::createRsyncCommand($source, $target, $filelist, $exclude); From 589ab1cabf5f0e50c50a39124e828735c6eb2b6e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 5 Jun 2015 16:49:01 +0200 Subject: [PATCH 178/214] Improved status messages --- .../Console/Command/TYPO3/BeUserCommand.php | 20 ++++++++++--------- .../Console/Command/TYPO3/CleanupCommand.php | 8 +++++--- .../Command/TYPO3/ClearCacheCommand.php | 8 +++++--- .../Console/Command/TYPO3/DomainCommand.php | 6 ++++-- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php index 4ab87a6..631c29b 100644 --- a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php @@ -75,6 +75,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $username = $input->getArgument('user'); $password = $input->getArgument('password'); + $output->writeln('

Injecting TYPO3 backend user

'); + // Set default user if not specified if (empty($username)) { $username = 'dev'; @@ -82,18 +84,18 @@ public function execute(InputInterface $input, OutputInterface $output) { // check username if (!preg_match('/^[-_a-zA-Z0-9\.]+$/', $username)) { - $output->writeln('Invalid username'); + $output->writeln('Invalid username'); return 1; } - $output->writeln('Using user: "' . htmlspecialchars($username) . '"'); + $output->writeln('

Using user: "' . htmlspecialchars($username) . '"

'); // Set default password if not specified if (empty($password)) { $password = 'dev'; } - $output->writeln('Using pass: "' . htmlspecialchars($password) . '"'); + $output->writeln('

Using pass: "' . htmlspecialchars($password) . '"

'); // ################## // Salting @@ -102,11 +104,11 @@ public function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption('plain')) { // Standard md5 $password = Typo3Utility::generatePassword($password, Typo3Utility::PASSWORD_TYPE_MD5); - $this->output->writeln('Generating plain (non salted) md5 password'); + $this->output->writeln('

Generating plain (non salted) md5 password

'); } else { // Salted md5 $password = Typo3Utility::generatePassword($password, Typo3Utility::PASSWORD_TYPE_MD5_SALTED); - $this->output->writeln('Generating salted md5 password'); + $this->output->writeln('

Generating salted md5 password

'); } // ############## @@ -136,7 +138,7 @@ public function execute(InputInterface $input, OutputInterface $output) { } if (!$dbFound) { - $output->writeln('No valid TYPO3 database found'); + $output->writeln('No valid TYPO3 database found'); } } else { // ############## @@ -229,12 +231,12 @@ protected function setTypo3UserForDatabase($database, $username, $password) { DatabaseConnection::exec($query); if ($beUserId) { - $this->output->writeln('User successfully updated to "' . $database . '"'); + $this->output->writeln('

User successfully updated to "' . $database . '"

'); } else { - $this->output->writeln('User successfully added to "' . $database . '"'); + $this->output->writeln('

User successfully added to "' . $database . '"

'); } } catch (\Exception $e) { - $this->output->writeln('User adding failed'); + $this->output->writeln('User adding failed'); } } } diff --git a/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php b/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php index c3ed9fc..a8bbdb6 100644 --- a/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/CleanupCommand.php @@ -55,6 +55,8 @@ public function execute(InputInterface $input, OutputInterface $output) { // ################## $dbName = $input->getArgument('db'); + $output->writeln('

Cleanup TYPO3 database

'); + // ############## // Loop through databases // ############## @@ -163,7 +165,7 @@ protected function cleanupTypo3Database($database) { } } - $this->output->writeln('Starting cleanup of database ' . $database . '...'); + $this->output->writeln('

Starting cleanup of database "' . $database . '"

'); DatabaseConnection::switchDatabase(DatabaseConnection::sanitizeSqlDatabase($database)); @@ -172,10 +174,10 @@ protected function cleanupTypo3Database($database) { DatabaseConnection::exec($query); if ($this->output->isVerbose()) { - $this->output->writeln(' -> Truncating table ' . $table . ''); + $this->output->writeln('

Truncating table ' . $table . '

'); } } - $this->output->writeln(' -> finished'); + $this->output->writeln('

finished

'); } } diff --git a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php index 79a58a6..acc33d2 100644 --- a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php @@ -57,6 +57,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $basePath = $this->getApplication()->getConfigValue('config', 'www_base_path', '/var/www/'); $maxDepth = 3; + $output->writeln('

Clear TYPO3 cache

'); + if ($input->getArgument('path')) { $basePath = $input->getArgument('path'); } @@ -68,7 +70,7 @@ public function execute(InputInterface $input, OutputInterface $output) { // Check if coreapi is installed if (!is_dir($dirPath . '/typo3conf/ext/coreapi/')) { - $output->writeln('EXT:coreapi is missing on ' . $dirPath . ', skipping'); + $output->writeln('

EXT:coreapi is missing on ' . $dirPath . ', skipping

'); continue; } @@ -78,14 +80,14 @@ public function execute(InputInterface $input, OutputInterface $output) { 'cache:clearallcaches' ); - $output->writeln('Running clearcache command on ' . $dirPath . ''); + $output->writeln('

Running clearcache command on ' . $dirPath . '

'); try { $command = new CommandBuilder('php'); $command->setArgumentList($params) ->executeInteractive(); } catch (\Exception $e) { - $output->writeln(' Failed with exception: ' . $e->getMessage() . ''); + $output->writeln(' Failed with exception: ' . $e->getMessage() . ''); } } diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php index 49a9d3d..321423e 100644 --- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php @@ -80,6 +80,8 @@ public function execute(InputInterface $input, OutputInterface $output) { // ################## $dbName = $input->getArgument('db'); + $output->writeln('

Updating TYPO3 domain entries

'); + // ############## // Loop through databases // ############## @@ -227,10 +229,10 @@ protected function showDomainList($dbName) { $query = 'SELECT domainName FROM sys_domain ORDER BY domainName ASC'; $domainList = DatabaseConnection::getCol($query); - $this->output->writeln('Domain list of "' . $dbName . '":'); + $this->output->writeln('

Domain list of "' . $dbName . '":

'); foreach ($domainList as $domain) { - $this->output->writeln(' ' . $domain . ''); + $this->output->writeln('

' . $domain . '

'); } $this->output->writeln(''); } From 7f3f1c1161e9e4db84d5cc4df8b458914bbce671 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 5 Jun 2015 16:49:17 +0200 Subject: [PATCH 179/214] Added error handler (all php errors will be converted to exceptions) --- src/app/CliTools/Console/Application.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/app/CliTools/Console/Application.php b/src/app/CliTools/Console/Application.php index c526750..324b536 100644 --- a/src/app/CliTools/Console/Application.php +++ b/src/app/CliTools/Console/Application.php @@ -99,6 +99,7 @@ public function getConfigValue($area, $confKey, $defaultValue = null) { * Initialize */ public function initialize() { + $this->initializeErrorHandler(); $this->initializeChecks(); $this->initializeConfiguration(); $this->initializePosixTrap(); @@ -221,6 +222,27 @@ protected function initializePosixTrap() { pcntl_signal(SIGINT, $signalHandler); } + /** + * Init error handler + */ + protected function initializeErrorHandler() { + $me = $this; + + $errorHandler = function ($errno, $errstr, $errfile, $errline, $errcontext) use($me) { + $msg = array( + 'Message: ' . $errstr, + 'File: ' . $errfile, + 'Line: ' . $errline, + ); + + $msg = implode("\n", $msg); + + throw new \RuntimeException($msg, $errno); + }; + + set_error_handler($errorHandler); + } + /** * PHP Checks */ From f91b138b46aa002433b61c5200fb6fb969d6313f Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 5 Jun 2015 16:53:48 +0200 Subject: [PATCH 180/214] Fixed wrong class naming --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 71e021e..eba770e 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -67,14 +67,14 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand /** * Sync configuration * - * @var ConfigReaderService + * @var ConfigReader */ protected $config = array(); /** * Task configuration * - * @var ConfigReaderService + * @var ConfigReader */ protected $taskConf = array(); From 36e1171292375d42071b1553cdeb36cd76e191a3 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Fri, 5 Jun 2015 17:04:09 +0200 Subject: [PATCH 181/214] Refactoring --- .../Command/Sync/AbstractSyncCommand.php | 27 ++++++++++++++++++- .../Console/Command/Sync/ServerCommand.php | 26 ------------------ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index 2308789..6eb4c1b 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -32,7 +32,6 @@ abstract class AbstractSyncCommand extends \CliTools\Console\Command\Sync\Abstra */ protected $confArea = 'server'; - /** * Validate configuration * @@ -58,6 +57,32 @@ protected function validateConfiguration() { return $ret; } + /** + * Read and validate configuration + */ + protected function readConfiguration() { + parent::readConfiguration(); + + $this->contextName = $this->getServerContext(); + + if (empty($this->contextName) || $this->contextName === '_' || empty($this->config[$this->contextName])) { + throw new \RuntimeException('No valid configuration found for context "' . $this->contextName . '"'); + } + + // Use server specific configuration + $this->output->writeln('

Syncing from "' . $this->contextName . '" server

'); + + // ################## + // Jump into section + // ################## + if ($this->config->exists('_')) { + // Merge global config with specific config + $this->config->setData(array_replace_recursive($this->config->getArray('_'), $this->config->getArray($this->contextName))); + } else { + $this->config->setData($this->config->getArray($this->contextName)); + } + } + /** * Get server context from user */ diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 2070988..691278b 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -72,32 +72,6 @@ protected function startup() { parent::startup(); } - /** - * Read and validate configuration - */ - protected function readConfiguration() { - parent::readConfiguration(); - - $this->contextName = $this->getServerContext(); - - if (empty($this->contextName) || $this->contextName === '_' || empty($this->config[$this->contextName])) { - throw new \RuntimeException('No valid configuration found for context "' . $this->contextName . '"'); - } - - // Use server specific configuration - $this->output->writeln('

Syncing from "' . $this->contextName . '" server

'); - - // ################## - // Jump into section - // ################## - if ($this->config->exists('_')) { - // Merge global config with specific config - $this->config->setData(array_replace_recursive($this->config->getArray('_'), $this->config->getArray($this->contextName))); - } else { - $this->config->setData($this->config->getArray($this->contextName)); - } - } - /** * Backup task */ From 2548bd483669ac1736ac00096b2add8b1409e9fe Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 8 Jun 2015 21:38:59 +0200 Subject: [PATCH 182/214] Fixed coding guidelines --- src/app/CliTools/Console/Application.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Application.php b/src/app/CliTools/Console/Application.php index 324b536..91922fb 100644 --- a/src/app/CliTools/Console/Application.php +++ b/src/app/CliTools/Console/Application.php @@ -226,9 +226,7 @@ protected function initializePosixTrap() { * Init error handler */ protected function initializeErrorHandler() { - $me = $this; - - $errorHandler = function ($errno, $errstr, $errfile, $errline, $errcontext) use($me) { + $errorHandler = function ($errno, $errstr, $errfile, $errline) { $msg = array( 'Message: ' . $errstr, 'File: ' . $errfile, From 899e8917cbf2c70603cb2d8de6afe1869b21186c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 8 Jun 2015 23:45:00 +0200 Subject: [PATCH 183/214] Added custom table filter Fixes #42 --- Documentation/Examples/clisync.yml | 35 +++++++++++++------ .../Console/Command/Sync/InitCommand.php | 33 ++++++++++++----- .../Console/Command/Sync/ServerCommand.php | 7 +++- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 4dc8d35..e7eefcf 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -8,9 +8,19 @@ server: ################## _: mysql: - # MySQL filter for typo3 (eg. no caching tables) + # MySQL predefined filter for typo3 (eg. no caching tables) filter: typo3 + # MySQL custom filter + #filter: + # - "/^cachingframework_.*/i" + # - "/^cf_.*/i" + # - "/^cache_.*/i" + # - "/^index_.*/i" + # - "/^sys_log$/i" + # - "/^sys_history$/i" + # - "/^tx_extbase_cache.*/i" + # Transfer compression (none if empty, bzip2 or gzip) compression: bzip2 @@ -18,6 +28,17 @@ server: mysqldump: option: "--opt --single-transaction" + rsync: + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + # directory exclude list/patterns + exclude: + - "/fileadmin/_processed_/**" + ################## # Config "production" ################## @@ -33,12 +54,6 @@ server: # set target as sub directroy (will be appended to working directory) #target: "html/" - # directory list/patterns - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - mysql: # mysql connection hostname: localhost @@ -58,7 +73,7 @@ share: rsync: # source/target directory or server via ssh (eg. backup-server:/backup/projectname) path: "/tmp/foo/" - # set target as sub directroy (will be appended to working directory) + # set target as sub directroy (will be appended to working directory #target: "html/" # List of directories for backup @@ -90,6 +105,6 @@ task: # These commands will be executed after backup, restore and sync finalize: # create user "dev" with password "dev" - - 'ct typo3:beuser' + - "ct typo3:beuser" # append toplevel-domain .vm to all domains - - 'ct typo3:domain' + - "ct typo3:domain" diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 080c110..00446d0 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -65,9 +65,19 @@ public function execute(InputInterface $input, OutputInterface $output) { ################## _: mysql: - # MySQL filter for typo3 (eg. no caching tables) + # MySQL predefined filter for typo3 (eg. no caching tables) filter: typo3 + # MySQL custom filter + #filter: + # - "/^cachingframework_.*/i" + # - "/^cf_.*/i" + # - "/^cache_.*/i" + # - "/^index_.*/i" + # - "/^sys_log$/i" + # - "/^sys_history$/i" + # - "/^tx_extbase_cache.*/i" + # Transfer compression (none if empty, bzip2 or gzip) compression: bzip2 @@ -75,6 +85,17 @@ public function execute(InputInterface $input, OutputInterface $output) { mysqldump: option: "--opt --single-transaction" + rsync: + # directory list/patterns + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + # directory exclude list/patterns + exclude: + - "/fileadmin/_processed_/**" + ################## # Config "production" ################## @@ -90,12 +111,6 @@ public function execute(InputInterface $input, OutputInterface $output) { # set target as sub directroy (will be appended to working directory) #target: "html/" - # directory list/patterns - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - mysql: # mysql connection hostname: localhost @@ -147,9 +162,9 @@ public function execute(InputInterface $input, OutputInterface $output) { # These commands will be executed after backup, restore and sync finalize: # create user "dev" with password "dev" - - \'ct typo3:beuser\' + - "ct typo3:beuser" # append toplevel-domain .vm to all domains - - \'ct typo3:domain\' + - "ct typo3:domain" '; PhpUtility::filePutContents($cliSyncFilePath, $content); diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 691278b..32dd24a 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -318,7 +318,12 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat $command = $commandDump; // get filter - $filterList = $this->getApplication()->getConfigValue('mysql-backup-filter', $filter); + if (is_array($filter)) { + $filterList = (array)$filter; + $filter = 'custom table filter'; + } else { + $filterList = $this->getApplication()->getConfigValue('mysql-backup-filter', $filter); + } if (empty($filterList)) { throw new \RuntimeException('MySQL dump filters "' . $filter . '" not available"'); From 8c37dcdf7c921ebb258ad3c5be1cef6ff4574a90 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 9 Jun 2015 00:17:17 +0200 Subject: [PATCH 184/214] Added better documentation --- Documentation/Examples/clisync.yml | 2 +- src/app/CliTools/Console/Command/Sync/InitCommand.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index e7eefcf..aad754c 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -11,7 +11,7 @@ server: # MySQL predefined filter for typo3 (eg. no caching tables) filter: typo3 - # MySQL custom filter + # MySQL custom filter (preg_match) #filter: # - "/^cachingframework_.*/i" # - "/^cf_.*/i" diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 00446d0..d8b5cec 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -68,7 +68,7 @@ public function execute(InputInterface $input, OutputInterface $output) { # MySQL predefined filter for typo3 (eg. no caching tables) filter: typo3 - # MySQL custom filter + # MySQL custom filter (preg_match) #filter: # - "/^cachingframework_.*/i" # - "/^cf_.*/i" From 1192ea123c9e4853ca55697d31e80f9b983bfccc Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 9 Jun 2015 00:20:46 +0200 Subject: [PATCH 185/214] Improved documentation --- Documentation/Examples/clisync.yml | 5 ++++- src/app/CliTools/Console/Command/Sync/InitCommand.php | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index aad754c..ec9aa61 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -29,7 +29,10 @@ server: option: "--opt --single-transaction" rsync: - # directory list/patterns + # set target as sub directroy (will be appended to working directory) + #target: "html/" + + # directory list/patterns for synchronization directory: - "/fileadmin/" - "/uploads/" diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index d8b5cec..4b4894c 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -86,7 +86,10 @@ public function execute(InputInterface $input, OutputInterface $output) { option: "--opt --single-transaction" rsync: - # directory list/patterns + # set target as sub directroy (will be appended to working directory) + #target: "html/" + + # directory list/patterns for synchronization directory: - "/fileadmin/" - "/uploads/" @@ -108,8 +111,6 @@ public function execute(InputInterface $input, OutputInterface $output) { rsync: # server and source directory (server host or name - see .ssh/config) path: "live-server:/var/www/website/htdocs" - # set target as sub directroy (will be appended to working directory) - #target: "html/" mysql: # mysql connection From 2d3e4c910c145919feede53ff04aee886903e9b9 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 9 Jun 2015 19:17:04 +0200 Subject: [PATCH 186/214] Cleaned up sync --- .../Console/Command/Sync/AbstractCommand.php | 6 +- .../Command/Sync/AbstractSyncCommand.php | 117 ++++++++++++++++- .../Console/Command/Sync/InitCommand.php | 9 +- .../Console/Command/Sync/ServerCommand.php | 121 ++---------------- 4 files changed, 132 insertions(+), 121 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index eba770e..dee85cb 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -320,7 +320,7 @@ protected function runFinalizeTasks() { protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { $this->output->writeln('Rsync from ' . $source . ' to ' . $target . ''); - $command = new CommandBuilder('rsync', '-rlptD --delete-after --progress -h'); + $command = new CommandBuilder('rsync', '-rlptD --delete-after --progress --human-readable'); // Add file list (external file with --files-from option) if (!empty($filelist)) { @@ -373,8 +373,8 @@ protected function getRsyncWorkingPath() { // remove right / $ret = rtrim($this->workingPath, '/'); - if ($this->config->exists('rsync.target')) { - $ret .= '/' . $this->config->get('rsync.target'); + if ($this->config->exists('rsync.workdir')) { + $ret .= '/' . $this->config->get('rsync.workdir'); } return $ret; diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php index 6eb4c1b..4fa0317 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php @@ -20,18 +20,14 @@ * along with this program. If not, see . */ +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Question\ChoiceQuestion; abstract class AbstractSyncCommand extends \CliTools\Console\Command\Sync\AbstractCommand { - /** - * Config area - * - * @var string - */ - protected $confArea = 'server'; - /** * Validate configuration * @@ -168,5 +164,112 @@ protected function getServerContext() { return $ret; } + /** + * Wrap command with ssh if needed + * + * @param CommandBuilderInterface $command + * @return CommandBuilderInterface + */ + protected function wrapRemoteCommand(CommandBuilderInterface $command) { + // Wrap in ssh if needed + if ($this->config->exists('ssh.hostname')) { + $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); + $sshCommand->addArgument($this->config->get('ssh.hostname')) + ->append($command, true); + + $command = $sshCommand; + } + + return $command; + } + + /** + * Create new mysql command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createRemoteMySqlCommand($database = null) { + $command = new RemoteCommandBuilder('mysql'); + $command + // batch mode + ->addArgument('-B') + // skip column names + ->addArgument('-N'); + + // Add username + if ($this->config->exists('mysql.username')) { + $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); + } + + // Add password + if ($this->config->exists('mysql.password')) { + $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); + } + + // Add hostname + if ($this->config->exists('mysql.hostname')) { + $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); + } + + if ($database !== null) { + $command->addArgument($database); + } + + return $command; + } + + /** + * Create new mysql command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createRemoteMySqlDumpCommand($database = null) { + $command = new RemoteCommandBuilder('mysqldump'); + + // Add username + if ($this->config->exists('mysql.username')) { + $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); + } + + // Add password + if ($this->config->exists('mysql.password')) { + $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); + } + + // Add hostname + if ($this->config->exists('mysql.hostname')) { + $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); + } + + // Add custom options + if ($this->config->exists('mysqldump.option')) { + $command->addArgumentRaw($this->config->get('mysqldump.option')); + } + + // Transfer compression + switch($this->config->get('mysql.compression')) { + case 'bzip2': + // Add pipe compressor (bzip2 compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + break; + + case 'gzip': + // Add pipe compressor (gzip compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); + break; + } + + + if ($database !== null) { + $command->addArgument($database); + } + + return $command; + } + } diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 4b4894c..70ba1b7 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -58,7 +58,7 @@ public function execute(InputInterface $input, OutputInterface $output) { ####################################### # Sync from server (eg. live server) ####################################### -server: +sync: ################## # Global config @@ -123,6 +123,13 @@ public function execute(InputInterface $input, OutputInterface $output) { - typo3:website_live - other_database +####################################### +# Deployment to server +####################################### + +deploy: + + ####################################### # Shared server (sharing between developers) ####################################### diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 32dd24a..35de8fa 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -32,6 +32,13 @@ class ServerCommand extends AbstractSyncCommand { + /** + * Config area + * + * @var string + */ + protected $confArea = 'sync'; + /** * Server configuration name * @var string @@ -154,13 +161,13 @@ protected function runTaskDatabase() { // ########## $this->output->writeln('

Fetching foreign database "' . $foreignDatabase . '"

'); - $mysqldump = $this->createMySqlDumpCommand($foreignDatabase); + $mysqldump = $this->createRemoteMySqlDumpCommand($foreignDatabase); if ($this->config['mysql']['filter']) { $mysqldump = $this->addFilterArguments($mysqldump, $foreignDatabase, $this->config['mysql']['filter']); } - $command = $this->wrapCommand($mysqldump); + $command = $this->wrapRemoteCommand($mysqldump); $command->setOutputRedirectToFile($dumpFile); $command->executeInteractive(); @@ -174,112 +181,6 @@ protected function runTaskDatabase() { } } - /** - * Create new mysql command - * - * @param null|string $database Database name - * - * @return RemoteCommandBuilder - */ - protected function createMySqlCommand($database = null) { - $command = new RemoteCommandBuilder('mysql'); - $command - // batch mode - ->addArgument('-B') - // skip column names - ->addArgument('-N'); - - // Add username - if ($this->config->exists('mysql.username')) { - $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); - } - - // Add password - if ($this->config->exists('mysql.password')) { - $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); - } - - // Add hostname - if ($this->config->exists('mysql.hostname')) { - $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); - } - - if ($database !== null) { - $command->addArgument($database); - } - - return $command; - } - - /** - * Create new mysql command - * - * @param null|string $database Database name - * - * @return RemoteCommandBuilder - */ - protected function createMySqlDumpCommand($database = null) { - $command = new RemoteCommandBuilder('mysqldump'); - - // Add username - if ($this->config->exists('mysql.username')) { - $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); - } - - // Add password - if ($this->config->exists('mysql.password')) { - $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); - } - - // Add hostname - if ($this->config->exists('mysql.hostname')) { - $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); - } - - // Add custom options - if ($this->config->exists('mysqldump.option')) { - $command->addArgumentRaw($this->config->get('mysqldump.option')); - } - - // Transfer compression - switch($this->config->get('mysql.compression')) { - case 'bzip2': - // Add pipe compressor (bzip2 compressed transfer via ssh) - $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); - break; - - case 'gzip': - // Add pipe compressor (gzip compressed transfer via ssh) - $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); - break; - } - - - if ($database !== null) { - $command->addArgument($database); - } - - return $command; - } - - /** - * Wrap command with ssh if needed - * - * @param CommandBuilderInterface $command - * @return CommandBuilderInterface - */ - protected function wrapCommand(CommandBuilderInterface $command) { - // Wrap in ssh if needed - if ($this->config->exists('ssh.hostname')) { - $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); - $sshCommand->addArgument($this->config->get('ssh.hostname')) - ->append($command, true); - - $command = $sshCommand; - } - - return $command; - } /** * Create rsync command for share sync @@ -332,10 +233,10 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat $this->output->writeln('

Using filter "' . $filter . '"

'); // Get table list (from cloned mysqldump command) - $tableListDumper = $this->createMySqlCommand($database); + $tableListDumper = $this->createRemoteMySqlCommand($database); $tableListDumper->addArgumentTemplate('-e %s', 'show tables;'); - $tableListDumper = $this->wrapCommand($tableListDumper); + $tableListDumper = $this->wrapRemoteCommand($tableListDumper); $tableList = $tableListDumper->execute()->getOutput(); // Filter table list From 208a837e021bfe6ec948fced528aa87c18fc91af Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 9 Jun 2015 19:17:32 +0200 Subject: [PATCH 187/214] Added first version of sync:deploy Relates #43 --- .../Console/Command/Sync/DeployCommand.php | 154 ++++++++++++++++++ src/config.ini | 1 + 2 files changed, 155 insertions(+) create mode 100644 src/app/CliTools/Console/Command/Sync/DeployCommand.php diff --git a/src/app/CliTools/Console/Command/Sync/DeployCommand.php b/src/app/CliTools/Console/Command/Sync/DeployCommand.php new file mode 100644 index 0000000..0f97c88 --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/DeployCommand.php @@ -0,0 +1,154 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use CliTools\Utility\FilterUtility; +use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; +use CliTools\Database\DatabaseConnection; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; + + +class DeployCommand extends AbstractSyncCommand { + + /** + * Config area + * + * @var string + */ + protected $confArea = 'deploy'; + + /** + * Server configuration name + * @var string + */ + protected $contextName; + + /** + * Configure command + */ + protected function configure() { + $this + ->setName('sync:deploy') + ->setDescription('Deploy files and database to server') + ->addArgument( + 'context', + InputArgument::OPTIONAL, + 'Configuration name for server' + ) + ->addOption( + 'rsync', + null, + InputOption::VALUE_NONE, + 'Run only rsync' + ); + } + + /** + * Startup task + */ + protected function startup() { + $this->output->writeln('

Starting server deployment

'); + parent::startup(); + } + + /** + * Backup task + */ + protected function runTask() { + // ################## + // Option specific runners + // ################## + $runRsync = true; + $runMysql = true; + + if ($this->input->getOption('mysql') || $this->input->getOption('rsync')) { + // don't run rsync if not specifiecd + $runRsync = $this->input->getOption('rsync'); + + // don't run mysql if not specifiecd + $runMysql = $this->input->getOption('mysql'); + } + + // ################## + // Run tasks + // ################## + + // Check database connection + if ($runMysql && $this->config->exists('mysql')) { + DatabaseConnection::ping(); + } + + // Sync files with rsync to local storage + if ($runRsync && $this->config->exists('rsync')) { + $this->output->writeln('

Starting FILE deployment

'); + $this->runTaskRsync(); + } + + // Sync database to local server + if ($runMysql && $this->config->exists('mysql')) { + $this->output->writeln('

Starting MYSQL deployment

'); + $this->output->writeln('

TODO - not implemented'); + } + } + + /** + * Sync files with rsync + */ + protected function runTaskRsync() { + // ################## + // Restore dirs + // ################## + $source = $this->getRsyncWorkingPath(); + $target = $this->getRsyncPathFromConfig(); + $command = $this->createRsyncCommand($source, $target); + + $command->executeInteractive(); + } + + /** + * Create rsync command for share sync + * + * @param string $source Source directory + * @param string $target Target directory + * @param array|null $filelist List of files (patterns) + * @param array|null $exclude List of excludes (patterns) + * + * @return CommandBuilder + */ + protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { + // Add file list (external file with --files-from option) + if (!$filelist && $this->config->exists('rsync.directory')) { + $filelist = $this->config->get('rsync.directory'); + } + + // Add exclude (external file with --exclude-from option) + if (!$exclude && $this->config->exists('rsync.exclude')) { + $exclude = $this->config->get('rsync.exclude'); + } + + return parent::createRsyncCommand($source, $target, $filelist, $exclude); + } + +} diff --git a/src/config.ini b/src/config.ini index f2ab0c8..dd808c0 100644 --- a/src/config.ini +++ b/src/config.ini @@ -48,6 +48,7 @@ class[] = "CliTools\Console\Command\Sync\InitCommand" class[] = "CliTools\Console\Command\Sync\ServerCommand" class[] = "CliTools\Console\Command\Sync\BackupCommand" class[] = "CliTools\Console\Command\Sync\RestoreCommand" +class[] = "CliTools\Console\Command\Sync\DeployCommand" class[] = "CliTools\Console\Command\TYPO3\BeUserCommand" class[] = "CliTools\Console\Command\TYPO3\InstallerCommand" From 2a4f333cb606129366d34c02a01bbbea22d1c9ae Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 9 Jun 2015 19:17:50 +0200 Subject: [PATCH 188/214] Updated clisync.yml example --- .editorconfig | 2 +- Documentation/Examples/clisync.yml | 181 +++++++++++++++++------------ 2 files changed, 109 insertions(+), 74 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8b65364..50bfd79 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,4 +8,4 @@ indent_size = 4 indent_style = tab [*.yml] -indent_size = 2 +indent_size = 4 diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index ec9aa61..222fa2f 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -1,104 +1,139 @@ ####################################### # Sync from server (eg. live server) ####################################### -server: +sync: ################## # Global config ################## - _: + _: mysql: # MySQL predefined filter for typo3 (eg. no caching tables) - filter: typo3 - - # MySQL custom filter (preg_match) - #filter: - # - "/^cachingframework_.*/i" - # - "/^cf_.*/i" - # - "/^cache_.*/i" - # - "/^index_.*/i" - # - "/^sys_log$/i" - # - "/^sys_history$/i" - # - "/^tx_extbase_cache.*/i" + filter: typo3 + + # MySQL custom filter (preg_match) + #filter: + # - "/^cachingframework_.*/i" + # - "/^cf_.*/i" + # - "/^cache_.*/i" + # - "/^index_.*/i" + # - "/^sys_log$/i" + # - "/^sys_history$/i" + # - "/^tx_extbase_cache.*/i" # Transfer compression (none if empty, bzip2 or gzip) - compression: bzip2 + compression: bzip2 # specific mysqldump settings - mysqldump: - option: "--opt --single-transaction" + mysqldump: + option: "--opt --single-transaction" rsync: # set target as sub directroy (will be appended to working directory) - #target: "html/" + #workdir: "html/" # directory list/patterns for synchronization - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" # directory exclude list/patterns - exclude: - - "/fileadmin/_processed_/**" + exclude: + - "/fileadmin/_processed_/**" ################## # Config "production" ################## - production: - # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) - ssh: - hostname: live-server + production: + # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) + ssh: + hostname: live-server + + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + path: "live-server:/var/www/website/htdocs" + + mysql: + # mysql connection + hostname: localhost + username: typo3 + password: loremipsum - # rsync for some directories - rsync: - # server and source directory (server host or name - see .ssh/config) - path: "live-server:/var/www/website/htdocs" - # set target as sub directroy (will be appended to working directory) - #target: "html/" + # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) + database: + - typo3:website_live + - other_database + +####################################### +# Deployment to server +####################################### +deploy: + + ################## + # Global config + ################## + _: + rsync: + # set target as sub directroy (will be appended to working directory) + workdir: "html/" + + # directory list/patterns for synchronization + directory: + - "/" + + # directory exclude list/patterns + exclude: + - ".git*" + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" - mysql: - # mysql connection - hostname: localhost - username: typo3 - password: loremipsum + ################## + # Config "production" + ################## + production: + # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) + ssh: + hostname: live-server - # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) - database: - - typo3:website_live - - other_database + # rsync for some directories + rsync: + # server and source directory (server host or name - see .ssh/config) + path: "live-server:/var/www/website/htdocs" ####################################### # Shared server (sharing between developers) ####################################### share: - rsync: - # source/target directory or server via ssh (eg. backup-server:/backup/projectname) - path: "/tmp/foo/" - # set target as sub directroy (will be appended to working directory - #target: "html/" - - # List of directories for backup - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - - # List of excludes (eg. specific files) - exclude: - # no avi files - - "/example/**/*.avi" - # no mp4 files - - "/example/**/*.mp4" - - mysql: - # MySQL filter for typo3 (eg. no caching tables) - filter: typo3 - - # List of databases for backup - database: - - typo3 + rsync: + # source/target directory or server via ssh (eg. backup-server:/backup/projectname) + path: "/tmp/foo/" + # set target as sub directroy (will be appended to working directory + #target: "html/" + + # List of directories for backup + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + # List of excludes (eg. specific files) + exclude: + # no avi files + - "/example/**/*.avi" + # no mp4 files + - "/example/**/*.mp4" + + mysql: + # MySQL filter for typo3 (eg. no caching tables) + filter: typo3 + + # List of databases for backup + database: + - typo3 ####################################### # Task configuration @@ -106,8 +141,8 @@ share: task: # These commands will be executed after backup, restore and sync - finalize: - # create user "dev" with password "dev" - - "ct typo3:beuser" - # append toplevel-domain .vm to all domains - - "ct typo3:domain" + finalize: + # create user "dev" with password "dev" + - "ct typo3:beuser" + # append toplevel-domain .vm to all domains + - "ct typo3:domain" From 1604c0882e4d68c806628cac76e83637d7da23ea Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 9 Jun 2015 19:38:11 +0200 Subject: [PATCH 189/214] Cleanup --- Documentation/Examples/clisync.yml | 6 +++--- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 222fa2f..d2072fb 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -30,7 +30,7 @@ sync: rsync: # set target as sub directroy (will be appended to working directory) - #workdir: "html/" + workdir: "" # directory list/patterns for synchronization directory: @@ -77,7 +77,7 @@ deploy: _: rsync: # set target as sub directroy (will be appended to working directory) - workdir: "html/" + workdir: "" # directory list/patterns for synchronization directory: @@ -112,7 +112,7 @@ share: # source/target directory or server via ssh (eg. backup-server:/backup/projectname) path: "/tmp/foo/" # set target as sub directroy (will be appended to working directory - #target: "html/" + workdir: "" # List of directories for backup directory: diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index dee85cb..bd07fcd 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -371,7 +371,7 @@ protected function getRsyncWorkingPath() { $ret = $this->workingPath; // remove right / - $ret = rtrim($this->workingPath, '/'); + $ret = rtrim($ret, '/'); if ($this->config->exists('rsync.workdir')) { $ret .= '/' . $this->config->get('rsync.workdir'); From 0318471026373c565f62c6fd520acc1e36dca417 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 9 Jun 2015 19:38:11 +0200 Subject: [PATCH 190/214] Squashed commit of the following: commit bc131b5a5c70e2b08aca8ed72fd6d6bd2ad8cf5e Author: Markus Blaschke Date: Thu Jun 11 00:42:10 2015 +0200 Refactoring sync [WIP] commit 4c605a6ccec2993d46b62ecd030fb30c65b5d712 Author: Markus Blaschke Date: Thu Jun 11 00:40:42 2015 +0200 Refactoring sync [WIP] commit fc7117d2f7ef3bef449f0a92959087aa015e1044 Author: Markus Blaschke Date: Thu Jun 11 00:40:22 2015 +0200 Refactoring sync [WIP] commit 6a7374b6d0d87028ff9e09d5860138f46f81f955 Author: Markus Blaschke Date: Thu Jun 11 00:39:54 2015 +0200 Refactoring sync [WIP] commit 51bcec6cab47b1bcb18e3e2b650012c910626934 Author: Markus Blaschke Date: Thu Jun 11 00:35:30 2015 +0200 Refactoring sync [WIP] commit e6ef0482776076be8c650cf60917fc0f39acf54b Author: Markus Blaschke Date: Thu Jun 11 00:31:12 2015 +0200 Refactoring sync [WIP] commit 5dc2e69b3152abbfcc4ae315b48862d77514f3ef Author: Markus Blaschke Date: Thu Jun 11 00:30:59 2015 +0200 Refactoring sync [WIP] commit 5dd1b8beed7ba477451bf6be70134f92b0e5b1a0 Author: Markus Blaschke Date: Thu Jun 11 00:29:50 2015 +0200 Refactoring sync [WIP] commit 7cf2280dea3a242b6fd7bc9298d189ad3001ae97 Author: Markus Blaschke Date: Thu Jun 11 00:25:04 2015 +0200 Refactoring sync [WIP] commit cab3ce4404f06491c71efe9d23f5e3d0f68c00a0 Author: Markus Blaschke Date: Wed Jun 10 22:40:42 2015 +0200 Refactoring sync [WIP] commit 137d44876a61b9fe57141c76689e612746ec79d7 Author: Markus Blaschke Date: Wed Jun 10 21:59:23 2015 +0200 Refactoring sync [WIP] commit c90889951f8034d12a884921c5333066c33409ce Author: Markus Blaschke Date: Wed Jun 10 21:48:17 2015 +0200 Refactoring sync [WIP] commit 6d70edf71153f1b76b33044d3de3615908e00d24 Author: Markus Blaschke Date: Wed Jun 10 21:42:44 2015 +0200 Refactoring sync [WIP] commit 262c43d5ff5d250435211f8332a23c37b8a7857f Author: Markus Blaschke Date: Wed Jun 10 21:23:05 2015 +0200 Refactoring sync [WIP] commit 76bc9ca5cb3e1e3afbbcd5098e9d3abb543701b0 Author: Markus Blaschke Date: Wed Jun 10 20:56:48 2015 +0200 Refactoring sync [WIP] --- CHANGELOG.md | 7 +- Documentation/Examples/clisync.yml | 235 ++++-- .../Console/Command/Sync/AbstractCommand.php | 725 ++++++++++++++++-- .../Sync/AbstractRemoteSyncCommand.php | 50 ++ .../Command/Sync/AbstractShareCommand.php | 40 +- .../Command/Sync/AbstractSyncCommand.php | 275 ------- .../Console/Command/Sync/BackupCommand.php | 72 +- .../Console/Command/Sync/DeployCommand.php | 81 +- .../Console/Command/Sync/RestoreCommand.php | 39 +- .../Console/Command/Sync/ServerCommand.php | 190 ++--- .../CliTools/Database/DatabaseConnection.php | 38 + 11 files changed, 1045 insertions(+), 707 deletions(-) create mode 100644 src/app/CliTools/Console/Command/Sync/AbstractRemoteSyncCommand.php delete mode 100644 src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 816431a..748bd7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,10 @@ CliTools Changelog - Added `make` (auto search for Makefile in tree) - Added `php:composer` (auto search for composer.json in tree) - Added `mysql:convert` for automatic changing charset and collation of one database -- Added `sync:server` for syncing any configured server to your local development system (reads clisync.yml) -- Added `sync:backup` for backup to a shared server (reads clisync.yml) -- Added `sync:restore` for restore from a shared server (reads clisync.yml) +- Added `sync:server` for syncing any configured server to your local development system (reads clisync.yml or .clisync.yml) +- Added `sync:backup` for backup to a shared server (reads clisync.yml or .clisync.yml) +- Added `sync:restore` for restore from a shared server (reads clisync.yml or .clisync.yml) +- Added `sync:deploy` for lightweight deployment to a foreign server (reads clisync.yml or .clisync.yml) - Added `typo3:domain --list` for only list the domains of one or all databases - Added `typo3:domain --remove=domain/pattern` for domain cleanup (eg. vagrant share) - Added `typo3:domain --duplication=suffix` for domain duplication diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index d2072fb..404d9ff 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -1,13 +1,33 @@ -####################################### -# Sync from server (eg. live server) -####################################### -sync: - - ################## - # Global config - ################## - _: +########################################################### +# Global (applied to all server sections) +########################################################### +# +# Configuration merge order: +# 1. context configuration will override all settings +# 2. sync/deploy/share GLOBAL will override default settings +# 3. GLOBAL are the defaults +# +# EXAMPLE: +# if you ned eg. another mysql hostname just set it in the +# context: +# +# sync: +# production: +# mysql: +# hostname: 192.168.56.2 +# +# All other configurations can be overwritten as well +# +# HINT: +# You can check the configuration with the "--config" option +# + +GLOBAL: + ## MYSQL mysql: + # mysql connection + hostname: localhost + # MySQL predefined filter for typo3 (eg. no caching tables) filter: typo3 @@ -26,25 +46,90 @@ sync: # specific mysqldump settings mysqldump: - option: "--opt --single-transaction" + option: "--opt --skip-lock-tables --single-transaction" + ## RSYNC rsync: # set target as sub directroy (will be appended to working directory) workdir: "" - # directory list/patterns for synchronization - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - - # directory exclude list/patterns + # exclude list/patterns for files and directories exclude: - - "/fileadmin/_processed_/**" + # Temp files + - "*~" + - "._*" - ################## - # Config "production" - ################## + # VCS + - ".git*" + - ".gitignore" + - ".gitmodules" + - ".svn" + + # Build files + - "composer.json" + - "bower.json" + - "gulpfile.js" + - "Gruntfile.js" + - "Makefile" + + # Caches and other files + - "node_modules" + - ".sass-cache" + - ".settings" + - ".bowerrc" + - ".buildpath" + - ".project" + + ## commands + command: + # Start-Tasks: shell command which should be run before run + startup: + # add some here + + # Final-Tasks: shell command which should be after run + finalize: + # add some here + + # EXAMPLE: local task + # - date + + # EXAMPLE: remote task (will be send over ssh) + #- { type: 'remote', command: 'date' } + + # EXAMPLE: create user "dev" with password "dev" + - "ct typo3:beuser" + # EXAMPLE: append toplevel-domain .vm to all domains + - "ct typo3:domain" + + + + +########################################################### +# Sync from server (eg. live server) +########################################################### +sync: + + ################## + # Global config (for sync) + ################## + GLOBAL: + mysql: + ## put your mysql settings here (see global conf) + + rsync: + # directory list/patterns for synchronization + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" + + # directory exclude list/patterns + exclude: + - "/fileadmin/_processed_/**" + + ################## + # Context "production" + ################## production: # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) ssh: @@ -56,42 +141,44 @@ sync: path: "live-server:/var/www/website/htdocs" mysql: - # mysql connection - hostname: localhost username: typo3 password: loremipsum - # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) - database: - - typo3:website_live - - other_database - -####################################### + # List of databases for synchronization + # examples: + # local:foreign + # samename + database: + - typo3:website_live + + + + +########################################################### # Deployment to server -####################################### +########################################################### deploy: - ################## - # Global config - ################## - _: - rsync: - # set target as sub directroy (will be appended to working directory) - workdir: "" + ################## + # Global config (for deploy) + ################## + GLOBAL: + mysql: + # global mysql configuration + rsync: # directory list/patterns for synchronization directory: - - "/" + - "/typo3conf/ext/" # directory exclude list/patterns exclude: - - ".git*" - "/fileadmin/" - "/uploads/" - "/typo3conf/l10n/" ################## - # Config "production" + # Context "production" ################## production: # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) @@ -103,46 +190,40 @@ deploy: # server and source directory (server host or name - see .ssh/config) path: "live-server:/var/www/website/htdocs" -####################################### + + + +########################################################### # Shared server (sharing between developers) -####################################### +########################################################### share: - rsync: - # source/target directory or server via ssh (eg. backup-server:/backup/projectname) - path: "/tmp/foo/" - # set target as sub directroy (will be appended to working directory - workdir: "" - - # List of directories for backup - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" + ################## + # Global config (for share) + ################## + GLOBAL: + mysql: + # List of databases for backup + database: + - typo3 - # List of excludes (eg. specific files) - exclude: - # no avi files - - "/example/**/*.avi" - # no mp4 files - - "/example/**/*.mp4" + rsync: + # List of directories for backup + directory: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" - mysql: - # MySQL filter for typo3 (eg. no caching tables) - filter: typo3 + # directory exclude list/patterns + exclude: + - "/fileadmin/" + - "/uploads/" + - "/typo3conf/l10n/" - # List of databases for backup - database: - - typo3 - -####################################### -# Task configuration -####################################### -task: - - # These commands will be executed after backup, restore and sync - finalize: - # create user "dev" with password "dev" - - "ct typo3:beuser" - # append toplevel-domain .vm to all domains - - "ct typo3:domain" + ################## + # Context "development" + ################## + development: + rsync: + # source/target directory or server via ssh (eg. backup-server:/backup/projectname) + path: "/tmp/foo/" diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index bd07fcd..1299629 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -23,18 +23,26 @@ use CliTools\Utility\PhpUtility; use CliTools\Utility\UnixUtility; use CliTools\Utility\ConsoleUtility; +use CliTools\Utility\FilterUtility; use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; +use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; use CliTools\Reader\ConfigReader; +use CliTools\Database\DatabaseConnection; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Yaml\Yaml; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Question\ChoiceQuestion; abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand { const CONFIG_FILE = 'clisync.yml'; - const PATH_DUMP = '/dump/'; - const PATH_DATA = '/data/'; + const GLOBAL_KEY = 'GLOBAL'; /** * Config area @@ -65,18 +73,49 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand protected $tempDir; /** - * Sync configuration + * Configuration * * @var ConfigReader */ protected $config = array(); /** - * Task configuration + * Context configuration * * @var ConfigReader */ - protected $taskConf = array(); + protected $contextConfig = array(); + + /** + * Configure command + */ + protected function configure() { + $this + ->setDescription('Sync files and database from server') + ->addArgument( + 'context', + InputArgument::OPTIONAL, + 'Configuration name for server' + ) + ->addOption( + 'mysql', + null, + InputOption::VALUE_NONE, + 'Run only mysql' + ) + ->addOption( + 'rsync', + null, + InputOption::VALUE_NONE, + 'Run only rsync' + ) + ->addOption( + 'config', + null, + InputOption::VALUE_NONE, + 'Show generated config' + ); + } /** * Initializes the command just after the input has been validated. @@ -91,29 +130,177 @@ abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand protected function initialize(InputInterface $input, OutputInterface $output) { parent::initialize($input, $output); + $this->initializeConfiguration(); + } + + /** + * Init configuration + */ + protected function initializeConfiguration() { + // Search for configuration in path + $this->findConfigurationInPath(); + + // Read configuration + $this->readConfiguration(); + } + + /** + * Validate configuration + * + * @return boolean + */ + protected function validateConfiguration() { + $ret = true; + + // Rsync (optional) + if ($this->contextConfig->exists('rsync')) { + if (!$this->validateConfigurationRsync()) { + $ret = false; + } + } + + // MySQL (optional) + if ($this->contextConfig->exists('mysql.database')) { + if (!$this->validateConfigurationMysql()) { + $ret = false; + } + } else { + // Clear mysql if any options set + $this->contextConfig->clear('mysql'); + } + + return $ret; + } + + /** + * Find configuration file in current path + */ + protected function findConfigurationInPath() { $confFileList = array( self::CONFIG_FILE, '.' . self::CONFIG_FILE, ); - // Find configuration file $this->confFilePath = UnixUtility::findFileInDirectortyTree($confFileList); if (empty($this->confFilePath)) { - throw new \RuntimeException('No ' . self::CONFIG_FILE . ' found in tree'); + $this->output->writeln('No ' . self::CONFIG_FILE . ' found in tree'); + throw new \CliTools\Exception\StopException(1); } $this->workingPath = dirname($this->confFilePath); - $output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); + $this->output->writeln('Found ' . self::CONFIG_FILE . ' directory: ' . $this->workingPath . ''); + } - // Read configuration - $this->readConfiguration(); + /** + * Read and validate configuration + */ + protected function readConfiguration() { + $this->config = new ConfigReader(); - // Validate configuration - if (!$this->validateConfiguration()) { - throw new \RuntimeException('Configuration could not be validated'); + if (empty($this->confArea)) { + throw new \RuntimeException('Config area not set, cannot continue'); + } + + if (!file_exists($this->confFilePath)) { + throw new \RuntimeException('Config file "' . $this->confFilePath . '" not found'); + } + + $conf = Yaml::parse(PhpUtility::fileGetContents($this->confFilePath)); + + // Switch to area configuration + if (!empty($conf)) { + $this->config->setData($conf); + } else { + throw new \RuntimeException('Could not parse "' . $this->confFilePath . '"'); + } + } + + /** + * Get context list from current configuration + * + * @return array|null + */ + protected function getContextListFromConfiguration() { + return $this->config->getArray($this->confArea); + } + + /** + * Get command list from current configuration + * + * @param string $section Section name for commands (startup, final) + * @return array + */ + protected function getCommandList($section) { + $ret = array(); + + if ($this->contextConfig->exists('command.' . $section)) { + $ret = $this->contextConfig->get('command.' . $section); + } + + return $ret; + } + + /** + * Build context configuration + * + * @param $context + */ + protected function buildContextConfiguration($context) { + $this->contextConfig = new ConfigReader(); + + // Fetch global conf + $globalConf = array(); + if ($this->config->exists(self::GLOBAL_KEY)) { + $globalConf = $this->config->get(self::GLOBAL_KEY); } + + // Fetch area conf + $areaConf = $this->config->get($this->confArea); + + // Fetch area global conf + $areaGlobalConf = array(); + if ($this->config->exists($this->confArea . '.' . self::GLOBAL_KEY)) { + $areaGlobalConf = $this->config->get($this->confArea . '.' . self::GLOBAL_KEY); + } + + // Fetch context conf + if (empty($areaConf[$context])) { + $this->output->writeln('No context "' . $context . '" found'); + throw new \CliTools\Exception\StopException(1); + } + $contextConf = $areaConf[$context]; + + + $arrayFilterRecursive = function($input, $callback) use (&$arrayFilterRecursive) { + $ret = array(); + foreach ($input as $key => $value) { + if (is_array($value)) { + $value = $arrayFilterRecursive($value, $callback); + } else { + if (strlen($value)==0) { + $value = null; + } + } + + if ($value !== null && $value !== false && $value !== true) { + $ret[$key] = $value; + } + } + + return $ret; + }; + + // Merge + $globalConf = $arrayFilterRecursive( $globalConf, 'strlen' ); + $areaGlobalConf = $arrayFilterRecursive( $areaGlobalConf, 'strlen' ); + $contextConf = $arrayFilterRecursive( $contextConf, 'strlen' ); + + $conf = array_replace_recursive($globalConf, $areaGlobalConf, $contextConf); + + // Set configuration + $this->contextConfig->setData($conf); } /** @@ -126,11 +313,23 @@ protected function initialize(InputInterface $input, OutputInterface $output) { * @throws \Exception */ public function execute(InputInterface $input, OutputInterface $output) { - $this->startup(); - try { - $this->runTask(); - $this->runFinalizeTasks(); + // Get context selection + $this->initContext(); + + if ($this->input->getOption('config')) { + // only show configuration + $this->showContextConfig(); + } else { + // Create temp directory and check environment + $this->startup(); + + // Run playbook + $this->runCommands('startup'); + $this->runMain(); + $this->runCommands('finalize'); + } + } catch (\Exception $e) { $this->cleanup(); throw $e; @@ -140,63 +339,111 @@ public function execute(InputInterface $input, OutputInterface $output) { } /** - * Read and validate configuration + * Init context */ - protected function readConfiguration() { - $this->config = new ConfigReader(); - $this->taskConf = new ConfigReader(); - - if (empty($this->confArea)) { - throw new \RuntimeException('Config area not set, cannot continue'); - } + protected function initContext() { + $context = $this->getContextFromUser(); + $this->buildContextConfiguration($context); - if (!file_exists($this->confFilePath)) { - throw new \RuntimeException('Config file "' . $this->confFilePath . '" not found'); - } - - $conf = Yaml::parse(PhpUtility::fileGetContents($this->confFilePath)); - - // store task specific configuration - if (!empty($conf['task'])) { - $this->taskConf->setData($conf['task']); - } - - // Switch to area configuration - if (!empty($conf)) { - $this->config->setData($conf[$this->confArea]); - } else { - throw new \RuntimeException('Could not parse "' . $this->confFilePath . '"'); + // Validate configuration + if (!$this->validateConfiguration()) { + $this->output->writeln('Configuration could not be validated'); + throw new \CliTools\Exception\StopException(1); } } /** - * Validate configuration - * - * @return boolean + * Get context from user */ - protected function validateConfiguration() { - $ret = true; + protected function getContextFromUser() { + $ret = null; - // Rsync (optional) - if ($this->config->exists('rsync')) { - if (!$this->validateConfigurationRsync()) { - $ret = false; + if (!$this->input->getArgument('context')) { + // ######################## + // Ask user for server context + // ######################## + + $serverList = $this->config->getList($this->confArea); + $serverList = array_diff($serverList, array(self::GLOBAL_KEY)); + + if (empty($serverList)) { + throw new \RuntimeException('No valid servers found in configuration'); } - } - // MySQL (optional) - if ($this->config->exists('mysql.database')) { - if (!$this->validateConfigurationMysql()) { - $ret = false; + $serverOptionList = array(); + + foreach ($serverList as $context) { + $line = array(); + + // hostname + $optPath = $context . '.ssh.hostname'; + if ($this->config->exists($optPath)) { + $line[] = 'host:' . $this->config->get($optPath); + } + + // rsync path + $optPath = $context . '.rsync.path'; + if ($this->config->exists($optPath)) { + $line[] = 'rsync:' . $this->config->get($optPath); + } + + // mysql database list + $optPath = $context . '.mysql.database'; + if ($this->config->exists($optPath)) { + $dbList = $this->config->getArray($optPath); + $foreignDbList = array(); + + foreach ($dbList as $databaseConf) { + if (strpos($databaseConf, ':') !== false) { + // local and foreign database in one string + list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); + $foreignDbList[] = $foreignDatabase; + } else { + // database equal + $foreignDbList[] = $databaseConf; + } + } + + if (!empty($foreignDbList)) { + $line[] .= 'mysql:' . implode(', ', $foreignDbList); + } + } + + if (!empty($line)) { + $line = implode(' ', $line); + } else { + // fallback + $line = $context; + } + + $serverOptionList[$context] = $line; + } + + try { + $question = new ChoiceQuestion('Please choose server context for synchronization', $serverOptionList); + $question->setMaxAttempts(1); + + $questionDialog = new QuestionHelper(); + + $ret = $questionDialog->ask($this->input, $this->output, $question); + } catch(\InvalidArgumentException $e) { + // Invalid server context, just stop here + throw new \CliTools\Exception\StopException(1); } } else { - // Clear mysql if any options set - $this->config->clear('mysql'); + $ret = $this->input->getArgument('context'); } return $ret; } + /** + * Show context configuration + */ + protected function showContextConfig() { + print_r($this->contextConfig->get()); + } + /** * Validate configuration (rsync) * @@ -214,7 +461,7 @@ protected function validateConfigurationRsync() { } // Check if there are any rsync directories - if (!$this->config->exists('rsync.directory')) { + if (!$this->contextConfig->exists('rsync.directory')) { $this->output->writeln('No rsync directory configuration found, filesync disabled'); } @@ -230,7 +477,7 @@ protected function validateConfigurationMysql() { $ret = true; // Check if one database is configured - if (!$this->config->exists('mysql.database')) { + if (!$this->contextConfig->exists('mysql.database')) { $this->output->writeln('No mysql database configuration found'); $ret = false; } @@ -294,17 +541,69 @@ protected function checkIfDockerExists() { } /** - * Run finalize tasks + * Run defined commands */ - protected function runFinalizeTasks() { - if ($this->taskConf->exists('finalize')) { - $this->output->writeln(' ---- Starting FINALIZE TASKS ---- '); + protected function runCommands($area) { + $commandList = $this->getCommandList($area); + + if (!empty($commandList)) { + $this->output->writeln(' ---- Starting ' . strtoupper($area) . ' commands ---- '); + + foreach ($commandList as $commandRow) { + + if (is_string($commandRow)) { + // Simple, local task + $command = new CommandBuilder(); + $command->parse($commandRow); + } elseif(is_array($commandRow)) { + // Complex task + $command = $this->buildComplexTask($commandRow); + } + + if ($command) { + $command->executeInteractive(); + } + } + } + } + + /** + * Build complex task + * + * @param array $task Task configuration + * + * @return CommandBuilder|CommandBuilderInterface + */ + protected function buildComplexTask(array $task) { + if (empty($task['type'])) { + $task['type'] = 'local'; + } + + if (empty($task['command'])) { + throw new \RuntimeException('Task command is empty'); + } - foreach ($this->taskConf->getArray('finalize') as $task) { + // Process task type + switch ($task['type']) { + case 'remote': + // Remote command + $command = new RemoteCommandBuilder(); + $command->parse($task['command']); + $command = $this->wrapRemoteCommand($command); + break; + + case 'local': + // Local command $command = new CommandBuilder(); - $command->parse($task)->executeInteractive(); - } + $command->parse($task['command']); + break; + + default: + throw new \RuntimeException('Unknown task type'); + break; } + + return $command; } /** @@ -350,12 +649,12 @@ protected function createRsyncCommand($source, $target, array $filelist = null, */ protected function getRsyncPathFromConfig() { $ret = false; - if ($this->config->exists('rsync.path')) { + if ($this->contextConfig->exists('rsync.path')) { // Use path from rsync - $ret = $this->config->get('rsync.path'); - } elseif($this->config->exists('ssh.hostname') && $this->config->exists('ssh.path')) { + $ret = $this->contextConfig->get('rsync.path'); + } elseif($this->contextConfig->exists('ssh.hostname') && $this->contextConfig->exists('ssh.path')) { // Build path from ssh configuration - $ret = $this->config->get('ssh.hostname') . ':' . $this->config->get('ssh.path'); + $ret = $this->contextConfig->get('ssh.hostname') . ':' . $this->contextConfig->get('ssh.path'); } return $ret; @@ -373,8 +672,8 @@ protected function getRsyncWorkingPath() { // remove right / $ret = rtrim($ret, '/'); - if ($this->config->exists('rsync.workdir')) { - $ret .= '/' . $this->config->get('rsync.workdir'); + if ($this->contextConfig->exists('rsync.workdir')) { + $ret .= '/' . $this->contextConfig->get('rsync.workdir'); } return $ret; @@ -453,4 +752,286 @@ protected function createMysqlBackupCommand($database, $dumpFile, $filter = null return $command; } + /** + * Wrap command with ssh if needed + * + * @param CommandBuilderInterface $command + * @return CommandBuilderInterface + */ + protected function wrapRemoteCommand(CommandBuilderInterface $command) { + // Wrap in ssh if needed + if ($this->contextConfig->exists('ssh.hostname')) { + $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); + $sshCommand->addArgument($this->contextConfig->get('ssh.hostname')) + ->append($command, true); + + $command = $sshCommand; + } + + return $command; + } + + /** + * Create new mysql command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createRemoteMySqlCommand($database = null) { + $command = new RemoteCommandBuilder('mysql'); + $command + // batch mode + ->addArgument('-B') + // skip column names + ->addArgument('-N'); + + // Add username + if ($this->contextConfig->exists('mysql.username')) { + $command->addArgumentTemplate('-u%s', $this->contextConfig->get('mysql.username')); + } + + // Add password + if ($this->contextConfig->exists('mysql.password')) { + $command->addArgumentTemplate('-p%s', $this->contextConfig->get('mysql.password')); + } + + // Add hostname + if ($this->contextConfig->exists('mysql.hostname')) { + $command->addArgumentTemplate('-h%s', $this->contextConfig->get('mysql.hostname')); + } + + if ($database !== null) { + $command->addArgument($database); + } + + return $command; + } + + + /** + * Create new mysql command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createLocalMySqlCommand($database = null) { + $command = new RemoteCommandBuilder('mysql'); + $command + // batch mode + ->addArgument('-B') + // skip column names + ->addArgument('-N'); + + // Add username + if (DatabaseConnection::getDbUsername()) { + $command->addArgumentTemplate('-u%s', DatabaseConnection::getDbUsername()); + } + + // Add password + if (DatabaseConnection::getDbPassword()) { + $command->addArgumentTemplate('-p%s', DatabaseConnection::getDbPassword()); + } + + // Add hostname + if (DatabaseConnection::getDbHostname()) { + $command->addArgumentTemplate('-h%s', DatabaseConnection::getDbHostname()); + } + + // Add hostname + if (DatabaseConnection::getDbPort()) { + $command->addArgumentTemplate('-P%s', DatabaseConnection::getDbPort()); + } + + if ($database !== null) { + $command->addArgument($database); + } + + return $command; + } + + /** + * Create new mysqldump command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createRemoteMySqlDumpCommand($database = null) { + $command = new RemoteCommandBuilder('mysqldump'); + + // Add username + if ($this->contextConfig->exists('mysql.username')) { + $command->addArgumentTemplate('-u%s', $this->contextConfig->get('mysql.username')); + } + + // Add password + if ($this->contextConfig->exists('mysql.password')) { + $command->addArgumentTemplate('-p%s', $this->contextConfig->get('mysql.password')); + } + + // Add hostname + if ($this->contextConfig->exists('mysql.hostname')) { + $command->addArgumentTemplate('-h%s', $this->contextConfig->get('mysql.hostname')); + } + + // Add custom options + if ($this->contextConfig->exists('mysqldump.option')) { + $command->addArgumentRaw($this->contextConfig->get('mysqldump.option')); + } + + // Transfer compression + switch($this->contextConfig->get('mysql.compression')) { + case 'bzip2': + // Add pipe compressor (bzip2 compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + break; + + case 'gzip': + // Add pipe compressor (gzip compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); + break; + } + + if ($database !== null) { + $command->addArgument($database); + } + + return $command; + } + + /** + * Create new mysqldump command + * + * @param null|string $database Database name + * + * @return RemoteCommandBuilder + */ + protected function createLocalMySqlDumpCommand($database = null) { + $command = new RemoteCommandBuilder('mysqldump'); + + // Add username + if (DatabaseConnection::getDbUsername()) { + $command->addArgumentTemplate('-u%s', DatabaseConnection::getDbUsername()); + } + + // Add password + if (DatabaseConnection::getDbPassword()) { + $command->addArgumentTemplate('-p%s', DatabaseConnection::getDbPassword()); + } + + // Add hostname + if (DatabaseConnection::getDbHostname()) { + $command->addArgumentTemplate('-h%s', DatabaseConnection::getDbHostname()); + } + + // Add hostname + if (DatabaseConnection::getDbPort()) { + $command->addArgumentTemplate('-P%s', DatabaseConnection::getDbPort()); + } + + // Add custom options + if ($this->contextConfig->exists('mysqldump.option')) { + $command->addArgumentRaw($this->contextConfig->get('mysqldump.option')); + } + + if ($database !== null) { + $command->addArgument($database); + } + + // Transfer compression + switch($this->contextConfig->get('mysql.compression')) { + case 'bzip2': + // Add pipe compressor (bzip2 compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); + break; + + case 'gzip': + // Add pipe compressor (gzip compressed transfer via ssh) + $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); + break; + } + + return $command; + } + + + /** + * Add mysqldump filter to command + * + * @param CommandBuilderInterface $commandDump Command + * @param string $database Database + * @param boolean $isRemote Remote filter + * + * @return CommandBuilderInterface + */ + protected function addMysqlDumpFilterArguments(CommandBuilderInterface $commandDump, $database, $isRemote = true) { + $command = $commandDump; + + $filter = $this->contextConfig->get('mysql.filter'); + + // get filter + if (is_array($filter)) { + $filterList = (array)$filter; + $filter = 'custom table filter'; + } else { + $filterList = $this->getApplication()->getConfigValue('mysql-backup-filter', $filter); + } + + if (empty($filterList)) { + throw new \RuntimeException('MySQL dump filters "' . $filter . '" not available"'); + } + + $this->output->writeln('

Using filter "' . $filter . '"

'); + + // Get table list (from cloned mysqldump command) + if ($isRemote) { + $tableListDumper = $this->createRemoteMySqlCommand($database); + } else { + $tableListDumper = $this->createLocalMySqlCommand($database); + } + + $tableListDumper->addArgumentTemplate('-e %s', 'show tables;'); + + if ($isRemote) { + $tableListDumper = $this->wrapRemoteCommand($tableListDumper); + } + $tableList = $tableListDumper->execute()->getOutput(); + + // Filter table list + $ignoredTableList = FilterUtility::mysqlIgnoredTableFilter($tableList, $filterList, $database); + + // Dump only structure + $commandStructure = clone $command; + $commandStructure + ->addArgument('--no-data') + ->clearPipes(); + + // Dump only data (only filtered tables) + $commandData = clone $command; + $commandData + ->addArgument('--no-create-info') + ->clearPipes(); + + if (!empty($ignoredTableList)) { + $commandData->addArgumentTemplateMultiple('--ignore-table=%s', $ignoredTableList); + } + + $commandPipeList = $command->getPipeList(); + + // Combine both commands to one + $command = new OutputCombineCommandBuilder(); + $command + ->addCommandForCombinedOutput($commandStructure) + ->addCommandForCombinedOutput($commandData); + + // Read compression pipe + if (!empty($commandPipeList)) { + $command->setPipeList($commandPipeList); + } + + return $command; + } + } diff --git a/src/app/CliTools/Console/Command/Sync/AbstractRemoteSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractRemoteSyncCommand.php new file mode 100644 index 0000000..f26efa2 --- /dev/null +++ b/src/app/CliTools/Console/Command/Sync/AbstractRemoteSyncCommand.php @@ -0,0 +1,50 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +abstract class AbstractRemoteSyncCommand extends AbstractCommand { + + /** + * Validate configuration + * + * @return boolean + */ + protected function validateConfiguration() { + $ret = parent::validateConfiguration(); + + $output = $this->output; + + // ################## + // SSH (optional) + // ################## + + if ($this->config->exists('ssh')) { + // Check if one database is configured + if (!$this->config->exists('ssh.hostname')) { + $output->writeln('No ssh hostname configuration found'); + $ret = false; + } + } + + return $ret; + } + +} diff --git a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php index 2b28411..ddc04cb 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractShareCommand.php @@ -20,16 +20,19 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; +abstract class AbstractShareCommand extends AbstractCommand { -abstract class AbstractShareCommand extends \CliTools\Console\Command\Sync\AbstractCommand { + const PATH_DUMP = '/dump/'; + const PATH_DATA = '/data/'; /** - * Config area - * - * @var string + * Configure command */ - protected $confArea = 'share'; + protected function configure() { + parent::configure(); + + $this->confArea = 'share'; + } /** * Validate configuration @@ -45,29 +48,4 @@ protected function validateConfiguration() { return $ret; } - /** - * Create rsync command for share sync - * - * @param string $source Rsync Source - * @param string $target Rsync target - * @param boolean $useExcludeInclude Use file/exclude lists - * - * @return CommandBuilderInterface - */ - protected function createShareRsyncCommand($source, $target, $useExcludeInclude = false) { - // File list - $filelist = null; - if ($useExcludeInclude && $this->config->exists('rsync.directory')) { - $filelist = $this->config->get('rsync.directory'); - } - - // Exclude list - $exclude = null; - if ($useExcludeInclude && $this->config->exists('rsync.exclude')) { - $exclude = $this->config->get('rsync.exclude'); - } - - return $this->createRsyncCommand($source, $target, $filelist, $exclude); - } - } diff --git a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php deleted file mode 100644 index 4fa0317..0000000 --- a/src/app/CliTools/Console/Command/Sync/AbstractSyncCommand.php +++ /dev/null @@ -1,275 +0,0 @@ - - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; -use Symfony\Component\Console\Helper\QuestionHelper; -use Symfony\Component\Console\Question\ChoiceQuestion; - -abstract class AbstractSyncCommand extends \CliTools\Console\Command\Sync\AbstractCommand { - - /** - * Validate configuration - * - * @return boolean - */ - protected function validateConfiguration() { - $ret = parent::validateConfiguration(); - - $output = $this->output; - - // ################## - // SSH (optional) - // ################## - - if ($this->config->exists('ssh')) { - // Check if one database is configured - if (!$this->config->exists('ssh.hostname')) { - $output->writeln('No ssh hostname configuration found'); - $ret = false; - } - } - - return $ret; - } - - /** - * Read and validate configuration - */ - protected function readConfiguration() { - parent::readConfiguration(); - - $this->contextName = $this->getServerContext(); - - if (empty($this->contextName) || $this->contextName === '_' || empty($this->config[$this->contextName])) { - throw new \RuntimeException('No valid configuration found for context "' . $this->contextName . '"'); - } - - // Use server specific configuration - $this->output->writeln('

Syncing from "' . $this->contextName . '" server

'); - - // ################## - // Jump into section - // ################## - if ($this->config->exists('_')) { - // Merge global config with specific config - $this->config->setData(array_replace_recursive($this->config->getArray('_'), $this->config->getArray($this->contextName))); - } else { - $this->config->setData($this->config->getArray($this->contextName)); - } - } - - /** - * Get server context from user - */ - protected function getServerContext() { - $ret = null; - - if (!$this->input->getArgument('context')) { - // ######################## - // Ask user for server context - // ######################## - - $serverList = $this->config->getList(); - $serverList = array_diff($serverList, array('_')); - - if (empty($serverList)) { - throw new \RuntimeException('No valid servers found in configuration'); - } - - $serverOptionList = array(); - - foreach ($serverList as $context) { - $line = array(); - - // hostname - $optPath = $context . '.ssh.hostname'; - if ($this->config->exists($optPath)) { - $line[] = 'host:' . $this->config->get($optPath); - } - - // rsync path - $optPath = $context . '.rsync.path'; - if ($this->config->exists($optPath)) { - $line[] = 'rsync:' . $this->config->get($optPath); - } - - // mysql database list - $optPath = $context . '.mysql.database'; - if ($this->config->exists($optPath)) { - $dbList = $this->config->getArray($optPath); - $foreignDbList = array(); - - foreach ($dbList as $databaseConf) { - if (strpos($databaseConf, ':') !== false) { - // local and foreign database in one string - list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); - $foreignDbList[] = $foreignDatabase; - } else { - // database equal - $foreignDbList[] = $databaseConf; - } - } - - if (!empty($foreignDbList)) { - $line[] .= 'mysql:' . implode(', ', $foreignDbList); - } - } - - if (!empty($line)) { - $line = implode(' ', $line); - } else { - // fallback - $line = $context; - } - - $serverOptionList[$context] = $line; - } - - try { - $question = new ChoiceQuestion('Please choose server context for synchronization', $serverOptionList); - $question->setMaxAttempts(1); - - $questionDialog = new QuestionHelper(); - - $ret = $questionDialog->ask($this->input, $this->output, $question); - } catch(\InvalidArgumentException $e) { - // Invalid server context, just stop here - throw new \CliTools\Exception\StopException(1); - } - } else { - $ret = $this->input->getArgument('context'); - } - - return $ret; - } - - /** - * Wrap command with ssh if needed - * - * @param CommandBuilderInterface $command - * @return CommandBuilderInterface - */ - protected function wrapRemoteCommand(CommandBuilderInterface $command) { - // Wrap in ssh if needed - if ($this->config->exists('ssh.hostname')) { - $sshCommand = new CommandBuilder('ssh', '-o BatchMode=yes'); - $sshCommand->addArgument($this->config->get('ssh.hostname')) - ->append($command, true); - - $command = $sshCommand; - } - - return $command; - } - - /** - * Create new mysql command - * - * @param null|string $database Database name - * - * @return RemoteCommandBuilder - */ - protected function createRemoteMySqlCommand($database = null) { - $command = new RemoteCommandBuilder('mysql'); - $command - // batch mode - ->addArgument('-B') - // skip column names - ->addArgument('-N'); - - // Add username - if ($this->config->exists('mysql.username')) { - $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); - } - - // Add password - if ($this->config->exists('mysql.password')) { - $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); - } - - // Add hostname - if ($this->config->exists('mysql.hostname')) { - $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); - } - - if ($database !== null) { - $command->addArgument($database); - } - - return $command; - } - - /** - * Create new mysql command - * - * @param null|string $database Database name - * - * @return RemoteCommandBuilder - */ - protected function createRemoteMySqlDumpCommand($database = null) { - $command = new RemoteCommandBuilder('mysqldump'); - - // Add username - if ($this->config->exists('mysql.username')) { - $command->addArgumentTemplate('-u%s', $this->config->get('mysql.username')); - } - - // Add password - if ($this->config->exists('mysql.password')) { - $command->addArgumentTemplate('-p%s', $this->config->get('mysql.password')); - } - - // Add hostname - if ($this->config->exists('mysql.hostname')) { - $command->addArgumentTemplate('-h%s', $this->config->get('mysql.hostname')); - } - - // Add custom options - if ($this->config->exists('mysqldump.option')) { - $command->addArgumentRaw($this->config->get('mysqldump.option')); - } - - // Transfer compression - switch($this->config->get('mysql.compression')) { - case 'bzip2': - // Add pipe compressor (bzip2 compressed transfer via ssh) - $command->addPipeCommand( new CommandBuilder('bzip2', '--compress --stdout') ); - break; - - case 'gzip': - // Add pipe compressor (gzip compressed transfer via ssh) - $command->addPipeCommand( new CommandBuilder('gzip', '--stdout') ); - break; - } - - - if ($database !== null) { - $command->addArgument($database); - } - - return $command; - } - - -} diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 8d722e0..785add0 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use Symfony\Component\Console\Input\InputOption; +use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; class BackupCommand extends AbstractShareCommand { @@ -28,21 +28,11 @@ class BackupCommand extends AbstractShareCommand { * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('sync:backup') - ->setDescription('Backup project files') - ->addOption( - 'mysql', - null, - InputOption::VALUE_NONE, - 'Run only mysql' - ) - ->addOption( - 'rsync', - null, - InputOption::VALUE_NONE, - 'Run only rsync' - ); + ->setDescription('Backup files and database from share'); } /** @@ -56,7 +46,7 @@ protected function startup() { /** * Backup task */ - protected function runTask() { + protected function runMain() { // ################## // Option specific runners // ################## @@ -71,18 +61,17 @@ protected function runTask() { $runMysql = $this->input->getOption('mysql'); } - // ################## // Backup dirs // ################## - if ($runRsync && $this->config->exists('rsync.directory')) { + if ($runRsync && $this->contextConfig->exists('rsync.directory')) { $this->runTaskRsync(); } // ################## // Backup databases // ################## - if ($runMysql && $this->config->exists('mysql.database')) { + if ($runMysql && $this->contextConfig->exists('mysql.database')) { $this->runTaskMysql(); } } @@ -93,25 +82,52 @@ protected function runTask() { protected function runTaskRsync() { $source = $this->getRsyncWorkingPath(); $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; - $command = $this->createShareRsyncCommand($source, $target, true); + + $fileList = array(); + if ($this->contextConfig->exists('rsync.directory')) { + $fileList = $this->contextConfig->get('rsync.directory'); + } + + $excludeList = array(); + if ($this->contextConfig->exists('rsync.exclude')) { + $excludeList = $this->contextConfig->get('rsync.exclude'); + } + + $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); $command->executeInteractive(); } - /** - * Sync files with mysql + * Sync database */ protected function runTaskMysql() { - foreach ($this->config->getArray('mysql.database') as $database) { - $this->output->writeln('Dumping database ' . $database . ''); + // ################## + // Sync databases + // ################## + foreach ($this->contextConfig->getArray('mysql.database') as $database) { + // make sure we don't have any leading whitespaces + $database = trim($database); // dump database - $dumpFile = $this->tempDir . '/mysql/' . $database . '.sql.bz2'; + $dumpFile = $this->tempDir . '/mysql/' . $database . '.dump'; + + // ########## + // Dump from server + // ########## + $this->output->writeln('

Dumping database "' . $database . '"

'); + + $mysqldump = $this->createLocalMySqlDumpCommand($database); + + if ($this->contextConfig->exists('mysql.filter')) { + $mysqldump = $this->addMysqlDumpFilterArguments($mysqldump, $database, false); + } - $dumpFilter = $this->config->get('mysql.filter'); + $command = new OutputCombineCommandBuilder(); + $command->addCommandForCombinedOutput($mysqldump); - $this->createMysqlBackupCommand($database, $dumpFile, $dumpFilter) - ->executeInteractive(); + $command + ->setOutputRedirectToFile($dumpFile) + ->executeInteractive(); } // ################## @@ -119,7 +135,7 @@ protected function runTaskMysql() { // ################## $source = $this->tempDir; $target = $this->getRsyncPathFromConfig() . self::PATH_DUMP; - $command = $this->createShareRsyncCommand($source, $target, false); + $command = $this->createRsyncCommand($source, $target); $command->executeInteractive(); } } diff --git a/src/app/CliTools/Console/Command/Sync/DeployCommand.php b/src/app/CliTools/Console/Command/Sync/DeployCommand.php index 0f97c88..009577e 100644 --- a/src/app/CliTools/Console/Command/Sync/DeployCommand.php +++ b/src/app/CliTools/Console/Command/Sync/DeployCommand.php @@ -20,49 +20,21 @@ * along with this program. If not, see . */ -use CliTools\Utility\FilterUtility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; use CliTools\Database\DatabaseConnection; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; - -class DeployCommand extends AbstractSyncCommand { - - /** - * Config area - * - * @var string - */ - protected $confArea = 'deploy'; - - /** - * Server configuration name - * @var string - */ - protected $contextName; +class DeployCommand extends AbstractRemoteSyncCommand { /** * Configure command */ protected function configure() { + parent::configure(); + + $this->confArea = 'deploy'; + $this ->setName('sync:deploy') - ->setDescription('Deploy files and database to server') - ->addArgument( - 'context', - InputArgument::OPTIONAL, - 'Configuration name for server' - ) - ->addOption( - 'rsync', - null, - InputOption::VALUE_NONE, - 'Run only rsync' - ); + ->setDescription('Deploy files and database to server'); } /** @@ -76,7 +48,7 @@ protected function startup() { /** * Backup task */ - protected function runTask() { + protected function runMain() { // ################## // Option specific runners // ################## @@ -96,18 +68,18 @@ protected function runTask() { // ################## // Check database connection - if ($runMysql && $this->config->exists('mysql')) { + if ($runMysql && $this->contextConfig->exists('mysql')) { DatabaseConnection::ping(); } // Sync files with rsync to local storage - if ($runRsync && $this->config->exists('rsync')) { + if ($runRsync && $this->contextConfig->exists('rsync')) { $this->output->writeln('

Starting FILE deployment

'); $this->runTaskRsync(); } // Sync database to local server - if ($runMysql && $this->config->exists('mysql')) { + if ($runMysql && $this->contextConfig->exists('mysql')) { $this->output->writeln('

Starting MYSQL deployment

'); $this->output->writeln('

TODO - not implemented'); } @@ -118,37 +90,24 @@ protected function runTask() { */ protected function runTaskRsync() { // ################## - // Restore dirs + // Deploy dirs // ################## $source = $this->getRsyncWorkingPath(); $target = $this->getRsyncPathFromConfig(); - $command = $this->createRsyncCommand($source, $target); - - $command->executeInteractive(); - } - /** - * Create rsync command for share sync - * - * @param string $source Source directory - * @param string $target Target directory - * @param array|null $filelist List of files (patterns) - * @param array|null $exclude List of excludes (patterns) - * - * @return CommandBuilder - */ - protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { - // Add file list (external file with --files-from option) - if (!$filelist && $this->config->exists('rsync.directory')) { - $filelist = $this->config->get('rsync.directory'); + $fileList = array(); + if ($this->contextConfig->exists('rsync.directory')) { + $fileList = $this->contextConfig->get('rsync.directory'); } - // Add exclude (external file with --exclude-from option) - if (!$exclude && $this->config->exists('rsync.exclude')) { - $exclude = $this->config->get('rsync.exclude'); + $excludeList = array(); + if ($this->contextConfig->exists('rsync.exclude')) { + $excludeList = $this->contextConfig->get('rsync.exclude'); } - return parent::createRsyncCommand($source, $target, $filelist, $exclude); + $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); + + $command->executeInteractive(); } } diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 35df4db..8a6ecb8 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -28,21 +28,11 @@ class RestoreCommand extends AbstractShareCommand { * Configure command */ protected function configure() { + parent::configure(); + $this ->setName('sync:restore') - ->setDescription('Restore project files') - ->addOption( - 'mysql', - null, - InputOption::VALUE_NONE, - 'Run only mysql' - ) - ->addOption( - 'rsync', - null, - InputOption::VALUE_NONE, - 'Run only rsync' - ); + ->setDescription('Restore files and database from share'); } /** @@ -56,7 +46,7 @@ protected function startup() { /** * Restore task */ - protected function runTask() { + protected function runMain() { // ################## // Option specific runners // ################## @@ -71,11 +61,10 @@ protected function runTask() { $runMysql = $this->input->getOption('mysql'); } - // ################## // Restore dirs // ################## - if ($runRsync && $this->config->exists('rsync.directory')) { + if ($runRsync && $this->contextConfig->exists('rsync.directory')) { $this->runTaskRsync(); } @@ -91,20 +80,30 @@ protected function runTask() { * Sync files with rsync */ protected function runTaskRsync() { - $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; + $source = $this->getRsyncPathFromConfig() . self::PATH_DATA; $target = $this->getRsyncWorkingPath(); - $command = $this->createShareRsyncCommand($source, $target, true); + + $fileList = array(); + if ($this->contextConfig->exists('rsync.directory')) { + $fileList = $this->contextConfig->get('rsync.directory'); + } + + $excludeList = array(); + if ($this->contextConfig->exists('rsync.exclude')) { + $excludeList = $this->contextConfig->get('rsync.exclude'); + } + + $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); $command->executeInteractive(); } - /** * Sync files with mysql */ protected function runTaskMysql() { $source = $this->getRsyncPathFromConfig() . self::PATH_DUMP; $target = $this->tempDir; - $command = $this->createShareRsyncCommand($source, $target, false); + $command = $this->createRsyncCommand($source, $target); $command->executeInteractive(); $iterator = new \DirectoryIterator($this->tempDir . '/mysql'); diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index 35de8fa..f416787 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -20,55 +20,21 @@ * along with this program. If not, see . */ -use CliTools\Utility\FilterUtility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; use CliTools\Database\DatabaseConnection; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputArgument; - -class ServerCommand extends AbstractSyncCommand { - - /** - * Config area - * - * @var string - */ - protected $confArea = 'sync'; - - /** - * Server configuration name - * @var string - */ - protected $contextName; +class ServerCommand extends AbstractRemoteSyncCommand { /** * Configure command */ protected function configure() { + parent::configure(); + + $this->confArea = 'sync'; + $this ->setName('sync:server') - ->setDescription('Sync files and database from server') - ->addArgument( - 'context', - InputArgument::OPTIONAL, - 'Configuration name for server' - ) - ->addOption( - 'mysql', - null, - InputOption::VALUE_NONE, - 'Run only mysql' - ) - ->addOption( - 'rsync', - null, - InputOption::VALUE_NONE, - 'Run only rsync' - ); + ->setDescription('Sync files and database from server'); } /** @@ -79,10 +45,35 @@ protected function startup() { parent::startup(); } + /** + * Validate configuration + * + * @return boolean + */ + protected function validateConfiguration() { + $ret = parent::validateConfiguration(); + + $output = $this->output; + + // ################## + // SSH (optional) + // ################## + + if ($this->contextConfig->exists('ssh')) { + // Check if one database is configured + if (!$this->contextConfig->exists('ssh.hostname')) { + $output->writeln('No ssh hostname configuration found'); + $ret = false; + } + } + + return $ret; + } + /** * Backup task */ - protected function runTask() { + protected function runMain() { // ################## // Option specific runners // ################## @@ -102,18 +93,18 @@ protected function runTask() { // ################## // Check database connection - if ($runMysql && $this->config->exists('mysql')) { + if ($runMysql && $this->contextConfig->exists('mysql')) { DatabaseConnection::ping(); } // Sync files with rsync to local storage - if ($runRsync && $this->config->exists('rsync')) { + if ($runRsync && $this->contextConfig->exists('rsync')) { $this->output->writeln('

Starting FILE sync

'); $this->runTaskRsync(); } // Sync database to local server - if ($runMysql && $this->config->exists('mysql')) { + if ($runMysql && $this->contextConfig->exists('mysql')) { $this->output->writeln('

Starting MYSQL sync

'); $this->runTaskDatabase(); } @@ -128,7 +119,18 @@ protected function runTaskRsync() { // ################## $source = $this->getRsyncPathFromConfig(); $target = $this->getRsyncWorkingPath(); - $command = $this->createRsyncCommand($source, $target); + + $fileList = array(); + if ($this->contextConfig->exists('rsync.directory')) { + $fileList = $this->contextConfig->get('rsync.directory'); + } + + $excludeList = array(); + if ($this->contextConfig->exists('rsync.exclude')) { + $excludeList = $this->contextConfig->get('rsync.exclude'); + } + + $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); $command->executeInteractive(); } @@ -140,7 +142,7 @@ protected function runTaskDatabase() { // ################## // Sync databases // ################## - foreach ($this->config->getArray('mysql.database') as $databaseConf) { + foreach ($this->contextConfig->getArray('mysql.database') as $databaseConf) { if (strpos($databaseConf, ':') !== false) { // local and foreign database in one string list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); @@ -163,8 +165,8 @@ protected function runTaskDatabase() { $mysqldump = $this->createRemoteMySqlDumpCommand($foreignDatabase); - if ($this->config['mysql']['filter']) { - $mysqldump = $this->addFilterArguments($mysqldump, $foreignDatabase, $this->config['mysql']['filter']); + if ($this->contextConfig->exists('mysql.filter')) { + $mysqldump = $this->addMysqlDumpFilterArguments($mysqldump, $foreignDatabase, $this->contextConfig->get('mysql.filter')); } $command = $this->wrapRemoteCommand($mysqldump); @@ -182,96 +184,4 @@ protected function runTaskDatabase() { } - /** - * Create rsync command for share sync - * - * @param string $source Source directory - * @param string $target Target directory - * @param array|null $filelist List of files (patterns) - * @param array|null $exclude List of excludes (patterns) - * - * @return CommandBuilder - */ - protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { - // Add file list (external file with --files-from option) - if (!$filelist && $this->config->exists('rsync.directory')) { - $filelist = $this->config->get('rsync.directory'); - } - - // Add exclude (external file with --exclude-from option) - if (!$exclude && $this->config->exists('rsync.exclude')) { - $exclude = $this->config->get('rsync.exclude'); - } - - return parent::createRsyncCommand($source, $target, $filelist, $exclude); - } - - /** - * Add filter to command - * - * @param CommandBuilderInterface $commandDump Command - * @param string $database Database - * @param string $filter Filter name - * - * @return CommandBuilderInterface - */ - protected function addFilterArguments(CommandBuilderInterface $commandDump, $database, $filter) { - $command = $commandDump; - - // get filter - if (is_array($filter)) { - $filterList = (array)$filter; - $filter = 'custom table filter'; - } else { - $filterList = $this->getApplication()->getConfigValue('mysql-backup-filter', $filter); - } - - if (empty($filterList)) { - throw new \RuntimeException('MySQL dump filters "' . $filter . '" not available"'); - } - - $this->output->writeln('

Using filter "' . $filter . '"

'); - - // Get table list (from cloned mysqldump command) - $tableListDumper = $this->createRemoteMySqlCommand($database); - $tableListDumper->addArgumentTemplate('-e %s', 'show tables;'); - - $tableListDumper = $this->wrapRemoteCommand($tableListDumper); - $tableList = $tableListDumper->execute()->getOutput(); - - // Filter table list - $ignoredTableList = FilterUtility::mysqlIgnoredTableFilter($tableList, $filterList, $database); - - // Dump only structure - $commandStructure = clone $command; - $commandStructure - ->addArgument('--no-data') - ->clearPipes(); - - // Dump only data (only filtered tables) - $commandData = clone $command; - $commandData - ->addArgument('--no-create-info') - ->clearPipes(); - - if (!empty($ignoredTableList)) { - $commandData->addArgumentTemplateMultiple('--ignore-table=%s', $ignoredTableList); - } - - $commandPipeList = $command->getPipeList(); - - // Combine both commands to one - $command = new OutputCombineCommandBuilder(); - $command - ->addCommandForCombinedOutput($commandStructure) - ->addCommandForCombinedOutput($commandData); - - // Readd compression pipe - if (!empty($commandPipeList)) { - $command->setPipeList($commandPipeList); - } - - return $command; - } - } diff --git a/src/app/CliTools/Database/DatabaseConnection.php b/src/app/CliTools/Database/DatabaseConnection.php index f55bde8..eab783f 100644 --- a/src/app/CliTools/Database/DatabaseConnection.php +++ b/src/app/CliTools/Database/DatabaseConnection.php @@ -21,6 +21,7 @@ */ use CliTools\Utility\ConsoleUtility; +use AD7six\Dsn\Dsn; class DatabaseConnection { @@ -103,6 +104,25 @@ public static function getDbPassword() { return self::$dbPassword; } + /** + * Get Db Hostname + * + * @return string + */ + public static function getDbHostname() { + return self::parseDsnValue('host'); + } + + /** + * Get Db Port + * + * @return string + */ + public static function getDbPort() { + return self::parseDsnValue('port'); + } + + /** * Get connection * @@ -593,4 +613,22 @@ public static function sanitizeSqlTable($table) { public static function sanitizeSqlDatabase($database) { return '`' . preg_replace('/[^_a-zA-Z0-9]/', '', $database) . '`'; } + + /** + * Parse DSN and return value + * + * @param string $key DSN Key + * @param string|null $default Default value + * @return string|null + */ + protected static function parseDsnValue($key, $default = NULL) { + $ret = $default; + + $pattern = sprintf('~%s=([^;]*)(?:;|$)~', preg_quote($key, '~')); + if (preg_match($pattern, self::$dbDsn, $matches)) { + $ret = $matches[1]; + } + + return $ret; + } } From e0f730a9455486dc168edc5161b072dad4a64c17 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 01:08:16 +0200 Subject: [PATCH 191/214] Cleanup --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 1299629..fda729a 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -994,10 +994,12 @@ protected function addMysqlDumpFilterArguments(CommandBuilderInterface $commandD $tableListDumper->addArgumentTemplate('-e %s', 'show tables;'); + // wrap with ssh (for remote execution) if ($isRemote) { $tableListDumper = $this->wrapRemoteCommand($tableListDumper); } - $tableList = $tableListDumper->execute()->getOutput(); + + $tableList = $tableListDumper->execute()->getOutput(); // Filter table list $ignoredTableList = FilterUtility::mysqlIgnoredTableFilter($tableList, $filterList, $database); From be6013b60a750f3892af170afe856d905a2607d3 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 01:10:19 +0200 Subject: [PATCH 192/214] Cleanup --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 4 ++-- src/app/CliTools/Utility/UnixUtility.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index fda729a..6c5375c 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -396,8 +396,8 @@ protected function getContextFromUser() { foreach ($dbList as $databaseConf) { if (strpos($databaseConf, ':') !== false) { // local and foreign database in one string - list($localDatabase, $foreignDatabase) = explode(':', $databaseConf, 2); - $foreignDbList[] = $foreignDatabase; + $databaseConf = explode(':', $databaseConf, 2); + $foreignDbList[] = $databaseConf[1]; } else { // database equal $foreignDbList[] = $databaseConf; diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index 2834e41..d39baec 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -317,7 +317,7 @@ public static function reloadTtyBanner($ttyName) { if (!empty($output)) { $outputLine = trim(reset($output)); $outputLineParts = preg_split('/[\s]+/', $outputLine); - list($pid, $cmd) = $outputLineParts; + list($pid) = $outputLineParts; posix_kill($pid, SIGHUP); } From c2633159acd56fa307c614401f37cd71b8cad71b Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 01:12:25 +0200 Subject: [PATCH 193/214] Cleanup --- src/app/CliTools/Console/Command/Sync/RestoreCommand.php | 2 -- src/app/CliTools/Database/DatabaseConnection.php | 1 - 2 files changed, 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 8a6ecb8..985d26c 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -20,8 +20,6 @@ * along with this program. If not, see . */ -use Symfony\Component\Console\Input\InputOption; - class RestoreCommand extends AbstractShareCommand { /** diff --git a/src/app/CliTools/Database/DatabaseConnection.php b/src/app/CliTools/Database/DatabaseConnection.php index eab783f..fb2a178 100644 --- a/src/app/CliTools/Database/DatabaseConnection.php +++ b/src/app/CliTools/Database/DatabaseConnection.php @@ -21,7 +21,6 @@ */ use CliTools\Utility\ConsoleUtility; -use AD7six\Dsn\Dsn; class DatabaseConnection { From 30852f961268cd664692c435296e723ffa0604b7 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 01:13:58 +0200 Subject: [PATCH 194/214] Fixed display issue in context selection --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 6c5375c..825c07f 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -376,19 +376,19 @@ protected function getContextFromUser() { $line = array(); // hostname - $optPath = $context . '.ssh.hostname'; + $optPath = $this->confArea . '.' . $context . '.ssh.hostname'; if ($this->config->exists($optPath)) { $line[] = 'host:' . $this->config->get($optPath); } // rsync path - $optPath = $context . '.rsync.path'; + $optPath = $this->confArea . '.' . $context . '.rsync.path'; if ($this->config->exists($optPath)) { $line[] = 'rsync:' . $this->config->get($optPath); } // mysql database list - $optPath = $context . '.mysql.database'; + $optPath = $this->confArea . '.' . $context . '.mysql.database'; if ($this->config->exists($optPath)) { $dbList = $this->config->getArray($optPath); $foreignDbList = array(); From de396fc8ce445258d8f28594b6d507cbf49bc716 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 11:54:42 +0200 Subject: [PATCH 195/214] Fixed mysqldump missing options --- src/app/CliTools/Console/Command/Sync/AbstractCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 825c07f..9c2a071 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -877,8 +877,8 @@ protected function createRemoteMySqlDumpCommand($database = null) { } // Add custom options - if ($this->contextConfig->exists('mysqldump.option')) { - $command->addArgumentRaw($this->contextConfig->get('mysqldump.option')); + if ($this->contextConfig->exists('mysql.mysqldump.option')) { + $command->addArgumentRaw($this->contextConfig->get('mysql.mysqldump.option')); } // Transfer compression @@ -932,8 +932,8 @@ protected function createLocalMySqlDumpCommand($database = null) { } // Add custom options - if ($this->contextConfig->exists('mysqldump.option')) { - $command->addArgumentRaw($this->contextConfig->get('mysqldump.option')); + if ($this->contextConfig->exists('mysql.mysqldump.option')) { + $command->addArgumentRaw($this->contextConfig->get('mysql.mysqldump.option')); } if ($database !== null) { From b46904f7040ff6490ef3a32eb0f1d240fd4d723a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 11:54:51 +0200 Subject: [PATCH 196/214] Added fileadmin temp to excludes --- Documentation/Examples/clisync.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 404d9ff..3b76748 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -126,6 +126,7 @@ sync: # directory exclude list/patterns exclude: - "/fileadmin/_processed_/**" + - "/fileadmin/_temp_/**" ################## # Context "production" From 0cb0badfaad87d70bfbe6c786426b4b88c074c33 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 18:46:26 +0200 Subject: [PATCH 197/214] Improved terminal title setting --- src/app/CliTools/Console/Application.php | 4 +- .../Console/Command/AbstractCommand.php | 42 +++++++++++++++++++ .../Console/Command/Docker/ComposeCommand.php | 2 + .../Console/Command/Docker/CreateCommand.php | 10 ++--- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/app/CliTools/Console/Application.php b/src/app/CliTools/Console/Application.php index 91922fb..e1e8920 100644 --- a/src/app/CliTools/Console/Application.php +++ b/src/app/CliTools/Console/Application.php @@ -377,11 +377,11 @@ public function getSettingsService() { } /** - * Set process title + * Set terminal title * * @param string $title Title */ - public function setProcessTitle($title) { + public function setTerminalTitle($title) { // DECSLPP. echo "\033]0;" . 'ct: ' . $title . "\033\\"; } diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index d49dfb2..568e624 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -211,4 +211,46 @@ protected function showFinishMessages() { $this->finishMessageList = array(); } + + /** + * Gets the application instance for this command. + * + * @return \CliTools\Console\Application An Application instance + * + * @api + */ + public function getApplication() { + return parent::getApplication(); + } + + /** + * Sets the terminal title of the command. + * + * This feature should be used only when creating a long process command, + * like a daemon. + * + * PHP 5.5+ or the proctitle PECL library is required + * + * @param string $title The terminal title + * + * @return Command The current instance + */ + public function setTerminalTitle($title) { + $args = func_get_args(); + + $titleList = array(); + foreach($args as $value) { + if (is_array($value)) { + $value = implode(' ', $value); + } + + $titleList[] = trim($value); + } + + $title = implode(' ', $titleList); + $title = trim($title); + + $this->getApplication()->setTerminalTitle($title); + return $this; + } } diff --git a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php index 4fe28a6..73ef5bb 100644 --- a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php @@ -52,6 +52,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $command->setArgumentList($paramList); } + $this->setTerminalTitle('docker-compose', $paramList); + $ret = $this->executeDockerCompose($command); return $ret; diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index 89fe8d1..946473b 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -137,7 +137,7 @@ protected function startInteractiveEditor($path) { try { $editor = new EditorCommandBuilder(); - $this->getApplication()->setProcessTitle('Edit ' . basename($path)); + $this->setTerminalTitle('Edit', basename($path)); $this->output->writeln('

Starting interactive EDITOR for file ' .$path . '

'); sleep(1); @@ -158,7 +158,7 @@ protected function startInteractiveEditor($path) { * @param string $repo Repository */ protected function createDockerInstance($path, $repo) { - $this->getApplication()->setProcessTitle('Cloning docker'); + $this->setTerminalTitle('Cloning docker'); $command = new CommandBuilder('git','clone --branch=master --recursive %s %s', array($repo, $path)); $command->executeInteractive(); @@ -171,7 +171,7 @@ protected function createDockerInstance($path, $repo) { * @param string $repo Repository */ protected function initCode($path, $repo) { - $this->getApplication()->setProcessTitle('Cloning code'); + $this->setTerminalTitle('Cloning code'); $path .= '/code'; @@ -240,7 +240,7 @@ protected function initDocumentRoot($path) { * @param string $makeCommand Makefile command */ protected function runMakefile($path, $makeCommand) { - $this->getApplication()->setProcessTitle('Run make'); + $this->setTerminalTitle('Run make'); $path .= '/code'; @@ -264,7 +264,7 @@ protected function runMakefile($path, $makeCommand) { * @param string $path Path */ protected function startDockerInstance($path) { - $this->getApplication()->setProcessTitle('Start docker'); + $this->setTerminalTitle('Start docker'); $this->output->writeln('Building docker containers "' . $path . '"'); From 818f4d22d184998275afcd9884ad80c6e460b3d3 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Thu, 11 Jun 2015 18:46:42 +0200 Subject: [PATCH 198/214] Added sync:deploy --- Documentation/USAGE-SYNC.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Documentation/USAGE-SYNC.md b/Documentation/USAGE-SYNC.md index a56fa7d..11bed8d 100644 --- a/Documentation/USAGE-SYNC.md +++ b/Documentation/USAGE-SYNC.md @@ -29,13 +29,13 @@ In the `clisync.yml` you can specify multiple servers. Now you can sync your `production` server to your local installation: ```bash -# Full sync (files and database) -ct sync:server production +# Full sync (files and database, with interactive context selection) +ct sync:server -# Only MySQL +# Only MySQL (from production context, without interactive context selection) ct sync:server production --mysql -# Only Files +# Only Files (from production context, without interactive context selection) ct sync:server production --rsync ``` @@ -65,6 +65,21 @@ ct sync:restore --rsync ``` +## Lightweight deployment (ct sync:deploy) + +With `sync:deploy` you can push your files to your production servers. +Please keep in mind that this feature is just an wrapped rsync and should only be +the simplest solution for deployment. For more advanced or centralized deployemnt try +solutions build on Jenkis, Ansible and others. + +```bash +# Push your project to your servers (with interactive context selection) +ct sync:deploy + +# Push your project to your staging server (without interactive context selection) +ct sync:deploy staging +``` + ## Advanced ssh options If you need some advaned ssh options (eg. other ports) use your `~/.ssh/config` configuration file: From c90c2ad33c32c179e86997ed944f96853af8060e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 20:41:37 +0200 Subject: [PATCH 199/214] Refactored sync commands --- .../Console/Command/Sync/AbstractCommand.php | 69 ++++++++++++++++++- .../Console/Command/Sync/BackupCommand.php | 12 +--- .../Console/Command/Sync/DeployCommand.php | 12 +--- .../Console/Command/Sync/RestoreCommand.php | 12 +--- .../Console/Command/Sync/ServerCommand.php | 13 +--- 5 files changed, 72 insertions(+), 46 deletions(-) diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 9c2a071..123d9cb 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -606,6 +606,61 @@ protected function buildComplexTask(array $task) { return $command; } + /** + * Create rsync command for sync + * + * @param string $source Source directory + * @param string $target Target directory + * @param string $confKey List of files (patterns) + * + * @return CommandBuilder + */ + protected function createRsyncCommandWithConfiguration($source, $target, $confKey) { + $options = array(); + + // ############# + // Filelist + // ############# + $fileList = array(); + if ($this->contextConfig->exists($confKey . '.directory')) { + $fileList = $this->contextConfig->get($confKey . '.directory'); + } + + // ############# + // Excludes + // ############# + $excludeList = array(); + if ($this->contextConfig->exists($confKey . '.exclude')) { + $excludeList = $this->contextConfig->get($confKey . '.exclude'); + } + + // ############# + // Max size + // ############# + if ($this->contextConfig->exists($confKey . '.conf.maxSize')) { + $options['max-size'] = array( + 'template' => '--max-size=%s', + 'params' => array( + $this->contextConfig->get($confKey . '.conf.maxSize') + ), + ); + } + + // ############# + // Min size + // ############# + if ($this->contextConfig->exists($confKey . '.conf.minSize')) { + $options['min-size'] = array( + 'template' => '--min-size=%s', + 'params' => array( + $this->contextConfig->get($confKey . '.conf.minSize') + ), + ); + } + + return $this->createRsyncCommand($source, $target, $fileList, $excludeList, $options); + } + /** * Create rsync command for sync * @@ -613,10 +668,11 @@ protected function buildComplexTask(array $task) { * @param string $target Target directory * @param array|null $filelist List of files (patterns) * @param array|null $exclude List of excludes (patterns) + * @param array|null $options Custom rsync options * * @return CommandBuilder */ - protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null) { + protected function createRsyncCommand($source, $target, array $filelist = null, array $exclude = null, array $options = null) { $this->output->writeln('Rsync from ' . $source . ' to ' . $target . ''); $command = new CommandBuilder('rsync', '-rlptD --delete-after --progress --human-readable'); @@ -631,6 +687,17 @@ protected function createRsyncCommand($source, $target, array $filelist = null, $this->rsyncAddExcludeList($command, $exclude); } + if (!empty($options)) { + foreach ($options as $optionValue) { + if (is_array($optionValue)) { + $command->addArgumentTemplateList($optionValue['template'], $optionValue['params']); + } else { + $command->addArgument($optionValue); + } + + } + } + // Paths should have leading / to prevent sync issues $source = rtrim($source, '/') . '/'; $target = rtrim($target, '/') . '/'; diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index 785add0..b53349e 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -83,17 +83,7 @@ protected function runTaskRsync() { $source = $this->getRsyncWorkingPath(); $target = $this->getRsyncPathFromConfig() . self::PATH_DATA; - $fileList = array(); - if ($this->contextConfig->exists('rsync.directory')) { - $fileList = $this->contextConfig->get('rsync.directory'); - } - - $excludeList = array(); - if ($this->contextConfig->exists('rsync.exclude')) { - $excludeList = $this->contextConfig->get('rsync.exclude'); - } - - $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); + $command = $this->createRsyncCommandWithConfiguration($source, $target, 'rsync'); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/DeployCommand.php b/src/app/CliTools/Console/Command/Sync/DeployCommand.php index 009577e..12fff68 100644 --- a/src/app/CliTools/Console/Command/Sync/DeployCommand.php +++ b/src/app/CliTools/Console/Command/Sync/DeployCommand.php @@ -95,17 +95,7 @@ protected function runTaskRsync() { $source = $this->getRsyncWorkingPath(); $target = $this->getRsyncPathFromConfig(); - $fileList = array(); - if ($this->contextConfig->exists('rsync.directory')) { - $fileList = $this->contextConfig->get('rsync.directory'); - } - - $excludeList = array(); - if ($this->contextConfig->exists('rsync.exclude')) { - $excludeList = $this->contextConfig->get('rsync.exclude'); - } - - $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); + $command = $this->createRsyncCommandWithConfiguration($source, $target, 'rsync'); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php index 985d26c..c2699c6 100644 --- a/src/app/CliTools/Console/Command/Sync/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Sync/RestoreCommand.php @@ -81,17 +81,7 @@ protected function runTaskRsync() { $source = $this->getRsyncPathFromConfig() . self::PATH_DATA; $target = $this->getRsyncWorkingPath(); - $fileList = array(); - if ($this->contextConfig->exists('rsync.directory')) { - $fileList = $this->contextConfig->get('rsync.directory'); - } - - $excludeList = array(); - if ($this->contextConfig->exists('rsync.exclude')) { - $excludeList = $this->contextConfig->get('rsync.exclude'); - } - - $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); + $command = $this->createRsyncCommandWithConfiguration($source, $target, 'rsync'); $command->executeInteractive(); } diff --git a/src/app/CliTools/Console/Command/Sync/ServerCommand.php b/src/app/CliTools/Console/Command/Sync/ServerCommand.php index f416787..27a0988 100644 --- a/src/app/CliTools/Console/Command/Sync/ServerCommand.php +++ b/src/app/CliTools/Console/Command/Sync/ServerCommand.php @@ -120,18 +120,7 @@ protected function runTaskRsync() { $source = $this->getRsyncPathFromConfig(); $target = $this->getRsyncWorkingPath(); - $fileList = array(); - if ($this->contextConfig->exists('rsync.directory')) { - $fileList = $this->contextConfig->get('rsync.directory'); - } - - $excludeList = array(); - if ($this->contextConfig->exists('rsync.exclude')) { - $excludeList = $this->contextConfig->get('rsync.exclude'); - } - - $command = $this->createRsyncCommand($source, $target, $fileList, $excludeList); - + $command = $this->createRsyncCommandWithConfiguration($source, $target, 'rsync'); $command->executeInteractive(); } From e6db382d240b3e8681fc4986ea73d1b418108efc Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 20:46:00 +0200 Subject: [PATCH 200/214] Added /src/conf directory --- src/conf/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/conf/.gitkeep diff --git a/src/conf/.gitkeep b/src/conf/.gitkeep new file mode 100644 index 0000000..e69de29 From d846e9328e3efe7a94deb984b15f04b36bb47251 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 20:46:11 +0200 Subject: [PATCH 201/214] Updated to Symfony 2.7.1 --- src/composer.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/composer.lock b/src/composer.lock index 725f601..6487db0 100644 --- a/src/composer.lock +++ b/src/composer.lock @@ -48,16 +48,16 @@ }, { "name": "symfony/console", - "version": "v2.7.0", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "7f0bec04961c61c961df0cb8c2ae88dbfd83f399" + "reference": "564398bc1f33faf92fc2ec86859983d30eb81806" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/7f0bec04961c61c961df0cb8c2ae88dbfd83f399", - "reference": "7f0bec04961c61c961df0cb8c2ae88dbfd83f399", + "url": "https://api.github.com/repos/symfony/Console/zipball/564398bc1f33faf92fc2ec86859983d30eb81806", + "reference": "564398bc1f33faf92fc2ec86859983d30eb81806", "shasum": "" }, "require": { @@ -101,20 +101,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-05-29 16:22:24" + "time": "2015-06-10 15:30:22" }, { "name": "symfony/yaml", - "version": "v2.7.0", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "4a29a5248aed4fb45f626a7bbbd330291492f5c3" + "reference": "9808e75c609a14f6db02f70fccf4ca4aab53c160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/4a29a5248aed4fb45f626a7bbbd330291492f5c3", - "reference": "4a29a5248aed4fb45f626a7bbbd330291492f5c3", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/9808e75c609a14f6db02f70fccf4ca4aab53c160", + "reference": "9808e75c609a14f6db02f70fccf4ca4aab53c160", "shasum": "" }, "require": { @@ -150,7 +150,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:21:08" + "time": "2015-06-10 15:30:22" } ], "packages-dev": [], From 6c146b48c187719e68e7e2212428326b8790befe Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 20:46:23 +0200 Subject: [PATCH 202/214] Updated clisync.yml conf --- Documentation/Examples/clisync.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 3b76748..08bd779 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -141,6 +141,10 @@ sync: # server and source directory (server host or name - see .ssh/config) path: "live-server:/var/www/website/htdocs" + #conf: + # maxSize: 20M + # minSize: 10kb + mysql: username: typo3 password: loremipsum From e406da3acced8bf2eaf7b89f0950285f8db1e98e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 20:50:58 +0200 Subject: [PATCH 203/214] Refactored sync:init --- .gitignore | 1 + CHANGELOG.md | 2 +- compile.sh | 5 + .../Console/Command/Sync/InitCommand.php | 124 +----------------- 4 files changed, 10 insertions(+), 122 deletions(-) diff --git a/.gitignore b/.gitignore index d400d6e..262d491 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.phar *.bak src/vendor/* +src/conf/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 748bd7b..aa52c58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ CliTools Changelog - Added `vagrant:share` with automatic domain setting for TYPO3 projects (ALPHA! not finished!) - TTY banner now will be reloaded (SIGHUB is send to getty tty1) - Added docker detection for sync features -- Updated to Symfony 2.7 +- Updated to Symfony 2.7.1 - Refactored some classes - Fixed some issues - Added gzip compression for PHAR diff --git a/compile.sh b/compile.sh index 42c5c64..d1a67b2 100755 --- a/compile.sh +++ b/compile.sh @@ -9,10 +9,15 @@ SCRIPT_DIR=$(dirname $(readlink -f "$0")) OLD_PWD=`pwd` +## copy configs +cp "$SCRIPT_DIR/Documentation/Examples/clisync.yml" "$SCRIPT_DIR/src/conf/" + +## run composer cd "$SCRIPT_DIR/src" composer install --no-dev composer dump-autoload --optimize --no-dev +## create phar cd "$SCRIPT_DIR/" box.phar build -c box.json diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 70ba1b7..1bb04d7 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -53,128 +53,10 @@ public function execute(InputInterface $input, OutputInterface $output) { return 1; } - $content = '# Example clisync configuration file - -####################################### -# Sync from server (eg. live server) -####################################### -sync: - - ################## - # Global config - ################## - _: - mysql: - # MySQL predefined filter for typo3 (eg. no caching tables) - filter: typo3 - - # MySQL custom filter (preg_match) - #filter: - # - "/^cachingframework_.*/i" - # - "/^cf_.*/i" - # - "/^cache_.*/i" - # - "/^index_.*/i" - # - "/^sys_log$/i" - # - "/^sys_history$/i" - # - "/^tx_extbase_cache.*/i" - - # Transfer compression (none if empty, bzip2 or gzip) - compression: bzip2 - - # specific mysqldump settings - mysqldump: - option: "--opt --single-transaction" - - rsync: - # set target as sub directroy (will be appended to working directory) - #target: "html/" - - # directory list/patterns for synchronization - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - - # directory exclude list/patterns - exclude: - - "/fileadmin/_processed_/**" - - ################## - # Config "production" - ################## - production: - # ssh server host or name (see .ssh/config, eg for mysql/mysqldump) - ssh: - hostname: live-server - - # rsync for some directories - rsync: - # server and source directory (server host or name - see .ssh/config) - path: "live-server:/var/www/website/htdocs" - - mysql: - # mysql connection - hostname: localhost - username: typo3 - password: loremipsum - - # List of databases for sync ("local:foreign" for different database names - or only "database" if same name should be used localy) - database: - - typo3:website_live - - other_database - -####################################### -# Deployment to server -####################################### - -deploy: - - -####################################### -# Shared server (sharing between developers) -####################################### -share: - - rsync: - # source/target directory or server via ssh (eg. backup-server:/backup/projectname) - path: "/tmp/foo/" - # set target as sub directroy (will be appended to working directory - #target: "html/" - - # List of directories for backup - directory: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - - # List of excludes (eg. specific files) - exclude: - # no avi files - - "/example/**/*.avi" - # no mp4 files - - "/example/**/*.mp4" - - mysql: - # MySQL filter for typo3 (eg. no caching tables) - filter: typo3 - - # List of databases for backup - database: - - typo3 - -####################################### -# Task configuration -####################################### -task: - - # These commands will be executed after backup, restore and sync - finalize: - # create user "dev" with password "dev" - - "ct typo3:beuser" - # append toplevel-domain .vm to all domains - - "ct typo3:domain" -'; + // fetch example + $content = PhpUtility::fileGetContents(CLITOOLS_ROOT_FS . '/conf/clisync.yml'); + // store in current working dir PhpUtility::filePutContents($cliSyncFilePath, $content); // Start editor with file (if $EDITOR is set) From db26d3daffe78c258991bcc2bd4a887ae450b5c8 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 21:46:38 +0200 Subject: [PATCH 204/214] Moved Shell classes out of console --- src/app/CliTools/Console/Command/AbstractCommand.php | 4 ++-- .../CliTools/Console/Command/AbstractTraceCommand.php | 2 +- .../CliTools/Console/Command/Apache/RestartCommand.php | 2 +- .../CliTools/Console/Command/Common/MakeCommand.php | 2 +- .../Console/Command/Docker/AbstractCommand.php | 4 ++-- src/app/CliTools/Console/Command/Docker/CliCommand.php | 2 +- .../CliTools/Console/Command/Docker/ComposeCommand.php | 2 +- .../CliTools/Console/Command/Docker/CreateCommand.php | 6 +++--- .../CliTools/Console/Command/Docker/ExecCommand.php | 2 +- .../CliTools/Console/Command/Docker/IftopCommand.php | 2 +- .../CliTools/Console/Command/Docker/MysqlCommand.php | 2 +- .../CliTools/Console/Command/Docker/RootCommand.php | 2 +- .../CliTools/Console/Command/Docker/ShellCommand.php | 2 +- .../CliTools/Console/Command/Docker/SniffCommand.php | 2 +- src/app/CliTools/Console/Command/Docker/UpCommand.php | 2 +- .../CliTools/Console/Command/Mysql/BackupCommand.php | 6 +++--- .../CliTools/Console/Command/Mysql/RestartCommand.php | 2 +- .../CliTools/Console/Command/Mysql/RestoreCommand.php | 2 +- .../CliTools/Console/Command/Php/ComposerCommand.php | 2 +- .../CliTools/Console/Command/Php/RestartCommand.php | 2 +- .../CliTools/Console/Command/Samba/RestartCommand.php | 2 +- .../CliTools/Console/Command/Sync/AbstractCommand.php | 10 +++++----- .../CliTools/Console/Command/Sync/BackupCommand.php | 2 +- src/app/CliTools/Console/Command/Sync/InitCommand.php | 2 +- .../Console/Command/System/CrontaskCommand.php | 2 +- .../Console/Command/System/OpenFilesCommand.php | 2 +- .../CliTools/Console/Command/System/RebootCommand.php | 2 +- .../Console/Command/System/ShutdownCommand.php | 2 +- .../CliTools/Console/Command/System/StartupCommand.php | 4 ++-- .../CliTools/Console/Command/System/UpdateCommand.php | 6 +++--- .../CliTools/Console/Command/System/VersionCommand.php | 2 +- .../Console/Command/TYPO3/ClearCacheCommand.php | 2 +- .../Console/Command/TYPO3/SchedulerCommand.php | 2 +- .../CliTools/Console/Command/Vagrant/ShareCommand.php | 4 ++-- .../CliTools/Exception/CommandExecutionException.php | 2 +- src/app/CliTools/Service/SelfUpdateService.php | 2 +- .../Shell/CommandBuilder/AbstractCommandBuilder.php | 2 +- .../Shell/CommandBuilder/CommandBuilder.php | 2 +- .../Shell/CommandBuilder/CommandBuilderInterface.php | 2 +- .../Shell/CommandBuilder/EditorCommandBuilder.php | 2 +- .../Shell/CommandBuilder/FullSelfCommandBuilder.php | 2 +- .../CommandBuilder/OutputCombineCommandBuilder.php | 2 +- .../Shell/CommandBuilder/RemoteCommandBuilder.php | 2 +- .../Shell/CommandBuilder/SelfCommandBuilder.php | 2 +- src/app/CliTools/{Console => }/Shell/Executor.php | 2 +- src/app/CliTools/Utility/DockerUtility.php | 2 +- src/app/CliTools/Utility/UnixUtility.php | 2 +- 47 files changed, 61 insertions(+), 61 deletions(-) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/AbstractCommandBuilder.php (99%) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/CommandBuilder.php (94%) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/CommandBuilderInterface.php (99%) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/EditorCommandBuilder.php (95%) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/FullSelfCommandBuilder.php (96%) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/OutputCombineCommandBuilder.php (98%) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/RemoteCommandBuilder.php (94%) rename src/app/CliTools/{Console => }/Shell/CommandBuilder/SelfCommandBuilder.php (96%) rename src/app/CliTools/{Console => }/Shell/Executor.php (99%) diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index 568e624..c06953a 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -24,8 +24,8 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\FullSelfCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\FullSelfCommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; abstract class AbstractCommand extends Command { diff --git a/src/app/CliTools/Console/Command/AbstractTraceCommand.php b/src/app/CliTools/Console/Command/AbstractTraceCommand.php index eb79f6c..13162f4 100644 --- a/src/app/CliTools/Console/Command/AbstractTraceCommand.php +++ b/src/app/CliTools/Console/Command/AbstractTraceCommand.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/app/CliTools/Console/Command/Apache/RestartCommand.php b/src/app/CliTools/Console/Command/Apache/RestartCommand.php index 64fe214..4dd389c 100644 --- a/src/app/CliTools/Console/Command/Apache/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Apache/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Common/MakeCommand.php b/src/app/CliTools/Console/Command/Common/MakeCommand.php index 9a11e8f..c21c5fd 100644 --- a/src/app/CliTools/Console/Command/Common/MakeCommand.php +++ b/src/app/CliTools/Console/Command/Common/MakeCommand.php @@ -22,7 +22,7 @@ use CliTools\Utility\UnixUtility; use CliTools\Utility\PhpUtility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php index 594269b..1cf5d23 100644 --- a/src/app/CliTools/Console/Command/Docker/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Docker/AbstractCommand.php @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; +use CliTools\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilderInterface; use CliTools\Utility\PhpUtility; abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/CliCommand.php b/src/app/CliTools/Console/Command/Docker/CliCommand.php index 03e5561..38f1844 100644 --- a/src/app/CliTools/Console/Command/Docker/CliCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CliCommand.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Shell\CommandBuilder\RemoteCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php index 73ef5bb..9d1d716 100644 --- a/src/app/CliTools/Console/Command/Docker/ComposeCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ComposeCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class ComposeCommand extends AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { diff --git a/src/app/CliTools/Console/Command/Docker/CreateCommand.php b/src/app/CliTools/Console/Command/Docker/CreateCommand.php index 946473b..0dc5757 100644 --- a/src/app/CliTools/Console/Command/Docker/CreateCommand.php +++ b/src/app/CliTools/Console/Command/Docker/CreateCommand.php @@ -21,9 +21,9 @@ */ use CliTools\Utility\PhpUtility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\EditorCommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Shell\CommandBuilder\EditorCommandBuilder; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/app/CliTools/Console/Command/Docker/ExecCommand.php b/src/app/CliTools/Console/Command/Docker/ExecCommand.php index 1a8f684..8f5629a 100644 --- a/src/app/CliTools/Console/Command/Docker/ExecCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ExecCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Shell\CommandBuilder\RemoteCommandBuilder; class ExecCommand extends AbstractCommand implements \CliTools\Console\Filter\AnyParameterFilterInterface { diff --git a/src/app/CliTools/Console/Command/Docker/IftopCommand.php b/src/app/CliTools/Console/Command/Docker/IftopCommand.php index 29c1ab6..6c9da42 100644 --- a/src/app/CliTools/Console/Command/Docker/IftopCommand.php +++ b/src/app/CliTools/Console/Command/Docker/IftopCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class IftopCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/MysqlCommand.php b/src/app/CliTools/Console/Command/Docker/MysqlCommand.php index 408fbf4..85fe6e0 100644 --- a/src/app/CliTools/Console/Command/Docker/MysqlCommand.php +++ b/src/app/CliTools/Console/Command/Docker/MysqlCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Shell\CommandBuilder\RemoteCommandBuilder; class MysqlCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/RootCommand.php b/src/app/CliTools/Console/Command/Docker/RootCommand.php index b2a1972..35571a5 100644 --- a/src/app/CliTools/Console/Command/Docker/RootCommand.php +++ b/src/app/CliTools/Console/Command/Docker/RootCommand.php @@ -23,7 +23,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Shell\CommandBuilder\RemoteCommandBuilder; class RootCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/ShellCommand.php b/src/app/CliTools/Console/Command/Docker/ShellCommand.php index be71d40..c9fd65f 100644 --- a/src/app/CliTools/Console/Command/Docker/ShellCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ShellCommand.php @@ -24,7 +24,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Shell\CommandBuilder\RemoteCommandBuilder; class ShellCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/SniffCommand.php b/src/app/CliTools/Console/Command/Docker/SniffCommand.php index 95bd9bc..9f1ac5b 100644 --- a/src/app/CliTools/Console/Command/Docker/SniffCommand.php +++ b/src/app/CliTools/Console/Command/Docker/SniffCommand.php @@ -26,7 +26,7 @@ use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class SniffCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Docker/UpCommand.php b/src/app/CliTools/Console/Command/Docker/UpCommand.php index a19637b..b558adb 100644 --- a/src/app/CliTools/Console/Command/Docker/UpCommand.php +++ b/src/app/CliTools/Console/Command/Docker/UpCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class UpCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php index 5254173..91bae94 100644 --- a/src/app/CliTools/Console/Command/Mysql/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/BackupCommand.php @@ -21,8 +21,8 @@ */ use CliTools\Database\DatabaseConnection; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; +use CliTools\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilderInterface; use CliTools\Utility\FilterUtility; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; @@ -177,7 +177,7 @@ protected function addFilterArguments(CommandBuilderInterface $commandDump, $dat } // Combine both commands to one - $command = new \CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder(); + $command = new \CliTools\Shell\CommandBuilder\OutputCombineCommandBuilder(); $command ->addCommandForCombinedOutput($commandStructure) ->addCommandForCombinedOutput($commandData); diff --git a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php index b3d502a..fa012bc 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php index bd26161..6758226 100644 --- a/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php +++ b/src/app/CliTools/Console/Command/Mysql/RestoreCommand.php @@ -25,7 +25,7 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class RestoreCommand extends AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Php/ComposerCommand.php b/src/app/CliTools/Console/Command/Php/ComposerCommand.php index 772f210..652370f 100644 --- a/src/app/CliTools/Console/Command/Php/ComposerCommand.php +++ b/src/app/CliTools/Console/Command/Php/ComposerCommand.php @@ -22,7 +22,7 @@ use CliTools\Utility\UnixUtility; use CliTools\Utility\PhpUtility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/Php/RestartCommand.php b/src/app/CliTools/Console/Command/Php/RestartCommand.php index 93e0611..86fca58 100644 --- a/src/app/CliTools/Console/Command/Php/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Php/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Samba/RestartCommand.php b/src/app/CliTools/Console/Command/Samba/RestartCommand.php index 059b90e..349be43 100644 --- a/src/app/CliTools/Console/Command/Samba/RestartCommand.php +++ b/src/app/CliTools/Console/Command/Samba/RestartCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class RestartCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php index 123d9cb..8d07784 100644 --- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php @@ -24,11 +24,11 @@ use CliTools\Utility\UnixUtility; use CliTools\Utility\ConsoleUtility; use CliTools\Utility\FilterUtility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\RemoteCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; -use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\RemoteCommandBuilder; +use CliTools\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilderInterface; +use CliTools\Shell\CommandBuilder\OutputCombineCommandBuilder; use CliTools\Reader\ConfigReader; use CliTools\Database\DatabaseConnection; use Symfony\Component\Console\Input\InputOption; diff --git a/src/app/CliTools/Console/Command/Sync/BackupCommand.php b/src/app/CliTools/Console/Command/Sync/BackupCommand.php index b53349e..5c261a2 100644 --- a/src/app/CliTools/Console/Command/Sync/BackupCommand.php +++ b/src/app/CliTools/Console/Command/Sync/BackupCommand.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\OutputCombineCommandBuilder; +use CliTools\Shell\CommandBuilder\OutputCombineCommandBuilder; class BackupCommand extends AbstractShareCommand { diff --git a/src/app/CliTools/Console/Command/Sync/InitCommand.php b/src/app/CliTools/Console/Command/Sync/InitCommand.php index 1bb04d7..31cbf99 100644 --- a/src/app/CliTools/Console/Command/Sync/InitCommand.php +++ b/src/app/CliTools/Console/Command/Sync/InitCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\PhpUtility; -use CliTools\Console\Shell\CommandBuilder\EditorCommandBuilder; +use CliTools\Shell\CommandBuilder\EditorCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/System/CrontaskCommand.php b/src/app/CliTools/Console/Command/System/CrontaskCommand.php index 72ff0b9..df3671c 100644 --- a/src/app/CliTools/Console/Command/System/CrontaskCommand.php +++ b/src/app/CliTools/Console/Command/System/CrontaskCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\UnixUtility; -use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/System/OpenFilesCommand.php b/src/app/CliTools/Console/Command/System/OpenFilesCommand.php index 6af3ef0..5979602 100644 --- a/src/app/CliTools/Console/Command/System/OpenFilesCommand.php +++ b/src/app/CliTools/Console/Command/System/OpenFilesCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\FormatUtility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/app/CliTools/Console/Command/System/RebootCommand.php b/src/app/CliTools/Console/Command/System/RebootCommand.php index 5a1c692..36bbc0c 100644 --- a/src/app/CliTools/Console/Command/System/RebootCommand.php +++ b/src/app/CliTools/Console/Command/System/RebootCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class RebootCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/System/ShutdownCommand.php b/src/app/CliTools/Console/Command/System/ShutdownCommand.php index 3eabf33..317ca11 100644 --- a/src/app/CliTools/Console/Command/System/ShutdownCommand.php +++ b/src/app/CliTools/Console/Command/System/ShutdownCommand.php @@ -22,7 +22,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; class ShutdownCommand extends \CliTools\Console\Command\AbstractCommand { diff --git a/src/app/CliTools/Console/Command/System/StartupCommand.php b/src/app/CliTools/Console/Command/System/StartupCommand.php index 539a291..f6dcaaa 100644 --- a/src/app/CliTools/Console/Command/System/StartupCommand.php +++ b/src/app/CliTools/Console/Command/System/StartupCommand.php @@ -22,8 +22,8 @@ use CliTools\Utility\UnixUtility; use CliTools\Database\DatabaseConnection; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/System/UpdateCommand.php b/src/app/CliTools/Console/Command/System/UpdateCommand.php index 04a683a..c39bcb3 100644 --- a/src/app/CliTools/Console/Command/System/UpdateCommand.php +++ b/src/app/CliTools/Console/Command/System/UpdateCommand.php @@ -21,8 +21,8 @@ */ use CliTools\Service\SelfUpdateService; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -87,7 +87,7 @@ protected function userUpdate(InputInterface $input, OutputInterface $output) { $command = new CommandBuilder('git', 'pull'); $command->executeInteractive(); - $command = new \CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder(); + $command = new \CliTools\Shell\CommandBuilder\SelfCommandBuilder(); $command->addArgument('user:rebuildsshconfig'); $command->executeInteractive(); } catch (\RuntimeException $e) { diff --git a/src/app/CliTools/Console/Command/System/VersionCommand.php b/src/app/CliTools/Console/Command/System/VersionCommand.php index d795501..c0205b4 100644 --- a/src/app/CliTools/Console/Command/System/VersionCommand.php +++ b/src/app/CliTools/Console/Command/System/VersionCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Database\DatabaseConnection; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use CliTools\Utility\UnixUtility; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php index acc33d2..f5c161c 100644 --- a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\Typo3Utility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php b/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php index f4e7277..83f5d66 100644 --- a/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php +++ b/src/app/CliTools/Console/Command/TYPO3/SchedulerCommand.php @@ -21,7 +21,7 @@ */ use CliTools\Utility\Typo3Utility; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php index 5cc1287..2c97fa3 100644 --- a/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php +++ b/src/app/CliTools/Console/Command/Vagrant/ShareCommand.php @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; -use CliTools\Console\Shell\CommandBuilder\SelfCommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\SelfCommandBuilder; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; diff --git a/src/app/CliTools/Exception/CommandExecutionException.php b/src/app/CliTools/Exception/CommandExecutionException.php index 6fb1c04..9fa52d5 100644 --- a/src/app/CliTools/Exception/CommandExecutionException.php +++ b/src/app/CliTools/Exception/CommandExecutionException.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilderInterface; +use CliTools\Shell\CommandBuilder\CommandBuilderInterface; class CommandExecutionException extends \RuntimeException { diff --git a/src/app/CliTools/Service/SelfUpdateService.php b/src/app/CliTools/Service/SelfUpdateService.php index 9e360aa..89a34c4 100644 --- a/src/app/CliTools/Service/SelfUpdateService.php +++ b/src/app/CliTools/Service/SelfUpdateService.php @@ -2,7 +2,7 @@ namespace CliTools\Service; -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; /* * CliTools Command diff --git a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php b/src/app/CliTools/Shell/CommandBuilder/AbstractCommandBuilder.php similarity index 99% rename from src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php rename to src/app/CliTools/Shell/CommandBuilder/AbstractCommandBuilder.php index 2de9474..45781b9 100644 --- a/src/app/CliTools/Console/Shell/CommandBuilder/AbstractCommandBuilder.php +++ b/src/app/CliTools/Shell/CommandBuilder/AbstractCommandBuilder.php @@ -1,6 +1,6 @@ . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; use CliTools\Console\Shell\Executor; class DockerUtility { diff --git a/src/app/CliTools/Utility/UnixUtility.php b/src/app/CliTools/Utility/UnixUtility.php index d39baec..135f059 100644 --- a/src/app/CliTools/Utility/UnixUtility.php +++ b/src/app/CliTools/Utility/UnixUtility.php @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -use CliTools\Console\Shell\CommandBuilder\CommandBuilder; +use CliTools\Shell\CommandBuilder\CommandBuilder; abstract class UnixUtility { From e4188bb9aa612876d036edb7cc943f72c477f95a Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 21:52:57 +0200 Subject: [PATCH 205/214] Updated credits --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 11b9d2d..2e3dbb4 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ CliTools is based on Symfony Components (Console). Thanks for support, ideas and issues ... - [Ingo Pfennigstorf](https://twitter.com/krautsock) - [Florian Tatzel](https://twitter.com/PanadeEdu) +- [Philipp Kitzberger](https://github.com/Kitzberger) - my (old) colleagues at [Lightwerk GmbH](http://www.lightwerk.de/) - my colleagues at [cron IT GmbH](http://www.cron.eu/) From 7251aa3da236d76bd4baf5836a330c4426ac3fea Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 21:53:17 +0200 Subject: [PATCH 206/214] Version bump to 1.9.911 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index 6dd9ff0..5d2e519 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.910'); +define('CLITOOLS_COMMAND_VERSION', '1.9.911'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From 099742dd49116149d4ac015c245454d37c0d44a5 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 21:56:04 +0200 Subject: [PATCH 207/214] Added aliases --- Documentation/Examples/ALIASES.md | 33 +++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 34 insertions(+) create mode 100644 Documentation/Examples/ALIASES.md diff --git a/Documentation/Examples/ALIASES.md b/Documentation/Examples/ALIASES.md new file mode 100644 index 0000000..c7b6c9b --- /dev/null +++ b/Documentation/Examples/ALIASES.md @@ -0,0 +1,33 @@ +[<-- Back to main section](../README.md) + +## Shell aliases + +```bash +# Shortcut for docker-compose (autosearch docker-compose.yml in up-dir, you don't have to be in directory with docker-compose.yml) +alias dcc='ct docker:compose' + +# Startup docker-container (and shutdown previous one, v1.9.0 and up) +alias dccup='ct docker:up' +alias dccstop='ct docker:compose stop' + +# Enter main docker container (as CLI_USER if available - if not specified then root is used) +alias dcshell='ct docker:shell' +alias dcsh='ct docker:shell' + +# Enter main docker container (as root) +alias dcroot='ct docker:root' + +# Execute predefined cli in docker container +alias dccrun='ct docker:cli' + +# Run command +alias dcexec='ct docker:exec' + +# Execute mysql client in docker container +alias dcsql='ct docker:mysql' +alias dcmysql='ct docker:mysql' + +# General shortcuts (with up-dir tree searching) +alias composer='ct php:composer' +alias make='ct make' +``` diff --git a/README.md b/README.md index 2e3dbb4..be5e5a6 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ CliTools is based on Symfony Components (Console). - [Usage `ct typo3:...` commands](/Documentation/USAGE-TYPO3.md) - [Usage `ct php:...` commands](/Documentation/USAGE-PHP.md) - [Command overview](/Documentation/COMMANDS.md) +- [Shell aliases](/Documentation/ALIASES.md) ## Credits From af39ad67168787d7b33520130a2bd321ede8aee2 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 21:56:58 +0200 Subject: [PATCH 208/214] Moved aliases to right directory --- Documentation/{Examples => }/ALIASES.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/{Examples => }/ALIASES.md (100%) diff --git a/Documentation/Examples/ALIASES.md b/Documentation/ALIASES.md similarity index 100% rename from Documentation/Examples/ALIASES.md rename to Documentation/ALIASES.md From 3d67b9432a4f3a5803d4cb12c943f4c0079fd66c Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 22:23:07 +0200 Subject: [PATCH 209/214] Cleanup --- .../Console/Command/Docker/SniffCommand.php | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/app/CliTools/Console/Command/Docker/SniffCommand.php b/src/app/CliTools/Console/Command/Docker/SniffCommand.php index 9f1ac5b..87708ac 100644 --- a/src/app/CliTools/Console/Command/Docker/SniffCommand.php +++ b/src/app/CliTools/Console/Command/Docker/SniffCommand.php @@ -41,18 +41,6 @@ protected function configure() { 'protocol', InputArgument::OPTIONAL, 'Protocol' - ) - ->addOption( - 'full', - null, - InputOption::VALUE_NONE, - 'Show full output (if supported by protocol)' - ) - ->addOption( - 'filter', - null, - InputOption::VALUE_NONE, - 'Additonal filter' ); } @@ -72,7 +60,6 @@ public function execute(InputInterface $input, OutputInterface $output) { $output->writeln('

Starting network sniffing

'); $protocol = $this->getProtocol(); - $fullOutput = $input->getOption('full'); $command = new CommandBuilder(); @@ -127,12 +114,16 @@ public function execute(InputInterface $input, OutputInterface $output) { case 'http': $output->writeln('

Using protocol "http"

'); $command->setCommand('tshark'); + $command->addArgumentRaw('tcp port 80 or tcp port 443 -2 -V -R "http.request" -Tfields -e ip.dst -e http.request.method -e http.request.full_uri'); + break; - if ($fullOutput) { - $command->addArgumentRaw('tcp port 80 or tcp port 443 -2 -V -R "http.request || http.response"'); - } else { - $command->addArgumentRaw('tcp port 80 or tcp port 443 -2 -V -R "http.request" -Tfields -e ip.dst -e http.request.method -e http.request.full_uri'); - } + // ############## + // HTTP (full) + // ############## + case 'http-full': + $output->writeln('

Using protocol "http" (full mode)

'); + $command->setCommand('tshark'); + $command->addArgumentRaw('tcp port 80 or tcp port 443 -2 -V -R "http.request || http.response"'); break; // ############## @@ -234,6 +225,8 @@ public function execute(InputInterface $input, OutputInterface $output) { break; } + $this->setTerminalTitle('sniffer', $protocol, '(' . $command->getCommand() .')'); + $command->executeInteractive(); return 0; @@ -250,7 +243,8 @@ protected function getProtocol() { if(!$this->input->getArgument('protocol')) { $protocolList = array( - 'http' => 'HTTP', + 'http' => 'HTTP (requests only)', + 'http-full' => 'HTTP (full)', 'solr' => 'Solr', 'elasticsearch' => 'Elasticsearch', 'memcache' => 'Memcache', From 21a383025a660b6da686dd27ed9ae0f685e561ae Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 22:23:26 +0200 Subject: [PATCH 210/214] Added terminal titles Fixed #45 --- src/app/CliTools/Console/Command/AbstractCommand.php | 3 +++ src/app/CliTools/Console/Command/Docker/ExecCommand.php | 1 + src/app/CliTools/Console/Command/Docker/RootCommand.php | 2 ++ src/app/CliTools/Console/Command/Docker/ShellCommand.php | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/app/CliTools/Console/Command/AbstractCommand.php b/src/app/CliTools/Console/Command/AbstractCommand.php index c06953a..99873e2 100644 --- a/src/app/CliTools/Console/Command/AbstractCommand.php +++ b/src/app/CliTools/Console/Command/AbstractCommand.php @@ -64,6 +64,9 @@ protected function initialize(InputInterface $input, OutputInterface $output) { $this->output = $output; ConsoleUtility::initialize($input, $output); + + // Set default terminal title + $this->setTerminalTitle(explode(':', $this->getName())); } /** diff --git a/src/app/CliTools/Console/Command/Docker/ExecCommand.php b/src/app/CliTools/Console/Command/Docker/ExecCommand.php index 8f5629a..19a7a1f 100644 --- a/src/app/CliTools/Console/Command/Docker/ExecCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ExecCommand.php @@ -47,6 +47,7 @@ public function execute(InputInterface $input, OutputInterface $output) { $paramList = $this->getFullParameterList(); $container = $this->getApplication()->getConfigValue('docker', 'container'); + if (!empty($paramList)) { $firstParam = array_shift($paramList); diff --git a/src/app/CliTools/Console/Command/Docker/RootCommand.php b/src/app/CliTools/Console/Command/Docker/RootCommand.php index 35571a5..de8fdf8 100644 --- a/src/app/CliTools/Console/Command/Docker/RootCommand.php +++ b/src/app/CliTools/Console/Command/Docker/RootCommand.php @@ -56,6 +56,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $container = $input->getArgument('container'); } + $this->setTerminalTitle('docker', 'root', $container); + $command = new RemoteCommandBuilder('bash'); $ret = $this->executeDockerExec($container, $command); diff --git a/src/app/CliTools/Console/Command/Docker/ShellCommand.php b/src/app/CliTools/Console/Command/Docker/ShellCommand.php index c9fd65f..575285c 100644 --- a/src/app/CliTools/Console/Command/Docker/ShellCommand.php +++ b/src/app/CliTools/Console/Command/Docker/ShellCommand.php @@ -71,6 +71,8 @@ public function execute(InputInterface $input, OutputInterface $output) { $cliUser = $this->getDockerEnv($container, 'CLI_USER'); } + $this->setTerminalTitle('docker', 'shell', $container); + $command = new RemoteCommandBuilder('bash'); if (!empty($cliUser)) { From 49c2cb79d978bc15779ab77eb756c2baa34c7f64 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 22:39:31 +0200 Subject: [PATCH 211/214] Version bump 1.9.912 --- src/command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.php b/src/command.php index 5d2e519..8effbbe 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.911'); +define('CLITOOLS_COMMAND_VERSION', '1.9.912'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php'; From 8443429fac98ab2003d943ee80a693ea1ac98e66 Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Mon, 15 Jun 2015 23:23:23 +0200 Subject: [PATCH 212/214] Cleanup --- src/app/CliTools/Console/Command/Docker/SniffCommand.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/CliTools/Console/Command/Docker/SniffCommand.php b/src/app/CliTools/Console/Command/Docker/SniffCommand.php index 87708ac..81129c4 100644 --- a/src/app/CliTools/Console/Command/Docker/SniffCommand.php +++ b/src/app/CliTools/Console/Command/Docker/SniffCommand.php @@ -21,7 +21,6 @@ */ use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Question\ChoiceQuestion; From 5244e959f7b28b53fa481b1df7f1bb683e5bfe8e Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 16 Jun 2015 20:22:51 +0200 Subject: [PATCH 213/214] Fixed wrong exclude in clisync.yml --- Documentation/Examples/clisync.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/Examples/clisync.yml b/Documentation/Examples/clisync.yml index 08bd779..59af1c1 100644 --- a/Documentation/Examples/clisync.yml +++ b/Documentation/Examples/clisync.yml @@ -219,12 +219,6 @@ share: - "/uploads/" - "/typo3conf/l10n/" - # directory exclude list/patterns - exclude: - - "/fileadmin/" - - "/uploads/" - - "/typo3conf/l10n/" - ################## # Context "development" ################## From ba647be3525900c8673e3aa7bee13a196862510d Mon Sep 17 00:00:00 2001 From: Markus Blaschke Date: Tue, 16 Jun 2015 20:33:04 +0200 Subject: [PATCH 214/214] Version bump 2.0.0 --- CHANGELOG.md | 12 +++++++++++- README.md | 4 ++-- src/command.php | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa52c58..9f9ab1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ CliTools Changelog ================== -1.10.0 - Upcoming +2.0.0 - 2015-06-16 ------------------ - Added GitHub based `self-update` - Added `make` (auto search for Makefile in tree) @@ -22,6 +22,7 @@ CliTools Changelog - Refactored some classes - Fixed some issues - Added gzip compression for PHAR +- SLOC: 5,999 1.9.0 - 2015-05-06 ------------------ @@ -34,6 +35,7 @@ CliTools Changelog - Refactored shell command execution (again) - Fixed code styling - Improved code and fixed some smaller bugs +- SLOC: 4,038 1.8.0 - 2015-04-26 ------------------ @@ -49,36 +51,44 @@ CliTools Changelog - Implemented command check - Improved disk usage warning (wall and growl, will trigger when usage is >=90 in local and remote mounts) - Refactored shell command execution +- SLOC: 3,562 1.7.4 - 2015-04-21 ------------------ - Improved `docker:tshark` +- SLOC: 2,787 1.7.3 - 2015-04-21 ------------------ - Fixed `docker:tshark` +- SLOC: 2,780 1.7.2 - 2015-04-21 ------------------ - Added required php modules checks - Added interactive error return code check +- SLOC: 2,777 1.7.0 - 2015-04-19 ------------------ - Added `docker:tshark`, easy network sniffing - Added `php:trace --all`, for immediate tracing all php processes - Fixed bugs +- SLOC: 2,755 1.6.3 - 2015-04-16 ------------------ - Added `docker:tshark`, easy network sniffing - Added `php:trace --all`, for immediate tracing all php processes - Fixed bugs +- SLOC: 2,832 1.6.2 - 2015-04-15 ------------------ - Fixed bugs +- SLOC: 2,811 1.5.1 - 2015-03-29 ------------------ - Added growl support +- SLOC: 2,773 diff --git a/README.md b/README.md index be5e5a6..2258f8b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # CliTools for Docker, PHP und MySQL development -![latest v1.9.0](https://img.shields.io/badge/latest-v1.9.0-green.svg?style=flat) -![License GPL3](https://img.shields.io/badge/license-GPL3-blue.svg?style=flat) +[![latest v2.0.0](https://img.shields.io/badge/latest-v2.0.0-green.svg?style=flat)](https://github.com/mblaschke/clitools/releases/tag/2.0.0) +[![License GPL3](https://img.shields.io/badge/license-GPL3-blue.svg?style=flat)](/LICENSE) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/mblaschke/clitools.svg)](http://isitmaintained.com/project/mblaschke/clitools "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/mblaschke/clitools.svg)](http://isitmaintained.com/project/mblaschke/clitools "Percentage of issues still open") diff --git a/src/command.php b/src/command.php index 8effbbe..9e191f4 100644 --- a/src/command.php +++ b/src/command.php @@ -20,7 +20,7 @@ */ error_reporting(E_ALL); -define('CLITOOLS_COMMAND_VERSION', '1.9.912'); +define('CLITOOLS_COMMAND_VERSION', '2.0.0'); define('CLITOOLS_ROOT_FS', __DIR__); require __DIR__ . '/vendor/autoload.php';