From 91ae2db2019d2f7b6e2c98431ca89cf0f526c7a5 Mon Sep 17 00:00:00 2001 From: Sarsharses Date: Thu, 23 Jul 2026 12:11:10 +0200 Subject: [PATCH] fix: Guard against race condition in FileStore::createCacheDir --- src/Cache/FileStore.php | 5 +++-- tests/Cache/FileStoreTest.php | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Cache/FileStore.php b/src/Cache/FileStore.php index 92b854d..aa21d77 100644 --- a/src/Cache/FileStore.php +++ b/src/Cache/FileStore.php @@ -87,8 +87,9 @@ public function getCacheFile(): string */ protected function createCacheDir() { - if ( ! file_exists($this->cacheDir)) { - mkdir($this->cacheDir); + if ( ! is_dir($this->cacheDir)) { + // Suppress "File exists" warning when a concurrent request wins the race. + @mkdir($this->cacheDir, 0777, true); } } diff --git a/tests/Cache/FileStoreTest.php b/tests/Cache/FileStoreTest.php index d006d6c..f99c174 100644 --- a/tests/Cache/FileStoreTest.php +++ b/tests/Cache/FileStoreTest.php @@ -149,6 +149,28 @@ public function it_creates_cache_file_if_file_does_not_exist(): void $this->assertEquals(null, $this->fileStore->get($this->checksum)); } + /** + * @test + * + * @covers ::createCacheFile + * @covers ::createCacheDir + */ + public function it_creates_nested_cache_dir_recursively(): void + { + $nestedDir = Config::get('file.dir') . 'nested' . DS . 'cache' . DS; + $cacheFile = Config::get('file.name'); + $fileStore = new FileStore($nestedDir, $cacheFile); + + $fileStore->set($this->checksum, 'Test'); + + $this->assertDirectoryExists($nestedDir); + $this->assertFileExists($nestedDir . $cacheFile); + + unlink($nestedDir . $cacheFile); + rmdir($nestedDir); + rmdir(\dirname($nestedDir)); + } + /** * @test *