Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[Filesystem] Added few new behaviors:

 - add a IOException and a main filesystem exception interface
 - whenever an action fails, an IOException is thrown
 - add access to the second and third arguments of touch() function
 - add a recursive option for chmod()
 - add a chown() method
 - add a chgrp() method
 - Switch the 'unlink' global function in Filesystem::symlink to Filesystem::remove.

BC break: mkdir() function now throws exception in case of failure instead of returning Boolean value.
  • Loading branch information...
commit 9355c28d0b8ede0202da7dd1e00f629d5e669769 1 parent 22d3e3e
Romain Neutron romainneutron authored
24 Exception/ExceptionInterface.php
... ... @@ -0,0 +1,24 @@
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Symfony package.
  5 + *
  6 + * (c) Fabien Potencier <fabien@symfony.com>
  7 + *
  8 + * For the full copyright and license information, please view the LICENSE
  9 + * file that was distributed with this source code.
  10 + */
  11 +
  12 +namespace Symfony\Component\Filesystem\Exception;
  13 +
  14 +/**
  15 + * Exception interface for all exceptions thrown by the component.
  16 + *
  17 + * @author Romain Neutron <imprec@gmail.com>
  18 + *
  19 + * @api
  20 + */
  21 +interface ExceptionInterface
  22 +{
  23 +
  24 +}
24 Exception/IOException.php
... ... @@ -0,0 +1,24 @@
  1 +<?php
  2 +
  3 +/*
  4 + * This file is part of the Symfony package.
  5 + *
  6 + * (c) Fabien Potencier <fabien@symfony.com>
  7 + *
  8 + * For the full copyright and license information, please view the LICENSE
  9 + * file that was distributed with this source code.
  10 + */
  11 +
  12 +namespace Symfony\Component\Filesystem\Exception;
  13 +
  14 +/**
  15 + * Exception class thrown when a filesystem operation failure happens
  16 + *
  17 + * @author Romain Neutron <imprec@gmail.com>
  18 + *
  19 + * @api
  20 + */
  21 +class IOException extends \RuntimeException implements ExceptionInterface
  22 +{
  23 +
  24 +}
141 Filesystem.php
@@ -28,6 +28,8 @@ class Filesystem
28 28 * @param string $originFile The original filename
29 29 * @param string $targetFile The target filename
30 30 * @param array $override Whether to override an existing file or not
  31 + *
  32 + * @throws Exception\IOException When copy fails
31 33 */
32 34 public function copy($originFile, $targetFile, $override = false)
33 35 {
@@ -40,7 +42,9 @@ public function copy($originFile, $targetFile, $override = false)
40 42 }
41 43
42 44 if ($doCopy) {
43   - copy($originFile, $targetFile);
  45 + if (true !== @copy($originFile, $targetFile)) {
  46 + throw new Exception\IOException(sprintf('Failed to copy %s to %s', $originFile, $targetFile));
  47 + }
44 48 }
45 49 }
46 50
@@ -48,22 +52,21 @@ public function copy($originFile, $targetFile, $override = false)
48 52 * Creates a directory recursively.
49 53 *
50 54 * @param string|array|\Traversable $dirs The directory path
51   - * @param int $mode The directory mode
  55 + * @param integer $mode The directory mode
52 56 *
53   - * @return Boolean true if the directory has been created, false otherwise
  57 + * @throws Exception\IOException On any directory creation failure
54 58 */
55 59 public function mkdir($dirs, $mode = 0777)
56 60 {
57   - $ret = true;
58 61 foreach ($this->toIterator($dirs) as $dir) {
59 62 if (is_dir($dir)) {
60 63 continue;
61 64 }
62 65
63   - $ret = @mkdir($dir, $mode, true) && $ret;
  66 + if (true !== @mkdir($dir, $mode, true)) {
  67 + throw new Exception\IOException(sprintf('Failed to create %s', $dir));
  68 + }
64 69 }
65   -
66   - return $ret;
67 70 }
68 71
69 72 /**
@@ -85,14 +88,24 @@ public function exists($files)
85 88 }
86 89
87 90 /**
88   - * Creates empty files.
  91 + * Sets access and modification time of file.
89 92 *
90 93 * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
  94 + * @param integer $time The touch time as a unix timestamp
  95 + * @param integer $atime The access time as a unix timestamp
  96 + *
  97 + * @throws Exception\IOException When touch fails
91 98 */
92   - public function touch($files)
  99 + public function touch($files, $time = null, $atime = null)
