[ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 /* 3 * $Id: TarTask.php 3076 2006-12-18 08:52:12Z fabien $ 4 * 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 * 17 * This software consists of voluntary contributions made by many individuals 18 * and is licensed under the LGPL. For more information please see 19 * <http://phing.info>. 20 */ 21 22 require_once 'phing/tasks/system/MatchingTask.php'; 23 include_once 'phing/util/SourceFileScanner.php'; 24 include_once 'phing/mappers/MergeMapper.php'; 25 include_once 'phing/util/StringHelper.php'; 26 27 /** 28 * Creates a tar archive using PEAR Archive_Tar. 29 * 30 * @author Hans Lellelid <hans@xmpl.org> (Phing) 31 * @author Stefano Mazzocchi <stefano@apache.org> (Ant) 32 * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) 33 * @author Magesh Umasankar 34 * @version $Revision: 1.10 $ 35 * @package phing.tasks.ext 36 */ 37 class TarTask extends MatchingTask { 38 39 const TAR_NAMELEN = 100; 40 41 const WARN = "warn"; 42 const FAIL = "fail"; 43 const OMIT = "omit"; 44 45 private $tarFile; 46 private $baseDir; 47 private $includeEmpty = true; // Whether to include empty dirs in the TAR 48 49 private $longFileMode = "warn"; 50 51 private $filesets = array(); 52 private $fileSetFiles = array(); 53 54 /** 55 * Indicates whether the user has been warned about long files already. 56 */ 57 private $longWarningGiven = false; 58 59 /** 60 * Compression mode. Available options "gzip", "bzip2", "none" (null). 61 */ 62 private $compression = null; 63 64 /** 65 * Ensures that PEAR lib exists. 66 */ 67 public function init() { 68 include_once 'Archive/Tar.php'; 69 if (!class_exists('Archive_Tar')) { 70 throw new BuildException("You must have installed the PEAR Archive_Tar class in order to use TarTask."); 71 } 72 } 73 74 /** 75 * Add a new fileset 76 * @return FileSet 77 */ 78 public function createTarFileSet() { 79 $this->fileset = new TarFileSet(); 80 $this->filesets[] = $this->fileset; 81 return $this->fileset; 82 } 83 84 /** 85 * Add a new fileset. Alias to createTarFileSet() for backwards compatibility. 86 * @return FileSet 87 * @see createTarFileSet() 88 */ 89 public function createFileSet() { 90 $this->fileset = new TarFileSet(); 91 $this->filesets[] = $this->fileset; 92 return $this->fileset; 93 } 94 95 /** 96 * Set is the name/location of where to create the tar file. 97 * @param PhingFile $destFile The output of the tar 98 */ 99 public function setDestFile(PhingFile $destFile) { 100 $this->tarFile = $destFile; 101 } 102 103 /** 104 * This is the base directory to look in for things to tar. 105 * @param PhingFile $baseDir 106 */ 107 public function setBasedir(PhingFile $baseDir) { 108 $this->baseDir = $baseDir; 109 } 110 111 /** 112 * Set the include empty dirs flag. 113 * @param boolean Flag if empty dirs should be tarred too 114 * @return void 115 * @access public 116 */ 117 function setIncludeEmptyDirs($bool) { 118 $this->includeEmpty = (boolean) $bool; 119 } 120 121 /** 122 * Set how to handle long files, those with a path>100 chars. 123 * Optional, default=warn. 124 * <p> 125 * Allowable values are 126 * <ul> 127 * <li> truncate - paths are truncated to the maximum length 128 * <li> fail - paths greater than the maximim cause a build exception 129 * <li> warn - paths greater than the maximum cause a warning and GNU is used 130 * <li> gnu - GNU extensions are used for any paths greater than the maximum. 131 * <li> omit - paths greater than the maximum are omitted from the archive 132 * </ul> 133 */ 134 public function setLongfile($mode) { 135 $this->longFileMode = $mode; 136 } 137 138 /** 139 * Set compression method. 140 * Allowable values are 141 * <ul> 142 * <li> none - no compression 143 * <li> gzip - Gzip compression 144 * <li> bzip2 - Bzip2 compression 145 * </ul> 146 */ 147 public function setCompression($mode) { 148 switch($mode) { 149 case "gzip": 150 $this->compression = "gz"; 151 break; 152 case "bzip2": 153 $this->compression = "bz2"; 154 break; 155 case "none": 156 $this->compression = null; 157 break; 158 default: 159 $this->log("Ignoring unknown compression mode: ".$mode, PROJECT_MSG_WARN); 160 $this->compression = null; 161 } 162 } 163 164 /** 165 * do the work 166 * @throws BuildException 167 */ 168 public function main() { 169 170 if ($this->tarFile === null) { 171 throw new BuildException("tarfile attribute must be set!", $this->getLocation()); 172 } 173 174 if ($this->tarFile->exists() && $this->tarFile->isDirectory()) { 175 throw new BuildException("tarfile is a directory!", $this->getLocation()); 176 } 177 178 if ($this->tarFile->exists() && !$this->tarFile->canWrite()) { 179 throw new BuildException("Can not write to the specified tarfile!", $this->getLocation()); 180 } 181 182 // shouldn't need to clone, since the entries in filesets 183 // themselves won't be modified -- only elements will be added 184 $savedFileSets = $this->filesets; 185 186 try { 187 if ($this->baseDir !== null) { 188 if (!$this->baseDir->exists()) { 189 throw new BuildException("basedir does not exist!", $this->getLocation()); 190 } 191 if (empty($this->filesets)) { // if there weren't any explicit filesets specivied, then 192 // create a default, all-inclusive fileset using the specified basedir. 193 $mainFileSet = new TarFileSet($this->fileset); 194 $mainFileSet->setDir($this->baseDir); 195 $this->filesets[] = $mainFileSet; 196 } 197 } 198 199 if (empty($this->filesets)) { 200 throw new BuildException("You must supply either a basedir " 201 . "attribute or some nested filesets.", 202 $this->getLocation()); 203 } 204 205 // check if tar is out of date with respect to each fileset 206 if($this->tarFile->exists()) { 207 $upToDate = true; 208 foreach($this->filesets as $fs) { 209 $files = $fs->getFiles($this->project, $this->includeEmpty); 210 if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) { 211 $upToDate = false; 212 } 213 for ($i=0, $fcount=count($files); $i < $fcount; $i++) { 214 if ($this->tarFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) { 215 throw new BuildException("A tar file cannot include itself", $this->getLocation()); 216 } 217 } 218 } 219 if ($upToDate) { 220 $this->log("Nothing to do: " . $this->tarFile->__toString() . " is up to date.", PROJECT_MSG_INFO); 221 return; 222 } 223 } 224 225 $this->log("Building tar: " . $this->tarFile->__toString(), PROJECT_MSG_INFO); 226 227 $tar = new Archive_Tar($this->tarFile->getAbsolutePath(), $this->compression); 228 229 // print errors 230 $tar->setErrorHandling(PEAR_ERROR_PRINT); 231 232 foreach($this->filesets as $fs) { 233 $files = $fs->getFiles($this->project, $this->includeEmpty); 234 if (count($files) > 1 && strlen($fs->getFullpath()) > 0) { 235 throw new BuildException("fullpath attribute may only " 236 . "be specified for " 237 . "filesets that specify a " 238 . "single file."); 239 } 240 $fsBasedir = $fs->getDir($this->project); 241 $filesToTar = array(); 242 for ($i=0, $fcount=count($files); $i < $fcount; $i++) { 243 $f = new PhingFile($fsBasedir, $files[$i]); 244 $filesToTar[] = $f->getAbsolutePath(); 245 } 246 $tar->addModify($filesToTar, '', $fsBasedir->getAbsolutePath()); 247 } 248 249 250 } catch (IOException $ioe) { 251 $msg = "Problem creating TAR: " . $ioe->getMessage(); 252 $this->filesets = $savedFileSets; 253 throw new BuildException($msg, $ioe, $this->getLocation()); 254 } 255 256 $this->filesets = $savedFileSets; 257 } 258 259 /** 260 * @param array $files array of filenames 261 * @param PhingFile $dir 262 * @return boolean 263 */ 264 protected function archiveIsUpToDate($files, $dir) { 265 $sfs = new SourceFileScanner($this); 266 $mm = new MergeMapper(); 267 $mm->setTo($this->tarFile->getAbsolutePath()); 268 return count($sfs->restrict($files, $dir, null, $mm)) == 0; 269 } 270 271 } 272 273 274 /** 275 * This is a FileSet with the option to specify permissions. 276 * 277 * Permissions are currently not implemented by PEAR Archive_Tar, 278 * but hopefully they will be in the future. 279 * 280 */ 281 class TarFileSet extends FileSet { 282 283 private $files = null; 284 285 private $mode = 0100644; 286 287 private $userName = ""; 288 private $groupName = ""; 289 private $prefix = ""; 290 private $fullpath = ""; 291 private $preserveLeadingSlashes = false; 292 293 /** 294 * Get a list of files and directories specified in the fileset. 295 * @return array a list of file and directory names, relative to 296 * the baseDir for the project. 297 */ 298 public function getFiles(Project $p, $includeEmpty = true) { 299 300 if ($this->files === null) { 301 302 $ds = $this->getDirectoryScanner($p); 303 $this->files = $ds->getIncludedFiles(); 304 305 if ($includeEmpty) { 306 307 // first any empty directories that will not be implicitly added by any of the files 308 $implicitDirs = array(); 309 foreach($this->files as $file) { 310 $implicitDirs[] = dirname($file); 311 } 312 313 $incDirs = $ds->getIncludedDirectories(); 314 315 // we'll need to add to that list of implicit dirs any directories 316 // that contain other *directories* (and not files), since otherwise 317 // we get duplicate directories in the resulting tar 318 foreach($incDirs as $dir) { 319 foreach($incDirs as $dircheck) { 320 if (!empty($dir) && $dir == dirname($dircheck)) { 321 $implicitDirs[] = $dir; 322 } 323 } 324 } 325 326 $implicitDirs = array_unique($implicitDirs); 327 328 // Now add any empty dirs (dirs not covered by the implicit dirs) 329 // to the files array. 330 331 foreach($incDirs as $dir) { // we cannot simply use array_diff() since we want to disregard empty/. dirs 332 if ($dir != "" && $dir != "." && !in_array($dir, $implicitDirs)) { 333 // it's an empty dir, so we'll add it. 334 $this->files[] = $dir; 335 } 336 } 337 } // if $includeEmpty 338 339 } // if ($this->files===null) 340 341 return $this->files; 342 } 343 344 /** 345 * A 3 digit octal string, specify the user, group and 346 * other modes in the standard Unix fashion; 347 * optional, default=0644 348 * @param string $octalString 349 */ 350 public function setMode($octalString) { 351 $octal = (int) $octalString; 352 $this->mode = 0100000 | $octal; 353 } 354 355 public function getMode() { 356 return $this->mode; 357 } 358 359 /** 360 * The username for the tar entry 361 * This is not the same as the UID, which is 362 * not currently set by the task. 363 */ 364 public function setUserName($userName) { 365 $this->userName = $userName; 366 } 367 368 public function getUserName() { 369 return $this->userName; 370 } 371 372 /** 373 * The groupname for the tar entry; optional, default="" 374 * This is not the same as the GID, which is 375 * not currently set by the task. 376 */ 377 public function setGroup($groupName) { 378 $this->groupName = $groupName; 379 } 380 381 public function getGroup() { 382 return $this->groupName; 383 } 384 385 /** 386 * If the prefix attribute is set, all files in the fileset 387 * are prefixed with that path in the archive. 388 * optional. 389 */ 390 public function setPrefix($prefix) { 391 $this->prefix = $prefix; 392 } 393 394 public function getPrefix() { 395 return $this->prefix; 396 } 397 398 /** 399 * If the fullpath attribute is set, the file in the fileset 400 * is written with that path in the archive. The prefix attribute, 401 * if specified, is ignored. It is an error to have more than one file specified in 402 * such a fileset. 403 */ 404 public function setFullpath($fullpath) { 405 $this->fullpath = $fullpath; 406 } 407 408 public function getFullpath() { 409 return $this->fullpath; 410 } 411 412 /** 413 * Flag to indicates whether leading `/'s should 414 * be preserved in the file names. 415 * Optional, default is <code>false</code>. 416 * @return void 417 */ 418 public function setPreserveLeadingSlashes($b) { 419 $this->preserveLeadingSlashes = (boolean) $b; 420 } 421 422 public function getPreserveLeadingSlashes() { 423 return $this->preserveLeadingSlashes; 424 } 425 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |