From 70acd85443c3883b2691326b8017c38c6688d53c Mon Sep 17 00:00:00 2001
From: Nicolas Grekas <nicolas.grekas@gmail.com>
Date: Mon, 2 Jun 2025 16:08:14 +0200
Subject: [PATCH 1/5] Allow Symfony ^8.0

---
 composer.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/composer.json b/composer.json
index c781e55b1..42bbfa08a 100644
--- a/composer.json
+++ b/composer.json
@@ -21,7 +21,7 @@
         "symfony/polyfill-mbstring": "~1.8"
     },
     "require-dev": {
-        "symfony/process": "^6.4|^7.0"
+        "symfony/process": "^6.4|^7.0|^8.0"
     },
     "autoload": {
         "psr-4": { "Symfony\\Component\\Filesystem\\": "" },

From a2c66f86d0a4a7282fa023df3b7c2368d89f2c8b Mon Sep 17 00:00:00 2001
From: Nicolas Grekas <nicolas.grekas@gmail.com>
Date: Mon, 2 Jun 2025 17:50:55 +0200
Subject: [PATCH 2/5] Bump Symfony 8 to PHP >= 8.4

---
 composer.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/composer.json b/composer.json
index 42bbfa08a..893c9a1e4 100644
--- a/composer.json
+++ b/composer.json
@@ -16,12 +16,12 @@
         }
     ],
     "require": {
-        "php": ">=8.2",
+        "php": ">=8.4",
         "symfony/polyfill-ctype": "~1.8",
         "symfony/polyfill-mbstring": "~1.8"
     },
     "require-dev": {
-        "symfony/process": "^6.4|^7.0|^8.0"
+        "symfony/process": "^7.4|^8.0"
     },
     "autoload": {
         "psr-4": { "Symfony\\Component\\Filesystem\\": "" },

From 7df39720b1634375cb474089f34342589bbeda21 Mon Sep 17 00:00:00 2001
From: Nicolas Grekas <nicolas.grekas@gmail.com>
Date: Thu, 24 Jul 2025 14:45:41 +0200
Subject: [PATCH 3/5] Fix typos

---
 Tests/FilesystemTestCase.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Tests/FilesystemTestCase.php b/Tests/FilesystemTestCase.php
index ce9176a47..0f060a12c 100644
--- a/Tests/FilesystemTestCase.php
+++ b/Tests/FilesystemTestCase.php
@@ -103,7 +103,7 @@ protected function getFileOwner($filepath)
     {
         $this->markAsSkippedIfPosixIsMissing();
 
-        return ($datas = posix_getpwuid($this->getFileOwnerId($filepath))) ? $datas['name'] : null;
+        return ($data = posix_getpwuid($this->getFileOwnerId($filepath))) ? $data['name'] : null;
     }
 
     protected function getFileGroupId($filepath)
@@ -119,8 +119,8 @@ protected function getFileGroup($filepath)
     {
         $this->markAsSkippedIfPosixIsMissing();
 
-        if ($datas = posix_getgrgid($this->getFileGroupId($filepath))) {
-            return $datas['name'];
+        if ($data = posix_getgrgid($this->getFileGroupId($filepath))) {
+            return $data['name'];
         }
 
         $this->markTestSkipped('Unable to retrieve file group name');

From a6c0406619a7c071c8ac6b58fd26580bbc4a2f87 Mon Sep 17 00:00:00 2001
From: Christian Flothmann <christian.flothmann@qossmic.com>
Date: Wed, 9 Oct 2024 11:06:51 +0200
Subject: [PATCH 4/5] run tests using PHPUnit 11.5

---
 phpunit.xml.dist | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index e7418f42c..de9ee5866 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/9.3/phpunit.xsd"
+         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.3/phpunit.xsd"
          backupGlobals="false"
          colors="true"
          bootstrap="vendor/autoload.php"
+         failOnDeprecation="true"
          failOnRisky="true"
          failOnWarning="true"
 >
@@ -18,7 +19,7 @@
         </testsuite>
     </testsuites>
 
-    <coverage>
+    <source ignoreSuppressionOfDeprecations="true">
         <include>
             <directory>./</directory>
         </include>
@@ -26,5 +27,9 @@
             <directory>./Tests</directory>
             <directory>./vendor</directory>
         </exclude>
-    </coverage>
+    </source>
+
+    <extensions>
+        <bootstrap class="Symfony\Bridge\PhpUnit\SymfonyExtension" />
+    </extensions>
 </phpunit>

From 7d2dac345a4e20bcdedc5963ceea97ebe40e70ca Mon Sep 17 00:00:00 2001
From: Christian Flothmann <christian.flothmann@open.de>
Date: Thu, 31 Jul 2025 14:36:46 +0200
Subject: [PATCH 5/5] replace PHPUnit annotations with attributes

---
 Tests/FilesystemTest.php | 18 ++++-------
 Tests/PathTest.php       | 67 +++++++++++-----------------------------
 2 files changed, 24 insertions(+), 61 deletions(-)

diff --git a/Tests/FilesystemTest.php b/Tests/FilesystemTest.php
index 4c3355c79..64d2525a3 100644
--- a/Tests/FilesystemTest.php
+++ b/Tests/FilesystemTest.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\Filesystem\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\Depends;
 use Symfony\Component\Filesystem\Exception\InvalidArgumentException;
 use Symfony\Component\Filesystem\Exception\IOException;
 use Symfony\Component\Filesystem\Path;
@@ -889,9 +891,7 @@ public function testSymlink()
         $this->assertEquals($file, readlink($link));
     }
 
-    /**
-     * @depends testSymlink
-     */
+    #[Depends('testSymlink')]
     public function testRemoveSymlink()
     {
         $this->markAsSkippedIfSymlinkIsMissing();
@@ -970,9 +970,7 @@ public function testLink()
         $this->assertEquals(fileinode($file), fileinode($link));
     }
 
-    /**
-     * @depends testLink
-     */
+    #[Depends('testLink')]
     public function testRemoveLink()
     {
         $this->markAsSkippedIfLinkIsMissing();
@@ -1142,9 +1140,7 @@ public function testReadLinkCanonicalizedPathDoesNotExist()
         $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'invalid'), true));
     }
 
