Skip to content

Instantly share code, notes, and snippets.

@Hounddog
Created September 27, 2012 09:16
Show Gist options
  • Save Hounddog/3793059 to your computer and use it in GitHub Desktop.
Save Hounddog/3793059 to your computer and use it in GitHub Desktop.
Phing Task to copy files if the properties change
<?php
/**
* V5
* LICENSE
*
* Insert License here
*
* @category Phing
* @package CopyPropertyTask
* @copyright Copyright (c) 2012 Doyousoft
* @license $license_information
* @version $Id
*/
/**
* Inlude Copytask for extending
*/
require_once "phing/tasks/system/CopyTask.php";
/**
* Phing task to Match the hash values of the files to be copied
* Enables to overwrite files if property changes
* @category Phing
* @package CopyPropertyTask
* @copyright Copyright (c) 2012 Doyousoft
* @version $Id
* @license $license_information
*/
class CopyPropertyTask extends CopyTask
{
/**
* The main entry point where everything gets in motion.
*
* @access public
* @return true on success
* @throws BuildException
*/
function main()
{
$this->validateAttributes();
if ($this->file !== null) {
if ($this->file->exists()) {
if ($this->destFile === null) {
$this->destFile = new PhingFile(
$this->destDir, (string) $this->file->getName()
);
}
if (
$this->overwrite === true
|| (
$this->file->lastModified()
> $this->destFile->lastModified()
)
) {
$this->fileCopyMap[$this->file->getAbsolutePath()]
= $this->destFile->getAbsolutePath();
} else if (
$this->hashMap(
$this->file->getAbsolutePath(),
$this->destFile->getAbsolutePath()
)
) {
$this->log('needs to be copied');
} else {
$this->log(
$this->file->getName()." omitted, is up to date"
);
}
} else {
// terminate build
$this->logError(
"Could not find file "
.$this->file->__toString()
." to copy."
);
}
}
$project = $this->getProject();
// process filelists
foreach ($this->filelists as $fl) {
$fromDir = $fl->getDir($project);
$srcFiles = $fl->getFiles($project);
$srcDirs = array($fl->getDir($project));
if (!$this->flatten && $this->mapperElement === null) {
$this->completeDirMap[$fromDir->getAbsolutePath()]
= $this->destDir->getAbsolutePath();
}
$this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs);
}
// process filesets
foreach ($this->filesets as $fs) {
$ds = $fs->getDirectoryScanner($project);
$fromDir = $fs->getDir($project);
$srcFiles = $ds->getIncludedFiles();
$srcDirs = $ds->getIncludedDirectories();
if (!$this->flatten && $this->mapperElement === null) {
$this->completeDirMap[$fromDir->getAbsolutePath()]
= $this->destDir->getAbsolutePath();
}
$this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs);
}
// go and copy the stuff
$this->doWork();
if ($this->destFile !== null) {
$this->destDir = null;
}
}
/**
* Compares source files to destination files to see if they
* should be copied.
*
* @access private
* @param string $fromDir
* @param string $toDir
* @param array $files
* @param array $dirs
* @return void
*/
private function _scan(&$fromDir, &$toDir, &$files, &$dirs)
{
/* mappers should be generic, so we get the mappers here and
pass them on to builMap. This method is not redundan like it seems */
$mapper = null;
if ($this->mapperElement !== null) {
$mapper = $this->mapperElement->getImplementation();
} else if ($this->flatten) {
$mapper = new FlattenMapper();
} else {
$mapper = new IdentityMapper();
}
$this->buildMap($fromDir, $toDir, $files, $mapper, $this->fileCopyMap);
$this->buildMap($fromDir, $toDir, $dirs, $mapper, $this->dirCopyMap);
}
/**
* Builds a map of filenames (from->to) that should be copied
*
* @access private
* @param string $fromDir
* @param string $toDir
* @param array $names
* @param object $mapper
* @param array $map
* @return void
*/
private function buildMap(&$fromDir, &$toDir, &$names, &$mapper, &$map)
{
$toCopy = null;
if ($this->overwrite) {
$v = array();
foreach ($names as $name) {
$result = $mapper->main($name);
if ($result !== null) {
$v[] = $name;
}
}
$toCopy = $v;
} else if ($this->hashMap($fromDir, $toDir, $names, $mapper, $map)) {
} else {
$ds = new SourceFileScanner($this);
$toCopy = $ds->restrict($names, $fromDir, $toDir, $mapper);
}
for ($i=0,$_i=count($toCopy); $i < $_i; $i++) {
$src = new PhingFile($fromDir, $toCopy[$i]);
$mapped = $mapper->main($toCopy[$i]);
$dest = new PhingFile($toDir, $mapped[0]);
$map[$src->getAbsolutePath()] = $dest->getAbsolutePath();
}
}
/**
* Match the file hashmap of parsed src File and target file
* @param string &$fromDir
* @param string &$toDir
* @param array &$names
* @param object &$mapper
* @param array &$map
*/
protected function hashMap(&$fromDir, &$toDir, &$names, &$mapper, &$map)
{
$v = array();
$toCopy = null;
foreach ($names as $name) {
$to = $toDir . '/' . $name;
$from = $fromDir . '/' .$name;
$fromFile = new PhingFile($from);
$toFile = new PhingFile($to);
$result = null;
if ($toFile->exists()) {
$toHash = hash_file('md5', $toFile);
$mapped = $mapper->main($name);
$dest = new PhingFile($fromDir, $mapped[0]);
if (
(is_array($this->filterChains)) &&
(!empty($this->filterChains))) {
$in = $this->fileUtils->getChainedReader(
new BufferedReader(
new FileReader($fromFile)
),
$this->filterChains, $this->getProject()
);
// New read() methods returns a big buffer.
while (-1 !== ($buffer = $in->read())) { // -1 indicates EOF
$fileContents = $buffer;
}
if ( $in !== null )
$in->close();
}
$fromHash = md5($fileContents);
if ($toHash !== $fromHash) {
if ($toFile->exists() && $toFile->isFile()) {
$toFile->delete();
}
}
} else {
$result = $mapper->main($name);
}
if ($result !== null) {
$v[] = $name;
}
}
$toCopy = $v;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment