Skip to content

Commit

Permalink
Avoiding stat of file with realpath
Browse files Browse the repository at this point in the history
  • Loading branch information
mtdowling committed Apr 3, 2015
1 parent 6d43be8 commit d921ca3
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
42 changes: 41 additions & 1 deletion src/JsonCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function load($path)
return json_decode(file_get_contents($path), true);
}

$real = realpath($path);
$real = $this->normalize($path);
$cache = str_replace($this->stripPath, '', $real);
$cache = str_replace(['\\', '/'], '_', $cache);
$cache = $this->cacheDir . DIRECTORY_SEPARATOR . $cache . '.php';
Expand All @@ -93,4 +93,44 @@ public function load($path)

return $data;
}

/**
* Resolve relative paths without using realpath (which causes an
* unnecessary fstat).
*
* @param $path
*
* @return string
*/
private function normalize($path)
{
static $replace = ['/', '\\'];

$parts = explode(
DIRECTORY_SEPARATOR,
// Normalize path separators
str_replace($replace, DIRECTORY_SEPARATOR, $path)
);

$segments = [];
foreach ($parts as $part) {
if ($part === '' || $part === '.') {
continue;
}
if ($part === '..') {
array_pop($segments);
} else {
$segments[] = $part;
}
}

$resolved = implode(DIRECTORY_SEPARATOR, $segments);

// Add a leading slash if necessary.
if (isset($parts[0]) && $parts[0] === '') {
$resolved = DIRECTORY_SEPARATOR . $resolved;
}

return $resolved;
}
}
27 changes: 27 additions & 0 deletions tests/JsonCompilerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,31 @@ public function testCanPurgeCachedFiles()
$entries = array_diff(scandir($c->getCacheDir()), ['.', '..']);
$this->assertEmpty($entries);
}

public function pathProvider()
{
return [
['/foo/baz/bar.qux', '/foo/baz/bar.qux'],
['/foo/baz/../bar.qux', '/foo/bar.qux'],
['/foo/baz/./bar.qux', '/foo/baz/bar.qux'],
['/foo/baz/../../bar.qux', '/bar.qux'],
['/../../bar.qux', '/bar.qux'],
// Extra slashes
['/foo//baz///bar.qux', '/foo/baz/bar.qux'],
// Relative with no leading slash
['foo/baz/../bar.qux', 'foo/bar.qux'],
['\\foo\\baz\\..\\.\\bar.qux', '/foo/bar.qux'],
];
}

/**
* @dataProvider pathProvider
*/
public function testResolvesRelativePaths($path, $resolved)
{
$j = new JsonCompiler();
$meth = new \ReflectionMethod('Aws\JsonCompiler', 'normalize');
$meth->setAccessible(true);
$this->assertEquals($resolved, $meth->invoke($j, $path));
}
}

0 comments on commit d921ca3

Please sign in to comment.