[Filesystem] Handle paths on different drives

This commit is contained in:
Christian Rishøj 2020-04-22 19:34:57 +02:00 committed by Nicolas Grekas
parent 08ded7fed6
commit 00e727ae4e
2 changed files with 21 additions and 18 deletions

View File

@ -455,28 +455,19 @@ class Filesystem
$startPath = str_replace('\\', '/', $startPath); $startPath = str_replace('\\', '/', $startPath);
} }
$stripDriveLetter = function ($path) { $splitDriveLetter = function ($path) {
if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) { return (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0]))
return substr($path, 2); ? [substr($path, 2), strtoupper($path[0])]
} : [$path, null];
return $path;
}; };
$endPath = $stripDriveLetter($endPath); $splitPath = function ($path, $absolute) {
$startPath = $stripDriveLetter($startPath);
// Split the paths into arrays
$startPathArr = explode('/', trim($startPath, '/'));
$endPathArr = explode('/', trim($endPath, '/'));
$normalizePathArray = function ($pathSegments, $absolute) {
$result = []; $result = [];
foreach ($pathSegments as $segment) { foreach (explode('/', trim($path, '/')) as $segment) {
if ('..' === $segment && ($absolute || \count($result))) { if ('..' === $segment && ($absolute || \count($result))) {
array_pop($result); array_pop($result);
} elseif ('.' !== $segment) { } elseif ('.' !== $segment && '' !== $segment) {
$result[] = $segment; $result[] = $segment;
} }
} }
@ -484,8 +475,16 @@ class Filesystem
return $result; return $result;
}; };
$startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath)); list($endPath, $endDriveLetter) = $splitDriveLetter($endPath);
$endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath)); list($startPath, $startDriveLetter) = $splitDriveLetter($startPath);
$startPathArr = $splitPath($startPath, static::isAbsolutePath($startPath));
$endPathArr = $splitPath($endPath, static::isAbsolutePath($endPath));
if ($endDriveLetter && $startDriveLetter && $endDriveLetter != $startDriveLetter) {
// End path is on another drive, so no relative path exists
return $endDriveLetter.':/'.($endPathArr ? implode('/', $endPathArr).'/' : '');
}
// Find for which directory the common path stops // Find for which directory the common path stops
$index = 0; $index = 0;

View File

@ -1111,10 +1111,14 @@ class FilesystemTest extends FilesystemTestCase
['/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'], ['/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'],
['/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'], ['/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'],
['C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'], ['C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'],
['C:/aa/bb/cc', 'c:/aa/dd/..', 'bb/cc/'],
['c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'], ['c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'],
['C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'], ['C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'],
['C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'], ['C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'],
['C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'], ['C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'],
['D:/', 'C:/aa/../bb/cc', 'D:/'],
['D:/aa/bb', 'C:/aa', 'D:/aa/bb/'],
['D:/../../aa/../bb/cc', 'C:/aa/dd/..', 'D:/bb/cc/'],
]; ];
if ('\\' === \DIRECTORY_SEPARATOR) { if ('\\' === \DIRECTORY_SEPARATOR) {