Skip to content

Commit b802c3a

Browse files
committed
Use different fs watchers
1 parent 677ffef commit b802c3a

File tree

11 files changed

+134
-50
lines changed

11 files changed

+134
-50
lines changed

.travis.yml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,6 @@ language: php
22

33
jobs:
44
include:
5-
- stage: "PHP7.2 - lowest"
6-
php: 7.2
7-
script:
8-
- composer update -n --prefer-dist --prefer-lowest --no-suggest
9-
- composer dump-autoload
10-
- composer ci:tests
11-
- composer ci:php:psalm
12-
13-
- stage: "PHP7.3 - highest"
14-
php: 7.3
15-
script:
16-
- composer update -n --prefer-dist --no-suggest
17-
- composer dump-autoload
18-
- composer ci:tests
19-
- composer ci:php:psalm
20-
215
- stage: "PHP7.4 - highest"
226
php: 7.4
237
script:

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
## 0.6.0 (2020-05-11)
1+
## 0.6.0 (2020-05-20)
22
* Fix: don't use child process for resource watching
3+
* Feature: add fswatch support
4+
* Fix: min required PHP version is set to 7.4
35

46
## 0.5.2 (2019-12-07)
57
* Fix: use predefined const for PHP binary [#59](https://github.com/seregazhuk/php-watcher/pull/59)

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
}
2525
],
2626
"require": {
27-
"php": "^7.2",
27+
"php": "^7.4",
2828
"ext-json": "*",
2929
"ext-pcntl": "*",
3030
"yosymfony/resource-watcher": "^2.0",
@@ -34,7 +34,8 @@
3434
"react/child-process": "^0.6.1",
3535
"react/stream": "^1.0.0",
3636
"symfony/finder": "^4.3 || ^5.0",
37-
"alecrabbit/php-cli-snake": "^0.5"
37+
"alecrabbit/php-cli-snake": "^0.5",
38+
"seregazhuk/reactphp-fswatch": "^0.1.0"
3839
},
3940
"autoload": {
4041
"psr-4": {

phpunit.xml.dist

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
<filter>
1717
<whitelist processUncoveredFilesFromWhitelist="true">
1818
<directory suffix=".php">src</directory>
19-
<exclude>
20-
<file>src/Filesystem/watcher.php</file>
21-
</exclude>
2219
</whitelist>
2320
</filter>
2421
</phpunit>

src/Filesystem/ChangesListener.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
<?php
22

33
declare(strict_types=1);
4-
namespace seregazhuk\PhpWatcher\Filesystem;
54

6-
use seregazhuk\PhpWatcher\Config\WatchList;
5+
namespace seregazhuk\PhpWatcher\Filesystem;
76

87
interface ChangesListener
98
{
10-
public function start(WatchList $watchList): void;
9+
public function start(): void;
1110

1211
public function onChange(callable $callback): void;
12+
13+
public function stop(): void;
1314
}

src/Filesystem/Factory.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace seregazhuk\PhpWatcher\Filesystem;
6+
7+
use React\EventLoop\LoopInterface;
8+
use seregazhuk\PhpWatcher\Config\WatchList;
9+
use seregazhuk\PhpWatcher\Filesystem\FsWatchBased\ChangesListener as FsWatchBased;
10+
use seregazhuk\PhpWatcher\Filesystem\ResourceWatcherBased\ChangesListener as ResourceBased;
11+
12+
final class Factory
13+
{
14+
public static function create(WatchList $watchList, LoopInterface $loop): ChangesListener
15+
{
16+
if (FsWatchBased::isAvailable()) {
17+
return new FsWatchBased($watchList, $loop);
18+
}
19+
20+
return new ResourceBased($watchList, $loop);
21+
}
22+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace seregazhuk\PhpWatcher\Filesystem\FsWatchBased;
6+
7+
use Evenement\EventEmitter;
8+
use React\EventLoop\LoopInterface;
9+
use seregazhuk\PhpWatcher\Config\WatchList;
10+
use seregazhuk\PhpWatcher\Filesystem\ChangesListener as ChangesListenerInterface;
11+
use Seregazhuk\ReactFsWatch\FsWatch;
12+
13+
final class ChangesListener extends EventEmitter implements ChangesListenerInterface
14+
{
15+
private FsWatch $fsWatch;
16+
17+
public function __construct(WatchList $watchList, LoopInterface $loop)
18+
{
19+
$this->fsWatch = new FsWatch($this->makeOptions($watchList), $loop);
20+
}
21+
22+
public static function isAvailable(): bool
23+
{
24+
return FsWatch::isAvailable();
25+
}
26+
27+
public function start(): void
28+
{
29+
$this->fsWatch->run();
30+
$this->fsWatch->on(
31+
'change',
32+
function () {
33+
$this->emit('change');
34+
}
35+
);
36+
}
37+
38+
public function onChange(callable $callback): void
39+
{
40+
$this->on('change', $callback);
41+
}
42+
43+
public function stop(): void
44+
{
45+
$this->fsWatch->stop();
46+
}
47+
48+
private function makeOptions(WatchList $watchList): string
49+
{
50+
$options = [];
51+
if ($watchList->ignore()) {
52+
$options[] = implode('-e ', $watchList->ignore());
53+
}
54+
55+
if ($watchList->fileExtensions()) {
56+
$options[] = implode(' ', $watchList->fileExtensions());
57+
}
58+
59+
if ($watchList->paths()) {
60+
$options[] = implode(' ', $watchList->paths());
61+
}
62+
63+
return implode(' ', $options);
64+
}
65+
}
Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
1-
<?php declare(strict_types=1);
1+
<?php
2+
3+
declare(strict_types=1);
24

35
namespace seregazhuk\PhpWatcher\Filesystem\ResourceWatcherBased;
46

57
use Evenement\EventEmitter;
68
use React\EventLoop\LoopInterface;
79
use seregazhuk\PhpWatcher\Config\WatchList;
10+
use seregazhuk\PhpWatcher\Filesystem\ChangesListener as ChangesListenerInterface;
11+
use Yosymfony\ResourceWatcher\ResourceWatcher;
812

9-
final class ChangesListener extends EventEmitter implements
10-
\seregazhuk\PhpWatcher\Filesystem\ChangesListener
13+
final class ChangesListener extends EventEmitter implements ChangesListenerInterface
1114
{
1215
private const INTERVAL = 0.15;
1316

14-
private $loop;
17+
private LoopInterface $loop;
18+
19+
private ResourceWatcher $watcher;
1520

16-
public function __construct(LoopInterface $loop)
21+
public function __construct(WatchList $watchList, LoopInterface $loop)
1722
{
1823
$this->loop = $loop;
24+
$this->watcher = ResourceWatcherBuilder::create($watchList);
1925
}
2026

21-
public function start(WatchList $watchList): void
27+
public function start(): void
2228
{
23-
$watcher = ResourceWatcherBuilder::create($watchList);
24-
2529
$this->loop->addPeriodicTimer(
2630
self::INTERVAL,
27-
function () use ($watcher) {
28-
if ($watcher->findChanges()->hasChanges()) {
31+
function () {
32+
if ($this->watcher->findChanges()->hasChanges()) {
2933
$this->emit('change');
3034
}
3135
}
@@ -36,4 +40,8 @@ public function onChange(callable $callback): void
3640
{
3741
$this->on('change', $callback);
3842
}
43+
44+
public function stop(): void
45+
{
46+
}
3947
}

src/Watcher.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
namespace seregazhuk\PhpWatcher;
66

77
use React\EventLoop\LoopInterface;
8-
use seregazhuk\PhpWatcher\Config\WatchList;
9-
use seregazhuk\PhpWatcher\Filesystem\ResourceWatcherBased\ChangesListener;
8+
use seregazhuk\PhpWatcher\Filesystem\ChangesListener;
109

1110
final class Watcher
1211
{
13-
private $loop;
12+
private LoopInterface $loop;
1413

15-
private $filesystemListener;
14+
private ChangesListener $filesystemListener;
1615

1716
public function __construct(LoopInterface $loop, ChangesListener $filesystemListener)
1817
{
@@ -22,13 +21,12 @@ public function __construct(LoopInterface $loop, ChangesListener $filesystemList
2221

2322
public function startWatching(
2423
ProcessRunner $processRunner,
25-
WatchList $watchList,
2624
int $signal,
2725
float $delayToRestart
2826
): void {
2927
$processRunner->start();
3028

31-
$this->filesystemListener->start($watchList);
29+
$this->filesystemListener->start();
3230
$this->filesystemListener->onChange(
3331
static function () use ($processRunner, $signal, $delayToRestart) {
3432
$processRunner->stop($signal);

src/WatcherCommand.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
declare(strict_types=1);
34

45
namespace seregazhuk\PhpWatcher;
@@ -9,7 +10,8 @@
910
use seregazhuk\PhpWatcher\Config\Builder;
1011
use seregazhuk\PhpWatcher\Config\Config;
1112
use seregazhuk\PhpWatcher\Config\InputExtractor;
12-
use seregazhuk\PhpWatcher\Filesystem\ResourceWatcherBased\ChangesListener;
13+
use seregazhuk\PhpWatcher\Filesystem\Factory as ChangesListenerFactory;
14+
use seregazhuk\PhpWatcher\Filesystem\ChangesListener;
1315
use seregazhuk\PhpWatcher\Screen\Screen;
1416
use seregazhuk\PhpWatcher\Screen\SpinnerFactory;
1517
use Symfony\Component\Console\Command\Command as BaseCommand;
@@ -60,32 +62,36 @@ protected function execute(InputInterface $input, OutputInterface $output)
6062
$config = $this->buildConfig(new InputExtractor($input));
6163
$spinner = SpinnerFactory::create($output, $config->spinnerDisabled());
6264

63-
$this->addTerminationListeners($loop, $spinner);
6465

6566
$screen = new Screen(new SymfonyStyle($input, $output), $spinner);
66-
$filesystem = new ChangesListener($loop);
67+
$filesystem = ChangesListenerFactory::create($config->watchList(), $loop);
6768

6869
$screen->showOptions($config->watchList());
6970
$processRunner = new ProcessRunner($loop, $screen, $config->command());
7071

7172
$watcher = new Watcher($loop, $filesystem);
7273
$watcher->startWatching(
7374
$processRunner,
74-
$config->watchList(),
7575
$config->signalToReload(),
7676
$config->delay()
7777
);
7878

79+
$this->addTerminationListeners($loop, $spinner, $filesystem);
80+
7981
return 0;
8082
}
8183

8284
/**
8385
* When terminating the watcher we need to manually restore the cursor after the spinner.
8486
*/
85-
private function addTerminationListeners(LoopInterface $loop, SpinnerInterface $spinner): void
86-
{
87-
$func = static function (int $signal) use ($spinner): void {
87+
private function addTerminationListeners(
88+
LoopInterface $loop,
89+
SpinnerInterface $spinner,
90+
ChangesListener $changesListener
91+
): void {
92+
$func = static function (int $signal) use ($spinner, $changesListener): void {
8893
$spinner->end();
94+
$changesListener->stop();
8995
exit($signal);
9096
};
9197

tests/Feature/ChangesListenerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ final class ChangesListenerTest extends TestCase
1919
public function it_emits_change_event_on_changes(): void
2020
{
2121
$loop = Factory::create();
22-
$listener = new ChangesListener($loop);
23-
$listener->start(new WatchList([Filesystem::fixturesDir()]));
22+
$listener = new ChangesListener(new WatchList([Filesystem::fixturesDir()]), $loop);
23+
$listener->start();
2424

2525
$loop->addTimer(1, [Filesystem::class, 'createHelloWorldPHPFile']);
2626
$eventWasEmitted = false;

0 commit comments

Comments
 (0)