Skip to content

Commit

Permalink
Switch to castor watcher binaries
Browse files Browse the repository at this point in the history
  • Loading branch information
maelanleborgne committed Nov 15, 2023
1 parent c348241 commit 4c77185
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 276 deletions.
46 changes: 46 additions & 0 deletions src/Tools/WatcherBinary.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Sensiolabs\TypeScriptBundle\Tools;

use Symfony\Component\Process\Process;

class WatcherBinary
{
public function __construct(
private string $executablePath,
) {
}

/**
* @param array<string> $extensions
*/
public function startWatch(string $watchPath, callable $callback, array $extensions = []): Process
{
$process = new Process([$this->executablePath, $watchPath]);

$process->start(function ($type, $buffer) use ($callback, $extensions) {
if (Process::ERR === $type) {
throw new \Exception($buffer);
} else {
$lines = explode("\n", $buffer);
$changedFiles = [];
foreach ($lines as $line) {
try {
$entry = json_decode($line, true, 512, \JSON_THROW_ON_ERROR);
if ($extensions && !\in_array(pathinfo($entry['name'], \PATHINFO_EXTENSION), $extensions)) {
continue;
}
$changedFiles[$entry['name']] = $entry['operation'];
} catch (\JsonException) {
continue;
}
}
foreach ($changedFiles as $file => $operation) {
$callback($file, $operation);
}
}
});

return $process;
}
}
33 changes: 33 additions & 0 deletions src/Tools/WatcherBinaryFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Sensiolabs\TypeScriptBundle\Tools;

class WatcherBinaryFactory
{
public function getBinaryFromServerSpecs($os): WatcherBinary
{
$binaryName = self::getBinaryNameFromServerSpecs($os);
$binaryPath = __DIR__.'/watcher/'.$binaryName;
if (!file_exists($binaryPath)) {
throw new \Exception(sprintf('The watcher binary could not be found at the provided path : "%s"', $binaryPath));
}

return new WatcherBinary($binaryPath);
}

public static function getBinaryNameFromServerSpecs($os)
{
$os = strtolower($os);
if (str_contains($os, 'darwin')) {
return 'watcher-darwin';
}
if (str_contains($os, 'linux')) {
return 'watcher-linux';
}
if (str_contains($os, 'win')) {
return 'watcher-windows.exe';
}

throw new \Exception(sprintf('Unknown platform or architecture (OS: %s).', $os));
}
}
24 changes: 0 additions & 24 deletions src/Tools/WatchexecBinary.php

This file was deleted.

140 changes: 0 additions & 140 deletions src/Tools/WatchexecBinaryFactory.php

This file was deleted.

Binary file added src/Tools/watcher/watcher-darwin
Binary file not shown.
Binary file added src/Tools/watcher/watcher-linux
Binary file not shown.
Binary file added src/Tools/watcher/watcher-windows.exe
Binary file not shown.
65 changes: 32 additions & 33 deletions src/TypeScriptBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

use Sensiolabs\TypeScriptBundle\Tools\TypeScriptBinary;
use Sensiolabs\TypeScriptBundle\Tools\TypescriptBinaryFactory;
use Sensiolabs\TypeScriptBundle\Tools\WatchexecBinary;
use Sensiolabs\TypeScriptBundle\Tools\WatchexecBinaryFactory;
use Sensiolabs\TypeScriptBundle\Tools\WatcherBinary;
use Sensiolabs\TypeScriptBundle\Tools\WatcherBinaryFactory;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\Process;
Expand All @@ -14,7 +14,7 @@ class TypeScriptBuilder
{
private ?SymfonyStyle $output = null;
private ?TypeScriptBinary $buildBinary = null;
private ?WatchexecBinary $watchexecBinary = null;
private ?WatcherBinary $watchexecBinary = null;

public function __construct(
private readonly array $typeScriptFilesPaths,
Expand Down Expand Up @@ -57,30 +57,32 @@ private function createBuildProcess(string $path, bool $watch = false): Process
return $buildProcess;
}

$watchProcess = $this->getWatchexecBinary()->createProcess($relativePath);
$watchProcess->setTimeout(null)->setIdleTimeout(null);
$this->output?->note(sprintf('Watching for changes in %s...', $relativePath));
if ($this->output?->isVerbose()) {
$this->output->writeln([
' Command:',
' '.$watchProcess->getCommandLine(),
]);
}
$watchProcess->start(function ($type, $buffer) {
if ('err' === $type) {
throw new \RuntimeException($buffer);
}
$path = trim($buffer);
if ('/' === $path) {
return;
}
$newProcess = $this->createBuildProcess($path);
$newProcess->wait(function ($type, $buffer) {
$this->output?->write($buffer);
});
});

return $watchProcess;
return $this->getWatchexecBinary()->startWatch($relativePath, fn ($path, $operation) => $this->createBuildProcess($path), ['ts']);
//
// $watchProcess = $this->getWatchexecBinary()->createProcess($relativePath);
// $watchProcess->setTimeout(null)->setIdleTimeout(null);
// $this->output?->note(sprintf('Watching for changes in %s...', $relativePath));
// if ($this->output?->isVerbose()) {
// $this->output->writeln([
// ' Command:',
// ' '.$watchProcess->getCommandLine(),
// ]);
// }
// $watchProcess->start(function ($type, $buffer) {
// if ('err' === $type) {
// throw new \RuntimeException($buffer);
// }
// $path = trim($buffer);
// if ('/' === $path) {
// return;
// }
// $newProcess = $this->createBuildProcess($path);
// $newProcess->wait(function ($type, $buffer) {
// $this->output?->write($buffer);
// });
// });
//
// return $watchProcess;
}

public function setOutput(SymfonyStyle $output): void
Expand All @@ -101,16 +103,13 @@ private function getBuildBinary(): TypeScriptBinary
$typescriptBinaryFactory->getBinaryFromServerSpecs(\PHP_OS, php_uname('m'), php_uname('r'));
}

private function getWatchexecBinary(): WatchexecBinary
private function getWatchexecBinary(): WatcherBinary
{
if ($this->watchexecBinary) {
return $this->watchexecBinary;
}
$watchexecBinaryFactory = new WatchexecBinaryFactory($this->binaryDownloadDir);
$watchexecBinaryFactory->setOutput($this->output);
$watchexecBinaryFactory = new WatcherBinaryFactory();

return $this->watchexecBinary = $this->watchexecBinaryPath ?
$watchexecBinaryFactory->getBinaryFromPath($this->watchexecBinaryPath) :
$watchexecBinaryFactory->getBinaryFromServerSpecs(\PHP_OS, php_uname('m'), php_uname('r'));
return $this->watchexecBinary = $watchexecBinaryFactory->getBinaryFromServerSpecs(\PHP_OS, php_uname('m'), php_uname('r'));
}
}
47 changes: 47 additions & 0 deletions tests/Tools/WatcherBinaryFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Sensiolabs\TypeScriptBundle\Tests\Tools;

use PHPUnit\Framework\TestCase;
use Sensiolabs\TypeScriptBundle\Tools\WatcherBinaryFactory;

class WatcherBinaryFactoryTest extends TestCase
{
private string $watchPath = __DIR__.'/../fixtures/assets/typescript';
private string $binaryDir = __DIR__.'/../../src/Tools/watcher';

public function testGetBinaryFromServerSpecs()
{
// Test that the binary exists and the process is created with the correct arguments
$binary = (new WatcherBinaryFactory())->getBinaryFromServerSpecs('Linux');
$process = $binary->startWatch($this->watchPath, fn ($path, $operation) => '');
$this->assertEquals('\''.realpath($this->binaryDir).'/watcher-linux\' \''.$this->watchPath.'\'', $process->getCommandLine());

// Test that an exception is thrown when the platform is not supported
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Unknown platform or architecture (OS: undefined).');
(new WatcherBinaryFactory())->getBinaryFromServerSpecs('Undefined');
}

/**
* @dataProvider provideServerSpecs
*/
public function testGetBinaryNameFromServerSpecs($os, $expectedBinaryName, $exception = null)
{
if (null !== $exception) {
$this->expectException($exception);
}

$this->assertEquals($expectedBinaryName, WatcherBinaryFactory::getBinaryNameFromServerSpecs($os));
}

public function provideServerSpecs()
{
return [
['Darwin', 'watcher-darwin'],
['Linux', 'watcher-linux'],
['Windows', 'watcher-windows.exe'],
['Undefined', null, \Exception::class],
];
}
}
Loading

0 comments on commit 4c77185

Please sign in to comment.