93 100 {
  101 + if (null === $time) {
  102 + $time = time();
  103 + }
  104 +
94 105 foreach ($this->toIterator($files) as $file) {
95   - touch($file);
  106 + if (true !== @touch($file, $time, $atime)) {
  107 + throw new Exception\IOException(sprintf('Failed to touch %s', $file));
  108 + }
96 109 }
97 110 }
98 111
@@ -100,6 +113,8 @@ public function touch($files)
100 113 * Removes files or directories.
101 114 *
102 115 * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
  116 + *
  117 + * @throws Exception\IOException When removal fails
103 118 */
104 119 public function remove($files)
105 120 {
@@ -113,13 +128,19 @@ public function remove($files)
113 128 if (is_dir($file) && !is_link($file)) {
114 129 $this->remove(new \FilesystemIterator($file));
115 130
116   - rmdir($file);
  131 + if (true !== @rmdir($file)) {
  132 + throw new Exception\IOException(sprintf('Failed to remove directory %s', $file));
  133 + }
117 134 } else {
118 135 // https://bugs.php.net/bug.php?id=52176
119 136 if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) {
120   - rmdir($file);
  137 + if (true !== @rmdir($file)) {
  138 + throw new Exception\IOException(sprintf('Failed to remove file %s', $file));
  139 + }
121 140 } else {
122   - unlink($file);
  141 + if (true !== @unlink($file)) {
  142 + throw new Exception\IOException(sprintf('Failed to remove file %s', $file));
  143 + }
123 144 }
124 145 }
125 146 }
@@ -128,14 +149,76 @@ public function remove($files)
128 149 /**
129 150 * Change mode for an array of files or directories.
130 151 *
131   - * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode
132   - * @param integer $mode The new mode (octal)
133   - * @param integer $umask The mode mask (octal)
  152 + * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode
  153 + * @param integer $mode The new mode (octal)
  154 + * @param integer $umask The mode mask (octal)
  155 + * @param Boolean $recursive Whether change the mod recursively or not
  156 + *
  157 + * @throws Exception\IOException When the change fail
134 158 */
135   - public function chmod($files, $mode, $umask = 0000)
  159 + public function chmod($files, $mode, $umask = 0000, $recursive = false)
136 160 {
137 161 foreach ($this->toIterator($files) as $file) {
138   - @chmod($file, $mode & ~$umask);
  162 + if ($recursive && is_dir($file) && !is_link($file)) {
  163 + $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
  164 + }
  165 + if (true !== @chmod($file, $mode & ~$umask)) {
  166 + throw new Exception\IOException(sprintf('Failed to chmod file %s', $file));
  167 + }
  168 + }
  169 + }
  170 +
  171 + /**
  172 + * Change the owner of an array of files or directories
  173 + *
  174 + * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner
  175 + * @param string $user The new owner user name
  176 + * @param Boolean $recursive Whether change the owner recursively or not
  177 + *
  178 + * @throws Exception\IOException When the change fail
  179 + */
  180 + public function chown($files, $user, $recursive = false)
  181 + {
  182 + foreach ($this->toIterator($files) as $file) {
  183 + if ($recursive && is_dir($file) && !is_link($file)) {
  184 + $this->chown(new \FilesystemIterator($file), $user, true);
  185 + }
  186 + if (is_link($file) && function_exists('lchown')) {
  187 + if (true !== @lchown($file, $user)) {
  188 + throw new Exception\IOException(sprintf('Failed to chown file %s', $file));
  189 + }
  190 + } else {
  191 + if (true !== @chown($file, $user)) {
  192 + throw new Exception\IOException(sprintf('Failed to chown file %s', $file));
  193 + }
  194 + }
  195 + }
  196 + }
  197 +
  198 + /**
  199 + * Change the group of an array of files or directories
  200 + *
  201 + * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group
  202 + * @param string $group The group name
  203 + * @param Boolean $recursive Whether change the group recursively or not
  204 + *
  205 + * @throws Exception\IOException When the change fail
  206 + */
  207 + public function chgrp($files, $group, $recursive = false)
  208 + {
  209 + foreach ($this->toIterator($files) as $file) {
  210 + if ($recursive && is_dir($file) && !is_link($file)) {
  211 + $this->chgrp(new \FilesystemIterator($file), $group, true);
  212 + }
  213 + if (is_link($file) && function_exists('lchgrp')) {
  214 + if (true !== @lchgrp($file, $group)) {
  215 + throw new Exception\IOException(sprintf('Failed to chgrp file %s', $file));
  216 + }
  217 + } else {
  218 + if (true !== @chgrp($file, $group)) {
  219 + throw new Exception\IOException(sprintf('Failed to chgrp file %s', $file));
  220 + }
  221 + }
139 222 }
140 223 }
141 224
@@ -145,18 +228,18 @@ public function chmod($files, $mode, $umask = 0000)
145 228 * @param string $origin The origin filename
146 229 * @param string $target The new filename
147 230 *
148   - * @throws \RuntimeException When target file already exists
149   - * @throws \RuntimeException When origin cannot be renamed
  231 + * @throws Exception\IOException When target file already exists
  232 + * @throws Exception\IOException When origin cannot be renamed
