diff --git a/src/MagentoHackathon/Composer/Magento/Deploystrategy/Copy.php b/src/MagentoHackathon/Composer/Magento/Deploystrategy/Copy.php index 3b3f698f..888cf09d 100644 --- a/src/MagentoHackathon/Composer/Magento/Deploystrategy/Copy.php +++ b/src/MagentoHackathon/Composer/Magento/Deploystrategy/Copy.php @@ -20,6 +20,11 @@ class Copy extends DeploystrategyAbstract */ public function createDelegate($source, $dest) { + list($mapSource, $mapDest) = $this->getCurrentMapping(); + $mapSource = $this->removeTrailingSlash($mapSource); + $mapDest = $this->removeTrailingSlash($mapDest); + $cleanDest = $this->removeTrailingSlash($dest); + $sourcePath = $this->getSourceDir() . '/' . $this->removeTrailingSlash($source); $destPath = $this->getDestDir() . '/' . $this->removeTrailingSlash($dest); @@ -36,20 +41,28 @@ public function createDelegate($source, $dest) // Namespace/ModuleDir => Namespace/, but Namespace/ModuleDir may exist // Namespace/ModuleDir => Namespace/ModuleDir, but ModuleDir may exist + // first iteration through, we need to update the mappings to correctly handle mismatch globs + if ($mapSource == $this->removeTrailingSlash($source) && $mapDest == $this->removeTrailingSlash($dest)) { + if (basename($sourcePath) !== basename($destPath)) { + $this->setCurrentMapping(array($mapSource, $mapDest . '/' . basename($source))); + $cleanDest = $cleanDest . '/' . basename($source); + } + } + if (file_exists($destPath) && is_dir($destPath)) { - if (basename($sourcePath) === basename($destPath)) { + if (strcmp(substr($cleanDest, strlen($mapDest)+1), substr($source, strlen($mapSource)+1)) === 0) { // copy each child of $sourcePath into $destPath foreach (new \DirectoryIterator($sourcePath) as $item) { $item = (string) $item; if (!strcmp($item, '.') || !strcmp($item, '..')) { continue; } - $childSource = $source . '/' . $item; + $childSource = $this->removeTrailingSlash($source) . '/' . $item; $this->create($childSource, substr($destPath, strlen($this->getDestDir())+1)); } return true; } else { - $destPath .= '/' . basename($source); + $destPath = $this->removeTrailingSlash($destPath) . '/' . basename($source); return $this->create($source, substr($destPath, strlen($this->getDestDir())+1)); } } diff --git a/src/MagentoHackathon/Composer/Magento/Deploystrategy/DeploystrategyAbstract.php b/src/MagentoHackathon/Composer/Magento/Deploystrategy/DeploystrategyAbstract.php index b8a80b55..e003007a 100644 --- a/src/MagentoHackathon/Composer/Magento/Deploystrategy/DeploystrategyAbstract.php +++ b/src/MagentoHackathon/Composer/Magento/Deploystrategy/DeploystrategyAbstract.php @@ -17,6 +17,13 @@ abstract class DeploystrategyAbstract */ protected $mappings = array(); + /** + * The current mapping of the deployment iteration + * + * @var array + */ + protected $currentMapping = array(); + /** * The magento installation's base directory * @@ -59,6 +66,7 @@ public function deploy() { foreach ($this->getMappings() as $data) { list ($source, $dest) = $data; + $this->setCurrentMapping($data); $this->create($source, $dest); } return $this; @@ -139,6 +147,26 @@ public function setMappings(array $mappings) $this->mappings = $mappings; } + /** + * Gets the current mapping used on the deployment iteration + * + * @return array + */ + public function getCurrentMapping() + { + return $this->currentMapping; + } + + /** + * Sets the current mapping used on the deployment iteration + * + * @param array $mapping + */ + public function setCurrentMapping($mapping) + { + $this->currentMapping = $mapping; + } + /** * Add a key value pair to mapping */ @@ -159,6 +187,7 @@ protected function removeTrailingSlash($path) * * @param string $source * @param string $dest + * @throws \ErrorException * @return bool */ public function create($source, $dest) @@ -184,7 +213,7 @@ public function create($source, $dest) file app/etc/ --> link app/etc/file to file file app/etc/a --> link app/etc/a to file file app/etc/a --> if app/etc/a is a file throw exception unless force is set, in that case rm and see above - file app/etc/a/ --> link app/etc/a/file to file regardless if app/etc/a existst or not + file app/etc/a/ --> link app/etc/a/file to file regardless if app/etc/a exists or not */ diff --git a/tests/MagentoHackathon/Composer/Magento/Deploystrategy/AbstractTest.php b/tests/MagentoHackathon/Composer/Magento/Deploystrategy/AbstractTest.php index 77ca87d3..2d1d21ea 100644 --- a/tests/MagentoHackathon/Composer/Magento/Deploystrategy/AbstractTest.php +++ b/tests/MagentoHackathon/Composer/Magento/Deploystrategy/AbstractTest.php @@ -146,6 +146,7 @@ public function testCreate() touch($this->sourceDir . DS . $src); $this->assertTrue(is_readable($this->sourceDir . DS . $src)); $this->assertFalse(is_readable($this->destDir . DS . $dest)); + $this->strategy->setCurrentMapping(array($src, $dest)); $this->strategy->create($src, $dest); $this->assertTrue(is_readable($this->destDir . DS . $dest)); } @@ -158,6 +159,7 @@ public function testCopyDirToDir() touch($this->sourceDir . DS . $src . DS . "local.xml"); $this->assertTrue(is_readable($this->sourceDir . DS . $src . DS . "local.xml")); $this->assertFalse(is_readable($this->destDir . DS . $dest . DS . "local.xml")); + $this->strategy->setCurrentMapping(array($src, $dest)); $this->strategy->create($src, $dest); $this->assertTrue(is_readable($this->destDir . DS . $dest . DS . "local.xml")); } @@ -173,6 +175,7 @@ public function testGlobTargetDirExists() $testTarget = $this->destDir . DS . $dest . DS . basename($globSource); + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $this->assertFileType(dirname($testTarget), self::TEST_FILETYPE_DIR); @@ -192,6 +195,7 @@ public function testTargetDirWithChildDirExists() $testTarget = $this->destDir . DS . $dest . DS . basename($globSource) . DS . basename($sourceContents); + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); //passthru("tree {$this->destDir}/$dest"); @@ -211,6 +215,7 @@ public function testTargetDirWithChildDirNotExists() $testTarget = $this->destDir . DS . $dest . DS . basename($globSource) . DS . basename($sourceContents); + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); //passthru("tree {$this->destDir}/$dest"); @@ -228,6 +233,7 @@ public function testGlobTargetDirDoesNotExists() $testTarget = $this->destDir . DS . $dest; + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $this->assertFileType(dirname($testTarget), self::TEST_FILETYPE_DIR); @@ -247,6 +253,7 @@ public function testGlobSlashDirectoryExists() $testTarget = $this->destDir . DS . $dest . basename($globSource); // second create has to identify symlink + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $this->assertFileType(dirname($testTarget), self::TEST_FILETYPE_DIR); @@ -265,6 +272,7 @@ public function testGlobSlashDirectoryDoesNotExists() $testTarget = $this->destDir . DS . $dest . basename($globSource); // second create has to identify symlink + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $this->assertFileType(dirname($testTarget), self::TEST_FILETYPE_DIR); @@ -284,6 +292,7 @@ public function testGlobWildcardTargetDirDoesNotExist() $dest = "targetdir"; + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $targetDir = $this->destDir . DS . $dest; @@ -312,6 +321,7 @@ public function testGlobWildcardTargetDirDoesExist() $dest = "targetdir"; $this->mkdir($this->destDir . DS . $dest); + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $targetDir = $this->destDir . DS . $dest; @@ -348,6 +358,7 @@ public function testSourceAndTargetAreDirsDoNotExist() $testTarget = $this->destDir . DS . $dest; $testTargetContent = $testTarget . DS . $sourceDirContent; + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $this->assertFileExists($testTarget); @@ -378,11 +389,12 @@ public function testSourceAndTargetAreDirsDoExist() $this->mkdir($this->destDir . DS . $dest); // The target should be created INSIDE the target directory because the target dir exists exist - // This is how bash commands (and therefore modman) process source and targer + // This is how bash commands (and therefore modman) process source and target $testTarget = $this->destDir . DS . $dest . DS . basename($globSource); $testTargetContent = $testTarget . DS . $sourceDirContent; + $this->strategy->setCurrentMapping(array($globSource, $dest)); $this->strategy->create($globSource, $dest); $this->assertFileExists($testTarget); diff --git a/tests/MagentoHackathon/Composer/Magento/Deploystrategy/CopyTest.php b/tests/MagentoHackathon/Composer/Magento/Deploystrategy/CopyTest.php index 7c2cbcdf..90c75881 100644 --- a/tests/MagentoHackathon/Composer/Magento/Deploystrategy/CopyTest.php +++ b/tests/MagentoHackathon/Composer/Magento/Deploystrategy/CopyTest.php @@ -23,4 +23,28 @@ public function getTestDeployStrategyFiletype($isDir = false) return self::TEST_FILETYPE_FILE; } -} \ No newline at end of file + + public function testCopyDirToDirOfSameName() + { + $sourceRoot = 'root'; + $sourceContents = "subdir/subdir/test.xml"; + + $this->mkdir($this->sourceDir . DS . $sourceRoot . DS . dirname($sourceContents)); + touch($this->sourceDir . DS . $sourceRoot . DS . $sourceContents); + + // intentionally using a differnt name to verify solution doesn't rely on identical src/dest paths + $dest = "dest/root"; + $this->mkdir($this->destDir . DS . $dest); + + $testTarget = $this->destDir . DS . $dest . DS . $sourceContents; + $this->strategy->setCurrentMapping(array($sourceRoot, $dest)); + + $this->strategy->create($sourceRoot, $dest); + $this->assertFileExists($testTarget); + + $this->strategy->setIsForced(true); + $this->strategy->create($sourceRoot, $dest); + + $this->assertFileNotExists(dirname(dirname($testTarget)) . DS . basename($testTarget)); + } +}