diff --git a/.gitignore b/.gitignore index 44e33d9..65bb426 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ composer.lock # Stuff from tests -tests/htdocs -tests/vendor -tests/composer.lock \ No newline at end of file +tests/move/htdocs +tests/copy/htdocs +tests/move/vendor +tests/copy/vendor +tests/move/composer.lock +tests/copy/composer.lock diff --git a/.travis.yml b/.travis.yml index 16cf310..a3bb4e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,12 @@ before_script: # We use the same repo straight from github because it required lesser amount of hacks # Here we force the same current git commit id for composer - - sed -i -e "s|%%TRAVIS_COMMIT%%|$TRAVIS_COMMIT|g" tests/composer.json + - sed -i -e "s|%%TRAVIS_COMMIT%%|$TRAVIS_COMMIT|g" tests/move/composer.json + - sed -i -e "s|%%TRAVIS_COMMIT%%|$TRAVIS_COMMIT|g" tests/copy/composer.json # Install test run into tests/ folder using tests/composer.json - - composer install --working-dir=./tests/ + - composer install --working-dir=./tests/move/ + - composer install --working-dir=./tests/copy/ script: # Sanity php syntax check @@ -31,4 +33,5 @@ script: - composer validate composer.json # Run the real tests finally - - "phpunit tests/*.php" + - "vendor/bin/phpunit tests/move/*.php" + - "vendor/bin/phpunit tests/copy/*.php" diff --git a/composer.json b/composer.json index 8a551d4..7e52dfa 100644 --- a/composer.json +++ b/composer.json @@ -24,5 +24,11 @@ }, "extra": { "class": "Koodimonni\\Composer\\Dropin" + }, + "scripts": { + "test": [ + "composer install --working-dir=./tests/move/ && vendor/bin/phpunit ./tests/move/*.php", + "composer install --working-dir=./tests/copy/ && vendor/bin/phpunit ./tests/copy/*.php" + ] } } diff --git a/readme.md b/readme.md index cd45a3a..3097c62 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/Koodimonni/Composer-Dropin-Installer.svg?branch=master)](https://travis-ci.org/Koodimonni/Composer-Dropin-Installer) [![Latest Stable Version](https://poser.pugx.org/koodimonni/composer-dropin-installer/v/stable)](https://packagist.org/packages/koodimonni/composer-dropin-installer) [![Total Downloads](https://poser.pugx.org/koodimonni/composer-dropin-installer/downloads)](https://packagist.org/packages/koodimonni/composer-dropin-installer) [![Latest Unstable Version](https://poser.pugx.org/koodimonni/composer-dropin-installer/v/unstable)](https://packagist.org/packages/koodimonni/composer-dropin-installer) [![License](https://poser.pugx.org/koodimonni/composer-dropin-installer/license)](https://packagist.org/packages/koodimonni/composer-dropin-installer) -This composer plugin helps you to move your composer packaged files where you want them to be. +This composer plugin helps you to move or copy your composer packaged files where you want them to be. Composer only allows you to install full directories into their own directories. There's really useful [composer/installers](https://github.com/composer/installers) for custom installation paths but it overwrites everything in folder and doesn't allow coexist of two or more projects. We just let composer install things and take it from there. @@ -96,6 +96,21 @@ I created this originally for installing multiple languages for WordPress with c } ``` +## Moving v. copying files + +By default this dropin installer moves files from the source to the destination, +which means the files disappear from the source. + +If you would prefer copying instead (which keeps the files at the source after +installation) insert the following configuration to your `composer.json` `config` +declarations: + +```json +"config": { + "dropin-installer": "copy" +} +``` + ##But how about the impossible looking syntax? Dropin syntax consists from four parts: ```"{path}": "{directive}:{target}:{files}"``` @@ -126,6 +141,15 @@ phpunit.xml ``` * Script requires unix filesystem (OS X,Linux) +## Testing + +Run PHPUnit tests with + + $ composer test + +Tests are run inside the `tests/` directory where two dummy Composer projects are used to test dropin +installation methods. + ##Todo * Handle deletions on removal and on update. This could be easily done with json-database in [vendor-dir] diff --git a/src/Dropin.php b/src/Dropin.php index aa77255..af6f062 100644 --- a/src/Dropin.php +++ b/src/Dropin.php @@ -170,13 +170,27 @@ public function dropNewFiles(PackageInterface $package){ $src = "{$vendorDir}/{$info['package']}"; } + $config = $this->composer->getPackage()->getConfig(); + $shouldCopy = isset($config['dropin-installer']) && $config['dropin-installer'] === 'copy'; + $installFiles = self::getFilesToInstall($info); - $this->io->write(" Moving dropin files...\n"); - if ($installFiles == "*") { - self::rmove($src,$dest); + if ($shouldCopy) { + $this->io->write(" Copying dropin files...\n"); + if ($installFiles == "*") { + self::rcopy($src, $dest); + } else { + foreach ($installFiles as $file) { + self::copy("{$src}/{$file}", $dest); + } + } } else { - foreach($installFiles as $file) { - self::move("{$src}/{$file}",$dest); + $this->io->write(" Moving dropin files...\n"); + if ($installFiles == "*") { + self::rmove($src, $dest); + } else { + foreach ($installFiles as $file) { + self::move("{$src}/{$file}", $dest); + } } } } @@ -300,6 +314,62 @@ private static function move($src, $dest){ } rename($src, "$dest/" . basename($src)); } + /** + * Recursively copy files from one directory to another + * + * @param string $src - Source of files being copied + * @param string $dest - Destination of files being copied + */ + private static function rcopy($src, $dest){ + // If source is not a directory stop processing + if(!is_dir($src)) { + echo "Source is not a directory"; + return false; + } + + // If the destination directory does not exist create it + if(!is_dir($dest)) { + if(!mkdir($dest,0777,true)) { + // If the destination directory could not be created stop processing + echo "Can't create destination path: {$dest}\n"; + return false; + } + } + + // Open the source directory to read in files + $i = new \DirectoryIterator($src); + foreach($i as $f) { + #Skip useless files&folders + if (self::isFileIgnored($f->getFilename())) continue; + + if($f->isFile()) { + copy($f->getRealPath(), "$dest/" . $f->getFilename()); + } else if(!$f->isDot() && $f->isDir()) { + self::rcopy($f->getRealPath(), "$dest/$f"); + #unlink($f->getRealPath()); + } + } + #We could Remove original directories but don't do it + #unlink($src); + } + /** + * Copy a file from one location to another. + * + * @param $src - File being copied + * @param $dest - Destinatin directory + */ + private static function copy($src, $dest) + { + // If the destination directory does not exist create it + if(!is_dir($dest)) { + if(!mkdir($dest,0777,true)) { + // If the destination directory could not be created stop processing + echo "Can't create destination path: {$dest}\n"; + return false; + } + } + copy($src, "$dest/" . basename($src)); + } /** * Returns type and information of dropin directive */ diff --git a/tests/copy/KoodimonniComposerCopiedFilesExistsTest.php b/tests/copy/KoodimonniComposerCopiedFilesExistsTest.php new file mode 100644 index 0000000..13fbf41 --- /dev/null +++ b/tests/copy/KoodimonniComposerCopiedFilesExistsTest.php @@ -0,0 +1,15 @@ +assertFileExists(dirname( __FILE__ ) . '/htdocs/dropin-test.php'); + } + public function testPackageFileExistsInVendor() + { + $this->assertFileExists(dirname( __FILE__ ) . '/vendor/dropininternal/dropin-test-package/dropin-test.php'); + } + +} diff --git a/tests/copy/composer.json b/tests/copy/composer.json new file mode 100644 index 0000000..b9f1bb4 --- /dev/null +++ b/tests/copy/composer.json @@ -0,0 +1,38 @@ +{ + "name": "koodimonni/composer-dropin-installer-tests", + "description": "composer.json for testing composer-dropin-installer", + "license": "WTFPL", + "type": "project", + "authors": [ + { + "name": "Onni Hakala", + "email": "onni@koodimonni.fi" + } + ], + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/Koodimonni/Composer-Dropin-Installer" + }, + { + "type": "path", + "url": "../testpkg" + }, + { + "packagist": false + } + ], + "require": { + "koodimonni/composer-dropin-installer": "dev-master#%%TRAVIS_COMMIT%%", + "dropininternal/dropin-test-package": "dev-master" + }, + "extra": { + "dropin-paths": { + "htdocs/": ["package:dropininternal/dropin-test-package"] + } + }, + "config": { + "dropin-installer": "copy" + }, + "minimum-stability": "dev" +} diff --git a/tests/phpunit.xml b/tests/copy/phpunit.xml similarity index 100% rename from tests/phpunit.xml rename to tests/copy/phpunit.xml diff --git a/tests/KoodimonniComposerFilesExistsTest.php b/tests/move/KoodimonniComposerMovedFilesExistsTest.php similarity index 79% rename from tests/KoodimonniComposerFilesExistsTest.php rename to tests/move/KoodimonniComposerMovedFilesExistsTest.php index 73a8f8c..422407f 100644 --- a/tests/KoodimonniComposerFilesExistsTest.php +++ b/tests/move/KoodimonniComposerMovedFilesExistsTest.php @@ -1,7 +1,7 @@ assertFileExists(dirname( __FILE__ ) . '/htdocs/wp-content/languages/fi.po'); @@ -11,4 +11,4 @@ public function testFinnishLanguageNotExistsInVendor() $this->assertFileNotExists(dirname( __FILE__ ) . '/vendor/koodimonni-language/fi/fi.po'); } -} \ No newline at end of file +} diff --git a/tests/composer.json b/tests/move/composer.json similarity index 100% rename from tests/composer.json rename to tests/move/composer.json diff --git a/tests/move/phpunit.xml b/tests/move/phpunit.xml new file mode 100644 index 0000000..e197d83 --- /dev/null +++ b/tests/move/phpunit.xml @@ -0,0 +1,6 @@ + + + + ./ + + \ No newline at end of file diff --git a/tests/testpkg/composer.json b/tests/testpkg/composer.json new file mode 100644 index 0000000..19d087a --- /dev/null +++ b/tests/testpkg/composer.json @@ -0,0 +1,5 @@ +{ + "name": "dropininternal/dropin-test-package", + "type": "library", + "version": "dev-master" +} diff --git a/tests/testpkg/dropin-test.php b/tests/testpkg/dropin-test.php new file mode 100644 index 0000000..2056365 --- /dev/null +++ b/tests/testpkg/dropin-test.php @@ -0,0 +1,3 @@ +