<?php
/**
 * $Id$
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the LGPL. For more information please see
 * <http://phing.info>.
 */

require_once 'phing/Task.php';
require_once 
'phing/tasks/ext/svn/SvnBaseTask.php';

/**
 * Retrive files added and modified between ${fromrev} and ${torev}
 *
 * @author MiRacLe <miracle@rpz.name>
 * @version $Id$
 * @package phing.tasks.ext.svn
 */
class SvnExportRevisionDiffTask extends SvnBaseTask {
    private 
$fromRevision 1;
    private 
$toRevision 'HEAD';
    function 
setFromRevision($rev) {
        
$this->fromRevision $rev;
    }
    function 
setToRevision($rev) {
        
$this->toRevision $rev;
    }    
    function 
main() {
        
$added_and_modified = array();
        
$deleted = array();
               
        if (
$xml $this->getRevListXML($this->toRevision)) { 
            
$entries $xml->list->entry;
            foreach (
$entries as $entry) {
                
$attrs $entry->attributes();
                
$is_dir = (string)$attrs['kind'] == 'dir';
                
$name = (string)$entry->name;
                
$size = ($is_dir) ? : (int)(string)$entry->size;
                
$attrs $entry->commit->attributes();
                
$rev = (int)(string)$attrs['revision'];
                
$added_and_modified[$name] = array('rev' => $rev,'dir' => $is_dir,'size' => $size);
            }        
            
            if (
$xml $this->getRevListXML($this->fromRevision)) {
                
$entries $xml->list->entry;
                foreach (
$entries as $entry) {
                    
$attrs $entry->attributes();
                    
$is_dir = (string)$attrs['kind'] == 'dir';
                    
$name = (string)$entry->name;
                    
$size = ($is_dir) ? : (int)(string)$entry->size;
                    
$attrs $entry->commit->attributes();
                    
$rev = (int)(string)$attrs['revision'];
                    if (isset(
$added_and_modified[$name]) && $added_and_modified[$name]['rev'] == $rev) {
                        unset(
$added_and_modified[$name]);
                    } else {
                        
$deleted[$name] = array('size' => $size);
                    }
                }
                
$this->setForce(true);        
                
$repo $this->getRepositoryUrl();
                foreach (
$added_and_modified as $entry => $info) {
                    if (
$info['dir']) {
                        
mkdir($this->getToDir().'/'.$entry);
                    } else {
                        
$this->setRepositoryUrl($repo .'/'.$entry);  //@fixme
                        
$this->setup('export');
                        
$this->log("Exporting SVN repository from '" $this->getRepositoryUrl() . "'");
                        
$this->run(array($this->getToDir().'/'.$entry));            
                    }
                }
                return 
true;
            }
            throw new 
BuildException("Unable retrieve list files for '" $this->fromRevision"' revision");
        }        
        throw new 
BuildException("Unable retrieve list files for '" $this->toRevision"' revision");
    }
    private function 
getRevListXML($rev) {
        
$cmd sprintf('%s list --xml --recursive --username "%s" --password "%s" --revision %s %s',
                        
$this->getSvnPath(),
                        
$this->getUsername(),
                        
$this->getPassword(),
                        
$rev,
                        
$this->getRepositoryUrl());
        
$output = array();
        
$this->log("Executing svn list ...");
        if (
exec($cmd,$output)) {
            
$this->log("export done.");
            
$xml implode(PHP_EOL,$output);
            return @
simplexml_load_string($xml);
        }
        throw new 
BuildException("Failed to run the '" $cmd "'");
    }
}
?>