-    /**
-     * @dataProvider providePathsForMakePathRelative
-     */
+    #[DataProvider('providePathsForMakePathRelative')]
     public function testMakePathRelative($endPath, $startPath, $expectedPath)
     {
         $path = $this->filesystem->makePathRelative($endPath, $startPath);
@@ -1430,9 +1426,7 @@ public function testMirrorFromSubdirectoryInToParentDirectory()
         $this->assertFileEquals($file1, $targetPath.'file1');
     }
 
-    /**
-     * @dataProvider providePathsForIsAbsolutePath
-     */
+    #[DataProvider('providePathsForIsAbsolutePath')]
     public function testIsAbsolutePath($path, $expectedResult)
     {
         $result = $this->filesystem->isAbsolutePath($path);
diff --git a/Tests/PathTest.php b/Tests/PathTest.php
index 285d55f0d..b818a7518 100644
--- a/Tests/PathTest.php
+++ b/Tests/PathTest.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\Filesystem\Tests;
 
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Filesystem\Path;
 
@@ -164,9 +165,7 @@ public static function provideCanonicalizationTests(): \Generator
         yield ['~/../../css/style.css', '/css/style.css'];
     }
 
-    /**
-     * @dataProvider provideCanonicalizationTests
-     */
+    #[DataProvider('provideCanonicalizationTests')]
     public function testCanonicalize(string $path, string $canonicalized)
     {
         $this->assertSame($canonicalized, Path::canonicalize($path));
@@ -227,9 +226,7 @@ public static function provideGetDirectoryTests(): \Generator
         yield ['D:/Folder/Aééé/Subfolder', 'D:/Folder/Aééé'];
     }
 
-    /**
-     * @dataProvider provideGetDirectoryTests
-     */
+    #[DataProvider('provideGetDirectoryTests')]
     public function testGetDirectory(string $path, string $directory)
     {
         $this->assertSame($directory, Path::getDirectory($path));
@@ -258,9 +255,7 @@ public static function provideGetFilenameWithoutExtensionTests(): \Generator
         yield ['/webmozart/symfony/.style.css', '.css', '.style'];
     }
 
-    /**
-     * @dataProvider provideGetFilenameWithoutExtensionTests
-     */
+    #[DataProvider('provideGetFilenameWithoutExtensionTests')]
     public function testGetFilenameWithoutExtension(string $path, ?string $extension, string $filename)
     {
         $this->assertSame($filename, Path::getFilenameWithoutExtension($path, $extension));
@@ -283,9 +278,7 @@ public static function provideGetExtensionTests(): \Generator
         yield ['/webmozart/symfony/style.ÄÖÜ', true, 'äöü'];
     }
 
-    /**
-     * @dataProvider provideGetExtensionTests
-     */
+    #[DataProvider('provideGetExtensionTests')]
     public function testGetExtension(string $path, bool $forceLowerCase, string $extension)
     {
         $this->assertSame($extension, Path::getExtension($path, $forceLowerCase));
@@ -329,10 +322,9 @@ public static function provideHasExtensionTests(): \Generator
     }
 
     /**
-     * @dataProvider provideHasExtensionTests
-     *
      * @param string|string[]|null $extension
      */
+    #[DataProvider('provideHasExtensionTests')]
     public function testHasExtension(bool $hasExtension, string $path, $extension, bool $ignoreCase)
     {
         $this->assertSame($hasExtension, Path::hasExtension($path, $extension, $ignoreCase));
@@ -354,9 +346,7 @@ public static function provideChangeExtensionTests(): \Generator
         yield ['', 'css', ''];
     }
 
-    /**
-     * @dataProvider provideChangeExtensionTests
-     */
+    #[DataProvider('provideChangeExtensionTests')]
     public function testChangeExtension(string $path, string $extension, string $pathExpected)
     {
         $this->assertSame($pathExpected, Path::changeExtension($path, $extension));
@@ -391,17 +381,13 @@ public static function provideIsAbsolutePathTests(): \Generator
         yield ['C:css/style.css', false];
     }
 
