Skip to content

Commit 20cfb71

Browse files
committed
chore(app): removing watch mode from bootstrap and using inotifywait instead.
1 parent 1b7e13d commit 20cfb71

File tree

6 files changed

+37
-283
lines changed

6 files changed

+37
-283
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@ It leverages the [amphp](https://github.com/amphp/amp) platform to make your pro
2929
> This project is aimed at linux distributions, some features may or not may work on Windows and/or MacOS.\
3030
> Feel free to contribute fixing issues for specific platforms.
3131
32-
# Get started
32+
# Prerequisites
33+
34+
You will need at least [php 8.3](https://www.php.net/downloads.php) and `inotify-tools` for [watch mode](#watch-mode).
3335

34-
You will need at least [php 8.3](https://www.php.net/downloads.php).
36+
```sh
37+
sudo apt install inotify-tools
38+
```
39+
40+
# Get started
3541

3642
Create a new project using one of the starter templates.
3743

bin/catpaw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ use CatPaw\Core\Interfaces\CommandRegisterInterface;
88
require 'vendor/autoload.php';
99

1010
Container::provide(CommandRegisterInterface::class, $command = new SimpleCommandRegister);
11-
$command->register(new ApplicationCommand(__FILE__))->unwrap($error) or die($error);
11+
$command->register(new ApplicationCommand)->unwrap($error) or die($error);

makefile

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@ preview: bin/catpaw sandbox/preview/main.php
2121
bin/catpaw \
2222
--environment=env.ini \
2323
--libraries=sandbox/preview/lib \
24-
--main=sandbox/preview/main.php
24+
--main=sandbox/preview/main.php \
25+
--die-on-stdin
2526

2627
watch: bin/catpaw src/main.php
27-
php -dxdebug.mode=off -dxdebug.start_with_request=no \
28-
bin/catpaw \
29-
--environment=env.ini \
30-
--libraries=src/lib \
31-
--main=src/main.php \
32-
--resources=src \
33-
--watch \
34-
--spawner="php -dxdebug.mode=debug -dxdebug.start_with_request=yes"
28+
while true; do \
29+
(inotifywait \
30+
-e modify,create,delete_self,delete,move_self,moved_from,moved_to \
31+
-r -P --format '%e' sandbox/preview | make preview); \
32+
done
3533

3634
start: bin/catpaw src/main.php
3735
php -dxdebug.mode=off -dxdebug.start_with_request=no \

src/lib/Core/Bootstrap.php

Lines changed: 9 additions & 238 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
<?php
2-
32
namespace CatPaw\Core;
43

54
use function Amp\async;
6-
use Amp\DeferredFuture;
7-
use function Amp\delay;
8-
use function Amp\File\isDirectory;
5+
use function Amp\ByteStream\getStdin;
96
use CatPaw\Core\Implementations\Environment\SimpleEnvironment;
107
use CatPaw\Core\Interfaces\EnvironmentInterface;
118
use Error;
12-
use function preg_split;
139
use Psr\Log\LoggerInterface;
14-
use function realpath;
1510
use ReflectionFunction;
1611
use Revolt\EventLoop;
1712
use Throwable;
1813

1914
class Bootstrap {
2015
private function __construct() {
2116
}
22-
2317

2418
/**
2519
* Initialize an application from a source file (that usually defines a global "main" function).
@@ -49,7 +43,7 @@ public static function initialize(string $fileName):Result {
4943
* @param array<string> $libraries libraries to load
5044
* @param array<string> $resources resources to load
5145
* @param string $environment
52-
* @param bool $dieOnChange die when a change to the main file, libraries or resources is detected
46+
* @param bool $dieOnStdin die when stdin receives data
5347
* @return void
5448
*/
5549
public static function start(
@@ -58,7 +52,7 @@ public static function start(
5852
array $libraries,
5953
array $resources,
6054
string $environment,
61-
bool $dieOnChange = false,
55+
bool $dieOnStdin = false,
6256
):void {
6357
try {
6458
foreach ($libraries as $library) {
@@ -90,7 +84,7 @@ public static function start(
9084
$env->set('MAIN', $main);
9185
$env->set('LIBRARIES', $libraries);
9286
$env->set('RESOURCES', $resources);
93-
$env->set('DIE_ON_CHANGE', $dieOnChange);
87+
$env->set('DIE_ON_CHANGE', $dieOnStdin);
9488

9589
if ($environment) {
9690
$env->withFileName($environment);
@@ -116,18 +110,11 @@ public static function start(
116110
$resource = $resourceLocal;
117111
}
118112

119-
if ($dieOnChange) {
120-
if (isPhar()) {
121-
self::kill("Watch mode is intended for development only, compiled phar applications cannot watch files for changes.");
122-
}
123-
self::onFileChange(
124-
main: $main,
125-
libraries: $libraries,
126-
resources: $resources,
127-
function: static function() {
128-
self::kill("Killing application...", 0);
129-
},
130-
);
113+
if ($dieOnStdin) {
114+
async(function() {
115+
getStdin()->read();
116+
self::kill("Killing application...", 0);
117+
});
131118
}
132119

133120
self::initialize($main)->unwrap($initializeError);
@@ -178,220 +165,4 @@ public static function kill(false|string|Error $error = false, false|int $code =
178165
die($code);
179166
}
180167
}
181-
182-
/**
183-
* @param string $initializer
184-
* @param string $spawner
185-
* @param string $fileName
186-
* @param array<string> $arguments
187-
* @param string $main
188-
* @param array<string> $libraries
189-
* @param array<string> $resources
190-
* @return void
191-
*/
192-
public static function spawn(
193-
string $initializer,
194-
string $spawner,
195-
string $fileName,
196-
array $arguments,
197-
string $main,
198-
array $libraries,
199-
array $resources,
200-
):void {
201-
try {
202-
EventLoop::onSignal(SIGHUP, static fn () => self::kill("Killing application..."));
203-
EventLoop::onSignal(SIGINT, static fn () => self::kill("Killing application..."));
204-
EventLoop::onSignal(SIGQUIT, static fn () => self::kill("Killing application..."));
205-
EventLoop::onSignal(SIGTERM, static fn () => self::kill("Killing application..."));
206-
207-
foreach ($libraries as $library) {
208-
Container::requireLibraries($library)->unwrap($requireError);
209-
if ($requireError) {
210-
self::kill((string)$requireError);
211-
}
212-
}
213-
214-
Container::loadDefaultProviders("Watcher")->unwrap($loadDefaultProvidersError);
215-
if ($loadDefaultProvidersError) {
216-
self::kill((string)$loadDefaultProvidersError);
217-
}
218-
219-
async(static function() use (
220-
$initializer,
221-
$spawner,
222-
$fileName,
223-
$arguments,
224-
$main,
225-
$libraries,
226-
$resources,
227-
) {
228-
if (!Container::isProvided(LoggerInterface::class)) {
229-
$logger = LoggerFactory::create()->unwrap($error);
230-
if ($error) {
231-
return error($error);
232-
}
233-
Container::provide(LoggerInterface::class, $logger);
234-
} else {
235-
$logger = Container::get(LoggerInterface::class)->unwrap($error);
236-
if ($error) {
237-
return error($error);
238-
}
239-
}
240-
241-
foreach ($arguments as &$argument) {
242-
$parts = preg_split('/=|\s/', $argument, 2);
243-
if (count($parts) < 2) {
244-
continue;
245-
}
246-
247-
$left = $parts[0];
248-
$right = $parts[1];
249-
$slashed = addslashes($right);
250-
$argument = "$left=\"$slashed\"";
251-
}
252-
253-
$argumentsStringified = join(' ', $arguments);
254-
$instruction = "$spawner $fileName $argumentsStringified";
255-
256-
echo "Spawning $instruction".PHP_EOL;
257-
258-
if (DIRECTORY_SEPARATOR === '/') {
259-
EventLoop::onSignal(SIGINT, static function() {
260-
self::kill();
261-
});
262-
}
263-
264-
/** @var false|DeferredFuture<void> $ready */
265-
$ready = false;
266-
267-
self::onFileChange(
268-
main: $main,
269-
libraries: $libraries,
270-
resources: $resources,
271-
function: static function() use (&$ready) {
272-
if (!$ready) {
273-
return;
274-
}
275-
$ready->complete();
276-
},
277-
);
278-
279-
while (true) {
280-
if ($ready) {
281-
$ready->getFuture()->await();
282-
}
283-
284-
if ('' !== $initializer) {
285-
Process::execute($initializer, out())->unwrap($error);
286-
if ($error) {
287-
self::kill($error);
288-
}
289-
}
290-
291-
$code = Process::execute($instruction, out())->unwrap($error);
292-
if ($error || $code > 0) {
293-
echo $error.PHP_EOL;
294-
$ready = new DeferredFuture;
295-
}
296-
}
297-
});
298-
299-
EventLoop::run();
300-
} catch (Throwable $error) {
301-
self::kill($error);
302-
}
303-
}
304-
305-
/**
306-
* Start a watcher which will detect file changes.
307-
* Useful for development mode.
308-
* @param string $main
309-
* @param array<string> $libraries
310-
* @param array<string> $resources
311-
* @param callable $function
312-
* @return void
313-
*/
314-
private static function onFileChange(
315-
string $main,
316-
array $libraries,
317-
array $resources,
318-
callable $function,
319-
):void {
320-
async(function() use (
321-
$main,
322-
$libraries,
323-
$resources,
324-
$function,
325-
) {
326-
$changes = [];
327-
$firstPass = true;
328-
329-
while (true) {
330-
clearstatcache();
331-
$countLastPass = count($changes);
332-
333-
$fileNames = match ($main) {
334-
'' => [],
335-
default => [$main => false]
336-
};
337-
/** @var array<string> $files */
338-
$files = [...$libraries, ...$resources];
339-
340-
foreach ($files as $file) {
341-
if (!File::exists($file)) {
342-
continue;
343-
}
344-
345-
if (!isDirectory($file)) {
346-
$fileNames[$file] = false;
347-
continue;
348-
}
349-
350-
$directory = $file;
351-
352-
$flatList = Directory::flat(realpath($directory))->unwrap($error);
353-
354-
if ($error) {
355-
return error($error);
356-
}
357-
358-
foreach ($flatList as $fileName) {
359-
$fileNames[$fileName] = false;
360-
}
361-
}
362-
363-
364-
$countThisPass = count($fileNames);
365-
if (!$firstPass && $countLastPass !== $countThisPass) {
366-
$function();
367-
}
368-
369-
foreach (array_keys($fileNames) as $fileName) {
370-
if (!File::exists($fileName)) {
371-
unset($changes[$fileName]);
372-
continue;
373-
}
374-
375-
$mtime = filemtime($fileName);
376-
377-
if (false === $mtime) {
378-
return error("Could not read file $fileName modification time.");
379-
}
380-
381-
if (!isset($changes[$fileName])) {
382-
$changes[$fileName] = $mtime;
383-
continue;
384-
}
385-
386-
if ($changes[$fileName] !== $mtime) {
387-
$changes[$fileName] = $mtime;
388-
$function();
389-
}
390-
}
391-
392-
$firstPass = false;
393-
delay(2);
394-
}
395-
});
396-
}
397168
}

src/lib/Core/Commands/ApplicationBundledCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function run(CommandContext $context):Result {
6969
libraries: $libraries,
7070
resources: $resources,
7171
environment: $environment,
72-
dieOnChange: false
72+
dieOnStdin: false
7373
);
7474

7575
return ok();

0 commit comments

Comments
 (0)