150 233 */
151 234 public function rename($origin, $target)
152 235 {
153 236 // we check that target does not exist
154 237 if (is_readable($target)) {
155   - throw new \RuntimeException(sprintf('Cannot rename because the target "%s" already exist.', $target));
  238 + throw new Exception\IOException(sprintf('Cannot rename because the target "%s" already exist.', $target));
156 239 }
157 240
158   - if (false === @rename($origin, $target)) {
159   - throw new \RuntimeException(sprintf('Cannot rename "%s" to "%s".', $origin, $target));
  241 + if (true !== @rename($origin, $target)) {
  242 + throw new Exception\IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target));
160 243 }
161 244 }
162 245
@@ -166,6 +249,8 @@ public function rename($origin, $target)
166 249 * @param string $originDir The origin directory path
167 250 * @param string $targetDir The symbolic link name
168 251 * @param Boolean $copyOnWindows Whether to copy files if on Windows
  252 + *
  253 + * @throws Exception\IOException When symlink fails
169 254 */
170 255 public function symlink($originDir, $targetDir, $copyOnWindows = false)
171 256 {
@@ -180,14 +265,16 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false)
180 265 $ok = false;
181 266 if (is_link($targetDir)) {
182 267 if (readlink($targetDir) != $originDir) {
183   - unlink($targetDir);
  268 + $this->remove($targetDir);
184 269 } else {
185 270 $ok = true;
186 271 }
187 272 }
188 273
189 274 if (!$ok) {
190   - symlink($originDir, $targetDir);
  275 + if (true !== @symlink($originDir, $targetDir)) {
  276 + throw new Exception\IOException(sprintf('Failed to create symbolic link from %s to %s', $originDir, $targetDir));
  277 + }
191 278 }
192 279 }
193 280
@@ -235,7 +322,7 @@ public function makePathRelative($endPath, $startPath)
235 322 * - $options['override'] Whether to override an existing file on copy or not (see copy())
236 323 * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
237 324 *
238   - * @throws \RuntimeException When file type is unknown
  325 + * @throws Exception\IOException When file type is unknown
