diff --git a/.idea/php.xml b/.idea/php.xml index 3cce9ae..ecc1ca2 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -22,6 +22,8 @@ + + diff --git a/.idea/symfony2.xml b/.idea/symfony2.xml new file mode 100644 index 0000000..632dba4 --- /dev/null +++ b/.idea/symfony2.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/syncit.iml b/.idea/syncit.iml index eaa5603..bce892f 100644 --- a/.idea/syncit.iml +++ b/.idea/syncit.iml @@ -19,10 +19,12 @@ + + diff --git a/composer.json b/composer.json index b8a840f..05371d5 100644 --- a/composer.json +++ b/composer.json @@ -11,13 +11,13 @@ ], "require": { "ramsey/uuid": "~3.9", - "somnambulist/domain": "^2.0", - "symfony/console": "^4.2", - "symfony/dotenv": "^4.2", - "symfony/finder": "^4.2", - "symfony/process": "^4.2", - "symfony/var-dumper": "^4.2", - "symfony/yaml": "^4.2" + "somnambulist/domain": "^2.5", + "symfony/console": "^4.4", + "symfony/dotenv": "^4.4", + "symfony/finder": "^4.4", + "symfony/process": "^4.4", + "symfony/var-dumper": "^4.4", + "symfony/yaml": "^4.4" }, "require-dev": { }, diff --git a/readme.md b/readme.md index 5b62672..db79582 100644 --- a/readme.md +++ b/readme.md @@ -28,6 +28,7 @@ SyncIt has only been tested on macOS Mojave. * phar archive * support for .env files (including overrides) * docker container resolution from a specified name + * groups to start/stop multiple tasks at the same time ## Setup @@ -49,27 +50,6 @@ This is provided as-is without warranty of any kind. Use at your own risk! __Caution:__ mis-configuring a mutagen session can cause serious data-loss! -### Lazy Install - -__Caution:__ you use the following at your own risk! No responsibility is taken -if the script causes bad things to happen. You have been warned. - -The following will download the current (at the time of writing) phar archive, -verify the SHA384 hash and copy the phar to `/usr/local/bin`, then symlink it to -`syncit` and verify it runs by calling `syncit --version`. The script has been -set up with verbose output. - -```bash -curl --silent --fail --location --retry 3 --output /tmp/mutagen-sync-it.phar --url https://github.com/somnambulist-tech/sync-it/releases/download/1.0.0-beta3/mutagen-sync-it.phar \ - && echo "e18ebaf1d7b2166797c33a5149e82d8cb1e810b7c52823615d717b612c6159c3483983992814acd459cd560bf6c7952d /tmp/mutagen-sync-it.phar" | shasum -a 384 -c \ - && mv -v /tmp/mutagen-sync-it.phar /usr/local/bin/mutagen-sync-it.phar \ - && chmod -v 755 /usr/local/bin/mutagen-sync-it.phar \ - && ln -vf -s /usr/local/bin/mutagen-sync-it.phar /usr/local/bin/syncit \ - && syncit --ansi --version --no-interaction -``` - -If the hash check fails, remove the phar archive. - ### Removing SyncIt Remove any symlinks you have and delete the phar file. No other files are created @@ -113,6 +93,9 @@ The above ensures that all syncs are created using `one-way-replica`. This ensures that no changes are written back to the source but the target will be overwritten. +__Note:__ that this will happily override your local in the source is set as a remote +and the target is a local folder. Be very careful! + ## The Config File The config file is split into 2 sections: @@ -144,6 +127,9 @@ mutagen: source_files: source: "${PROJECT_DIR}" target: "docker://container_1/app" + groups: + - group1 + - group2 options: sync-mode: one-way-replica ignore: @@ -214,6 +200,11 @@ This allows the task name to be used consistently regardless of mutagen version. The target supports different transport mechanisms e.g. docker:// ssh:// etc. Be sure to read the format / rules at: https://mutagen.io/documentation/transports/ +Multiple group names can be set on each tasks under the `groups:` entry. This +will allow start/stop to work with all those tasks tagged with that group name. +For example: a web app with a JavaScript build pipeline may have many tasks. These +can now be grouped into app/build making it easier to start/stop in one go. + #### Docker Containers When using docker; to make life easier you should use named containers with diff --git a/src/Commands/BaseCommand.php b/src/Commands/BaseCommand.php index 5a85505..59c2584 100644 --- a/src/Commands/BaseCommand.php +++ b/src/Commands/BaseCommand.php @@ -1,6 +1,4 @@ -getOption('label')) { + if (!$labels = $input->getArgument('label')) { + return []; + } + } + + if (count($labels) === 1) { + $label = trim($labels[0]); + + if ('all' == $label) { + $labels = $tasks->keys()->toArray(); + } elseif (!$tasks->keys()->contains($label)) { + $labels = $tasks + ->filter(function (SyncTask $task) use ($label) { + return $task->getGroups()->contains($label); + }) + ->keys() + ->toArray() + ; + } + } + + return $labels; + } +} diff --git a/src/Commands/Behaviours/ListConfiguredTasks.php b/src/Commands/Behaviours/ListConfiguredTasks.php index 040b2c4..0d77782 100644 --- a/src/Commands/Behaviours/ListConfiguredTasks.php +++ b/src/Commands/Behaviours/ListConfiguredTasks.php @@ -1,6 +1,4 @@ -setName('start') ->setDescription('Starts the configured mutagen sync tasks') - ->addArgument('label', InputArgument::IS_ARRAY|InputArgument::OPTIONAL, 'The labels to stop or all', []) - ->addOption('label', 'l', InputOption::VALUE_IS_ARRAY|InputOption::VALUE_OPTIONAL, 'The task label(s) to start (mutagen >0.9.0)') + ->addArgument('label', InputArgument::IS_ARRAY|InputArgument::OPTIONAL, 'The labels/group to start or all to start all', []) + ->addOption('label', 'l', InputOption::VALUE_IS_ARRAY|InputOption::VALUE_OPTIONAL, 'The task label(s) to start or group name') ->addOption('list', null, InputOption::VALUE_NONE, 'List available tasks') ->setHelp(<<<'HELP' Starts the specified, or all, configured sync tasks as defined in the current @@ -116,21 +116,6 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - private function getLabelsFromInput(InputInterface $input, Collection $tasks): array - { - if (!$labels = $input->getOption('label')) { - if (!$labels = $input->getArgument('label')) { - return []; - } - } - - if (isset($labels[0]) && 'all' === trim($labels[0])) { - $labels = $tasks->keys()->toArray(); - } - - return $labels; - } - private function buildStartCommand(SyncTask $task): Collection { $command = new Collection([ @@ -138,10 +123,7 @@ private function buildStartCommand(SyncTask $task): Collection $task->getSource(), $task->getTarget(), ]); - - if ($this->getMutagen()->hasLabels()) { - $command->add(sprintf('--label="%s"', $task->getLabel())); - } + $command->add(sprintf('--label="%s"', $task->getLabel())); $task->getOptions()->each(function ($value, $key) use ($command) { if (is_null($value) && in_array($key, ['ignore-vcs', 'no-ignore-vcs'])) { diff --git a/src/Commands/StatusCommand.php b/src/Commands/StatusCommand.php index a2b5d71..7bf406b 100644 --- a/src/Commands/StatusCommand.php +++ b/src/Commands/StatusCommand.php @@ -1,6 +1,4 @@ -getMutagen()->getVersion() ) ) - ->setHeaders(['Label', 'Identifier', 'Conn State', 'Sync Status']) + ->setHeaders(['Label', 'Groups', 'Identifier', 'Conn State', 'Sync Status']) ; $tasks->each(function (SyncTask $task) use ($table) { if ($task->isRunning()) { $table->addRow([ $task->getLabel(), + $task->getGroups()->implode(', '), $task->getSession()->getId(), $task->getSession()->getConnectionState(), $task->getSession()->getStatus() ?? '--', @@ -58,6 +57,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } else { $table->addRow([ $task->getLabel(), + $task->getGroups()->implode(', '), '--', '--', 'stopped', diff --git a/src/Commands/StopCommand.php b/src/Commands/StopCommand.php index f7d0081..493b6c0 100644 --- a/src/Commands/StopCommand.php +++ b/src/Commands/StopCommand.php @@ -1,6 +1,4 @@ -setName('stop') ->setDescription('Stops all configured mutagen sync tasks') ->addArgument('label', InputArgument::OPTIONAL|InputArgument::IS_ARRAY, 'The labels to stop or all', []) - ->addOption('label', 'l', InputOption::VALUE_OPTIONAL|InputOption::VALUE_IS_ARRAY, 'The task label(s) to stop', []) + ->addOption('label', 'l', InputOption::VALUE_OPTIONAL|InputOption::VALUE_IS_ARRAY, 'The task label(s) or group to stop', []) ->addOption('list', null, InputOption::VALUE_NONE, 'List available tasks') ->setHelp(<<<'HELP' Stop a specified, or all, sync tasks as defined in the current projects config @@ -79,7 +78,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - $this->getMutagen()->assertDaemonIsRunning($input, $output, false); + $this->getMutagen()->assertDaemonIsRunning($input, $output); $tasks = $this->getMutagen()->getSessions()->map($this->getConfig()->getTasks()); $labels = $this->getLabelsFromInput($input, $tasks); @@ -97,29 +96,6 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - private function getLabelsFromInput(InputInterface $input, Collection $tasks): array - { - if (!$labels = $input->getOption('label')) { - if (!$labels = $input->getArgument('label')) { - return []; - } - } - - if (isset($labels[0]) && 'all' === trim($labels[0])) { - $labels = $tasks->keys()->toArray(); - } - - return $labels; - } - - /** - * @param InputInterface $input - * @param OutputInterface $output - * @param Collection $tasks - * @param array $labels - * - * @return array|int - */ private function promptForLabelsToStop(InputInterface $input, OutputInterface $output, Collection $tasks, array $labels) { $label = strtolower((string)$this->tools()->choose('Which task would you like to stop? ', $tasks->keys()->prepend( 'All & Daemon')->prepend('All')->toArray())); @@ -142,11 +118,6 @@ private function promptForLabelsToStop(InputInterface $input, OutputInterface $o return $labels; } - /** - * @param OutputInterface $output - * @param Collection $tasks - * @param array|string[] $labels - */ private function stopSelectedTasks(OutputInterface $output, Collection $tasks, array $labels): void { $this->tools()->info('Stopping %s sync tasks', count($labels)); @@ -162,21 +133,10 @@ private function stopSelectedTasks(OutputInterface $output, Collection $tasks, a }); } - /** - * @param OutputInterface $output - * @param SyncTask $task - * - * @return bool - */ private function stopTask(OutputInterface $output, SyncTask $task): bool { $command = new Collection(['mutagen', 'sync', 'terminate']); - - if ($this->getMutagen()->hasLabels()) { - $command->add(sprintf('--label-selector=%s', $task->getLabel())); - } else { - $command->add($task->getSession()->getId()); - } + $command->add(sprintf('--label-selector=%s', $task->getLabel())); $proc = $this->runProcessViaHelper($output, $command); diff --git a/src/Commands/ViewCommand.php b/src/Commands/ViewCommand.php index 4bc3994..f29170a 100644 --- a/src/Commands/ViewCommand.php +++ b/src/Commands/ViewCommand.php @@ -1,6 +1,4 @@ -addRow(['Source (alpha)', $task->getSource()]) ->addRow(['Target (beta)', $task->getTarget()]) ->addRow(['Using Common', $task->shouldUseCommon() ? 'Yes' : 'No']) + ->addRow(['Groups', $task->getGroups()->implode(', ')]) ->addRow(['Running', $task->isRunning() ? 'Yes' : 'No']) ->addRow(['Session', $task->getSession() ? $task->getSession()->getId() : '--']) ; diff --git a/src/Models/Config.php b/src/Models/Config.php index 86602e8..8447ab5 100644 --- a/src/Models/Config.php +++ b/src/Models/Config.php @@ -1,6 +1,4 @@ -common = $common; $this->tasks = $tasks; $this->parameters = $parameters; } - /** - * @return Collection - */ public function getCommon(): Collection { return $this->common; } - /** - * @return Collection|SyncTask[] - */ - public function getTasks() + public function getTasks(): Collection { return $this->tasks; } - /** - * @return Collection - */ public function getParameters(): Collection { return $this->parameters; diff --git a/src/Models/CopyMode.php b/src/Models/CopyMode.php index c26d82b..f32180b 100644 --- a/src/Models/CopyMode.php +++ b/src/Models/CopyMode.php @@ -1,6 +1,4 @@ -id = $id; @@ -63,41 +52,26 @@ public function toString(): string return (string)$this->id; } - /** - * @return string - */ public function getId(): string { return $this->id; } - /** - * @return string - */ public function getSource(): string { return $this->source; } - /** - * @return string - */ public function getTarget(): string { return $this->target; } - /** - * @return string|null - */ public function getConnectionState(): ?string { return $this->connectionState; } - /** - * @return string|null - */ public function getStatus(): ?string { return $this->status; diff --git a/src/Models/Sessions.php b/src/Models/Sessions.php index ee70e1a..875f1c0 100644 --- a/src/Models/Sessions.php +++ b/src/Models/Sessions.php @@ -1,6 +1,4 @@ -items = $items; @@ -50,10 +43,6 @@ public function all(): Collection /** * Maps any available sessions to the appropriate task - * - * @param Collection $tasks - * - * @return Collection */ public function map(Collection $tasks): Collection { diff --git a/src/Models/SymlinkMode.php b/src/Models/SymlinkMode.php index 54c3486..8eabf39 100644 --- a/src/Models/SymlinkMode.php +++ b/src/Models/SymlinkMode.php @@ -1,6 +1,4 @@ -label = $label; $this->source = $source; @@ -68,75 +61,54 @@ public function __construct(string $label, string $source, string $target, bool $this->useCommon = $useCommon; $this->options = $options; $this->ignore = $ignore; + $this->groups = $groups; } - /** - * @param MutagenSession $session - */ public function attachSession(MutagenSession $session): void { $this->session = $session; } - /** - * @return bool - */ public function isRunning(): bool { return $this->session instanceof MutagenSession && $this->session->getId(); } - /** - * @return string - */ public function getLabel(): string { return $this->label; } - /** - * @return string - */ public function getSource(): string { return $this->source; } - /** - * @return string - */ public function getTarget(): string { return $this->target; } - /** - * @return bool - */ public function shouldUseCommon(): bool { return $this->useCommon; } - /** - * @return Collection - */ public function getOptions(): Collection { return $this->options; } - /** - * @return Collection - */ public function getIgnore(): Collection { return $this->ignore; } - /** - * @return MutagenSession|null - */ + public function getGroups(): Collection + { + return $this->groups; + } + public function getSession(): ?MutagenSession { return $this->session; diff --git a/src/Services/Compiler.php b/src/Services/Compiler.php index 4d27613..977f769 100644 --- a/src/Services/Compiler.php +++ b/src/Services/Compiler.php @@ -1,6 +1,4 @@ -addFile($phar, $file); } + $testFor = [ + 'include_paths.php', 'platform_check.php', 'installed.php', 'InstalledVersions.php', 'installed.json', + ]; + $this->addFile($phar, new SplFileInfo($basePath . '/vendor/autoload.php')); $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/autoload_namespaces.php')); $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/autoload_psr4.php')); @@ -81,11 +83,14 @@ public function compile($pharFile = 'mutagen-sync-it.phar') $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/autoload_files.php')); $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/autoload_real.php')); $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/autoload_static.php')); - if (file_exists($basePath . '/vendor/composer/include_paths.php')) { - $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/include_paths.php')); - } $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/ClassLoader.php')); + foreach ($testFor as $test) { + if (file_exists($basePath . '/vendor/composer/' . $test)) { + $this->addFile($phar, new SplFileInfo($basePath . '/vendor/composer/' . $test)); + } + } + $this->addBin($phar); // Stubs diff --git a/src/Services/Config/ConfigLocator.php b/src/Services/Config/ConfigLocator.php index 28e3a24..73076a0 100644 --- a/src/Services/Config/ConfigLocator.php +++ b/src/Services/Config/ConfigLocator.php @@ -1,6 +1,4 @@ -containerResolver = $containerResolver; @@ -77,6 +70,7 @@ private function createTasksFrom(array $configTasks, Collection $common): Collec $data = Collection::collect($data); $options = $data->value('options', new Collection())->unique(); $ignore = $data->value('ignore', new Collection())->unique(); + $groups = $data->value('groups', new Collection())->unique(); if ($data->get('use_common', true)) { $options = $common @@ -99,7 +93,8 @@ private function createTasksFrom(array $configTasks, Collection $common): Collec (string)$data->get('target'), (bool)$data->get('use_common', true), $options, - $ignore + $ignore, + $groups ) ); } diff --git a/src/Services/Console/ConsoleHelper.php b/src/Services/Console/ConsoleHelper.php index c546d1d..b9bccde 100644 --- a/src/Services/Console/ConsoleHelper.php +++ b/src/Services/Console/ConsoleHelper.php @@ -43,12 +43,6 @@ class ConsoleHelper */ private $noOutput = false; - /** - * Constructor - * - * @param InputInterface $input - * @param OutputInterface $output - */ public function __construct(InputInterface $input, OutputInterface $output) { $this->input = $input; diff --git a/src/Services/DockerContainerResolver.php b/src/Services/DockerContainerResolver.php index 46ed80d..c62bdfa 100644 --- a/src/Services/DockerContainerResolver.php +++ b/src/Services/DockerContainerResolver.php @@ -1,6 +1,4 @@ -getVersion(), self::MUTAGEN_MIN_VERSION, '>='); } - public function hasLabels(): bool - { - return version_compare($this->getVersion(), '0.9.0', '>='); - } - public function getSessions(): Sessions { return (new MutagenSessionParser())->sessions(); diff --git a/src/Services/MutagenSessionParser.php b/src/Services/MutagenSessionParser.php index 7d8f6b5..4fb996f 100644 --- a/src/Services/MutagenSessionParser.php +++ b/src/Services/MutagenSessionParser.php @@ -1,6 +1,4 @@ -