Skip to content

Commit 38d3a96

Browse files
ausinicolas-grekas
authored andcommitted
[Filesystem] Follow symlinks when dumping files
1 parent b2f79d8 commit 38d3a96

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

Filesystem.php

+6
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,12 @@ public function dumpFile(string $filename, $content)
669669

670670
$dir = \dirname($filename);
671671

672+
if (is_link($filename) && $linkTarget = $this->readlink($filename)) {
673+
$this->dumpFile(Path::makeAbsolute($linkTarget, $dir), $content);
674+
675+
return;
676+
}
677+
672678
if (!is_dir($dir)) {
673679
$this->mkdir($dir);
674680
}

Tests/FilesystemTest.php

+65-2
Original file line numberDiff line numberDiff line change
@@ -1091,14 +1091,16 @@ public function testReadBrokenLink()
10911091
{
10921092
$this->markAsSkippedIfSymlinkIsMissing();
10931093

1094-
if ('\\' === \DIRECTORY_SEPARATOR) {
1095-
$this->markTestSkipped('Windows does not support creating "broken" symlinks');
1094+
if ('\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 70400) {
1095+
$this->markTestSkipped('Windows does not support reading "broken" symlinks in PHP < 7.4.0');
10961096
}
10971097

10981098
$file = $this->workspace.'/file';
10991099
$link = $this->workspace.'/link';
11001100

1101+
touch($file);
11011102
$this->filesystem->symlink($file, $link);
1103+
$this->filesystem->remove($file);
11021104

11031105
$this->assertEquals($file, $this->filesystem->readlink($link));
11041106
$this->assertNull($this->filesystem->readlink($link, true));
@@ -1605,6 +1607,38 @@ public function testDumpFileOverwritesAnExistingFile()
16051607
$this->assertStringEqualsFile($filename, 'bar');
16061608
}
16071609

1610+
public function testDumpFileFollowsSymlink()
1611+
{
1612+
$filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo.txt';
1613+
file_put_contents($filename, 'FOO BAR');
1614+
$linknameA = $this->workspace.\DIRECTORY_SEPARATOR.'bar.txt';
1615+
$linknameB = $this->workspace.\DIRECTORY_SEPARATOR.'baz.txt';
1616+
$this->filesystem->symlink($filename, $linknameA);
1617+
$this->filesystem->symlink($linknameA, $linknameB);
1618+
1619+
$this->filesystem->dumpFile($linknameB, 'bar');
1620+
1621+
$this->assertFileExists($filename);
1622+
$this->assertFileExists($linknameA);
1623+
$this->assertFileExists($linknameB);
1624+
$this->assertStringEqualsFile($filename, 'bar');
1625+
$this->assertStringEqualsFile($linknameA, 'bar');
1626+
$this->assertStringEqualsFile($linknameB, 'bar');
1627+
1628+
// Windows does not support reading "broken" symlinks in PHP < 7.4.0
1629+
if ('\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 70400) {
1630+
return;
1631+
}
1632+
1633+
$this->filesystem->remove($filename);
1634+
$this->filesystem->dumpFile($linknameB, 'baz');
1635+
1636+
$this->assertFileExists($filename);
1637+
$this->assertStringEqualsFile($filename, 'baz');
1638+
$this->assertStringEqualsFile($linknameA, 'baz');
1639+
$this->assertStringEqualsFile($linknameB, 'baz');
1640+
}
1641+
16081642
public function testDumpFileWithFileScheme()
16091643
{
16101644
$scheme = 'file://';
@@ -1678,6 +1712,35 @@ public function testAppendToFileWithResource()
16781712
}
16791713
}
16801714

1715+
public function testAppendToFileFollowsSymlink()
1716+
{
1717+
$filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo.txt';
1718+
file_put_contents($filename, 'foo');
1719+
$linknameA = $this->workspace.\DIRECTORY_SEPARATOR.'bar.txt';
1720+
$linknameB = $this->workspace.\DIRECTORY_SEPARATOR.'baz.txt';
1721+
$this->filesystem->symlink($filename, $linknameA);
1722+
$this->filesystem->symlink($linknameA, $linknameB);
1723+
1724+
$this->filesystem->appendToFile($linknameA, 'bar');
1725+
$this->filesystem->appendToFile($linknameB, 'baz');
1726+
1727+
$this->assertFileExists($filename);
1728+
$this->assertFileExists($linknameA);
1729+
$this->assertFileExists($linknameB);
1730+
$this->assertStringEqualsFile($filename, 'foobarbaz');
1731+
$this->assertStringEqualsFile($linknameA, 'foobarbaz');
1732+
$this->assertStringEqualsFile($linknameB, 'foobarbaz');
1733+
1734+
$this->filesystem->remove($filename);
1735+
$this->filesystem->appendToFile($linknameB, 'foo');
1736+
$this->filesystem->appendToFile($linknameA, 'bar');
1737+
1738+
$this->assertFileExists($filename);
1739+
$this->assertStringEqualsFile($filename, 'foobar');
1740+
$this->assertStringEqualsFile($linknameA, 'foobar');
1741+
$this->assertStringEqualsFile($linknameB, 'foobar');
1742+
}
1743+
16811744
public function testAppendToFileWithScheme()
16821745
{
16831746
$scheme = 'file://';

0 commit comments

Comments
 (0)