Skip to content

Commit

Permalink
Helpers: added findCommonDirectory()
Browse files Browse the repository at this point in the history
  • Loading branch information
milo committed Feb 21, 2019
1 parent fc4644f commit 8bbf089
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/Framework/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,35 @@ public static function purge(string $dir): void
}


/**
* Find common directory for given paths. All files or directories must exist.
* @return string Empty when not found. Slash and back slash chars normalized to DIRECTORY_SEPARATOR.
*/
public static function findCommonDirectory(array $paths): string
{
$splitPaths = array_map(function ($s) {
$real = realpath($s);
if ($s === '') {
throw new \RuntimeException("Path must not be empty.");
} elseif ($real === false) {
throw new \RuntimeException("File or directory '$s' does not exist.");
}
return explode(DIRECTORY_SEPARATOR, $real);
}, $paths);

$first = (array) array_shift($splitPaths);
for ($i = 0; $i < count($first); $i++) {
foreach ($splitPaths as $s) {
if ($first[$i] !== ($s[$i] ?? null)) {
break 2;
}
}
}
$common = implode(DIRECTORY_SEPARATOR, array_slice($first, 0, $i));
return is_dir($common) ? $common : dirname($common);
}


/**
* Parse phpDoc comment.
* @internal
Expand Down
56 changes: 56 additions & 0 deletions tests/Framework/Helpers.findCommonDirectory.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

use Tester\Assert;
use Tester\Helpers;

require __DIR__ . '/../bootstrap.php';

Assert::same('', Helpers::findCommonDirectory([]));

Assert::match(__DIR__ . DIRECTORY_SEPARATOR . 'fixtures.helpers', Helpers::findCommonDirectory([
__DIR__ . '/fixtures.helpers/a',
__DIR__ . '/fixtures.helpers/aa',
]));

Assert::match(__DIR__ . DIRECTORY_SEPARATOR . 'fixtures.helpers', Helpers::findCommonDirectory([
__DIR__ . '/fixtures.helpers/a/file.txt',
__DIR__ . '/fixtures.helpers/aa/file.txt',
]));

Assert::match(__DIR__ . DIRECTORY_SEPARATOR . 'fixtures.helpers', Helpers::findCommonDirectory([
__DIR__ . '/fixtures.helpers/a/',
__DIR__ . '/fixtures.helpers/aa/file.txt',
]));

Assert::match(getcwd(), Helpers::findCommonDirectory([
'.',
]));

Assert::match(dirname(getcwd()), Helpers::findCommonDirectory([
'..',
]));


// Root directories always end by directory separator.
if (is_dir('C:/')) {
Assert::match('C:\\', Helpers::findCommonDirectory([
'C:',
]));
}

if (is_dir('/')) {
Assert::match(realpath('/'), Helpers::findCommonDirectory([ // realpath() - may point to C:\ in Cygwin
'/',
]));
}


Assert::exception(function () {
Helpers::findCommonDirectory(['']);
}, RuntimeException::class, 'Path must not be empty.');

Assert::exception(function () {
Helpers::findCommonDirectory(['does-not-exist']);
}, RuntimeException::class, "File or directory 'does-not-exist' does not exist.");
Empty file.
Empty file.

0 comments on commit 8bbf089

Please sign in to comment.