Ticket #221: phing.symlinks[1].patch
| File phing.symlinks[1].patch, 8.5 kB (added by Bruce Weirdan <weirdan@gmail.com>, 6 months ago) |
|---|
-
classes/phing/system/io/File.php
old new 405 405 return @is_file($this->path); 406 406 } 407 407 408 public function isLink() { 409 clearstatcache(); 410 $fs = FileSystem::getFileSystem(); 411 if ($fs->checkAccess($this) !== true) { 412 throw new IOException("No read access to " . $this->path); 413 } 414 return @is_link($this->path); 415 } 416 417 public function getLinkTarget() 418 { 419 return @readlink($this->path); 420 } 421 408 422 /** 409 423 * Tests whether the path represented by this object is a hidden file. 410 424 * … … 608 622 * @param File $destFile The new abstract pathname for the named file 609 623 * @return true if and only if the renaming succeeded; false otherwise 610 624 */ 611 public function copyTo(File $destFile ) {625 public function copyTo(File $destFile, $resolveSymlinks = true) { 612 626 $fs = FileSystem::getFileSystem(); 613 627 614 628 if ($fs->checkAccess($this) !== true) { … … 618 632 if ($fs->checkAccess($destFile, true) !== true) { 619 633 throw new IOException("File::copyTo() No write access to ".$destFile->getPath()); 620 634 } 621 return $fs->copy($this, $destFile );635 return $fs->copy($this, $destFile, $resolveSymlinks); 622 636 } 623 637 624 638 /** -
classes/phing/system/io/UnixFileSystem.php
old new 271 271 * @param File $f 272 272 * @return boolean 273 273 */ 274 function canDelete(File $f)274 function canDelete(File $f) 275 275 { 276 276 @clearstatcache(); 277 277 $dir = dirname($f->getAbsolutePath()); 278 278 return (bool) @is_writable($dir); 279 279 } 280 281 282 /** 283 * Copy a file. 284 * 285 * This method overrides generic copy method to add support for copying 286 * symlinks as is (without resolving them to ordinary files). 287 * 288 * @param File $src Source path and name file to copy 289 * @param File $dest Destination path and name of new file 290 * @param bool $resolveSymlinks whether to resolve symlink to their content 291 * 292 * @return void 293 * @throws Exception if file cannot be copied or symlink cannot be created 294 */ 295 function copy(File $src, File $dest, $resolveSymlinks = true) { 296 if ($resolveSymlinks || !$src->isLink()) { // copy as usual (content) 297 return parent::copy($src, $dest); 298 } else { // do not resolve symlinks, copy as is 299 $destPath = $dest->getAbsolutePath(); 300 $linkTarget = $src->getLinkTarget(); 301 if (false === @symlink($linkTarget, $destPath)) { 302 $msg = "FileSystem::copy() FAILED. Cannot create symlink from $destPath to $linkTarget."; 303 throw new Exception($msg); 304 } 305 306 // chmod has no effects on symlinks, so we do not have to chmod created symlink 307 } 308 } 280 309 281 310 } -
classes/phing/tasks/system/CopyTask.php
old new 49 49 protected $preserveLMT = true; // sync timestamps (from xml attribute) 50 50 protected $includeEmpty = true; // include empty dirs? (from XML) 51 51 protected $flatten = false; // apply the FlattenMapper right way (from XML) 52 protected $resolveSymlinks = true; // resolve symlinks (copy them as their content) ? 52 53 protected $mapperElement = null; 53 54 54 55 protected $fileCopyMap = array(); // asoc array containing mapped file names … … 118 119 $this->includeEmpty = (boolean) $bool; 119 120 } 120 121 122 /** 123 * Set the resolve symlinks flag. Obviously meaningless on filesystems 124 * without symlink support. 125 * 126 * @param boolean Flag if symlinks should be copied as their content 127 * @return void 128 * @access public 129 */ 130 function setResolveSymlinks($bool) { 131 $this->resolveSymlinks = (boolean) $bool; 132 } 121 133 134 122 135 /** 123 136 * Set the file. We have to manually take care of the 124 137 * type that is coming due to limited type support in php … … 160 173 $this->destDir = $dir; 161 174 } 162 175 176 163 177 /** 164 178 * Nested creator, creates a FileSet for this task 165 179 * … … 230 244 foreach($this->filesets as $fs) { 231 245 $ds = $fs->getDirectoryScanner($project); 232 246 $fromDir = $fs->getDir($project); 247 248 if (!$this->resolveSymlinks) { 249 $ds->setTreatDirSymlinksAsFiles(true); 250 } 251 233 252 $srcFiles = $ds->getIncludedFiles(); 234 253 $srcDirs = $ds->getIncludedDirectories(); 235 254 236 255 if (!$this->flatten && $this->mapperElement === null) 237 256 { 238 257 $this->completeDirMap[$fromDir->getAbsolutePath()] = $this->destDir->getAbsolutePath(); … … 376 395 $toSlot->setValue($toFile->getPath()); 377 396 $toBasenameSlot->setValue($toFile->getName()); 378 397 379 FileUtils::copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject() );398 FileUtils::copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject(), $this->resolveSymlinks); 380 399 381 400 $count++; 382 401 } catch (IOException $ioe) { -
classes/phing/util/DirectoryScanner.php
old new 188 188 /** if there are no deselected files */ 189 189 protected $everythingIncluded = true; 190 190 191 protected $treatDirSymlinksAsFiles = false; 192 191 193 /** 192 194 * Does the path match the start of this pattern up to the first "**". 193 195 * This is a static mehtod and should always be called static … … 419 421 return $list; 420 422 } 421 423 424 public function setTreatDirSymlinksAsFiles($bool = true) 425 { 426 $this->treatDirSymlinksAsFiles = (bool) $bool; 427 } 428 422 429 /** 423 430 * Scans the passed dir for files and directories. Found files and 424 431 * directories are placed in their respective collections, based on the … … 450 457 $file = $_rootdir . DIRECTORY_SEPARATOR . $newfiles[$i]; 451 458 $name = $_vpath . $newfiles[$i]; 452 459 453 if (@is_dir($file) ) {460 if (@is_dir($file) && !(@is_link($file) && $this->treatDirSymlinksAsFiles)) { 454 461 if ($this->isIncluded($name)) { 455 462 if (!$this->isExcluded($name)) { 456 463 if ($this->isSelected($name, $file)) { -
classes/phing/util/FileUtils.php
old new 70 70 * @param boolean $preserveLastModified 71 71 * @param array $filterChains 72 72 * @param Project $project 73 * @param boolean $resolveSymlinks 73 74 * @return void 74 75 */ 75 public static function copyFile(File $sourceFile, File $destFile, $overwrite = false, $preserveLastModified = true, &$filterChains = null, Project $project ) {76 public static function copyFile(File $sourceFile, File $destFile, $overwrite = false, $preserveLastModified = true, &$filterChains = null, Project $project, $resolveSymlinks = true) { 76 77 77 78 if ($overwrite || !$destFile->exists() || $destFile->lastModified() < $sourceFile->lastModified()) { 78 79 if ($destFile->exists() && $destFile->isFile()) { … … 101 102 $out->close(); 102 103 } else { 103 104 // simple copy (no filtering) 104 $sourceFile->copyTo($destFile );105 $sourceFile->copyTo($destFile, $resolveSymlinks); 105 106 } 106 107 107 if ($preserveLastModified) { 108 $destFile->setLastModified($sourceFile->lastModified()); 109 } 108 // changing LMT on symlinks fails for some reason so we attempt it 109 // only if we are sure the created file is not a symlink (either it 110 // was resolved to file content due to the resolveSymlinks flag or 111 // the source file wasn't symlink in the first place) 112 113 if ($resolveSymlinks || !$sourceFile->isLink()) { 114 if ($preserveLastModified) { 115 $destFile->setLastModified($sourceFile->lastModified()); 116 } 117 } 110 118 111 119 } 112 120 }
