-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update ::url_stat()
for directories
#16
base: 0.x
Are you sure you want to change the base?
Update ::url_stat()
for directories
#16
Conversation
@BrianHenryIE I've created a |
Ok, I was able to do that here in the GitHub UI – I had branched from the 0.4.0. tag earlier, so no need for a rebase per se. If you're curious what I'm doing – I'm writing a |
@BrianHenryIE I'm running your branch against PHP 7.4.33, Xdebug 3.1.6, and Flysystem 2.5.0. With no changes to the existing test suite, this line isn't covered. I tried making the following modifications to an existing test in attempt to get that coverage. diff --git a/tests/StreamWrapperTest.php b/tests/StreamWrapperTest.php
index 2d24b3a..584572d 100644
--- a/tests/StreamWrapperTest.php
+++ b/tests/StreamWrapperTest.php
@@ -40,11 +40,14 @@ afterEach(function () {
$this->registry->unregister('fly');
});
-it('can create and delete directories', function () {
+it('can detect, create, and delete directories', function () {
+ $this->assertFalse(is_dir('fly://foo'));
$result = mkdir('fly://foo');
expect($result)->toBeTrue();
+ $this->assertTrue(is_dir('fly://foo'));
rmdir('fly://foo');
-});
+ $this->assertFalse(is_dir('fly://foo'));
+})->only();
it('handles opening a nonexistent directory', function () {
$dir = opendir('fly://foo'); Unfortunately, the test fails, and I'm having trouble sorting out why. Any ideas?
|
I noticed the directory created was called ![]() But... as in #9, $this->filesystem = new Filesystem(
new \League\Flysystem\Local\LocalFilesystemAdapter(
sys_get_temp_dir() . '/' . uniqid('flystream')
),
[],
$pathNormalizer
); I'll take a look at backporting your |
I think this is ready to go now. |
$this->assertTrue(is_dir('fly://foo')); | ||
$rmResult = rmdir('fly://foo'); | ||
expect($rmResult)->toBeTrue(); | ||
clearstatcache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BrianHenryIE I'm wondering if this clearstatcache()
call shouldn't be in StreamWrapper->rmdir()
instead?
Below are some related bits of a conversation I had with Edorian in the #help
channel on the phpcommunity.org Discord earlier about this. Please give them a look and let me know what you think.
statcache
only every caches the last accessed file/dir. Some references:
rmdir
: https://github.com/php/php-src/blob/064ea9c505889fb84b2b3fc41230be26cc58a345/ext/standard/file.c#L1152
unlink
: https://github.com/php/php-src/blob/064ea9c505889fb84b2b3fc41230be26cc58a345/ext/standard/file.c#L1300Which should go through https://github.com/php/php-src/blob/38501ed48a6a8d9ad57605d6a49e796230ac4b42/main/php_streams.h#L158 and end up :
plain_files_unlink
https://github.com/php/php-src/blob/0fe3a91494e9aece3ae948cf9bf9d3476686e0a5/main/streams/plain_wrapper.c#L1269
php_plain_files_rmdir
https://github.com/php/php-src/blob/0fe3a91494e9aece3ae948cf9bf9d3476686e0a5/main/streams/plain_wrapper.c#L1500On empty directories everything looks fine to me:
<?php $dir = __DIR__ . '/tmp'; @rmdir($dir); mkdir($dir); var_dump("Exists:"); var_dump(stat($dir)['mtime']); rmdir($dir); var_dump("Cached?"); var_dump(stat($dir)['mtime']);=> php foo.php string(7) "Exists:" int(1738881324) string(7) "Cached?" PHP Warning: stat(): stat failed for /Users/edo/private/experiments/tmp in /Users/edo/private/experiments/foo.php on line 14
So the second
stat
call is not stale/cached information?https://www.php.net/manual/en/streamwrapper.rmdir.php doesn't mention this, but I'm guessing that an implementation of
streamWrapper->rmdir()
has to handle callingclearstatcache()
internally rather than PHP handling it automatically.Custom stream wrapper don't have to work on a local (or any) file system, so I don't think they can do anything automatically.
But if you call underlying system functions for file manipulation these should do a
clearstatcache
then. (LikeLocalFilesystemAdapter
should do?)Yeah looks like you're right on
url_stat
being cached by stat cache<?php $x = new class { public $context; public function url_stat(string $path, int $flags): array|false { var_dump("url_stat: $path"); return []; } }; stream_wrapper_register('test', get_class($x)); $dir = 'test://foo/bar'; var_dump(is_dir($dir)); var_dump(is_dir($dir)); var_dump(is_dir($dir));=> php foo.php string(24) "url_stat: test://foo/bar" bool(false) bool(false) bool(false)
But here neither unlink nor rmdir clears the stat cache with a trivial implementation by its self:
So yeah, with the added context of this being stream wrappers this makes more sense
From what I can see for stream wrappers this isn't done by php, the reasoning for that is beyond me though (or my tests are wrong somehow).
I don't seem to be able to specify 0.4.0 as the target for the PR.
::directoryExists()
is a Flysystem 3.0 function which I call when it's available, otherwise I have a re-implementation.This is working well in my integration tests for BrianHenryIE/strauss#139
Closes #15 !