239 326 */
240 327 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
241 328 {
@@ -262,7 +349,7 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o
262 349 } elseif (is_file($file) || ($copyOnWindows && is_link($file))) {
263 350 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
264 351 } else {
265   - throw new \RuntimeException(sprintf('Unable to guess "%s" file type.', $file));
  352 + throw new Exception\IOException(sprintf('Unable to guess "%s" file type.', $file));
266 353 }
267 354 }
268 355 }
32 README.md
Source Rendered
@@ -3,29 +3,37 @@ Filesystem Component
3 3
4 4 Filesystem provides basic utility to manipulate the file system:
5 5
6   - use Symfony\Component\Filesystem\Filesystem;
  6 +```php
  7 +<?php
7 8
8   - $filesystem = new Filesystem();
  9 +use Symfony\Component\Filesystem\Filesystem;
9 10
10   - $filesystem->copy($originFile, $targetFile, $override = false);
  11 +$filesystem = new Filesystem();
11 12
12   - $filesystem->mkdir($dirs, $mode = 0777);
  13 +$filesystem->copy($originFile, $targetFile, $override = false);
13 14
14   - $filesystem->touch($files);
  15 +$filesystem->mkdir($dirs, $mode = 0777);
15 16
16   - $filesystem->remove($files);
  17 +$filesystem->touch($files, $time = null, $atime = null);
17 18
18   - $filesystem->chmod($files, $mode, $umask = 0000);
  19 +$filesystem->remove($files);
19 20
20   - $filesystem->rename($origin, $target);
  21 +$filesystem->chmod($files, $mode, $umask = 0000, $recursive = false);
21 22
22   - $filesystem->symlink($originDir, $targetDir, $copyOnWindows = false);
  23 +$filesystem->chown($files, $user, $recursive = false);
23 24
24   - $filesystem->makePathRelative($endPath, $startPath);
  25 +$filesystem->chgrp($files, $group, $recursive = false);
25 26
26   - $filesystem->mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array());
  27 +$filesystem->rename($origin, $target);
27 28
28   - $filesystem->isAbsolutePath($file);
  29 +$filesystem->symlink($originDir, $targetDir, $copyOnWindows = false);
  30 +
  31 +$filesystem->makePathRelative($endPath, $startPath);
  32 +
  33 +$filesystem->mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array());
  34 +
  35 +$filesystem->isAbsolutePath($file);
  36 +```
29 37
30 38 Resources
31 39 ---------
242 Tests/FilesystemTest.php
@@ -70,6 +70,17 @@ public function testCopyCreatesNewFile()
70 70 $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
71 71 }
72 72
  73 + /**
  74 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
  75 + */
  76 + public function testCopyFails()
  77 + {
  78 + $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
  79 + $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
  80 +
  81 + $this->filesystem->copy($sourceFilePath, $targetFilePath);
  82 + }
  83 +
73 84 public function testCopyOverridesExistingFileIfModified()
74 85 {
75 86 $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
@@ -144,9 +155,8 @@ public function testMkdirCreatesDirectoriesRecursively()
144 155 .DIRECTORY_SEPARATOR.'directory'
145 156 .DIRECTORY_SEPARATOR.'sub_directory';
146 157
147   - $result = $this->filesystem->mkdir($directory);
  158 + $this->filesystem->mkdir($directory);
148 159
149   - $this->assertTrue($result);
150 160 $this->assertTrue(is_dir($directory));
151 161 }
152 162
@@ -157,9 +167,8 @@ public function testMkdirCreatesDirectoriesFromArray()
157 167 $basePath.'1', $basePath.'2', $basePath.'3'
158 168 );
159 169
160   - $result = $this->filesystem->mkdir($directories);
  170 + $this->filesystem->mkdir($directories);
161 171
162   - $this->assertTrue($result);
163 172 $this->assertTrue(is_dir($basePath.'1'));
164 173 $this->assertTrue(is_dir($basePath.'2'));
165 174 $this->assertTrue(is_dir($basePath.'3'));
@@ -172,30 +181,24 @@ public function testMkdirCreatesDirectoriesFromTraversableObject()
172 181 $basePath.'1', $basePath.'2', $basePath.'3'
173 182 ));
174 183
175   - $result = $this->filesystem->mkdir($directories);
  184 + $this->filesystem->mkdir($directories);
176 185
177   - $this->assertTrue($result);
178 186 $this->assertTrue(is_dir($basePath.'1'));
179 187 $this->assertTrue(is_dir($basePath.'2'));
180 188 $this->assertTrue(is_dir($basePath.'3'));
181 189 }
182 190
183   - public function testMkdirCreatesDirectoriesEvenIfItFailsToCreateOneOfThem()
  191 + /**
  192 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
  193 + */
  194 + public function testMkdirCreatesDirectoriesFails()
184 195 {
185 196 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
186   - $directories = array(
187   - $basePath.'1', $basePath.'2', $basePath.'3'
188   - );
  197 + $dir = $basePath.'2';
189 198
190   - // create a file to make that directory cannot be created
191   - file_put_contents($basePath.'2', '');
  199 + file_put_contents($dir, '');
192 200
193   - $result = $this->filesystem->mkdir($directories);
194   -
195   - $this->assertFalse($result);
196   - $this->assertTrue(is_dir($basePath.'1'));
197   - $this->assertFalse(is_dir($basePath.'2'));
198   - $this->assertTrue(is_dir($basePath.'3'));
  201 + $this->filesystem->mkdir($dir);
199 202 }
200 203
201 204 public function testTouchCreatesEmptyFile()
@@ -207,6 +210,16 @@ public function testTouchCreatesEmptyFile()
207 210 $this->assertFileExists($file);
208 211 }
209 212
  213 + /**
  214 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
  215 + */
  216 + public function testTouchFails()
  217 + {
  218 + $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';
  219 +
  220 + $this->filesystem->touch($file);
  221 + }
  222 +
