1
0
mirror of https://github.com/danog/file.git synced 2024-11-26 11:54:54 +01:00

Use shared style defintions; update styles

This commit is contained in:
Aaron Piotrowski 2018-10-27 10:57:31 -05:00
parent 4f54f94358
commit 76cdea9af7
No known key found for this signature in database
GPG Key ID: ADD1EF783EDE9EEB
31 changed files with 649 additions and 364 deletions

View File

@ -1,39 +1,12 @@
<?php <?php
return PhpCsFixer\Config::create() $config = new Amp\CodeStyle\Config();
->setRiskyAllowed(true) $config->getFinder()
->setRules([ ->in(__DIR__ . '/lib')
"@PSR1" => true, ->in(__DIR__ . '/test');
"@PSR2" => true,
"braces" => [ $cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
"allow_single_line_closure" => true,
"position_after_functions_and_oop_constructs" => "same", $config->setCacheFile($cacheDir . '/.php_cs.cache');
],
"array_syntax" => ["syntax" => "short"], return $config;
"cast_spaces" => true,
"combine_consecutive_unsets" => true,
"function_to_constant" => true,
"no_multiline_whitespace_before_semicolons" => true,
"no_unused_imports" => true,
"no_useless_else" => true,
"no_useless_return" => true,
"no_whitespace_before_comma_in_array" => true,
"no_whitespace_in_blank_line" => true,
"non_printable_character" => true,
"normalize_index_brace" => true,
"ordered_imports" => true,
"php_unit_construct" => true,
"php_unit_dedicate_assert" => true,
"php_unit_fqcn_annotation" => true,
"phpdoc_summary" => true,
"phpdoc_types" => true,
"psr4" => true,
"return_type_declaration" => ["space_before" => "none"],
"short_scalar_cast" => true,
"single_blank_line_before_namespace" => true,
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__ . "/lib")
->in(__DIR__ . "/test")
);

View File

