diff options
author | Ben Burgess <88810029+bx80@users.noreply.github.com> | 2022-03-08 03:39:56 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-08 03:39:56 +0300 |
commit | aa71a21596f684533aedaf6f8644345aa79883c3 (patch) | |
tree | 6365552d548ae38c3775a64d963947e27f7c784b | |
parent | ad1d93c0d303aafde519f1864d223ada410ea43c (diff) |
Handle case only file name updates on case insensitive file systems (#18865)
* Added unit test for case-sensitive unlink
* Use case-insensitive comparison in directoryDiff() if a case-insensitive filesystem is detected
* Fix misleading method name
* Update tests/PHPUnit/Unit/FilesystemTest.php
Co-authored-by: Justin Velluppillai <justin@innocraft.com>
* Update tests/PHPUnit/Unit/FilesystemTest.php
Co-authored-by: Justin Velluppillai <justin@innocraft.com>
Co-authored-by: Justin Velluppillai <justin@innocraft.com>
-rw-r--r-- | core/Filesystem.php | 23 | ||||
-rw-r--r-- | tests/PHPUnit/Unit/FilesystemTest.php | 66 |
2 files changed, 88 insertions, 1 deletions
diff --git a/core/Filesystem.php b/core/Filesystem.php index 4a7e7de106..5b8101291f 100644 --- a/core/Filesystem.php +++ b/core/Filesystem.php @@ -314,7 +314,11 @@ class Filesystem return str_replace($target, '', $file); }, $targetFiles); - $diff = array_diff($targetFiles, $sourceFiles); + if (FileSystem::isFileSystemCaseInsensitive()) { + $diff = array_udiff($targetFiles, $sourceFiles, 'strcasecmp'); + } else { + $diff = array_diff($targetFiles, $sourceFiles); + } return array_values($diff); } @@ -558,6 +562,23 @@ class Filesystem } /** + * Check if the filesystem is case sensitive by writing a temporary file + * + * @return bool + */ + public static function isFileSystemCaseInsensitive() : bool + { + $testFileName = 'caseSensitivityTest.txt'; + $pathTmp = StaticContainer::get('path.tmp'); + @file_put_contents($pathTmp.'/'.$testFileName, 'Nothing to see here.'); + if (\file_exists($pathTmp.'/'.strtolower($testFileName))) { + // Wrote caseSensitivityTest.txt but casesensitivitytest.txt exists, so case insensitive + return true; + } + return false; + } + + /** * in tmp/ (sub-)folder(s) we create empty index.htm|php files * * @param $path diff --git a/tests/PHPUnit/Unit/FilesystemTest.php b/tests/PHPUnit/Unit/FilesystemTest.php index b21705e796..4913ee0844 100644 --- a/tests/PHPUnit/Unit/FilesystemTest.php +++ b/tests/PHPUnit/Unit/FilesystemTest.php @@ -14,6 +14,7 @@ use Piwik\Tests\Framework\TestCase\SystemTestCase; /** * @group Core + * @group FileSystem */ class FilesystemTest extends \PHPUnit\Framework\TestCase { @@ -193,6 +194,51 @@ class FilesystemTest extends \PHPUnit\Framework\TestCase $this->assertEquals(array(), $result); } + public function test_unlockTargetFilesNotPresentInSource_doNotAttemptToUnlinkFilesWithTheSameCaseInsensitiveName() + { + $sourceInsensitive = $this->createCaseInsensitiveSourceFiles(); + $targetInsensitive = $this->createCaseInsensitiveTargetFiles(); + + // Target: /CoreHome/vue/src/Menudropdown/Menudropdown.vue' + // Source: /CoreHome/vue/src/MenuDropdown/MenuDropdown.vue' + + $result = Filesystem::directoryDiff($sourceInsensitive, $targetInsensitive); + + if (Filesystem::isFileSystemCaseInsensitive()) { + + // Case insensitive filesystem: + // Since the target and source will be treated as the same file then we do not want directoryDiff() to + // report a difference as copying the source command will overwrite the target file. Reporting a difference + // will cause the target file to be unlinked after the copy which will result in a missing file. + + $this->assertEquals(array(), $result); + + } else { + + // Case sensitive filesystem: + // directoryDiff() should report a difference and we should be able to unlink the target file safely after + // the source file has been copied. + + // make sure there is a difference between those folders + $this->assertNotEmpty($result); + + Filesystem::unlinkTargetFilesNotPresentInSource($sourceInsensitive, $targetInsensitive); + + // make sure there is no longer a difference + $result = Filesystem::directoryDiff($sourceInsensitive, $targetInsensitive); + $this->assertEquals(array(), $result); + + $result = Filesystem::directoryDiff($targetInsensitive, $sourceInsensitive); + $this->assertEquals(array( + '/CoreHome/vue/src/MenuDropdown', + '/CoreHome/vue/src/MenuDropdown/MenuDropdown.vue', + '/CoreHome/vue/src/MenuDropdown/index.htm', + '/CoreHome/vue/src/MenuDropdown/index.php', + ), $result); + + } + } + private function createSourceFiles() { $source = $this->createEmptySource(); @@ -265,6 +311,26 @@ class FilesystemTest extends \PHPUnit\Framework\TestCase return $this->testPath . '/target'; } + private function createCaseInsensitiveTargetFiles() + { + $target = $this->createEmptyTarget(); + Filesystem::mkdir($target . '/CoreHome/vue/src/Menudropdown'); + + file_put_contents($target . '/CoreHome/vue/src/Menudropdown/Menudropdown.vue', ''); + + return $target; + } + + private function createCaseInsensitiveSourceFiles() + { + $source = $this->createEmptySource(); + Filesystem::mkdir($source . '/CoreHome/vue/src/MenuDropdown'); + + file_put_contents($source . '/CoreHome/vue/src/MenuDropdown/MenuDropdown.vue', ''); + + return $source; + } + public function test_getFileSize_ZeroSize() { File::setFileSize(0); |