10000 [Filesystem] Fixed makePathRelative · symfony/symfony@2bc1150 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2bc1150

Browse files
ausifabpot
authored andcommitted
[Filesystem] Fixed makePathRelative
1 parent 2adfb37 commit 2bc1150

File tree

2 files changed

+32
-22
lines changed

2 files changed

+32
-22
lines changed

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -358,34 +358,37 @@ public function makePathRelative($endPath, $startPath)
358358
$startPath = str_replace('\\', '/', $startPath);
359359
}
360360

361+
$stripDriveLetter = function ($path) {
362+
if (strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
363+
return substr($path, 2);
364+
}
365+
366+
return $path;
367+
};
368+
369+
$endPath = $stripDriveLetter($endPath);
370+
$startPath = $stripDriveLetter($startPath);
371+
361372
// Split the paths into arrays
362373
$startPathArr = explode('/', trim($startPath, '/'));
363374
$endPathArr = explode('/', trim($endPath, '/'));
364375

365-
if ('/' !== $startPath[0]) {
366-
array_shift($startPathArr);
367-
}
368-
369-
if ('/' !== $endPath[0]) {
370-
array_shift($endPathArr);
371-
}
372-
373-
$normalizePathArray = function ($pathSegments) {
376+
$normalizePathArray = function ($pathSegments, $absolute) {
374377
$result = array();
375378

376379
foreach ($pathSegments as $segment) {
377-
if ('..' === $segment) {
380+
if ('..' === $segment && ($absolute || count($result))) {
378381
array_pop($result);
379-
} else {
382+
} elseif ('.' !== $segment) {
380383
$result[] = $segment;
381384
}
382385
}
383386

384387
return $result;
385388
};
386389

387-
$startPathArr = $normalizePathArray($startPathArr);
388-
$endPathArr = $normalizePathArray($endPathArr);
390+
$startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
391+
$endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
389392

390393
// Find for which directory the common path stops
391394
$index = 0;
@@ -394,19 +397,14 @@ public function makePathRelative($endPath, $startPath)
394397
}
395398

396399
// Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
397-
if (count($startPathArr) === 1 && $startPathArr[0] === '') {
400+
if (1 === count($startPathArr) && '' === $startPathArr[0]) {
398401
$depth = 0;
399402
} else {
400403
$depth = count($startPathArr) - $index;
401404
}
402405

403-
// When we need to traverse from the start, and we are starting from a root path, don't add '../'
404-
if ('/' === $startPath[0] && 0 === $index && 0 === $depth) {
405-
$traverser = '';
406-
} else {
407-
// Repeated "../" for each level need to reach the common path
408-
$traverser = str_repeat('../', $depth);
409-
}
406+
// Repeated "../" for each level need to reach the common path
407+
$traverser = str_repeat('../', $depth);
410408

411409
$endPathRemainder = implode('/', array_slice($endPathArr, $index));
412410

@@ -500,7 +498,7 @@ public function isAbsolutePath($file)
500498
{
501499
return strspn($file, '/\\', 0, 1)
502500
|| (strlen($file) > 3 && ctype_alpha($file[0])
503-
&& substr($file, 1, 1) === ':'
501+
&& ':' === substr($file, 1, 1)
504502
&& strspn($file, '/\\', 2, 1)
505503
)
506504
|| null !== parse_url($file, PHP_URL_SCHEME)

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ public function providePathsForMakePathRelative()
847847
array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
848848
array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
849849
array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
850+
array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
850851
array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
851852
array('/aa/bb', '/aa/bb', './'),
852853
array('/aa/bb', '/aa/bb/', './'),
@@ -878,6 +879,17 @@ public function providePathsForMakePathRelative()
878879
array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'),
879880
array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
880881
array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'),
882+
array('aa/bb', 'aa/cc', '../bb/'),
883+
array('aa/cc', 'bb/cc', '../../aa/cc/'),
884+
array('aa/bb', 'aa/./cc', '../bb/'),
885+
array('aa/./bb', 'aa/cc', '../bb/'),
886+
array('aa/./bb', 'aa/./cc', '../bb/'),
887+
array('../../', '../../', './'),
888+
array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'),
889+
array('../../../', '../../', '../'),
890+
array('', '', './'),
891+
array('', 'aa/', '../'),
892+
array('aa/', '', 'aa/'),
881893
);
882894

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

0 commit comments

Comments
 (0)
0