Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit583fdf1

Browse files
committed
[Filesystem] Add a cross-platform readlink/realpath methods for nested links
1 parent47cb0c3 commit583fdf1

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

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

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,72 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false)
340340
}
341341
}
342342

343+
/**
344+
* Return the next direct target of a link.
345+
*
346+
* To recursively follow links until a final target
347+
* is reached, use @see Filesystem::realpath($path).
348+
*
349+
* @param string $path A link path.
350+
*
351+
* @return string Return the resolved link.
352+
*
353+
* @throws IOException When the link does not exist or is not readable.
354+
*/
355+
publicfunctionreadlink($path)
356+
{
357+
if (!$this->exists($path)) {
358+
thrownewIOException(sprintf('The link %s does not exist and cannot be read.',$path));
359+
}
360+
361+
if (!is_link($path)) {
362+
thrownewIOException(sprintf('The path %s is not a link.',$path));
363+
}
364+
365+
// /link1 -> /link2 -> /file
366+
367+
// Windows: readlink(/link1) => /file
368+
// realpath(/link1) => /link2
369+
370+
// Unix: readlink(/link1) => /link2
371+
// realpath(/link1) => /file
372+
373+
if ('\\' ===DIRECTORY_SEPARATOR) {
374+
returnrealpath($path);
375+
}
376+
377+
returnreadlink($path);
378+
}
379+
380+
/**
381+
* Return the final target of a link by recursively following links.
382+
*
383+
* To find only the direct next target of a link,
384+
* use @see Filesystem::readlink($path).
385+
*
386+
* @param string $path A link path.
387+
*
388+
* @return string Return the final target of the link.
389+
*
390+
* @throws IOException When the link does not exist or is not readable.
391+
*/
392+
publicfunctionrealpath($path)
393+
{
394+
if (!$this->exists($path)) {
395+
thrownewIOException(sprintf('The link %s does not exist and cannot be read.',$path));
396+
}
397+
398+
if (!is_link($path)) {
399+
thrownewIOException(sprintf('The path %s is not a link.',$path));
400+
}
401+
402+
if ('\\' ===DIRECTORY_SEPARATOR) {
403+
returnreadlink($path);
404+
}
405+
406+
returnrealpath($path);
407+
}
408+
343409
/**
344410
* Given an existing path, convert it to a path relative to a given starting path.
345411
*

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,80 @@ public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
799799
$this->assertEquals($file,readlink($link2));
800800
}
801801

802+
publicfunctiontestReadLink()
803+
{
804+
$this->markAsSkippedIfSymlinkIsMissing();
805+
806+
$file =$this->workspace.DIRECTORY_SEPARATOR.'file';
807+
$link1 =$this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
808+
$link2 =$this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';
809+
810+
touch($file);
811+
812+
$this->filesystem->symlink($file,$link1);
813+
$this->filesystem->symlink($link1,$link2);
814+
815+
$this->assertTrue(is_link($link1));
816+
$this->assertEquals($file,$this->filesystem->readlink($link1));
817+
$this->assertTrue(is_link($link2));
818+
$this->assertEquals($link1,$this->filesystem->readlink($link2));
819+
}
820+
821+
/**
822+
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
823+
*/
824+
publicfunctiontestReadLinkNotLink()
825+
{
826+
$file =$this->workspace.DIRECTORY_SEPARATOR.'file';
827+
touch($file);
828+
$this->filesystem->readlink($file);
829+
}
830+
831+
/**
832+
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
833+
*/
834+
publicfunctiontestReadLinkFails()
835+
{
836+
$this->filesystem->readlink($this->workspace.DIRECTORY_SEPARATOR.'invalid');
837+
}
838+
839+
publicfunctiontestRealPath()
840+
{
841+
$this->markAsSkippedIfSymlinkIsMissing();
842+
843+
$file =$this->workspace.DIRECTORY_SEPARATOR.'file';
844+
$link1 =$this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
845+
$link2 =$this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';
846+
847+
touch($file);
848+
849+
$this->filesystem->symlink($file,$link1);
850+
$this->filesystem->symlink($link1,$link2);
851+
852+
$this->assertTrue(is_link($link1));
853+
$this->assertEquals($file,$this->filesystem->realpath($link1));
854+
$this->assertTrue(is_link($link2));
855+
$this->assertEquals($file,$this->filesystem->realpath($link2));
856+
}
857+
858+
/**
859+
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
860+
*/
861+
publicfunctiontestRealPathNotLink()
862+
{
863+
$file =$this->workspace.DIRECTORY_SEPARATOR.'file';
864+
touch($file);
865+
$this->filesystem->realpath($file);
866+
}
867+
868+
/**
869+
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
870+
*/
871+
publicfunctiontestRealPathFails()
872+
{
873+
$this->filesystem->realpath($this->workspace.DIRECTORY_SEPARATOR.'invalid');
874+
}
875+
802876
/**
803877
* @dataProvider providePathsForMakePathRelative
804878
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp