home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / phing / tasks / ext / ZipTask.php < prev   
Encoding:
PHP Script  |  2007-09-25  |  8.8 KB  |  266 lines

  1. <?php
  2. /*
  3.  *  $Id: ZipTask.php 240 2007-09-25 20:43:37Z mrook $
  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. include_once 'phing/lib/Zip.php';
  27.  
  28. /**
  29.  * Creates a zip archive using PEAR Archive_Zip (which is presently unreleased
  30.  * and included with Phing).
  31.  *
  32.  * @author    Michiel Rook <michiel.rook@gmail.com>
  33.  * @version   $Revision: 1.2 $
  34.  * @package   phing.tasks.ext
  35.  * @since     2.1.0
  36.  */
  37. class ZipTask extends MatchingTask {
  38.     
  39.     /**
  40.      * @var PhingFile
  41.      */
  42.     private $zipFile;
  43.     
  44.     /**
  45.      * @var PhingFile
  46.      */
  47.     private $baseDir;
  48.     
  49.     /**
  50.      * Whether to include empty dirs in the archive.
  51.      */
  52.     private $includeEmpty = true;
  53.     
  54.     private $filesets = array();
  55.     private $fileSetFiles = array();
  56.  
  57.     /**
  58.      * Add a new fileset.
  59.      * @return FileSet
  60.      */
  61.     public function createFileSet() {
  62.         $this->fileset = new ZipFileSet();
  63.         $this->filesets[] = $this->fileset;
  64.         return $this->fileset;
  65.     }
  66.  
  67.     /**
  68.      * Set is the name/location of where to create the zip file.
  69.      * @param PhingFile $destFile The output of the zip
  70.      */
  71.     public function setDestFile(PhingFile $destFile) {
  72.         $this->zipFile = $destFile;
  73.     }
  74.  
  75.     /**
  76.      * This is the base directory to look in for things to zip.
  77.      * @param PhingFile $baseDir
  78.      */
  79.     public function setBasedir(PhingFile $baseDir) {
  80.         $this->baseDir = $baseDir;
  81.     }
  82.  
  83.     /**
  84.      * Set the include empty dirs flag.
  85.      * @param  boolean  Flag if empty dirs should be tarred too
  86.      * @return void
  87.      * @access public
  88.      */
  89.     function setIncludeEmptyDirs($bool) {
  90.         $this->includeEmpty = (boolean) $bool;
  91.     }
  92.     
  93.     /**
  94.      * do the work
  95.      * @throws BuildException
  96.      */
  97.     public function main() {
  98.     
  99.         if ($this->zipFile === null) {
  100.             throw new BuildException("zipfile attribute must be set!", $this->getLocation());
  101.         }
  102.  
  103.         if ($this->zipFile->exists() && $this->zipFile->isDirectory()) {
  104.             throw new BuildException("zipfile is a directory!", $this->getLocation());
  105.         }
  106.  
  107.         if ($this->zipFile->exists() && !$this->zipFile->canWrite()) {
  108.             throw new BuildException("Can not write to the specified zipfile!", $this->getLocation());
  109.         }
  110.  
  111.         // shouldn't need to clone, since the entries in filesets
  112.         // themselves won't be modified -- only elements will be added
  113.         $savedFileSets = $this->filesets;
  114.         
  115.         try {
  116.             if ($this->baseDir !== null) {
  117.                 if (!$this->baseDir->exists()) {
  118.                     throw new BuildException("basedir does not exist!", $this->getLocation());
  119.                 }
  120.                 
  121.                 if (empty($this->filesets))
  122.                 {
  123.                     // add the main fileset to the list of filesets to process.
  124.                     $mainFileSet = new ZipFileSet($this->fileset);
  125.                     $mainFileSet->setDir($this->baseDir);
  126.                     $this->filesets[] = $mainFileSet;
  127.                 }
  128.             }
  129.  
  130.             if (empty($this->filesets)) {
  131.                 throw new BuildException("You must supply either a basedir "
  132.                                          . "attribute or some nested filesets.",
  133.                                          $this->getLocation());
  134.             }                        
  135.             
  136.             // check if zip is out of date with respect to each
  137.             // fileset
  138.             $upToDate = true;
  139.             foreach($this->filesets as $fs) {
  140.                 $files = $fs->getFiles($this->project, $this->includeEmpty);
  141.                 if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) {
  142.                     $upToDate = false;
  143.                 }
  144.                 for ($i=0, $fcount=count($files); $i < $fcount; $i++) {
  145.                     if ($this->zipFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) {
  146.                         throw new BuildException("A zip file cannot include itself", $this->getLocation());
  147.                     }
  148.                 }
  149.             }
  150.             
  151.             if ($upToDate) {
  152.                 $this->log("Nothing to do: " . $this->zipFile->__toString() . " is up to date.", Project::MSG_INFO);
  153.                 return;
  154.             }
  155.  
  156.             $this->log("Building zip: " . $this->zipFile->__toString(), Project::MSG_INFO);
  157.             
  158.             $zip = new Archive_Zip($this->zipFile->getAbsolutePath());
  159.             
  160.             foreach($this->filesets as $fs) {
  161.                 
  162.                 $files = $fs->getFiles($this->project, $this->includeEmpty);
  163.                 
  164.                 $fsBasedir = (null != $this->baseDir) ? $this->baseDir :
  165.                                     $fs->getDir($this->project);
  166.                 
  167.                 $filesToZip = array();
  168.                 for ($i=0, $fcount=count($files); $i < $fcount; $i++) {
  169.                     $f = new PhingFile($fsBasedir, $files[$i]);
  170.                     $filesToZip[] = $f->getAbsolutePath();
  171.                     $this->log("Adding " . $f->getPath() . " to archive.", Project::MSG_VERBOSE);                        
  172.                 }
  173.                 $zip->add($filesToZip, array('remove_path' => $fsBasedir->getCanonicalPath()));
  174.             }
  175.                          
  176.                 
  177.         } catch (IOException $ioe) {
  178.                 $msg = "Problem creating ZIP: " . $ioe->getMessage();
  179.                 $this->filesets = $savedFileSets;
  180.                 throw new BuildException($msg, $ioe, $this->getLocation());
  181.         }
  182.         
  183.         $this->filesets = $savedFileSets;
  184.     }
  185.            
  186.     /**
  187.      * @param array $files array of filenames
  188.      * @param PhingFile $dir
  189.      * @return boolean
  190.      */
  191.     protected function archiveIsUpToDate($files, $dir) {
  192.         $sfs = new SourceFileScanner($this);
  193.         $mm = new MergeMapper();
  194.         $mm->setTo($this->zipFile->getAbsolutePath());
  195.         return count($sfs->restrict($files, $dir, null, $mm)) == 0;
  196.     }
  197.    
  198. }
  199.  
  200.  
  201.  
  202.  
  203. /**
  204.  * This is a FileSet with the to specify permissions.
  205.  * 
  206.  * Permissions are currently not implemented by PEAR Archive_Tar,
  207.  * but hopefully they will be in the future.
  208.  * 
  209.  */
  210. class ZipFileSet extends FileSet {
  211.  
  212.     private $files = null;
  213.  
  214.     /**
  215.      *  Get a list of files and directories specified in the fileset.
  216.      *  @return array a list of file and directory names, relative to
  217.      *    the baseDir for the project.
  218.      */
  219.     public function getFiles(Project $p, $includeEmpty = true) {
  220.     
  221.         if ($this->files === null) {
  222.         
  223.             $ds = $this->getDirectoryScanner($p);
  224.             $this->files = $ds->getIncludedFiles();
  225.             
  226.             if ($includeEmpty) {
  227.             
  228.                 // first any empty directories that will not be implicitly added by any of the files
  229.                 $implicitDirs = array();
  230.                 foreach($this->files as $file) {
  231.                     $implicitDirs[] = dirname($file);
  232.                 } 
  233.                 
  234.                 $incDirs = $ds->getIncludedDirectories();
  235.                 
  236.                 // we'll need to add to that list of implicit dirs any directories
  237.                 // that contain other *directories* (and not files), since otherwise
  238.                 // we get duplicate directories in the resulting tar
  239.                 foreach($incDirs as $dir) {
  240.                     foreach($incDirs as $dircheck) {
  241.                         if (!empty($dir) && $dir == dirname($dircheck)) {
  242.                             $implicitDirs[] = $dir;
  243.                         }
  244.                     }
  245.                 }
  246.                 
  247.                 $implicitDirs = array_unique($implicitDirs);
  248.                 
  249.                 // Now add any empty dirs (dirs not covered by the implicit dirs)
  250.                 // to the files array. 
  251.                 
  252.                 foreach($incDirs as $dir) { // we cannot simply use array_diff() since we want to disregard empty/. dirs
  253.                     if ($dir != "" && $dir != "." && !in_array($dir, $implicitDirs)) {
  254.                         // it's an empty dir, so we'll add it.
  255.                         $this->files[] = $dir;
  256.                     }
  257.                 }
  258.             } // if $includeEmpty
  259.             
  260.         } // if ($this->files===null)
  261.         
  262.         return $this->files;
  263.     }
  264.  
  265. }
  266.