@ -39,7 +39,7 @@
"require-dev": { "require-dev": {
"amphp/phpunit-util": "^1", "amphp/phpunit-util": "^1",
"phpunit/phpunit": "^6", "phpunit/phpunit": "^6",
"friendsofphp/php-cs-fixer": "^2.3" "amphp/php-cs-fixer-config": "dev-master"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@ -6,11 +6,13 @@ use Amp\Failure;
use Amp\Promise; use Amp\Promise;
use Amp\Success; use Amp\Success;
class BlockingDriver implements Driver { class BlockingDriver implements Driver
{
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function open(string $path, string $mode): Promise { public function open(string $path, string $mode): Promise
{
$mode = \str_replace(['b', 't', 'e'], '', $mode); $mode = \str_replace(['b', 't', 'e'], '', $mode);
switch ($mode) { switch ($mode) {
@ -42,7 +44,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function stat(string $path): Promise { public function stat(string $path): Promise
{
if ($stat = StatCache::get($path)) { if ($stat = StatCache::get($path)) {
return new Success($stat); return new Success($stat);
} elseif ($stat = @\stat($path)) { } elseif ($stat = @\stat($path)) {
@ -58,7 +61,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exists(string $path): Promise { public function exists(string $path): Promise
{
if ($exists = @\file_exists($path)) { if ($exists = @\file_exists($path)) {
\clearstatcache(true, $path); \clearstatcache(true, $path);
} }
@ -75,7 +79,8 @@ class BlockingDriver implements Driver {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
public function size(string $path): Promise { public function size(string $path): Promise
{
if (!@\file_exists($path)) { if (!@\file_exists($path)) {
return new Failure(new FilesystemException( return new Failure(new FilesystemException(
"Path does not exist" "Path does not exist"
@ -107,7 +112,8 @@ class BlockingDriver implements Driver {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<bool> * @return \Amp\Promise<bool>
*/ */
public function isdir(string $path): Promise { public function isdir(string $path): Promise
{
if (!@\file_exists($path)) { if (!@\file_exists($path)) {
return new Success(false); return new Success(false);
} }
@ -127,7 +133,8 @@ class BlockingDriver implements Driver {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<bool> * @return \Amp\Promise<bool>
*/ */
public function isfile(string $path): Promise { public function isfile(string $path): Promise
{
if (!@\file_exists($path)) { if (!@\file_exists($path)) {
return new Success(false); return new Success(false);
} }
@ -144,7 +151,8 @@ class BlockingDriver implements Driver {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
public function mtime(string $path): Promise { public function mtime(string $path): Promise
{
if (!@\file_exists($path)) { if (!@\file_exists($path)) {
return new Failure(new FilesystemException( return new Failure(new FilesystemException(
"Path does not exist" "Path does not exist"
@ -163,7 +171,8 @@ class BlockingDriver implements Driver {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
public function atime(string $path): Promise { public function atime(string $path): Promise
{
if (!@\file_exists($path)) { if (!@\file_exists($path)) {
return new Failure(new FilesystemException( return new Failure(new FilesystemException(
"Path does not exist" "Path does not exist"
@ -181,7 +190,8 @@ class BlockingDriver implements Driver {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
public function ctime(string $path): Promise { public function ctime(string $path): Promise
{
if (!@\file_exists($path)) { if (!@\file_exists($path)) {
return new Failure(new FilesystemException( return new Failure(new FilesystemException(
"Path does not exist" "Path does not exist"
@ -197,7 +207,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function lstat(string $path): Promise { public function lstat(string $path): Promise
{
if ($stat = @\lstat($path)) { if ($stat = @\lstat($path)) {
\clearstatcache(true, $path); \clearstatcache(true, $path);
} else { } else {
@ -210,7 +221,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function symlink(string $target, string $link): Promise { public function symlink(string $target, string $link): Promise
{
if (!@\symlink($target, $link)) { if (!@\symlink($target, $link)) {
return new Failure(new FilesystemException("Could not create symbolic link")); return new Failure(new FilesystemException("Could not create symbolic link"));
} }
@ -221,7 +233,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function link(string $target, string $link): Promise { public function link(string $target, string $link): Promise
{
if (!@\link($target, $link)) { if (!@\link($target, $link)) {
return new Failure(new FilesystemException("Could not create hard link")); return new Failure(new FilesystemException("Could not create hard link"));
} }
@ -232,7 +245,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function readlink(string $path): Promise { public function readlink(string $path): Promise
{
if (!($result = @\readlink($path))) { if (!($result = @\readlink($path))) {
return new Failure(new FilesystemException("Could not read symbolic link")); return new Failure(new FilesystemException("Could not read symbolic link"));
} }
@ -243,7 +257,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rename(string $from, string $to): Promise { public function rename(string $from, string $to): Promise
{
if (!@\rename($from, $to)) { if (!@\rename($from, $to)) {
return new Failure(new FilesystemException("Could not rename file")); return new Failure(new FilesystemException("Could not rename file"));
} }
@ -254,7 +269,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function unlink(string $path): Promise { public function unlink(string $path): Promise
{
StatCache::clear($path); StatCache::clear($path);
return new Success((bool) @\unlink($path)); return new Success((bool) @\unlink($path));
} }
@ -262,14 +278,16 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise { public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise
{
return new Success((bool) @\mkdir($path, $mode, $recursive)); return new Success((bool) @\mkdir($path, $mode, $recursive));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rmdir(string $path): Promise { public function rmdir(string $path): Promise
{
StatCache::clear($path); StatCache::clear($path);
return new Success((bool) @\rmdir($path)); return new Success((bool) @\rmdir($path));
} }
@ -277,7 +295,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function scandir(string $path): Promise { public function scandir(string $path): Promise
{
if (!@\is_dir($path)) { if (!@\is_dir($path)) {
return new Failure(new FilesystemException( return new Failure(new FilesystemException(
"Not a directory" "Not a directory"
@ -298,14 +317,16 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chmod(string $path, int $mode): Promise { public function chmod(string $path, int $mode): Promise
{
return new Success((bool) @\chmod($path, $mode)); return new Success((bool) @\chmod($path, $mode));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chown(string $path, int $uid, int $gid): Promise { public function chown(string $path, int $uid, int $gid): Promise
{
if ($uid !== -1 && !@\chown($path, $uid)) { if ($uid !== -1 && !@\chown($path, $uid)) {
return new Failure(new FilesystemException( return new Failure(new FilesystemException(
\error_get_last()["message"] \error_get_last()["message"]
@ -324,7 +345,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function touch(string $path, int $time = null, int $atime = null): Promise { public function touch(string $path, int $time = null, int $atime = null): Promise
{
$time = $time ?? \time(); $time = $time ?? \time();
$atime = $atime ?? $time; $atime = $atime ?? $time;
return new Success((bool) \touch($path, $time, $atime)); return new Success((bool) \touch($path, $time, $atime));
@ -333,7 +355,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function get(string $path): Promise { public function get(string $path): Promise
{
$result = @\file_get_contents($path); $result = @\file_get_contents($path);
return ($result === false) return ($result === false)
? new Failure(new FilesystemException(\error_get_last()["message"])) ? new Failure(new FilesystemException(\error_get_last()["message"]))
@ -343,7 +366,8 @@ class BlockingDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function put(string $path, string $contents): Promise { public function put(string $path, string $contents): Promise
{
$result = @\file_put_contents($path, $contents); $result = @\file_put_contents($path, $contents);
return ($result === false) return ($result === false)
? new Failure(new FilesystemException(\error_get_last()["message"])) ? new Failure(new FilesystemException(\error_get_last()["message"]))

View File

@ -9,7 +9,8 @@ use Amp\Promise;
use Amp\Success; use Amp\Success;
use function Amp\call; use function Amp\call;
class BlockingHandle implements Handle { class BlockingHandle implements Handle
{
private $fh; private $fh;
private $path; private $path;
private $mode; private $mode;
@ -19,13 +20,15 @@ class BlockingHandle implements Handle {
* @param string $path * @param string $path
* @param string $mode * @param string $mode
*/ */
public function __construct($fh, string $path, string $mode) { public function __construct($fh, string $path, string $mode)
{
$this->fh = $fh; $this->fh = $fh;
$this->path = $path; $this->path = $path;
$this->mode = $mode; $this->mode = $mode;
} }
public function __destruct() { public function __destruct()
{
if ($this->fh !== null) { if ($this->fh !== null) {
\fclose($this->fh); \fclose($this->fh);
} }
@ -34,7 +37,8 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function read(int $length = self::DEFAULT_READ_LENGTH): Promise { public function read(int $length = self::DEFAULT_READ_LENGTH): Promise
{
if ($this->fh === null) { if ($this->fh === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -53,7 +57,8 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function write(string $data): Promise { public function write(string $data): Promise
{
if ($this->fh === null) { if ($this->fh === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -72,7 +77,8 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function end(string $data = ""): Promise { public function end(string $data = ""): Promise
{
return call(function () use ($data) { return call(function () use ($data) {
$promise = $this->write($data); $promise = $this->write($data);
@ -86,7 +92,8 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close(): Promise { public function close(): Promise
{
if ($this->fh === null) { if ($this->fh === null) {
return new Success; return new Success;
} }
@ -106,7 +113,8 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function seek(int $position, int $whence = \SEEK_SET): Promise { public function seek(int $position, int $whence = \SEEK_SET): Promise
{
if ($this->fh === null) { if ($this->fh === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -129,7 +137,8 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function tell(): int { public function tell(): int
{
if ($this->fh === null) { if ($this->fh === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -140,7 +149,8 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function eof(): bool { public function eof(): bool
{
if ($this->fh === null) { if ($this->fh === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -151,14 +161,16 @@ class BlockingHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function path(): string { public function path(): string
{
return $this->path; return $this->path;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mode(): string { public function mode(): string
{
return $this->mode; return $this->mode;
} }
} }

View File

@ -4,7 +4,8 @@ namespace Amp\File;
use Amp\Promise; use Amp\Promise;
interface Driver { interface Driver
{
/** /**
* Open a handle for the specified path. * Open a handle for the specified path.
* *

View File

@ -6,18 +6,21 @@ use Amp\Deferred;
use Amp\Promise; use Amp\Promise;
use Amp\Success; use Amp\Success;
class EioDriver implements Driver { class EioDriver implements Driver
{
/** @var \Amp\File\Internal\EioPoll */ /** @var \Amp\File\Internal\EioPoll */
private $poll; private $poll;
public function __construct() { public function __construct()
{
$this->poll = new Internal\EioPoll; $this->poll = new Internal\EioPoll;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function open(string $path, string $mode): Promise { public function open(string $path, string $mode): Promise
{
$flags = \EIO_O_NONBLOCK | \EIO_O_FSYNC | $this->parseMode($mode); $flags = \EIO_O_NONBLOCK | \EIO_O_FSYNC | $this->parseMode($mode);
$chmod = ($flags & \EIO_O_CREAT) ? 0644 : 0; $chmod = ($flags & \EIO_O_CREAT) ? 0644 : 0;
@ -30,7 +33,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function parseMode(string $mode): int { private function parseMode(string $mode): int
{
$mode = \str_replace(['b', 't', 'e'], '', $mode); $mode = \str_replace(['b', 't', 'e'], '', $mode);
switch ($mode) { switch ($mode) {
@ -50,7 +54,8 @@ class EioDriver implements Driver {
} }
} }
private function onOpenHandle($openArr, $result, $req) { private function onOpenHandle($openArr, $result, $req)
{
list($mode, $path, $deferred) = $openArr; list($mode, $path, $deferred) = $openArr;
if ($result === -1) { if ($result === -1) {
@ -64,7 +69,8 @@ class EioDriver implements Driver {
} }
} }
private function onOpenFtruncate($openArr, $result, $req) { private function onOpenFtruncate($openArr, $result, $req)
{
list($fh, $mode, $path, $deferred) = $openArr; list($fh, $mode, $path, $deferred) = $openArr;
if ($result === -1) { if ($result === -1) {
@ -75,7 +81,8 @@ class EioDriver implements Driver {
} }
} }
private function onOpenFstat($openArr, $result, $req) { private function onOpenFstat($openArr, $result, $req)
{
list($fh, $mode, $path, $deferred) = $openArr; list($fh, $mode, $path, $deferred) = $openArr;
if ($result === -1) { if ($result === -1) {
$deferred->fail(new FilesystemException(\eio_get_last_error($req))); $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
@ -89,7 +96,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function stat(string $path): Promise { public function stat(string $path): Promise
{
if ($stat = StatCache::get($path)) { if ($stat = StatCache::get($path)) {
return new Success($stat); return new Success($stat);
} }
@ -104,7 +112,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onStat($data, $result, $req) { private function onStat($data, $result, $req)
{
list($deferred, $path) = $data; list($deferred, $path) = $data;
if ($result === -1) { if ($result === -1) {
$deferred->resolve(null); $deferred->resolve(null);
@ -117,7 +126,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exists(string $path): Promise { public function exists(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -130,7 +140,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function isdir(string $path): Promise { public function isdir(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -147,7 +158,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function isfile(string $path): Promise { public function isfile(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -164,7 +176,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function size(string $path): Promise { public function size(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -187,7 +200,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mtime(string $path): Promise { public function mtime(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -206,7 +220,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function atime(string $path): Promise { public function atime(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -225,7 +240,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function ctime(string $path): Promise { public function ctime(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -244,7 +260,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function lstat(string $path): Promise { public function lstat(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -254,7 +271,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onLstat($deferred, $result, $req) { private function onLstat($deferred, $result, $req)
{
if ($result === -1) { if ($result === -1) {
$deferred->resolve(null); $deferred->resolve(null);
} else { } else {
@ -265,7 +283,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function symlink(string $target, string $link): Promise { public function symlink(string $target, string $link): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -278,7 +297,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function link(string $target, string $link): Promise { public function link(string $target, string $link): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -291,7 +311,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function readlink(string $path): Promise { public function readlink(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -301,7 +322,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onReadlink($deferred, $result, $req) { private function onReadlink($deferred, $result, $req)
{
if ($result === -1) { if ($result === -1) {
$deferred->fail(new FilesystemException(\eio_get_last_error($req))); $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
} else { } else {
@ -309,7 +331,8 @@ class EioDriver implements Driver {
} }
} }
private function onGenericResult($deferred, $result, $req) { private function onGenericResult($deferred, $result, $req)
{
if ($result === -1) { if ($result === -1) {
$deferred->fail(new FilesystemException(\eio_get_last_error($req))); $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
} else { } else {
@ -320,7 +343,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rename(string $from, string $to): Promise { public function rename(string $from, string $to): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -333,7 +357,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function unlink(string $path): Promise { public function unlink(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -344,7 +369,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onUnlink($data, $result, $req) { private function onUnlink($data, $result, $req)
{
list($deferred, $path) = $data; list($deferred, $path) = $data;
if ($result === -1) { if ($result === -1) {
@ -358,21 +384,22 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise { public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
$priority = \EIO_PRI_DEFAULT; $priority = \EIO_PRI_DEFAULT;
if ($recursive) { if ($recursive) {
$path = str_replace("/", DIRECTORY_SEPARATOR, $path); $path = \str_replace("/", DIRECTORY_SEPARATOR, $path);
$arrayPath = explode(DIRECTORY_SEPARATOR, $path); $arrayPath = \explode(DIRECTORY_SEPARATOR, $path);
$tmpPath = ""; $tmpPath = "";
$callback = function () use ( $callback = function () use (
&$callback, &$arrayPath, &$tmpPath, $mode, $priority, $deferred &$callback, &$arrayPath, &$tmpPath, $mode, $priority, $deferred
) { ) {
$tmpPath .= DIRECTORY_SEPARATOR . array_shift($arrayPath); $tmpPath .= DIRECTORY_SEPARATOR . \array_shift($arrayPath);
if (empty($arrayPath)) { if (empty($arrayPath)) {
\eio_mkdir($tmpPath, $mode, $priority, [$this, "onGenericResult"], $deferred); \eio_mkdir($tmpPath, $mode, $priority, [$this, "onGenericResult"], $deferred);
@ -400,7 +427,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rmdir(string $path): Promise { public function rmdir(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -411,7 +439,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onRmdir($data, $result, $req) { private function onRmdir($data, $result, $req)
{
list($deferred, $path) = $data; list($deferred, $path) = $data;
if ($result === -1) { if ($result === -1) {
@ -425,7 +454,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function scandir(string $path): Promise { public function scandir(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -436,7 +466,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onScandir($deferred, $result, $req) { private function onScandir($deferred, $result, $req)
{
if ($result === -1) { if ($result === -1) {
$deferred->fail(new FilesystemException(\eio_get_last_error($req))); $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
} else { } else {
@ -447,7 +478,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chmod(string $path, int $mode): Promise { public function chmod(string $path, int $mode): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -460,7 +492,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chown(string $path, int $uid, int $gid): Promise { public function chown(string $path, int $uid, int $gid): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -473,7 +506,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function touch(string $path, int $time = null, int $atime = null): Promise { public function touch(string $path, int $time = null, int $atime = null): Promise
{
$time = $time ?? \time(); $time = $time ?? \time();
$atime = $atime ?? $time; $atime = $atime ?? $time;
@ -489,7 +523,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function get(string $path): Promise { public function get(string $path): Promise
{
$flags = $flags = \EIO_O_RDONLY; $flags = $flags = \EIO_O_RDONLY;
$mode = 0; $mode = 0;
$priority = \EIO_PRI_DEFAULT; $priority = \EIO_PRI_DEFAULT;
@ -502,7 +537,8 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onGetOpen($deferred, $result, $req) { private function onGetOpen($deferred, $result, $req)
{
if ($result === -1) { if ($result === -1) {
$deferred->fail(new FilesystemException(\eio_get_last_error($req))); $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
} else { } else {
@ -511,7 +547,8 @@ class EioDriver implements Driver {
} }
} }
private function onGetFstat($fhAndPromisor, $result, $req) { private function onGetFstat($fhAndPromisor, $result, $req)
{
list($fh, $deferred) = $fhAndPromisor; list($fh, $deferred) = $fhAndPromisor;
if ($result === -1) { if ($result === -1) {
@ -525,7 +562,8 @@ class EioDriver implements Driver {
\eio_read($fh, $length, $offset, $priority, [$this, "onGetRead"], $fhAndPromisor); \eio_read($fh, $length, $offset, $priority, [$this, "onGetRead"], $fhAndPromisor);
} }
private function onGetRead($fhAndPromisor, $result, $req) { private function onGetRead($fhAndPromisor, $result, $req)
{
list($fh, $deferred) = $fhAndPromisor; list($fh, $deferred) = $fhAndPromisor;
\eio_close($fh); \eio_close($fh);
@ -540,7 +578,8 @@ class EioDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function put(string $path, string $contents): Promise { public function put(string $path, string $contents): Promise
{
$flags = \EIO_O_RDWR | \EIO_O_CREAT; $flags = \EIO_O_RDWR | \EIO_O_CREAT;
$mode = \EIO_S_IRUSR | \EIO_S_IWUSR | \EIO_S_IXUSR; $mode = \EIO_S_IRUSR | \EIO_S_IWUSR | \EIO_S_IXUSR;
$priority = \EIO_PRI_DEFAULT; $priority = \EIO_PRI_DEFAULT;
@ -554,13 +593,14 @@ class EioDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function onPutOpen($data, $result, $req) { private function onPutOpen($data, $result, $req)
{
list($contents, $deferred) = $data; list($contents, $deferred) = $data;
if ($result === -1) { if ($result === -1) {
$deferred->fail(new FilesystemException(\eio_get_last_error($req))); $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
} else { } else {
$length = strlen($contents); $length = \strlen($contents);
$offset = 0; $offset = 0;
$priority = \EIO_PRI_DEFAULT; $priority = \EIO_PRI_DEFAULT;
$callback = [$this, "onPutWrite"]; $callback = [$this, "onPutWrite"];
@ -569,7 +609,8 @@ class EioDriver implements Driver {
} }
} }
private function onPutWrite($fhAndPromisor, $result, $req) { private function onPutWrite($fhAndPromisor, $result, $req)
{
list($fh, $deferred) = $fhAndPromisor; list($fh, $deferred) = $fhAndPromisor;
\eio_close($fh); \eio_close($fh);

View File

@ -9,7 +9,8 @@ use Amp\Promise;
use Amp\Success; use Amp\Success;
use function Amp\call; use function Amp\call;
class EioHandle implements Handle { class EioHandle implements Handle
{
/** @var \Amp\File\Internal\EioPoll */ /** @var \Amp\File\Internal\EioPoll */
private $poll; private $poll;
@ -40,7 +41,8 @@ class EioHandle implements Handle {
/** @var \Amp\Promise|null */ /** @var \Amp\Promise|null */
private $closing; private $closing;
public function __construct(Internal\EioPoll $poll, $fh, string $path, string $mode, int $size) { public function __construct(Internal\EioPoll $poll, $fh, string $path, string $mode, int $size)
{
$this->poll = $poll; $this->poll = $poll;
$this->fh = $fh; $this->fh = $fh;
$this->path = $path; $this->path = $path;
@ -54,7 +56,8 @@ class EioHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function read(int $length = self::DEFAULT_READ_LENGTH): Promise { public function read(int $length = self::DEFAULT_READ_LENGTH): Promise
{
if ($this->isActive) { if ($this->isActive) {
throw new PendingOperationError; throw new PendingOperationError;
} }
@ -79,7 +82,8 @@ class EioHandle implements Handle {
return $deferred->promise(); return $deferred->promise();
} }
private function onRead(Deferred $deferred, $result, $req) { private function onRead(Deferred $deferred, $result, $req)
{
$this->isActive = false; $this->isActive = false;
if ($result === -1) { if ($result === -1) {
@ -98,7 +102,8 @@ class EioHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function write(string $data): Promise { public function write(string $data): Promise
{
if ($this->isActive && $this->queue->isEmpty()) { if ($this->isActive && $this->queue->isEmpty()) {
throw new PendingOperationError; throw new PendingOperationError;
} }
@ -124,7 +129,8 @@ class EioHandle implements Handle {
return $promise; return $promise;
} }
private function push(string $data): Promise { private function push(string $data): Promise
{
$length = \strlen($data); $length = \strlen($data);
$deferred = new Deferred; $deferred = new Deferred;
@ -146,7 +152,8 @@ class EioHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function end(string $data = ""): Promise { public function end(string $data = ""): Promise
{
return call(function () use ($data) { return call(function () use ($data) {
$promise = $this->write($data); $promise = $this->write($data);
$this->writable = false; $this->writable = false;
@ -158,7 +165,8 @@ class EioHandle implements Handle {
}); });
} }
private function onWrite(Deferred $deferred, $result, $req) { private function onWrite(Deferred $deferred, $result, $req)
{
if ($this->queue->isEmpty()) { if ($this->queue->isEmpty()) {
$deferred->fail(new ClosedException('No pending write, the file may have been closed')); $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
} }
@ -188,7 +196,8 @@ class EioHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close(): Promise { public function close(): Promise
{
if ($this->closing) { if ($this->closing) {
return $this->closing; return $this->closing;
} }
@ -201,7 +210,8 @@ class EioHandle implements Handle {
return $deferred->promise(); return $deferred->promise();
} }
private function onClose(Deferred $deferred, $result, $req) { private function onClose(Deferred $deferred, $result, $req)
{
// Ignore errors when closing file, as the handle will become invalid anyway. // Ignore errors when closing file, as the handle will become invalid anyway.
$deferred->resolve(); $deferred->resolve();
} }
@ -209,7 +219,8 @@ class EioHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function seek(int $offset, int $whence = \SEEK_SET): Promise { public function seek(int $offset, int $whence = \SEEK_SET): Promise
{
if ($this->isActive) { if ($this->isActive) {
throw new PendingOperationError; throw new PendingOperationError;
} }
@ -236,28 +247,32 @@ class EioHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function tell(): int { public function tell(): int
{
return $this->position; return $this->position;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function eof(): bool { public function eof(): bool
{
return !$this->queue->isEmpty() ? false : ($this->size <= $this->position); return !$this->queue->isEmpty() ? false : ($this->size <= $this->position);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function path(): string { public function path(): string
{
return $this->path; return $this->path;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mode(): string { public function mode(): string
{
return $this->mode; return $this->mode;
} }
} }

View File

@ -2,8 +2,10 @@
namespace Amp\File; namespace Amp\File;
class FilesystemException extends \Exception { class FilesystemException extends \Exception
public function __construct(string $message, \Throwable $previous = null) { {
public function __construct(string $message, \Throwable $previous = null)
{
parent::__construct($message, 0, $previous); parent::__construct($message, 0, $previous);
} }
} }

View File

@ -6,7 +6,8 @@ use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream; use Amp\ByteStream\OutputStream;
use Amp\Promise; use Amp\Promise;
interface Handle extends InputStream, OutputStream { interface Handle extends InputStream, OutputStream
{
const DEFAULT_READ_LENGTH = 8192; const DEFAULT_READ_LENGTH = 8192;
/** /**

View File

@ -6,7 +6,8 @@ use Amp\CallableMaker;
use Amp\Loop; use Amp\Loop;
use Amp\Promise; use Amp\Promise;
class EioPoll { class EioPoll
{
use CallableMaker; use CallableMaker;
/** @var resource */ /** @var resource */
@ -21,7 +22,8 @@ class EioPoll {
/** @var callable */ /** @var callable */
private $onDone; private $onDone;
public function __construct() { public function __construct()
{
$this->onDone = $this->callableFromInstanceMethod("done"); $this->onDone = $this->callableFromInstanceMethod("done");
if (!self::$stream) { if (!self::$stream) {
@ -40,11 +42,13 @@ class EioPoll {
Loop::setState(self::class, new class($this->watcher) { Loop::setState(self::class, new class($this->watcher) {
private $watcher; private $watcher;
public function __construct(string $watcher) { public function __construct(string $watcher)
{
$this->watcher = $watcher; $this->watcher = $watcher;
} }
public function __destruct() { public function __destruct()
{
Loop::cancel($this->watcher); Loop::cancel($this->watcher);
// Ensure there are no active operations anymore. This is a safe-guard as some operations might not be // Ensure there are no active operations anymore. This is a safe-guard as some operations might not be
@ -55,7 +59,8 @@ class EioPoll {
}); });
} }
public function listen(Promise $promise) { public function listen(Promise $promise)
{
if ($this->requests++ === 0) { if ($this->requests++ === 0) {
Loop::enable($this->watcher); Loop::enable($this->watcher);
} }
@ -63,7 +68,8 @@ class EioPoll {
$promise->onResolve($this->onDone); $promise->onResolve($this->onDone);
} }
private function done() { private function done()
{
if (--$this->requests === 0) { if (--$this->requests === 0) {
Loop::disable($this->watcher); Loop::disable($this->watcher);
} }

View File

@ -14,7 +14,8 @@ use Amp\Parallel\Worker\Task;
* *
* @internal * @internal
*/ */
class FileTask implements Task { class FileTask implements Task
{
const ENV_PREFIX = "amp/file#"; const ENV_PREFIX = "amp/file#";
/** @var string */ /** @var string */
@ -33,7 +34,8 @@ class FileTask implements Task {
* *
* @throws \Error * @throws \Error
*/ */
public function __construct(string $operation, array $args = [], int $id = null) { public function __construct(string $operation, array $args = [], int $id = null)
{
if (!\strlen($operation)) { if (!\strlen($operation)) {
throw new \Error('Operation must be a non-empty string'); throw new \Error('Operation must be a non-empty string');
} }
@ -49,7 +51,8 @@ class FileTask implements Task {
* @throws \Amp\File\FilesystemException * @throws \Amp\File\FilesystemException
* @throws \Error * @throws \Error
*/ */
public function run(Environment $environment) { public function run(Environment $environment)
{
if ('f' === $this->operation[0]) { if ('f' === $this->operation[0]) {
if ("fopen" === $this->operation) { if ("fopen" === $this->operation) {
$path = $this->args[0]; $path = $this->args[0];
@ -152,7 +155,8 @@ class FileTask implements Task {
* *
* @return string * @return string
*/ */
private static function makeId(int $id): string { private static function makeId(int $id): string
{
return self::ENV_PREFIX . $id; return self::ENV_PREFIX . $id;
} }
} }

View File

@ -6,7 +6,8 @@ use Amp\CallableMaker;
use Amp\Loop; use Amp\Loop;
use Amp\Promise; use Amp\Promise;
class UvPoll { class UvPoll
{
use CallableMaker; use CallableMaker;
/** @var string */ /** @var string */
@ -18,7 +19,8 @@ class UvPoll {
/** @var callable */ /** @var callable */
private $onDone; private $onDone;
public function __construct() { public function __construct()
{
$this->onDone = $this->callableFromInstanceMethod("done"); $this->onDone = $this->callableFromInstanceMethod("done");
$this->watcher = Loop::repeat(\PHP_INT_MAX / 2, function () { $this->watcher = Loop::repeat(\PHP_INT_MAX / 2, function () {
@ -30,17 +32,20 @@ class UvPoll {
Loop::setState(self::class, new class($this->watcher) { Loop::setState(self::class, new class($this->watcher) {
private $watcher; private $watcher;
public function __construct(string $watcher) { public function __construct(string $watcher)
{
$this->watcher = $watcher; $this->watcher = $watcher;
} }
public function __destruct() { public function __destruct()
{
Loop::cancel($this->watcher); Loop::cancel($this->watcher);
} }
}); });
} }
public function listen(Promise $promise) { public function listen(Promise $promise)
{
if ($this->requests++ === 0) { if ($this->requests++ === 0) {
Loop::enable($this->watcher); Loop::enable($this->watcher);
} }
@ -48,7 +53,8 @@ class UvPoll {
$promise->onResolve($this->onDone); $promise->onResolve($this->onDone);
} }
private function done() { private function done()
{
if (--$this->requests === 0) { if (--$this->requests === 0) {
Loop::disable($this->watcher); Loop::disable($this->watcher);
} }

View File

@ -11,7 +11,8 @@ use Amp\Promise;
use Amp\Success; use Amp\Success;
use function Amp\call; use function Amp\call;
class ParallelDriver implements Driver { class ParallelDriver implements Driver
{
/** /**
* @var \Amp\Parallel\Worker\Pool * @var \Amp\Parallel\Worker\Pool
*/ */
@ -20,14 +21,16 @@ class ParallelDriver implements Driver {
/** /**
* @param \Amp\Parallel\Worker\Pool|null $pool * @param \Amp\Parallel\Worker\Pool|null $pool
*/ */
public function __construct(Pool $pool = null) { public function __construct(Pool $pool = null)
{
$this->pool = $pool ?: Worker\pool(); $this->pool = $pool ?: Worker\pool();
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function open(string $path, string $mode): Promise { public function open(string $path, string $mode): Promise
{
return call(function () use ($path, $mode) { return call(function () use ($path, $mode) {
$worker = $this->pool->getWorker(); $worker = $this->pool->getWorker();
try { try {
@ -41,7 +44,8 @@ class ParallelDriver implements Driver {
}); });
} }
private function runFileTask(Internal\FileTask $task): \Generator { private function runFileTask(Internal\FileTask $task): \Generator
{
try { try {
return yield $this->pool->enqueue($task); return yield $this->pool->enqueue($task);
} catch (TaskException $exception) { } catch (TaskException $exception) {
@ -54,7 +58,8 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function unlink(string $path): Promise { public function unlink(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$result = yield from $this->runFileTask(new Internal\FileTask("unlink", [$path])); $result = yield from $this->runFileTask(new Internal\FileTask("unlink", [$path]));
StatCache::clear($path); StatCache::clear($path);
@ -65,7 +70,8 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function stat(string $path): Promise { public function stat(string $path): Promise
{
if ($stat = StatCache::get($path)) { if ($stat = StatCache::get($path)) {
return new Success($stat); return new Success($stat);
} }
@ -82,14 +88,16 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rename(string $from, string $to): Promise { public function rename(string $from, string $to): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("rename", [$from, $to]))); return new Coroutine($this->runFileTask(new Internal\FileTask("rename", [$from, $to])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function isfile(string $path): Promise { public function isfile(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$stat = yield $this->stat($path); $stat = yield $this->stat($path);
if (empty($stat)) { if (empty($stat)) {
@ -105,7 +113,8 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function isdir(string $path): Promise { public function isdir(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$stat = yield $this->stat($path); $stat = yield $this->stat($path);
if (empty($stat)) { if (empty($stat)) {
@ -121,42 +130,48 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function link(string $target, string $link): Promise { public function link(string $target, string $link): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("link", [$target, $link]))); return new Coroutine($this->runFileTask(new Internal\FileTask("link", [$target, $link])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function symlink(string $target, string $link): Promise { public function symlink(string $target, string $link): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("symlink", [$target, $link]))); return new Coroutine($this->runFileTask(new Internal\FileTask("symlink", [$target, $link])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function readlink(string $path): Promise { public function readlink(string $path): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("readlink", [$path]))); return new Coroutine($this->runFileTask(new Internal\FileTask("readlink", [$path])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise { public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("mkdir", [$path, $mode, $recursive]))); return new Coroutine($this->runFileTask(new Internal\FileTask("mkdir", [$path, $mode, $recursive])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function scandir(string $path): Promise { public function scandir(string $path): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("scandir", [$path]))); return new Coroutine($this->runFileTask(new Internal\FileTask("scandir", [$path])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rmdir(string $path): Promise { public function rmdir(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$result = yield from $this->runFileTask(new Internal\FileTask("rmdir", [$path])); $result = yield from $this->runFileTask(new Internal\FileTask("rmdir", [$path]));
StatCache::clear($path); StatCache::clear($path);
@ -167,28 +182,32 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chmod(string $path, int $mode): Promise { public function chmod(string $path, int $mode): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("chmod", [$path, $mode]))); return new Coroutine($this->runFileTask(new Internal\FileTask("chmod", [$path, $mode])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chown(string $path, int $uid, int $gid): Promise { public function chown(string $path, int $uid, int $gid): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("chown", [$path, $uid, $gid]))); return new Coroutine($this->runFileTask(new Internal\FileTask("chown", [$path, $uid, $gid])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exists(string $path): Promise { public function exists(string $path): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("exists", [$path]))); return new Coroutine($this->runFileTask(new Internal\FileTask("exists", [$path])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function size(string $path): Promise { public function size(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$stat = yield $this->stat($path); $stat = yield $this->stat($path);
if (empty($stat)) { if (empty($stat)) {
@ -204,7 +223,8 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mtime(string $path): Promise { public function mtime(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$stat = yield $this->stat($path); $stat = yield $this->stat($path);
if (empty($stat)) { if (empty($stat)) {
@ -217,7 +237,8 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function atime(string $path): Promise { public function atime(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$stat = yield $this->stat($path); $stat = yield $this->stat($path);
if (empty($stat)) { if (empty($stat)) {
@ -230,7 +251,8 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function ctime(string $path): Promise { public function ctime(string $path): Promise
{
return call(function () use ($path) { return call(function () use ($path) {
$stat = yield $this->stat($path); $stat = yield $this->stat($path);
if (empty($stat)) { if (empty($stat)) {
@ -243,28 +265,32 @@ class ParallelDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function lstat(string $path): Promise { public function lstat(string $path): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("lstat", [$path]))); return new Coroutine($this->runFileTask(new Internal\FileTask("lstat", [$path])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function touch(string $path, int $time = null, int $atime = null): Promise { public function touch(string $path, int $time = null, int $atime = null): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("touch", [$path, $time, $atime]))); return new Coroutine($this->runFileTask(new Internal\FileTask("touch", [$path, $time, $atime])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function get(string $path): Promise { public function get(string $path): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("get", [$path]))); return new Coroutine($this->runFileTask(new Internal\FileTask("get", [$path])));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function put(string $path, string $contents): Promise { public function put(string $path, string $contents): Promise
{
return new Coroutine($this->runFileTask(new Internal\FileTask("put", [$path, $contents]))); return new Coroutine($this->runFileTask(new Internal\FileTask("put", [$path, $contents])));
} }
} }

View File

@ -12,7 +12,8 @@ use Amp\Promise;
use Amp\Success; use Amp\Success;
use function Amp\call; use function Amp\call;
class ParallelHandle implements Handle { class ParallelHandle implements Handle
{
/** @var \Amp\Parallel\Worker\Worker */ /** @var \Amp\Parallel\Worker\Worker */
private $worker; private $worker;
@ -50,7 +51,8 @@ class ParallelHandle implements Handle {
* @param int $size * @param int $size
* @param string $mode * @param string $mode
*/ */
public function __construct(Worker $worker, int $id, string $path, int $size, string $mode) { public function __construct(Worker $worker, int $id, string $path, int $size, string $mode)
{
$this->worker = $worker; $this->worker = $worker;
$this->id = $id; $this->id = $id;
$this->path = $path; $this->path = $path;
@ -59,7 +61,8 @@ class ParallelHandle implements Handle {
$this->position = $this->mode[0] === 'a' ? $this->size : 0; $this->position = $this->mode[0] === 'a' ? $this->size : 0;
} }
public function __destruct() { public function __destruct()
{
if ($this->id !== null) { if ($this->id !== null) {
$this->close(); $this->close();
} }
@ -68,14 +71,16 @@ class ParallelHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function path(): string { public function path(): string
{
return $this->path; return $this->path;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close(): Promise { public function close(): Promise
{
if ($this->closing) { if ($this->closing) {
return $this->closing; return $this->closing;
} }
@ -95,11 +100,13 @@ class ParallelHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function eof(): bool { public function eof(): bool
{
return $this->pendingWrites === 0 && $this->size <= $this->position; return $this->pendingWrites === 0 && $this->size <= $this->position;
} }
public function read(int $length = self::DEFAULT_READ_LENGTH): Promise { public function read(int $length = self::DEFAULT_READ_LENGTH): Promise
{
if ($this->id === null) { if ($this->id === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -111,7 +118,8 @@ class ParallelHandle implements Handle {
return new Coroutine($this->doRead($length)); return new Coroutine($this->doRead($length));
} }
private function doRead(int $length): \Generator { private function doRead(int $length): \Generator
{
$this->busy = true; $this->busy = true;
try { try {
@ -130,7 +138,8 @@ class ParallelHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function write(string $data): Promise { public function write(string $data): Promise
{
if ($this->id === null) { if ($this->id === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -149,7 +158,8 @@ class ParallelHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function end(string $data = ""): Promise { public function end(string $data = ""): Promise
{
return call(function () use ($data) { return call(function () use ($data) {
$promise = $this->write($data); $promise = $this->write($data);
$this->writable = false; $this->writable = false;
@ -161,7 +171,8 @@ class ParallelHandle implements Handle {
}); });
} }
private function doWrite(string $data): \Generator { private function doWrite(string $data): \Generator
{
++$this->pendingWrites; ++$this->pendingWrites;
$this->busy = true; $this->busy = true;
@ -184,7 +195,8 @@ class ParallelHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function seek(int $offset, int $whence = SEEK_SET): Promise { public function seek(int $offset, int $whence = SEEK_SET): Promise
{
if ($this->id === null) { if ($this->id === null) {
throw new ClosedException("The file has been closed"); throw new ClosedException("The file has been closed");
} }
@ -196,7 +208,8 @@ class ParallelHandle implements Handle {
return new Coroutine($this->doSeek($offset, $whence)); return new Coroutine($this->doSeek($offset, $whence));
} }
private function doSeek(int $offset, int $whence) { private function doSeek(int $offset, int $whence)
{
switch ($whence) { switch ($whence) {
case \SEEK_SET: case \SEEK_SET:
case \SEEK_CUR: case \SEEK_CUR:
@ -225,21 +238,24 @@ class ParallelHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function tell(): int { public function tell(): int
{
return $this->position; return $this->position;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function size(): int { public function size(): int
{
return $this->size; return $this->size;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mode(): string { public function mode(): string
{
return $this->mode; return $this->mode;
} }
} }

View File

@ -2,7 +2,8 @@
namespace Amp\File; namespace Amp\File;
class PendingOperationError extends \Error { class PendingOperationError extends \Error
{
public function __construct( public function __construct(
string $message = "The previous file operation must complete before another can be started", string $message = "The previous file operation must complete before another can be started",
int $code = 0, int $code = 0,

View File

@ -4,13 +4,15 @@ namespace Amp\File;
use Amp\Loop; use Amp\Loop;
class StatCache { class StatCache
{
private static $cache = []; private static $cache = [];
private static $timeouts = []; private static $timeouts = [];
private static $ttl = 3; private static $ttl = 3;
private static $now = null; private static $now = null;
private static function init() { private static function init()
{
self::$now = \time(); self::$now = \time();
$watcher = Loop::repeat(1000, function () { $watcher = Loop::repeat(1000, function () {
@ -33,22 +35,26 @@ class StatCache {
private $watcher; private $watcher;
private $driver; private $driver;
public function __construct(string $watcher) { public function __construct(string $watcher)
{
$this->watcher = $watcher; $this->watcher = $watcher;
$this->driver = Loop::get(); $this->driver = Loop::get();
} }
public function __destruct() { public function __destruct()
{
$this->driver->cancel($this->watcher); $this->driver->cancel($this->watcher);
} }
}); });
} }
public static function get(string $path) { public static function get(string $path)
{
return isset(self::$cache[$path]) ? self::$cache[$path] : null; return isset(self::$cache[$path]) ? self::$cache[$path] : null;
} }
public static function set(string $path, array $stat) { public static function set(string $path, array $stat)
{
if (self::$ttl <= 0) { if (self::$ttl <= 0) {
return; return;
} }
@ -61,11 +67,13 @@ class StatCache {
self::$timeouts[$path] = self::$now + self::$ttl; self::$timeouts[$path] = self::$now + self::$ttl;
} }
public static function ttl(int $seconds) { public static function ttl(int $seconds)
{
self::$ttl = $seconds; self::$ttl = $seconds;
} }
public static function clear(string $path = null) { public static function clear(string $path = null)
{
if (isset($path)) { if (isset($path)) {
unset( unset(
self::$cache[$path], self::$cache[$path],

View File

@ -9,7 +9,8 @@ use Amp\Loop;
use Amp\Promise; use Amp\Promise;
use Amp\Success; use Amp\Success;
class UvDriver implements Driver { class UvDriver implements Driver
{
/** @var \Amp\Loop\Driver */ /** @var \Amp\Loop\Driver */
private $driver; private $driver;
@ -22,7 +23,8 @@ class UvDriver implements Driver {
/** /**
* @param \Amp\Loop\UvDriver $driver * @param \Amp\Loop\UvDriver $driver
*/ */
public function __construct(Loop\UvDriver $driver) { public function __construct(Loop\UvDriver $driver)
{
$this->driver = $driver; $this->driver = $driver;
$this->loop = $driver->getHandle(); $this->loop = $driver->getHandle();
$this->poll = new UvPoll; $this->poll = new UvPoll;
@ -31,7 +33,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function open(string $path, string $mode): Promise { public function open(string $path, string $mode): Promise
{
$flags = $this->parseMode($mode); $flags = $this->parseMode($mode);
$chmod = ($flags & \UV::O_CREAT) ? 0644 : 0; $chmod = ($flags & \UV::O_CREAT) ? 0644 : 0;
@ -53,7 +56,8 @@ class UvDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function parseMode(string $mode): int { private function parseMode(string $mode): int
{
$mode = \str_replace(['b', 't', 'e'], '', $mode); $mode = \str_replace(['b', 't', 'e'], '', $mode);
switch ($mode) { switch ($mode) {
@ -73,7 +77,8 @@ class UvDriver implements Driver {
} }
} }
private function onOpenHandle($fh, array $openArr) { private function onOpenHandle($fh, array $openArr)
{
list($mode) = $openArr; list($mode) = $openArr;
if ($mode[0] === "w") { if ($mode[0] === "w") {
@ -102,7 +107,8 @@ class UvDriver implements Driver {
} }
} }
private function finalizeHandle($fh, $size, array $openArr) { private function finalizeHandle($fh, $size, array $openArr)
{
list($mode, $path, $deferred) = $openArr; list($mode, $path, $deferred) = $openArr;
$handle = new UvHandle($this->driver, $this->poll, $fh, $path, $mode, $size); $handle = new UvHandle($this->driver, $this->poll, $fh, $path, $mode, $size);
$deferred->resolve($handle); $deferred->resolve($handle);
@ -111,7 +117,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function stat(string $path): Promise { public function stat(string $path): Promise
{
if ($stat = StatCache::get($path)) { if ($stat = StatCache::get($path)) {
return new Success($stat); return new Success($stat);
} }
@ -143,7 +150,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exists(string $path): Promise { public function exists(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -156,7 +164,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function isdir(string $path): Promise { public function isdir(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -173,7 +182,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function isfile(string $path): Promise { public function isfile(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -190,7 +200,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function size(string $path): Promise { public function size(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -213,7 +224,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mtime(string $path): Promise { public function mtime(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -232,7 +244,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function atime(string $path): Promise { public function atime(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -251,7 +264,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function ctime(string $path): Promise { public function ctime(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->stat($path)->onResolve(function ($error, $result) use ($deferred) { $this->stat($path)->onResolve(function ($error, $result) use ($deferred) {
@ -270,7 +284,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function lstat(string $path): Promise { public function lstat(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -288,7 +303,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function symlink(string $target, string $link): Promise { public function symlink(string $target, string $link): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -302,7 +318,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function link(string $target, string $link): Promise { public function link(string $target, string $link): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -316,14 +333,15 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function readlink(string $path): Promise { public function readlink(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
\uv_fs_readlink($this->loop, $path, function ($fh, $target) use ($deferred) { \uv_fs_readlink($this->loop, $path, function ($fh, $target) use ($deferred) {
if (!(bool) $fh) { if (!(bool) $fh) {
$deferred->fail(new FilesystemException("Could not read symbolic link")); $deferred->fail(new FilesystemException("Could not read symbolic link"));
return; return;
} }
@ -336,7 +354,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rename(string $from, string $to): Promise { public function rename(string $from, string $to): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -351,7 +370,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function unlink(string $path): Promise { public function unlink(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -366,19 +386,20 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise { public function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
if ($recursive) { if ($recursive) {
$path = str_replace("/", DIRECTORY_SEPARATOR, $path); $path = \str_replace("/", DIRECTORY_SEPARATOR, $path);
$arrayPath = explode(DIRECTORY_SEPARATOR, $path); $arrayPath = \explode(DIRECTORY_SEPARATOR, $path);
$tmpPath = ""; $tmpPath = "";
$callback = function () use ( $callback = function () use (
&$callback, &$arrayPath, &$tmpPath, $mode, $deferred &$callback, &$arrayPath, &$tmpPath, $mode, $deferred
) { ) {
$tmpPath .= DIRECTORY_SEPARATOR . array_shift($arrayPath); $tmpPath .= DIRECTORY_SEPARATOR . \array_shift($arrayPath);
if (empty($arrayPath)) { if (empty($arrayPath)) {
\uv_fs_mkdir($this->loop, $tmpPath, $mode, function ($fh) use ($deferred) { \uv_fs_mkdir($this->loop, $tmpPath, $mode, function ($fh) use ($deferred) {
@ -410,7 +431,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function rmdir(string $path): Promise { public function rmdir(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -425,11 +447,12 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function scandir(string $path): Promise { public function scandir(string $path): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
uv_fs_readdir($this->loop, $path, 0, function ($fh, $data) use ($deferred, $path) { \uv_fs_readdir($this->loop, $path, 0, function ($fh, $data) use ($deferred, $path) {
if (empty($fh)) { if (empty($fh)) {
$deferred->fail(new FilesystemException("Failed reading contents from {$path}")); $deferred->fail(new FilesystemException("Failed reading contents from {$path}"));
} else { } else {
@ -443,7 +466,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chmod(string $path, int $mode): Promise { public function chmod(string $path, int $mode): Promise
{
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -457,7 +481,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function chown(string $path, int $uid, int $gid): Promise { public function chown(string $path, int $uid, int $gid): Promise
{
// @TODO Return a failure in windows environments // @TODO Return a failure in windows environments
$deferred = new Deferred; $deferred = new Deferred;
$this->poll->listen($deferred->promise()); $this->poll->listen($deferred->promise());
@ -472,7 +497,8 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function touch(string $path, int $time = null, int $atime = null): Promise { public function touch(string $path, int $time = null, int $atime = null): Promise
{
$time = $time ?? \time(); $time = $time ?? \time();
$atime = $atime ?? $time; $atime = $atime ?? $time;
@ -490,14 +516,16 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function get(string $path): Promise { public function get(string $path): Promise
{
$promise = new Coroutine($this->doGet($path)); $promise = new Coroutine($this->doGet($path));
$this->poll->listen($promise); $this->poll->listen($promise);
return $promise; return $promise;
} }
private function doGet($path): \Generator { private function doGet($path): \Generator
{
$promise = $this->doFsOpen($path, $flags = \UV::O_RDONLY, $mode = 0); $promise = $this->doFsOpen($path, $flags = \UV::O_RDONLY, $mode = 0);
if (!$fh = yield $promise) { if (!$fh = yield $promise) {
throw new FilesystemException("Failed opening file handle: {$path}"); throw new FilesystemException("Failed opening file handle: {$path}");
@ -530,7 +558,8 @@ class UvDriver implements Driver {
return yield $deferred->promise(); return yield $deferred->promise();
} }
private function doFsOpen($path, $flags, $mode) { private function doFsOpen($path, $flags, $mode)
{
$deferred = new Deferred; $deferred = new Deferred;
\uv_fs_open($this->loop, $path, $flags, $mode, function ($fh) use ($deferred, $path) { \uv_fs_open($this->loop, $path, $flags, $mode, function ($fh) use ($deferred, $path) {
@ -540,7 +569,8 @@ class UvDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function doFsStat($fh) { private function doFsStat($fh)
{
$deferred = new Deferred; $deferred = new Deferred;
\uv_fs_fstat($this->loop, $fh, function ($fh, $stat) use ($deferred) { \uv_fs_fstat($this->loop, $fh, function ($fh, $stat) use ($deferred) {
@ -556,7 +586,8 @@ class UvDriver implements Driver {
return $deferred->promise(); return $deferred->promise();
} }
private function doFsRead($fh, $offset, $len) { private function doFsRead($fh, $offset, $len)
{
$deferred = new Deferred; $deferred = new Deferred;
\uv_fs_read($this->loop, $fh, $offset, $len, function ($fh, $nread, $buffer) use ($deferred) { \uv_fs_read($this->loop, $fh, $offset, $len, function ($fh, $nread, $buffer) use ($deferred) {
@ -569,14 +600,16 @@ class UvDriver implements Driver {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function put(string $path, string $contents): Promise { public function put(string $path, string $contents): Promise
{
$promise = new Coroutine($this->doPut($path, $contents)); $promise = new Coroutine($this->doPut($path, $contents));
$this->poll->listen($promise); $this->poll->listen($promise);
return $promise; return $promise;
} }
private function doPut($path, $contents): \Generator { private function doPut($path, $contents): \Generator
{
$flags = \UV::O_WRONLY | \UV::O_CREAT; $flags = \UV::O_WRONLY | \UV::O_CREAT;
$mode = \UV::S_IRWXU | \UV::S_IRUSR; $mode = \UV::S_IRWXU | \UV::S_IRUSR;
@ -587,7 +620,7 @@ class UvDriver implements Driver {
} }
$deferred = new Deferred; $deferred = new Deferred;
$len = strlen($contents); $len = \strlen($contents);
\uv_fs_write($this->loop, $fh, $contents, $offset = 0, function ($fh, $result) use ($deferred, $len) { \uv_fs_write($this->loop, $fh, $contents, $offset = 0, function ($fh, $result) use ($deferred, $len) {
\uv_fs_close($this->loop, $fh, function () use ($deferred, $result, $len) { \uv_fs_close($this->loop, $fh, function () use ($deferred, $result, $len) {

View File

@ -11,7 +11,8 @@ use Amp\Promise;
use Amp\Success; use Amp\Success;
use function Amp\call; use function Amp\call;
class UvHandle implements Handle { class UvHandle implements Handle
{
/** @var UvPoll */ /** @var UvPoll */
private $poll; private $poll;
@ -53,7 +54,8 @@ class UvHandle implements Handle {
* @param string $mode * @param string $mode
* @param int $size * @param int $size
*/ */
public function __construct(Loop\UvDriver $driver, UvPoll $poll, $fh, string $path, string $mode, int $size) { public function __construct(Loop\UvDriver $driver, UvPoll $poll, $fh, string $path, string $mode, int $size)
{
$this->poll = $poll; $this->poll = $poll;
$this->fh = $fh; $this->fh = $fh;
$this->path = $path; $this->path = $path;
@ -65,7 +67,8 @@ class UvHandle implements Handle {
$this->queue = new \SplQueue; $this->queue = new \SplQueue;
} }
public function read(int $length = self::DEFAULT_READ_LENGTH): Promise { public function read(int $length = self::DEFAULT_READ_LENGTH): Promise
{
if ($this->isActive) { if ($this->isActive) {
throw new PendingOperationError; throw new PendingOperationError;
} }
@ -86,7 +89,7 @@ class UvHandle implements Handle {
$deferred->fail(new StreamException("Reading from the file failed: " . $error)); $deferred->fail(new StreamException("Reading from the file failed: " . $error));
} }
} else { } else {
$length = strlen($buffer); $length = \strlen($buffer);
$this->position = $this->position + $length; $this->position = $this->position + $length;
$deferred->resolve($length ? $buffer : null); $deferred->resolve($length ? $buffer : null);
} }
@ -100,7 +103,8 @@ class UvHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function write(string $data): Promise { public function write(string $data): Promise
{
if ($this->isActive && $this->queue->isEmpty()) { if ($this->isActive && $this->queue->isEmpty()) {
throw new PendingOperationError; throw new PendingOperationError;
} }
@ -129,7 +133,8 @@ class UvHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function end(string $data = ""): Promise { public function end(string $data = ""): Promise
{
return call(function () use ($data) { return call(function () use ($data) {
$promise = $this->write($data); $promise = $this->write($data);
$this->writable = false; $this->writable = false;
@ -141,7 +146,8 @@ class UvHandle implements Handle {
}); });
} }
private function push(string $data): Promise { private function push(string $data): Promise
{
$length = \strlen($data); $length = \strlen($data);
$deferred = new Deferred; $deferred = new Deferred;
@ -182,7 +188,8 @@ class UvHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function seek(int $offset, int $whence = \SEEK_SET): Promise { public function seek(int $offset, int $whence = \SEEK_SET): Promise
{
if ($this->isActive) { if ($this->isActive) {
throw new PendingOperationError; throw new PendingOperationError;
} }
@ -210,35 +217,40 @@ class UvHandle implements Handle {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function tell(): int { public function tell(): int
{
return $this->position; return $this->position;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function eof(): bool { public function eof(): bool
{
return !$this->queue->isEmpty() ? false : ($this->size <= $this->position); return !$this->queue->isEmpty() ? false : ($this->size <= $this->position);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function path(): string { public function path(): string
{
return $this->path; return $this->path;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function mode(): string { public function mode(): string
{
return $this->mode; return $this->mode;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function close(): Promise { public function close(): Promise
{
if ($this->closing) { if ($this->closing) {
return $this->closing; return $this->closing;
} }

View File

@ -13,7 +13,8 @@ const LOOP_STATE_IDENTIFIER = Driver::class;
* @param \Amp\File\Driver $driver Use the specified object as the application-wide filesystem instance * @param \Amp\File\Driver $driver Use the specified object as the application-wide filesystem instance
* @return \Amp\File\Driver * @return \Amp\File\Driver
*/ */
function filesystem(Driver $driver = null): Driver { function filesystem(Driver $driver = null): Driver
{
if ($driver === null) { if ($driver === null) {
$driver = Loop::getState(LOOP_STATE_IDENTIFIER); $driver = Loop::getState(LOOP_STATE_IDENTIFIER);
if ($driver) { if ($driver) {
@ -36,7 +37,8 @@ function filesystem(Driver $driver = null): Driver {
* *
* @return \Amp\File\Driver * @return \Amp\File\Driver
*/ */
function driver(): Driver { function driver(): Driver
{
$driver = Loop::get(); $driver = Loop::get();
if ($driver instanceof Loop\UvDriver) { if ($driver instanceof Loop\UvDriver) {
@ -61,7 +63,8 @@ function driver(): Driver {
* @param string $mode * @param string $mode
* @return \Amp\Promise<\Amp\File\Handle> * @return \Amp\Promise<\Amp\File\Handle>
*/ */
function open(string $path, string $mode): Promise { function open(string $path, string $mode): Promise
{
return filesystem()->open($path, $mode); return filesystem()->open($path, $mode);
} }
@ -74,7 +77,8 @@ function open(string $path, string $mode): Promise {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<array|null> * @return \Amp\Promise<array|null>
*/ */
function stat(string $path): Promise { function stat(string $path): Promise
{
return filesystem()->stat($path); return filesystem()->stat($path);
} }
@ -87,7 +91,8 @@ function stat(string $path): Promise {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<bool> * @return \Amp\Promise<bool>
*/ */
function exists(string $path): Promise { function exists(string $path): Promise
{
return filesystem()->exists($path); return filesystem()->exists($path);
} }
@ -101,7 +106,8 @@ function exists(string $path): Promise {
* @fails \Amp\Files\FilesystemException If the path does not exist or is not a file * @fails \Amp\Files\FilesystemException If the path does not exist or is not a file
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
function size(string $path): Promise { function size(string $path): Promise
{
return filesystem()->size($path); return filesystem()->size($path);
} }
@ -114,7 +120,8 @@ function size(string $path): Promise {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<bool> * @return \Amp\Promise<bool>
*/ */
function isdir(string $path): Promise { function isdir(string $path): Promise
{
return filesystem()->isdir($path); return filesystem()->isdir($path);
} }
@ -127,7 +134,8 @@ function isdir(string $path): Promise {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<bool> * @return \Amp\Promise<bool>
*/ */
function isfile(string $path): Promise { function isfile(string $path): Promise
{
return filesystem()->isfile($path); return filesystem()->isfile($path);
} }
@ -138,7 +146,8 @@ function isfile(string $path): Promise {
* @fails \Amp\Files\FilesystemException If the path does not exist * @fails \Amp\Files\FilesystemException If the path does not exist
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
function mtime(string $path): Promise { function mtime(string $path): Promise
{
return filesystem()->mtime($path); return filesystem()->mtime($path);
} }
@ -149,7 +158,8 @@ function mtime(string $path): Promise {
* @fails \Amp\Files\FilesystemException If the path does not exist * @fails \Amp\Files\FilesystemException If the path does not exist
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
function atime($path) { function atime($path)
{
return filesystem()->atime($path); return filesystem()->atime($path);
} }
@ -160,7 +170,8 @@ function atime($path) {
* @fails \Amp\Files\FilesystemException If the path does not exist * @fails \Amp\Files\FilesystemException If the path does not exist
* @return \Amp\Promise<int> * @return \Amp\Promise<int>
*/ */
function ctime(string $path): Promise { function ctime(string $path): Promise
{
return filesystem()->ctime($path); return filesystem()->ctime($path);
} }
@ -173,7 +184,8 @@ function ctime(string $path): Promise {
* @param string $path An absolute file system path * @param string $path An absolute file system path
* @return \Amp\Promise<array|null> * @return \Amp\Promise<array|null>
*/ */
function lstat(string $path): Promise { function lstat(string $path): Promise
{
return filesystem()->lstat($path); return filesystem()->lstat($path);
} }
@ -185,7 +197,8 @@ function lstat(string $path): Promise {
* @fails \Amp\Files\FilesystemException If the operation fails * @fails \Amp\Files\FilesystemException If the operation fails
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function symlink(string $original, string $link): Promise { function symlink(string $original, string $link): Promise
{
return filesystem()->symlink($original, $link); return filesystem()->symlink($original, $link);
} }
@ -197,7 +210,8 @@ function symlink(string $original, string $link): Promise {
* @fails \Amp\Files\FilesystemException If the operation fails * @fails \Amp\Files\FilesystemException If the operation fails
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function link(string $original, string $link): Promise { function link(string $original, string $link): Promise
{
return filesystem()->symlink($original, $link); return filesystem()->symlink($original, $link);
} }
@ -208,7 +222,8 @@ function link(string $original, string $link): Promise {
* @fails \Amp\Files\FilesystemException If the operation fails * @fails \Amp\Files\FilesystemException If the operation fails
* @return \Amp\Promise<string> * @return \Amp\Promise<string>
*/ */
function readlink(string $path): Promise { function readlink(string $path): Promise
{
return filesystem()->readlink($path); return filesystem()->readlink($path);
} }
@ -220,7 +235,8 @@ function readlink(string $path): Promise {
* @fails \Amp\Files\FilesystemException If the operation fails * @fails \Amp\Files\FilesystemException If the operation fails
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function rename(string $from, string $to): Promise { function rename(string $from, string $to): Promise
{
return filesystem()->rename($from, $to); return filesystem()->rename($from, $to);
} }
@ -230,7 +246,8 @@ function rename(string $from, string $to): Promise {
* @param string $path * @param string $path
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function unlink(string $path): Promise { function unlink(string $path): Promise
{
return filesystem()->unlink($path); return filesystem()->unlink($path);
} }
@ -242,7 +259,8 @@ function unlink(string $path): Promise {
* @param bool $recursive * @param bool $recursive
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise { function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise
{
return filesystem()->mkdir($path, $mode, $recursive); return filesystem()->mkdir($path, $mode, $recursive);
} }
@ -252,7 +270,8 @@ function mkdir(string $path, int $mode = 0777, bool $recursive = false): Promise
* @param string $path * @param string $path
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function rmdir(string $path): Promise { function rmdir(string $path): Promise
{
return filesystem()->rmdir($path); return filesystem()->rmdir($path);
} }
@ -264,7 +283,8 @@ function rmdir(string $path): Promise {
* @param string $path * @param string $path
* @return \Amp\Promise<array> * @return \Amp\Promise<array>
*/ */
function scandir(string $path): Promise { function scandir(string $path): Promise
{
return filesystem()->scandir($path); return filesystem()->scandir($path);
} }
@ -275,7 +295,8 @@ function scandir(string $path): Promise {
* @param int $mode * @param int $mode
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function chmod(string $path, int $mode): Promise { function chmod(string $path, int $mode): Promise
{
return filesystem()->chmod($path, $mode); return filesystem()->chmod($path, $mode);
} }
@ -287,7 +308,8 @@ function chmod(string $path, int $mode): Promise {
* @param int $gid -1 to ignore * @param int $gid -1 to ignore
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function chown(string $path, int $uid, int $gid = -1): Promise { function chown(string $path, int $uid, int $gid = -1): Promise
{
return filesystem()->chown($path, $uid, $gid); return filesystem()->chown($path, $uid, $gid);
} }
@ -301,7 +323,8 @@ function chown(string $path, int $uid, int $gid = -1): Promise {
* @param int $atime The access time. If $atime is not supplied, value passed to the $time parameter is used. * @param int $atime The access time. If $atime is not supplied, value passed to the $time parameter is used.
* @return \Amp\Promise<null> * @return \Amp\Promise<null>
*/ */
function touch(string $path, int $time = null, int $atime = null): Promise { function touch(string $path, int $time = null, int $atime = null): Promise
{
return filesystem()->touch($path, $time, $atime); return filesystem()->touch($path, $time, $atime);
} }
@ -311,7 +334,8 @@ function touch(string $path, int $time = null, int $atime = null): Promise {
* @param string $path The file path from which to buffer contents * @param string $path The file path from which to buffer contents
* @return \Amp\Promise<string> * @return \Amp\Promise<string>
*/ */
function get(string $path): Promise { function get(string $path): Promise
{
return filesystem()->get($path); return filesystem()->get($path);
} }
@ -322,6 +346,7 @@ function get(string $path): Promise {
* @param string $contents The data to write to the specified $path * @param string $contents The data to write to the specified $path
* @return \Amp\Promise A promise resolving to the integer length written upon success * @return \Amp\Promise A promise resolving to the integer length written upon success
*/ */
function put(string $path, string $contents): Promise { function put(string $path, string $contents): Promise
{
return filesystem()->put($path, $contents); return filesystem()->put($path, $contents);
} }

View File

@ -4,11 +4,13 @@ namespace Amp\File\Test;
use Amp\File; use Amp\File;
abstract class AsyncHandleTest extends HandleTest { abstract class AsyncHandleTest extends HandleTest
{
/** /**
* @expectedException \Amp\File\PendingOperationError * @expectedException \Amp\File\PendingOperationError
*/ */
public function testSimultaneousReads() { public function testSimultaneousReads()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -26,7 +28,8 @@ abstract class AsyncHandleTest extends HandleTest {
/** /**
* @expectedException \Amp\File\PendingOperationError * @expectedException \Amp\File\PendingOperationError
*/ */
public function testSeekWhileReading() { public function testSeekWhileReading()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -44,7 +47,8 @@ abstract class AsyncHandleTest extends HandleTest {
/** /**
* @expectedException \Amp\File\PendingOperationError * @expectedException \Amp\File\PendingOperationError
*/ */
public function testReadWhileWriting() { public function testReadWhileWriting()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -63,7 +67,8 @@ abstract class AsyncHandleTest extends HandleTest {
/** /**
* @expectedException \Amp\File\PendingOperationError * @expectedException \Amp\File\PendingOperationError
*/ */
public function testWriteWhileReading() { public function testWriteWhileReading()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");

View File

@ -6,8 +6,10 @@ use Amp\File;
use Amp\Loop; use Amp\Loop;
use function Amp\asyncCall; use function Amp\asyncCall;
class BlockingDriverTest extends DriverTest { class BlockingDriverTest extends DriverTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
Loop::run(function () use ($cb) { Loop::run(function () use ($cb) {
File\filesystem(new File\BlockingDriver); File\filesystem(new File\BlockingDriver);
asyncCall($cb); asyncCall($cb);

View File

@ -6,8 +6,10 @@ use Amp\File;
use Amp\Loop; use Amp\Loop;
use function Amp\asyncCall; use function Amp\asyncCall;
class BlockingHandleTest extends HandleTest { class BlockingHandleTest extends HandleTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
Loop::run(function () use ($cb) { Loop::run(function () use ($cb) {
File\filesystem(new File\BlockingDriver); File\filesystem(new File\BlockingDriver);
asyncCall($cb); asyncCall($cb);

View File

@ -5,19 +5,23 @@ namespace Amp\File\Test;
use Amp\File as file; use Amp\File as file;
use Amp\PHPUnit\TestCase; use Amp\PHPUnit\TestCase;
abstract class DriverTest extends TestCase { abstract class DriverTest extends TestCase
protected function setUp() { {
protected function setUp()
{
Fixture::init(); Fixture::init();
File\StatCache::clear(); File\StatCache::clear();
} }
protected function tearDown() { protected function tearDown()
{
Fixture::clear(); Fixture::clear();
} }
abstract protected function execute(callable $cb); abstract protected function execute(callable $cb);
public function testScandir() { public function testScandir()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$actual = yield File\scandir($fixtureDir); $actual = yield File\scandir($fixtureDir);
@ -29,7 +33,8 @@ abstract class DriverTest extends TestCase {
/** /**
* @expectedException \Amp\File\FilesystemException * @expectedException \Amp\File\FilesystemException
*/ */
public function testScandirThrowsIfPathNotADirectory() { public function testScandirThrowsIfPathNotADirectory()
{
$this->execute(function () { $this->execute(function () {
(yield File\scandir(__FILE__)); (yield File\scandir(__FILE__));
}); });
@ -38,14 +43,16 @@ abstract class DriverTest extends TestCase {
/** /**
* @expectedException \Amp\File\FilesystemException * @expectedException \Amp\File\FilesystemException
*/ */
public function testScandirThrowsIfPathDoesntExist() { public function testScandirThrowsIfPathDoesntExist()
{
$this->execute(function () { $this->execute(function () {
$path = Fixture::path() . "/nonexistent"; $path = Fixture::path() . "/nonexistent";
(yield File\scandir($path)); (yield File\scandir($path));
}); });
} }
public function testSymlink() { public function testSymlink()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
@ -57,7 +64,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testReadlink() { public function testReadlink()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
@ -69,10 +77,11 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function readlinkPathProvider() { public function readlinkPathProvider()
{
return [ return [
'nonExistingPath' => [function () { 'nonExistingPath' => [function () {
return Fixture::path() . '/' . uniqid(); return Fixture::path() . '/' . \uniqid();
}], }],
'notLink' => [function () { 'notLink' => [function () {
return Fixture::path(); return Fixture::path();
@ -86,7 +95,8 @@ abstract class DriverTest extends TestCase {
* *
* @param \Closure $linkResolver * @param \Closure $linkResolver
*/ */
public function testReadlinkError(\Closure $linkResolver) { public function testReadlinkError(\Closure $linkResolver)
{
$this->execute(function () use ($linkResolver) { $this->execute(function () use ($linkResolver) {
$link = $linkResolver(); $link = $linkResolver();
@ -94,7 +104,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testLstat() { public function testLstat()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
@ -106,7 +117,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testFileStat() { public function testFileStat()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$stat = (yield File\stat("{$fixtureDir}/small.txt")); $stat = (yield File\stat("{$fixtureDir}/small.txt"));
@ -115,7 +127,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testDirStat() { public function testDirStat()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$stat = (yield File\stat("{$fixtureDir}/dir")); $stat = (yield File\stat("{$fixtureDir}/dir"));
@ -124,7 +137,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testNonexistentPathStatResolvesToNull() { public function testNonexistentPathStatResolvesToNull()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$stat = (yield File\stat("{$fixtureDir}/nonexistent")); $stat = (yield File\stat("{$fixtureDir}/nonexistent"));
@ -132,7 +146,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testExists() { public function testExists()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$this->assertFalse(yield File\exists("{$fixtureDir}/nonexistent")); $this->assertFalse(yield File\exists("{$fixtureDir}/nonexistent"));
@ -140,14 +155,16 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testGet() { public function testGet()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$this->assertSame("small", yield File\get("{$fixtureDir}/small.txt")); $this->assertSame("small", yield File\get("{$fixtureDir}/small.txt"));
}); });
} }
public function testSize() { public function testSize()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/small.txt"; $path = "{$fixtureDir}/small.txt";
@ -161,7 +178,8 @@ abstract class DriverTest extends TestCase {
/** /**
* @expectedException \Amp\File\FilesystemException * @expectedException \Amp\File\FilesystemException
*/ */
public function testSizeFailsOnNonexistentPath() { public function testSizeFailsOnNonexistentPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/nonexistent"; $path = "{$fixtureDir}/nonexistent";
@ -172,7 +190,8 @@ abstract class DriverTest extends TestCase {
/** /**
* @expectedException \Amp\File\FilesystemException * @expectedException \Amp\File\FilesystemException
*/ */
public function testSizeFailsOnDirectoryPath() { public function testSizeFailsOnDirectoryPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/dir"; $path = "{$fixtureDir}/dir";
@ -182,7 +201,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testIsdirResolvesTrueOnDirectoryPath() { public function testIsdirResolvesTrueOnDirectoryPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/dir"; $path = "{$fixtureDir}/dir";
@ -190,7 +210,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testIsdirResolvesFalseOnFilePath() { public function testIsdirResolvesFalseOnFilePath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/small.txt"; $path = "{$fixtureDir}/small.txt";
@ -198,7 +219,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testIsdirResolvesFalseOnNonexistentPath() { public function testIsdirResolvesFalseOnNonexistentPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/nonexistent"; $path = "{$fixtureDir}/nonexistent";
@ -206,7 +228,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testIsfileResolvesTrueOnFilePath() { public function testIsfileResolvesTrueOnFilePath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/small.txt"; $path = "{$fixtureDir}/small.txt";
@ -214,7 +237,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testIsfileResolvesFalseOnDirectoryPath() { public function testIsfileResolvesFalseOnDirectoryPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/dir"; $path = "{$fixtureDir}/dir";
@ -222,7 +246,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testIsfileResolvesFalseOnNonexistentPath() { public function testIsfileResolvesFalseOnNonexistentPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/nonexistent"; $path = "{$fixtureDir}/nonexistent";
@ -230,7 +255,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testRename() { public function testRename()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
@ -247,7 +273,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testUnlink() { public function testUnlink()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$toUnlink = "{$fixtureDir}/unlink"; $toUnlink = "{$fixtureDir}/unlink";
@ -257,7 +284,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testMkdirRmdir() { public function testMkdirRmdir()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
@ -280,7 +308,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testMtime() { public function testMtime()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/small.txt"; $path = "{$fixtureDir}/small.txt";
@ -294,7 +323,8 @@ abstract class DriverTest extends TestCase {
/** /**
* @expectedException \Amp\File\FilesystemException * @expectedException \Amp\File\FilesystemException
*/ */
public function testMtimeFailsOnNonexistentPath() { public function testMtimeFailsOnNonexistentPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/nonexistent"; $path = "{$fixtureDir}/nonexistent";
@ -302,7 +332,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testAtime() { public function testAtime()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/small.txt"; $path = "{$fixtureDir}/small.txt";
@ -316,7 +347,8 @@ abstract class DriverTest extends TestCase {
/** /**
* @expectedException \Amp\File\FilesystemException * @expectedException \Amp\File\FilesystemException
*/ */
public function testAtimeFailsOnNonexistentPath() { public function testAtimeFailsOnNonexistentPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/nonexistent"; $path = "{$fixtureDir}/nonexistent";
@ -324,7 +356,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
public function testCtime() { public function testCtime()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/small.txt"; $path = "{$fixtureDir}/small.txt";
@ -338,7 +371,8 @@ abstract class DriverTest extends TestCase {
/** /**
* @expectedException \Amp\File\FilesystemException * @expectedException \Amp\File\FilesystemException
*/ */
public function testCtimeFailsOnNonexistentPath() { public function testCtimeFailsOnNonexistentPath()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
$path = "{$fixtureDir}/nonexistent"; $path = "{$fixtureDir}/nonexistent";
@ -349,7 +383,8 @@ abstract class DriverTest extends TestCase {
/** /**
* @group slow * @group slow
*/ */
public function testTouch() { public function testTouch()
{
$this->execute(function () { $this->execute(function () {
$fixtureDir = Fixture::path(); $fixtureDir = Fixture::path();
@ -367,7 +402,8 @@ abstract class DriverTest extends TestCase {
}); });
} }
private function assertStatSame(array $expected, array $actual) { private function assertStatSame(array $expected, array $actual)
{
$filter = function (array $stat) { $filter = function (array $stat) {
$filtered = \array_filter( $filtered = \array_filter(
$stat, $stat,
@ -377,7 +413,7 @@ abstract class DriverTest extends TestCase {
ARRAY_FILTER_USE_KEY ARRAY_FILTER_USE_KEY
); );
ksort($filtered); \ksort($filtered);
return $filtered; return $filtered;
}; };
@ -389,7 +425,8 @@ abstract class DriverTest extends TestCase {
* @param array $stat * @param array $stat
* @return string * @return string
*/ */
private function getPermissionsFromStat(array $stat): string { private function getPermissionsFromStat(array $stat): string
{
return \substr(\decoct($stat["mode"]), 1); return \substr(\decoct($stat["mode"]), 1);
} }
} }

View File

@ -6,8 +6,10 @@ use Amp\File;
use Amp\Loop; use Amp\Loop;
use function Amp\asyncCall; use function Amp\asyncCall;
class EioDriverTest extends DriverTest { class EioDriverTest extends DriverTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
if (!\extension_loaded("eio")) { if (!\extension_loaded("eio")) {
$this->markTestSkipped( $this->markTestSkipped(
"eio extension not loaded" "eio extension not loaded"

View File

@ -6,8 +6,10 @@ use Amp\File;
use Amp\Loop; use Amp\Loop;
use function Amp\asyncCall; use function Amp\asyncCall;
class EioHandleTest extends AsyncHandleTest { class EioHandleTest extends AsyncHandleTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
if (!\extension_loaded("eio")) { if (!\extension_loaded("eio")) {
$this->markTestSkipped( $this->markTestSkipped(
"eio extension not loaded" "eio extension not loaded"

View File

@ -2,18 +2,21 @@
namespace Amp\File\Test; namespace Amp\File\Test;
final class Fixture { final class Fixture
{
private static $fixtureId; private static $fixtureId;
public static function path() { public static function path()
{
if (empty(self::$fixtureId)) { if (empty(self::$fixtureId)) {
self::$fixtureId = \uniqid(); self::$fixtureId = \uniqid();
} }
return \sys_get_temp_dir() . "/amphp_file_fixture/" . strtr(__CLASS__, "\\", ".") . self::$fixtureId; return \sys_get_temp_dir() . "/amphp_file_fixture/" . \strtr(__CLASS__, "\\", ".") . self::$fixtureId;
} }
public static function init() { public static function init()
{
$fixtureDir = self::path(); $fixtureDir = self::path();
self::clear(); self::clear();
if (!\mkdir($fixtureDir, $mode = 0777, $recursive = true)) { if (!\mkdir($fixtureDir, $mode = 0777, $recursive = true)) {
@ -33,7 +36,8 @@ final class Fixture {
} }
} }
public static function clear() { public static function clear()
{
$fixtureDir = self::path(); $fixtureDir = self::path();
if (!\file_exists($fixtureDir)) { if (!\file_exists($fixtureDir)) {
return; return;

View File

@ -6,19 +6,23 @@ use Amp\ByteStream\ClosedException;
use Amp\File; use Amp\File;
use Amp\PHPUnit\TestCase; use Amp\PHPUnit\TestCase;
abstract class HandleTest extends TestCase { abstract class HandleTest extends TestCase
protected function setUp() { {
protected function setUp()
{
Fixture::init(); Fixture::init();
File\StatCache::clear(); File\StatCache::clear();
} }
protected function tearDown() { protected function tearDown()
{
Fixture::clear(); Fixture::clear();
} }
abstract protected function execute(callable $cb); abstract protected function execute(callable $cb);
public function testWrite() { public function testWrite()
{
$this->execute(function () { $this->execute(function () {
$path = Fixture::path() . "/write"; $path = Fixture::path() . "/write";
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
@ -37,7 +41,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testWriteAfterClose() { public function testWriteAfterClose()
{
$this->execute(function () { $this->execute(function () {
$path = Fixture::path() . "/write"; $path = Fixture::path() . "/write";
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
@ -49,7 +54,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testDoubleClose() { public function testDoubleClose()
{
$this->execute(function () { $this->execute(function () {
$path = Fixture::path() . "/write"; $path = Fixture::path() . "/write";
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
@ -59,7 +65,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testWriteAfterEnd() { public function testWriteAfterEnd()
{
$this->execute(function () { $this->execute(function () {
$path = Fixture::path() . "/write"; $path = Fixture::path() . "/write";
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
@ -72,7 +79,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testReadingToEof() { public function testReadingToEof()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -96,7 +104,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testSequentialReads() { public function testSequentialReads()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -112,7 +121,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testReadingFromOffset() { public function testReadingFromOffset()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -131,7 +141,8 @@ abstract class HandleTest extends TestCase {
/** /**
* @expectedException \Error * @expectedException \Error
*/ */
public function testSeekThrowsOnInvalidWhence() { public function testSeekThrowsOnInvalidWhence()
{
$this->execute(function () { $this->execute(function () {
try { try {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
@ -143,7 +154,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testSeekSetCur() { public function testSeekSetCur()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -156,7 +168,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testSeekSetEnd() { public function testSeekSetEnd()
{
$this->execute(function () { $this->execute(function () {
$size = yield File\size(__FILE__); $size = yield File\size(__FILE__);
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
@ -168,7 +181,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testPath() { public function testPath()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -177,7 +191,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testMode() { public function testMode()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");
@ -186,7 +201,8 @@ abstract class HandleTest extends TestCase {
}); });
} }
public function testClose() { public function testClose()
{
$this->execute(function () { $this->execute(function () {
/** @var \Amp\File\Handle $handle */ /** @var \Amp\File\Handle $handle */
$handle = yield File\open(__FILE__, "r"); $handle = yield File\open(__FILE__, "r");

View File

@ -7,8 +7,10 @@ use Amp\Loop;
use Amp\Parallel\Worker\DefaultPool; use Amp\Parallel\Worker\DefaultPool;
use function Amp\call; use function Amp\call;
class ParallelDriverTest extends DriverTest { class ParallelDriverTest extends DriverTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
Loop::run(function () use ($cb) { Loop::run(function () use ($cb) {
$pool = new DefaultPool; $pool = new DefaultPool;

View File

@ -7,8 +7,10 @@ use Amp\Loop;
use Amp\Parallel\Worker\DefaultPool; use Amp\Parallel\Worker\DefaultPool;
use function Amp\call; use function Amp\call;
class ParallelHandleTest extends AsyncHandleTest { class ParallelHandleTest extends AsyncHandleTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
Loop::run(function () use ($cb) { Loop::run(function () use ($cb) {
$pool = new DefaultPool; $pool = new DefaultPool;

View File

@ -6,8 +6,10 @@ use Amp\File;
use Amp\Loop; use Amp\Loop;
use function Amp\asyncCall; use function Amp\asyncCall;
class UvDriverTest extends DriverTest { class UvDriverTest extends DriverTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
if (!\extension_loaded("uv")) { if (!\extension_loaded("uv")) {
$this->markTestSkipped( $this->markTestSkipped(
"php-uv extension not loaded" "php-uv extension not loaded"
@ -28,7 +30,8 @@ class UvDriverTest extends DriverTest {
* *
* @param \Closure $linkResolver * @param \Closure $linkResolver
*/ */
public function testReadlinkError(\Closure $linkResolver) { public function testReadlinkError(\Closure $linkResolver)
{
$this->markTestSkipped('UvDriver Test Skipped: Causes Crash'); $this->markTestSkipped('UvDriver Test Skipped: Causes Crash');
} }
} }

View File

@ -6,8 +6,10 @@ use Amp\File;
use Amp\Loop; use Amp\Loop;
use function Amp\asyncCall; use function Amp\asyncCall;
class UvHandleTest extends AsyncHandleTest { class UvHandleTest extends AsyncHandleTest
protected function execute(callable $cb) { {
protected function execute(callable $cb)
{
if (!\extension_loaded("uv")) { if (!\extension_loaded("uv")) {
$this->markTestSkipped( $this->markTestSkipped(
"php-uv extension not loaded" "php-uv extension not loaded"