210 223 public function testTouchCreatesEmptyFilesFromArray()
211 224 {
212 225 $basePath = $this->workspace.DIRECTORY_SEPARATOR;
@@ -367,11 +380,41 @@ public function testChmodChangesFileMode()
367 380 {
368 381 $this->markAsSkippedIfChmodIsMissing();
369 382
370   - $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  383 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  384 + mkdir($dir);
  385 + $file = $dir.DIRECTORY_SEPARATOR.'file';
  386 + touch($file);
  387 +
  388 + $this->filesystem->chmod($file, 0400);
  389 + $this->filesystem->chmod($dir, 0753);
  390 +
  391 + $this->assertEquals(753, $this->getFilePermisions($dir));
  392 + $this->assertEquals(400, $this->getFilePermisions($file));
  393 + }
  394 +
  395 + public function testChmodWrongMod()
  396 + {
  397 + $this->markAsSkippedIfChmodIsMissing();
  398 +
  399 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
  400 + touch($dir);
  401 +
  402 + $this->filesystem->chmod($dir, 'Wrongmode');
  403 + }
  404 +
  405 + public function testChmodRecursive()
  406 + {
  407 + $this->markAsSkippedIfChmodIsMissing();
  408 +
  409 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  410 + mkdir($dir);
  411 + $file = $dir.DIRECTORY_SEPARATOR.'file';
371 412 touch($file);
372 413
373   - $this->filesystem->chmod($file, 0753);
  414 + $this->filesystem->chmod($file, 0400, 0000, true);
  415 + $this->filesystem->chmod($dir, 0753, 0000, true);
374 416
  417 + $this->assertEquals(753, $this->getFilePermisions($dir));
375 418 $this->assertEquals(753, $this->getFilePermisions($file));
376 419 }
377 420
@@ -420,6 +463,138 @@ public function testChmodChangesModeOfTraversableFileObject()
420 463 $this->assertEquals(753, $this->getFilePermisions($directory));
421 464 }
422 465
  466 + public function testChown()
  467 + {
  468 + $this->markAsSkippedIfPosixIsMissing();
  469 +
  470 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  471 + mkdir($dir);
  472 +
  473 + $this->filesystem->chown($dir, $this->getFileOwner($dir));
  474 + }
  475 +
  476 + public function testChownRecursive()
  477 + {
  478 + $this->markAsSkippedIfPosixIsMissing();
  479 +
  480 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  481 + mkdir($dir);
  482 + $file = $dir.DIRECTORY_SEPARATOR.'file';
  483 + touch($file);
  484 +
  485 + $this->filesystem->chown($dir, $this->getFileOwner($dir), true);
  486 + }
  487 +
  488 + public function testChownSymlink()
  489 + {
  490 + $this->markAsSkippedIfSymlinkIsMissing();
  491 +
  492 + $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  493 + $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  494 +
  495 + touch($file);
  496 +
  497 + $this->filesystem->symlink($file, $link);
  498 +
  499 + $this->filesystem->chown($link, $this->getFileOwner($link));
  500 + }
  501 +
  502 + /**
  503 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
  504 + */
  505 + public function testChownSymlinkFails()
  506 + {
  507 + $this->markAsSkippedIfSymlinkIsMissing();
  508 +
  509 + $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  510 + $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  511 +
  512 + touch($file);
  513 +
  514 + $this->filesystem->symlink($file, $link);
  515 +
  516 + $this->filesystem->chown($link, 'user' . time() . mt_rand(1000, 9999));
  517 + }
  518 +
  519 + /**
  520 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
  521 + */
  522 + public function testChownFail()
  523 + {
  524 + $this->markAsSkippedIfPosixIsMissing();
  525 +
  526 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  527 + mkdir($dir);
  528 +
  529 + $this->filesystem->chown($dir, 'user' . time() . mt_rand(1000, 9999));
  530 + }
  531 +
  532 + public function testChgrp()
  533 + {
  534 + $this->markAsSkippedIfPosixIsMissing();
  535 +
  536 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  537 + mkdir($dir);
  538 +
  539 + $this->filesystem->chgrp($dir, $this->getFileGroup($dir));
  540 + }
  541 +
  542 + public function testChgrpRecursive()
  543 + {
  544 + $this->markAsSkippedIfPosixIsMissing();
  545 +
  546 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  547 + mkdir($dir);
  548 + $file = $dir.DIRECTORY_SEPARATOR.'file';
  549 + touch($file);
  550 +
  551 + $this->filesystem->chgrp($dir, $this->getFileGroup($dir), true);
  552 + }
  553 +
  554 + public function testChgrpSymlink()
  555 + {
  556 + $this->markAsSkippedIfSymlinkIsMissing();
  557 +
  558 + $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  559 + $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  560 +
  561 + touch($file);
  562 +
  563 + $this->filesystem->symlink($file, $link);
  564 +
  565 + $this->filesystem->chgrp($link, $this->getFileGroup($link));
  566 + }
  567 +
  568 + /**
  569 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
  570 + */
  571 + public function testChgrpSymlinkFails()
  572 + {
  573 + $this->markAsSkippedIfSymlinkIsMissing();
  574 +
  575 + $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
  576 + $link = $this->workspace.DIRECTORY_SEPARATOR.'link';
  577 +
  578 + touch($file);
  579 +
  580 + $this->filesystem->symlink($file, $link);
  581 +
  582 + $this->filesystem->chgrp($link, 'user' . time() . mt_rand(1000, 9999));
  583 + }
  584 +
  585 + /**
  586 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
  587 + */
  588 + public function testChgrpFail()
  589 + {
  590 + $this->markAsSkippedIfPosixIsMissing();
  591 +
  592 + $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
  593 + mkdir($dir);
  594 +
  595 + $this->filesystem->chgrp($dir, 'user' . time() . mt_rand(1000, 9999));
  596 + }
  597 +