-    /**
-     * @dataProvider provideIsAbsolutePathTests
-     */
+    #[DataProvider('provideIsAbsolutePathTests')]
     public function testIsAbsolute(string $path, bool $isAbsolute)
     {
         $this->assertSame($isAbsolute, Path::isAbsolute($path));
     }
 
-    /**
-     * @dataProvider provideIsAbsolutePathTests
-     */
+    #[DataProvider('provideIsAbsolutePathTests')]
     public function testIsRelative(string $path, bool $isAbsolute)
     {
         $this->assertSame(!$isAbsolute, Path::isRelative($path));
@@ -433,9 +419,7 @@ public static function provideGetRootTests(): \Generator
         yield ['phar://C:', 'phar://C:/'];
     }
 
-    /**
-     * @dataProvider provideGetRootTests
-     */
+    #[DataProvider('provideGetRootTests')]
     public function testGetRoot(string $path, string $root)
     {
         $this->assertSame($root, Path::getRoot($path));
@@ -529,9 +513,7 @@ public static function provideMakeAbsoluteTests(): \Generator
         yield ['D:\\css\\style.css', 'D:/webmozart/symfony', 'D:/css/style.css'];
     }
 
-    /**
-     * @dataProvider provideMakeAbsoluteTests
-     */
+    #[DataProvider('provideMakeAbsoluteTests')]
     public function testMakeAbsolute(string $relativePath, string $basePath, string $absolutePath)
     {
         $this->assertSame($absolutePath, Path::makeAbsolute($relativePath, $basePath));
@@ -579,9 +561,7 @@ public static function provideAbsolutePathsWithDifferentRoots(): \Generator
         yield ['phar://C:\\css\\style.css', 'C:\\webmozart\\symfony'];
     }
 
-    /**
-     * @dataProvider provideAbsolutePathsWithDifferentRoots
-     */
+    #[DataProvider('provideAbsolutePathsWithDifferentRoots')]
     public function testMakeAbsoluteDoesNotFailIfDifferentRoot(string $basePath, string $absolutePath)
     {
         // If a path in partition D: is passed, but $basePath is in partition
@@ -682,9 +662,7 @@ public static function provideMakeRelativeTests(): \Generator
         yield ['\\webmozart\\symfony\\css\\style.css', '/webmozart/symfony', 'css/style.css'];
     }
 
-    /**
-     * @dataProvider provideMakeRelativeTests
-     */
+    #[DataProvider('provideMakeRelativeTests')]
     public function testMakeRelative(string $absolutePath, string $basePath, string $relativePath)
     {
         $this->assertSame($relativePath, Path::makeRelative($absolutePath, $basePath));
@@ -705,9 +683,7 @@ public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty()
         Path::makeRelative('/webmozart/symfony/css/style.css', '');
     }
 
-    /**
-     * @dataProvider provideAbsolutePathsWithDifferentRoots
-     */
+    #[DataProvider('provideAbsolutePathsWithDifferentRoots')]
     public function testMakeRelativeFailsIfDifferentRoot(string $absolutePath, string $basePath)
     {
         $this->expectException(\InvalidArgumentException::class);
@@ -724,9 +700,7 @@ public static function provideIsLocalTests(): \Generator
         yield ['', false];
     }
 
-    /**
-     * @dataProvider provideIsLocalTests
-     */
+    #[DataProvider('provideIsLocalTests')]
     public function testIsLocal(string $path, bool $isLocal)
     {
         $this->assertSame($isLocal, Path::isLocal($path));
@@ -843,10 +817,9 @@ public static function provideGetLongestCommonBasePathTests(): \Generator
     }
 
     /**
-     * @dataProvider provideGetLongestCommonBasePathTests
-     *
      * @param string[] $paths
      */
+    #[DataProvider('provideGetLongestCommonBasePathTests')]
     public function testGetLongestCommonBasePath(array $paths, ?string $basePath)
     {
         $this->assertSame($basePath, Path::getLongestCommonBasePath(...$paths));
@@ -933,9 +906,7 @@ public static function provideIsBasePathTests(): \Generator
         yield ['phar://C:/base/path', 'phar://D:/base/path', false];
     }
 
-    /**
-     * @dataProvider provideIsBasePathTests
-     */
+    #[DataProvider('provideIsBasePathTests')]
     public function testIsBasePath(string $path, string $ofPath, bool $result)
     {
         $this->assertSame($result, Path::isBasePath($path, $ofPath));
@@ -1012,9 +983,7 @@ public static function provideJoinTests(): \Generator
         yield [['phar://C:/', '/path/to/test'], 'phar://C:/path/to/test'];
     }
 
-    /**
-     * @dataProvider provideJoinTests
-     */
+    #[DataProvider('provideJoinTests')]
     public function testJoin(array $paths, $result)
     {
         $this->assertSame($result, Path::join(...$paths));
