diff options
-rw-r--r-- | lib/private/Files/View.php | 15 | ||||
-rw-r--r-- | tests/lib/Files/ViewTest.php | 71 |
2 files changed, 81 insertions, 5 deletions
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 67f89180994..3ce21a3489b 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -2104,14 +2104,19 @@ class View { * @return bool */ private function createParentDirectories($filePath) { - $parentDirectory = dirname($filePath); - while(!$this->file_exists($parentDirectory)) { - $result = $this->createParentDirectories($parentDirectory); - if($result === false) { + $directoryParts = explode('/', $filePath); + $directoryParts = array_filter($directoryParts); + foreach($directoryParts as $key => $part) { + $currentPathElements = array_slice($directoryParts, 0, $key); + $currentPath = '/' . implode('/', $currentPathElements); + if($this->is_file($currentPath)) { return false; } + if(!$this->file_exists($currentPath)) { + $this->mkdir($currentPath); + } } - $this->mkdir($filePath); + return true; } } diff --git a/tests/lib/Files/ViewTest.php b/tests/lib/Files/ViewTest.php index 4c264472385..8ec9619087c 100644 --- a/tests/lib/Files/ViewTest.php +++ b/tests/lib/Files/ViewTest.php @@ -12,6 +12,7 @@ use OC\Files\Cache\Watcher; use OC\Files\Storage\Common; use OC\Files\Mount\MountPoint; use OC\Files\Storage\Temporary; +use OC\Files\View; use OCP\Files\Config\IMountProvider; use OCP\Files\FileInfo; use OCP\Lock\ILockingProvider; @@ -2499,4 +2500,74 @@ class ViewTest extends \Test\TestCase { $this->assertNotEquals($rootInfo->getEtag(), $newInfo->getEtag()); $this->assertEquals(0, $newInfo->getSize()); } + + public function testCreateParentDirectories() { + $view = $this->getMockBuilder(View::class) + ->disableOriginalConstructor() + ->setMethods([ + 'is_file', + 'file_exists', + 'mkdir', + ]) + ->getMock(); + + $view + ->expects($this->at(0)) + ->method('is_file') + ->with('/new') + ->willReturn(false); + $view + ->expects($this->at(1)) + ->method('file_exists') + ->with('/new') + ->willReturn(true); + $view + ->expects($this->at(2)) + ->method('is_file') + ->with('/new/folder') + ->willReturn(false); + $view + ->expects($this->at(3)) + ->method('file_exists') + ->with('/new/folder') + ->willReturn(false); + $view + ->expects($this->at(4)) + ->method('mkdir') + ->with('/new/folder'); + $view + ->expects($this->at(5)) + ->method('is_file') + ->with('/new/folder/structure') + ->willReturn(false); + $view + ->expects($this->at(6)) + ->method('file_exists') + ->with('/new/folder/structure') + ->willReturn(false); + $view + ->expects($this->at(7)) + ->method('mkdir') + ->with('/new/folder/structure'); + + $this->assertTrue(self::invokePrivate($view, 'createParentDirectories', ['/new/folder/structure'])); + } + + public function testCreateParentDirectoriesWithExistingFile() { + $view = $this->getMockBuilder(View::class) + ->disableOriginalConstructor() + ->setMethods([ + 'is_file', + 'file_exists', + 'mkdir', + ]) + ->getMock(); + + $view + ->expects($this->once()) + ->method('is_file') + ->with('/file.txt') + ->willReturn(true); + $this->assertFalse(self::invokePrivate($view, 'createParentDirectories', ['/file.txt/folder/structure'])); + } } |