423 598 public function testRename()
424 599 {
425 600 $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
@@ -433,7 +608,7 @@ public function testRename()
433 608 }
434 609
435 610 /**
436   - * @expectedException \RuntimeException
  611 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
437 612 */
438 613 public function testRenameThrowsExceptionIfTargetAlreadyExists()
439 614 {
@@ -447,7 +622,7 @@ public function testRenameThrowsExceptionIfTargetAlreadyExists()
447 622 }
448 623
449 624 /**
450   - * @expectedException \RuntimeException
  625 + * @expectedException Symfony\Component\Filesystem\Exception\IOException
451 626 */
452 627 public function testRenameThrowsExceptionOnError()
453 628 {
@@ -644,6 +819,22 @@ private function getFilePermisions($filePath)
644 819 return (int) substr(sprintf('%o', fileperms($filePath)), -3);
645 820 }
646 821
  822 + private function getFileOwner($filepath)
  823 + {
  824 + $infos = stat($filepath);
  825 + if ($datas = posix_getpwuid($infos['uid'])) {
  826 + return $datas['name'];
  827 + }
  828 + }
  829 +
  830 + private function getFileGroup($filepath)
  831 + {
  832 + $infos = stat($filepath);
  833 + if ($datas = posix_getgrgid($infos['gid'])) {
  834 + return $datas['name'];
  835 + }
  836 + }
  837 +
647 838 private function markAsSkippedIfSymlinkIsMissing()
648 839 {
649 840 if (!function_exists('symlink')) {
@@ -657,4 +848,11 @@ private function markAsSkippedIfChmodIsMissing()
657 848 $this->markTestSkipped('chmod is not supported on windows');
658 849 }
659 850 }
  851 +
  852 + private function markAsSkippedIfPosixIsMissing()
  853 + {
  854 + if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
  855 + $this->markTestSkipped('Posix uids are not available on windows');
  856 + }
  857 + }
660 858 }

0 comments on commit 9355c28

Romain Neutron

you should submit a PR as a workaround for this bug

Markus Staab

Will do tomorrow

Please sign in to comment.
Something went wrong with that request. Please try again.