8000 bug #22321 [Filesystem] Fixed makePathRelative (ausi) · symfony/symfony@3b42d88 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3b42d88

Browse files
committed
bug #22321 [Filesystem] Fixed makePathRelative (ausi)
This PR was squashed before being merged into the 2.7 branch (closes #22321). Discussion ---------- [Filesystem] Fixed makePathRelative | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Updating to Symfony 3.2.7 @agoat noticed a bug with `Filesystem::makePathRelative()` in contao/core-bundle#751: - In Symfony 3.2.6 `makePathRelative('aa/cc', 'bb/cc')` returned correctly `../../aa/cc` - In Symfony 3.2.7 the same method call returns `./` I think this issue was introduced with #22133. While working on the fix I noticed some other issues too: - An unnecessary if construct that did nothing, fc745f4 - Missing normalization of `./` path segments, 15982d4 - `../` got ignored at the beginning of relative paths, 9586e88 - The documentation of the method only allowed absolute paths, but there are already unit tests ([FilesystemTest.php:1097](https://github.com/symfony/symfony/blob/ab93feae3f9a16c4f18c5736435d18fa36338d2c/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php#L1097)) that test the behavior of relative paths, cec473e This pull request fixes all these issues and adds tests for them. Commits ------- 2bc1150 [Filesystem] Fixed makePathRelative
2 parents b973ecf + 2bc1150 commit 3b42d88

File tree

2 files changed

+30
-20
lines changed

2 files changed

+30
-20
lines changed

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -368,34 +368,37 @@ public function makePathRelative($endPath, $startPath)
368368
$startPath = str_replace('\\', '/', $startPath);
369369
}
370370

371+
$stripDriveLetter = function ($path) {
372+
if (strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
373+
return substr($path, 2);
374+
}
375+
376+
return $path;
377+
};
378+
379+
$endPath = $stripDriveLetter($endPath);
380+
$startPath = $stripDriveLetter($startPath);
381+
371382
// Split the paths into arrays
372383
$startPathArr = explode('/', trim($startPath, '/'));
373384
$endPathArr = explode('/', trim($endPath, '/'));
374385

375-
if ('/' !== $startPath[0]) {
376-
array_shift($startPathArr);
377-
}
378-
379-
if ('/' !== $endPath[0]) {
380-
array_shift($endPathArr);
381-
}
382-
383-
$normalizePathArray = function ($pathSegments) {
386+
$normalizePathArray = function ($pathSegments, $absolute) {
384387
$result = array();
385388

386389
foreach ($pathSegments as $segment) {
387-
if ('..' === $segment) {
390+
if ('..' === $segment && ($absolute || count($result))) {
388391
array_pop($result);
389-
} else {
392+
} elseif ('.' !== $segment) {
390393
$result[] = $segment;
391394
}
392395
}
393396

394397
return $result;
395398
};
396399

397-
$startPathArr = $normalizePathArray($startPathArr);
398-
$endPathArr = $normalizePathArray($endPathArr);
400+
$startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
401+
$endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
399402

400403
// Find for which directory the common path stops
401404
$index = 0;
@@ -410,13 +413,8 @@ public function makePathRelative($endPath, $startPath)
410413
$depth = count($startPathArr) - $index;
411414
}
412415

413-
// When we need to traverse from the start, and we are starting from a root path, don't add '../'
414-
if ('/' === $startPath[0] && 0 === $index && 0 === $depth) {
415-
$traverser = '';
416-
} else {
417-
// Repeated "../" for each level need to reach the common path
418-
$traverser = str_repeat('../', $depth);
419-
}
416+
// Repeated "../" for each level need to reach the common path
417+
$traverser = str_repeat('../', $depth);
420418

421419
$endPathRemainder = implode('/', array_slice($endPathArr, $index));
422420

src/Symfony/Component/Filesystem/Tests/FilesystemTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,7 @@ public function providePathsForMakePathRelative()
850850
array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
851851
array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
852852
array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
853+
array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
853854
array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
854855
array('/aa/bb', '/aa/bb', './'),
855856
array('/aa/bb', '/aa/bb/', './'),
@@ -881,6 +882,17 @@ public function providePathsForMakePathRelative()
881882
array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'),
882883
array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
883884
array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'),
885+
array('aa/bb', 'aa/cc', '../bb/'),
886+
array('aa/cc', 'bb/cc', '../../aa/cc/'),
887+
array('aa/bb', 'aa/./cc', '../bb/'),
888+
array('aa/./bb', 'aa/cc', '../bb/'),
889+
array('aa/./bb', 'aa/./cc', '../bb/'),
890+
array('../../', '../../', './'),
891+
array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'),
892+
array('../../../', '../../', '../'),
893+
array('', '', './'),
894+
array('', 'aa/', '../'),
895+
array('aa/', '', 'aa/'),
884896
467E );
885897

886898
if ('\\' === DIRECTORY_SEPARATOR) {

0 commit comments

Comments
 (0)
0