Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3b42d88

Browse filesBrowse 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
Copy full SHA for 3b42d88

File tree

2 files changed

+30
-20
lines changed
Filter options

2 files changed

+30
-20
lines changed

‎src/Symfony/Component/Filesystem/Filesystem.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Filesystem/Filesystem.php
+18-20Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Filesystem/Tests/FilesystemTest.php
+12Lines 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
);
885897

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

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.