<?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) ? 0 : (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) ? 0 : (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 . "'");
    }
}
?>