| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- <?php
- declare(strict_types=1);
- /**
- * This file is part of Hyperf.
- *
- * @link https://www.hyperf.io
- * @document https://hyperf.wiki
- * @contact group@hyperf.io
- * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
- */
- namespace Hyperf\Watcher\Driver;
- use Hyperf\Engine\Channel;
- use Hyperf\Stringable\Str;
- use Hyperf\Watcher\Option;
- use InvalidArgumentException;
- use function Hyperf\Watcher\exec;
- class FindNewerDriver extends AbstractDriver
- {
- protected string $tmpFile = '/tmp/hyperf_find.php';
- protected bool $scanning = false;
- protected int $count = 0;
- public function __construct(protected Option $option)
- {
- parent::__construct($option);
- $ret = exec('which find');
- if (empty($ret['output'])) {
- throw new InvalidArgumentException('find not exists.');
- }
- // create two files
- exec('echo 1 > ' . $this->getToModifyFile());
- exec('echo 1 > ' . $this->getToScanFile());
- }
- public function watch(Channel $channel): void
- {
- $seconds = $this->option->getScanIntervalSeconds();
- $this->timerId = $this->timer->tick($seconds, function () use ($channel) {
- if ($this->scanning) {
- return;
- }
- $this->scanning = true;
- $changedFiles = $this->scan();
- ++$this->count;
- // update mtime
- if ($changedFiles) {
- exec('echo 1 > ' . $this->getToModifyFile());
- exec('echo 1 > ' . $this->getToScanFile());
- }
- foreach ($changedFiles as $file) {
- $channel->push($file);
- $this->scanning = false;
- return;
- }
- $this->scanning = false;
- });
- }
- protected function find(array $targets, array $ext = []): array
- {
- $changedFiles = [];
- $shell = '';
- $len = count($targets);
- // merge find command
- for ($i = 0; $i < $len; ++$i) {
- $dest = $targets[$i];
- $symbol = ($i == $len - 1) ? '' : '&';
- $file = $this->getToScanFile();
- $shell = $shell . sprintf('find %s -newer %s -type f', $dest, $file) . $symbol;
- }
- $ret = exec($shell);
- if ($ret['code'] === 0 && strlen($ret['output'])) {
- $stdout = $ret['output'];
- $lineArr = explode(PHP_EOL, $stdout);
- foreach ($lineArr as $pathName) {
- if (empty($pathName)) {
- continue;
- }
- if (! empty($ext) && ! Str::endsWith($pathName, $ext)) {
- continue;
- }
- $changedFiles[] = $pathName;
- }
- }
- return $changedFiles;
- }
- protected function scan(): array
- {
- $ext = $this->option->getExt();
- $dirs = array_map(fn ($dir) => BASE_PATH . '/' . $dir, $this->option->getWatchDir());
- $files = array_map(fn ($file) => BASE_PATH . '/' . $file, $this->option->getWatchFile());
- if ($files) {
- $dirs[] = implode(' ', $files);
- }
- return $this->find($dirs, $ext);
- }
- protected function getToModifyFile(): string
- {
- return $this->tmpFile . ($this->count % 2);
- }
- protected function getToScanFile(): string
- {
- return $this->tmpFile . (($this->count + 1) % 2);
- }
- }
|