diff --git a/docs/api/patches-lock.md b/docs/api/patches-lock.md index 5cb3afea..df001f00 100644 --- a/docs/api/patches-lock.md +++ b/docs/api/patches-lock.md @@ -15,4 +15,4 @@ weight: 40 ``` * Each patch definition will look like the [expanded format]({{< relref "../usage/defining-patches.md#expanded-format" >}}) that users can put into their `composer.json` or external patches file. * No _removals_ or _changes_ will be made to the patch definition object. _Additional_ keys may be created, so any JSON parsing you're doing should be tolerant of new keys. -* The `extra` object in each patch definition may contain a number of attributes set by other projects. The core plugin will not do anything with that data beyond reading/writing it to/from `patches.lock` and you probably shouldn't either (unless you were the one responsible for putting it there in the first place). +* The `extra` object in each patch definition may contain a number of attributes set by other projects or by the user and should be treated as free-form input. diff --git a/docs/troubleshooting/guide.md b/docs/troubleshooting/guide.md index e14e8bc4..f4916058 100644 --- a/docs/troubleshooting/guide.md +++ b/docs/troubleshooting/guide.md @@ -20,11 +20,6 @@ See the [system requirements]({{< relref "../getting-started/system-requirements Composer Patches requires at least _some_ mechanism for applying patches. If you don't have any installed, you'll see a fair number of errors. You should install some combination of GNU `patch`, BSD `patch`, `git`, or other applicable software. macOS users commonly need to `brew install gpatch` to get a modern version of `patch` on their system. -## Set `preferred-install` to `source` - -The Git patcher included with this plugin is the most reliable method of applying patches. However, the Git patcher won't even _attempt_ to apply a patch if the target directory isn't cloned from Git. To avoid this situation, you should either set `"preferred-install": "source"` or set specific packages to be installed from source in your Composer configuration. Patches may still be successfully applied without this setting, but if you're working on a team, you'll have much more consistent results with the Git patcher. - - ## Download patches securely If you've been referred here, you're trying to download patches over HTTP without explicitly telling Composer that you want to do that. See the [`secure-http`]({{< relref "../usage/configuration.md#secure-http" >}}) documentation for more information. diff --git a/docs/usage/commands.md b/docs/usage/commands.md index c69610fe..e2929e35 100644 --- a/docs/usage/commands.md +++ b/docs/usage/commands.md @@ -1,6 +1,6 @@ --- title: Commands -weight: 40 +weight: 50 --- ## `composer patches-relock` diff --git a/docs/usage/configuration.md b/docs/usage/configuration.md index ab0da432..38857bee 100644 --- a/docs/usage/configuration.md +++ b/docs/usage/configuration.md @@ -131,10 +131,9 @@ You probably don't need to change this value unless you're building a plugin tha "extra": { "composer-patches": { "disable-patchers": [ - "\\cweagans\\Composer\\Patcher\\BsdPatchPatcher", + "\\cweagans\\Composer\\Patcher\\FreeformPatcher", "\\cweagans\\Composer\\Patcher\\GitPatcher", - "\\cweagans\\Composer\\Patcher\\GnuGPatchPatcher", - "\\cweagans\\Composer\\Patcher\\GnuPatchPatcher" + "\\cweagans\\Composer\\Patcher\\GitInitPatcher" ] } } @@ -147,30 +146,13 @@ You probably don't need to change this value unless you're building a plugin tha For completeness, all of the patchers that ship with the plugin are listed above, but you should _not_ list all of them. If no patchers are available, the plugin will throw an exception during `composer install`. +`GitPatcher` and `GitInitPatcher` should be enabled and disabled together -- don't disable one without the other. + After changing this value, you should re-lock and re-apply patches to your project. ## Relevant configuration provided by Composer -### `preferred-install` - -```json -{ - [...], - "config": { - "preferred-install": "source" - } -} -``` - -**Default value**: `"dist"` - -The relevant Composer documentation for this parameter can be found [here](https://getcomposer.org/doc/06-config.md#preferred-install). - -If you're applying patches that were generated with `git`, setting `preferred-install` to `"source"` is **highly recommended** (either by changing the setting for all packages or by setting that value on a per-package basis as shown in the Composer documentation. This will allow the `GitPatcher` to apply patches as often as possible (the `GitPatcher` won't even _attempt_ to apply a patch if the target directory isn't managed by `git`). Git is the most reliable patcher available to Composer Patches. _Not_ changing this setting will result in other patchers attempting to apply patches. Historically, these patchers have had varying degrees of success depending on a number of factors, so it's better to use the `GitPatcher` when you're able to do so. - ---- - ### `secure-http` ```json diff --git a/docs/usage/defining-patches.md b/docs/usage/defining-patches.md index b7a020dd..5651e09b 100644 --- a/docs/usage/defining-patches.md +++ b/docs/usage/defining-patches.md @@ -85,7 +85,7 @@ Internally, the plugin uses the expanded format for _all_ patches. Similar to th 2. Any package-specific depth override set globally in the plugin (see `cweagans\Composer\Util::getDefaultPackagePatchDepth()` for details.) 3. The global [`default-patch-depth`]({{< relref "configuration.md#default-patch-depth" >}}) -`extra` is primarily a place for developers to store extra data related to a patch, but if you just need a place to put some extra data about a patch, `extra` is a good place for it. No validation is performed on the contents of `extra` and no functionality other than the reading/writing of `patches.lock` uses the data. +`extra` is primarily a place for developers to store extra data related to a patch, but if you just need a place to put some extra data about a patch, `extra` is a good place for it. No validation is performed on the contents of `extra`. The [Freeform patcher]({{< relref "freeform-patcher.md" >}}) stores data here. ## Locations diff --git a/docs/usage/freeform-patcher.md b/docs/usage/freeform-patcher.md new file mode 100644 index 00000000..a61ec84d --- /dev/null +++ b/docs/usage/freeform-patcher.md @@ -0,0 +1,94 @@ +--- +title: Freeform Patcher +weight: 30 +--- + +{{< lead text="The core patchers try to take care of as many cases as possible, but sometimes you need custom behavior." >}} + +Composer Patches now includes a "freeform patcher", which essentially lets you define a patcher and its arguments in your patch definition. + +## Usage + +To use the freeform patcher, you must use the [expanded format]({{< relref "defining-patches.md#expanded-format" >}}) for your patch definition. You'll need to add a few extra values to the `extra` key in your patch definition like so: + +```json +{ + [...], + "extra": { + "patches": { + "the/project": [ + { + "description": "This is another patch", + "url": "https://www.example.com/different/path/to/file.patch" + "depth": 123 + "extra": { + "freeform": { + "executable": "/path/to/your/executable", + "args": "--verbose %s %s %s", + } + }, + }, + ] + } + } +} +``` + +If the `executable` and `args` values are not populated, the freeform patcher will not perform any work. + +The `%s` placeholders will be populated by escaped arguments that are always provided in this order: + +1. Patch depth +2. Path to the location on disk where the dependency was installed +3. Local path to the patch file + +It is not possible to change the order of these arguments, but you can always create a small wrapper script in your project and handle the arguments how you'd like. + +In this example, the command that would be run by the patcher is +```shell +/path/to/your/executable --verbose '/full/path/to/vendor/the/project' '123' '/full/path/to/file.patch` +``` + +{{< callout title="$PATH will be searched for executables" >}} +If the executable you want to run is included in your `$PATH`, you do not have to specify the full path to the executable. +{{< /callout >}} + +## Dry run + +If your patcher is capable of testing whether or not a patch can be applied (for instance, `patch` can do this with the `--dry-run` argument), you can also supply a set of dry run arguments that will be run first: + +```json +{ + [...], + "extra": { + "patches": { + "the/project": [ + { + "description": "This is another patch", + "url": "https://www.example.com/different/path/to/file.patch" + "depth": 123 + "extra": { + "freeform": { + "executable": "/path/to/your/executable", + "args": "--verbose %s %s %s", + "dry_run_args": "--verbose --dry-run %s %s %s" + } + }, + }, + ] + } + } +} +``` + +The arguments will be provided in the same order as the `args` value. + +## Tips + +### Exit codes matter + +If your tool returns an exit code of `0`, Composer Patches will assume that the patch was applied correctly (or that the dry run was successful and the patch should be applied). If it returns anything other than `0`, Composer Patches will assume that the patch was unsuccessful (or that the dry run indicated that attempting to apply the patch would be unsuccessful). + +### Always run in verbose mode + +Any patcher you configure here should always include the `--verbose` flag (or whatever your patcher's equivalent is). The output will not be printed to the console during normal operation, but if you are running composer with the `--verbose` flag (for instance, with `composer install --verbose` or `composer install -v`), the output will be printed so that you can see what was happening. diff --git a/docs/usage/recommended-workflows.md b/docs/usage/recommended-workflows.md index 82152518..2f123197 100644 --- a/docs/usage/recommended-workflows.md +++ b/docs/usage/recommended-workflows.md @@ -1,6 +1,6 @@ --- title: Recommended Workflows -weight: 30 +weight: 40 --- {{< lead text="Common workflows for working with Composer Patches on a team." >}} diff --git a/src/Capability/Patcher/CorePatcherProvider.php b/src/Capability/Patcher/CorePatcherProvider.php index 9f7623c9..16cda827 100644 --- a/src/Capability/Patcher/CorePatcherProvider.php +++ b/src/Capability/Patcher/CorePatcherProvider.php @@ -2,10 +2,9 @@ namespace cweagans\Composer\Capability\Patcher; -use cweagans\Composer\Patcher\BsdPatchPatcher; +use cweagans\Composer\Patcher\FreeformPatcher; use cweagans\Composer\Patcher\GitPatcher; -use cweagans\Composer\Patcher\GnuGPatchPatcher; -use cweagans\Composer\Patcher\GnuPatchPatcher; +use cweagans\Composer\Patcher\GitInitPatcher; class CorePatcherProvider extends BasePatcherProvider { @@ -16,9 +15,8 @@ public function getPatchers(): array { return [ new GitPatcher($this->composer, $this->io), - new GnuPatchPatcher($this->composer, $this->io), - new GnuGPatchPatcher($this->composer, $this->io), - new BsdPatchPatcher($this->composer, $this->io), + new GitInitPatcher($this->composer, $this->io), + new FreeformPatcher($this->composer, $this->io) ]; } } diff --git a/src/Command/DoctorCommand.php b/src/Command/DoctorCommand.php index 8a2e057f..bc167390 100644 --- a/src/Command/DoctorCommand.php +++ b/src/Command/DoctorCommand.php @@ -109,66 +109,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->write(""); $io->write("Common configuration issues"); $io->write("================================================================================"); - $preferred_install_issues = false; - $pi = $composer->getConfig()->get('preferred-install'); - $io->write( - str_pad("preferred-install is set:", 77) . (is_null($pi) ? " no" : "yes") - ); - - if (is_null($pi)) { - $preferred_install_issues = true; - } - - if (is_string($pi)) { - $io->write( - str_pad("preferred-install set to 'source' for all/some packages:", 77) . - ($pi === "source" ? "yes" : " no") - ); - } - - if (is_string($pi) && $pi !== "source") { - $preferred_install_issues = true; - } - - if (is_array($pi)) { - $patched_packages = $plugin->getPatchCollection()->getPatchedPackages(); - foreach ($patched_packages as $package) { - if (in_array($package, array_values($pi))) { - $io->write( - str_pad("preferred-install set to 'source' for $package:", 77) . "yes" - ); - continue; - } - - foreach ($pi as $pattern => $value) { - $pattern = strtr($pattern, ['*' => '.*', '/' => '\/']); - if (preg_match("/$pattern/", $package)) { - $io->write( - str_pad("preferred-install set to 'source' for $package:", 77) . - ($value === "source" ? "yes" : " no") - ); - - if ($value !== "source") { - $preferred_install_issues = true; - } - - break 2; - } - } - - $preferred_install_issues = true; - } - } - - if ($preferred_install_issues) { - $suggestions[] = [ - "message" => "Setting 'preferred-install' to 'source' either globally or for each patched dependency " . - "is highly recommended for consistent results", - "link" => - "https://docs.cweagans.net/composer-patches/troubleshooting/guide#set-preferred-install-to-source" - ]; - } - $has_http_urls = false; foreach ($plugin->getPatchCollection()->getPatchedPackages() as $package) { foreach ($plugin->getPatchCollection()->getPatchesForPackage($package) as $patch) { diff --git a/src/Patch.php b/src/Patch.php index 5d488643..7ad5cc37 100644 --- a/src/Patch.php +++ b/src/Patch.php @@ -56,7 +56,7 @@ class Patch implements JsonSerializable * * @var array */ - public array $extra; + public array $extra = []; /** * Create a Patch from a serialized representation. diff --git a/src/Patcher/BsdPatchPatcher.php b/src/Patcher/BsdPatchPatcher.php deleted file mode 100644 index 84350999..00000000 --- a/src/Patcher/BsdPatchPatcher.php +++ /dev/null @@ -1,42 +0,0 @@ -executeCommand( - '%s -p%s --posix --batch --dry-run -d %s -i %s', - $this->patchTool(), - $patch->depth, - $path, - $patch->localPath - ); - if (!$status) { - return false; - } - - return $this->executeCommand( - '%s -p%s --verbose --posix --batch -d %s -i %s', - $this->patchTool(), - $patch->depth, - $path, - $patch->localPath - ); - } - - public function canUse(): bool - { - $output = ""; - $result = $this->executor->execute($this->patchTool() . ' --version', $output); - // TODO: Is it a valid assumption to assume that if GNU is *not* in the version output, that it's BSD patch? - return ($result === 0) && (!str_contains($output, 'GNU patch')); - } -} diff --git a/src/Patcher/FreeformPatcher.php b/src/Patcher/FreeformPatcher.php new file mode 100644 index 00000000..0c93b59a --- /dev/null +++ b/src/Patcher/FreeformPatcher.php @@ -0,0 +1,59 @@ +extra['freeform']['executable'] ?? ''; + $args = $patch->extra['freeform']['args'] ?? ''; + + // Optional. + $dryRunArgs = $patch->extra['freeform']['dry_run_args'] ?? ''; + + // If we don't have what we need, exit. + if (empty($patchTool) || empty($args)) { + $this->io->write( + 'Required configuration for FreeformPatcher not present. Skipping.', + true, + IOInterface::VERBOSE + ); + return false; + } + + // If we have dry-run args, do a dry-run. + if (!empty($dryRunArgs)) { + $status = $this->executeCommand( + '%s ' . $args, + $patchTool, + $patch->depth, + $path, + $patch->localPath, + ); + if (!$status) { + return false; + } + } + + // Apply the patch. + return $this->executeCommand( + '%s ' . $args, + $patchTool, + $patch->depth, + $path, + $patch->localPath, + ); + } + + public function canUse(): bool + { + // Hardcoded to true because apply() will bail out if the freeform args are not set on the patch (or globally). + // Users who opt-in to this patcher are responsible for providing a valid executable and arguments. + return true; + } +} diff --git a/src/Patcher/GitInitPatcher.php b/src/Patcher/GitInitPatcher.php new file mode 100644 index 00000000..8a2c39c3 --- /dev/null +++ b/src/Patcher/GitInitPatcher.php @@ -0,0 +1,42 @@ +io->write("Creating temporary fake git repo in $path to apply patch", true, IOInterface::VERBOSE); + + // Create a fake Git repo -- just enough to make Git think it's looking at a real repo. + $dirs = [ + $path . '/.git', + $path . '/.git/objects', + $path . '/.git/refs', + ]; + foreach ($dirs as $dir) { + mkdir($dir); + } + file_put_contents($path . '/.git/HEAD', "ref: refs/heads/main"); + + + // Use the git patcher to apply the patch. + $status = parent::apply($patch, $path); + + // Clean up the fake git repo. + unlink($path . '/.git/HEAD'); + foreach (array_reverse($dirs) as $dir) { + rmdir($dir); + } + + return $status; + } +} diff --git a/src/Patcher/GitPatcher.php b/src/Patcher/GitPatcher.php index 551162dd..7255ed6b 100644 --- a/src/Patcher/GitPatcher.php +++ b/src/Patcher/GitPatcher.php @@ -14,6 +14,7 @@ public function apply(Patch $patch, string $path): bool // If the path isn't a git repo, don't even try. // @see https://stackoverflow.com/a/27283285 if (!is_dir($path . '/.git')) { + $this->io->write("$path is not a git repo. Skipping Git patcher.", true, IOInterface::VERBOSE); return false; } diff --git a/src/Patcher/GnuGPatchPatcher.php b/src/Patcher/GnuGPatchPatcher.php deleted file mode 100644 index 657186e6..00000000 --- a/src/Patcher/GnuGPatchPatcher.php +++ /dev/null @@ -1,8 +0,0 @@ -executeCommand( - '%s -p%s --dry-run --no-backup-if-mismatch -d %s -i %s', - $this->patchTool(), - $patch->depth, - $path, - $patch->localPath - ); - if (!$status) { - return false; - } - - return $this->executeCommand( - '%s -p%s --no-backup-if-mismatch --verbose -d %s -i %s', - $this->patchTool(), - $patch->depth, - $path, - $patch->localPath - ); - } - - public function canUse(): bool - { - $output = ""; - $result = $this->executor->execute($this->patchTool() . ' --version', $output); - return ($result === 0) && (str_contains($output, 'GNU patch')); - } -} diff --git a/src/Resolver/ResolverBase.php b/src/Resolver/ResolverBase.php index f02f9121..158e5620 100644 --- a/src/Resolver/ResolverBase.php +++ b/src/Resolver/ResolverBase.php @@ -70,6 +70,9 @@ public function findPatchesInJson(array $patches): array $patch->package = $package; $patch->url = $def['url']; $patch->description = $def['description']; + $patch->sha256 = $def['sha256'] ?? null; + $patch->depth = $def['depth'] ?? null; + $patch->extra = $def['extra'] ?? []; $patches[$package][$index] = $patch; } diff --git a/tests/_data/fixtures/apply-git-patch-from-web-using-init/composer.json b/tests/_data/fixtures/apply-git-patch-from-web-using-init/composer.json new file mode 100644 index 00000000..60c3033f --- /dev/null +++ b/tests/_data/fixtures/apply-git-patch-from-web-using-init/composer.json @@ -0,0 +1,36 @@ +{ + "name": "cweagans/composer-patches-test-project", + "description": "Project for use in cweagans/composer-patches acceptance tests.", + "type": "project", + "license": "BSD-3-Clause", + "repositories": [ + { + "type": "path", + "url": "../../../../" + } + ], + "require": { + "cweagans/composer-patches": "*@dev", + "cweagans/composer-patches-testrepo": "~1.0" + }, + "extra": { + "patches": { + "cweagans/composer-patches-testrepo": { + "Add a file": "https://patch-diff.githubusercontent.com/raw/cweagans/composer-patches-testrepo/pull/1.patch" + } + } + }, + "config": { + "preferred-install": "dist", + "composer-patches": { + "disable-patchers": [ + "\\cweagans\\Composer\\Patcher\\BsdPatchPatcher", + "\\cweagans\\Composer\\Patcher\\GnuGPatchPatcher", + "\\cweagans\\Composer\\Patcher\\GnuPatchPatcher" + ] + }, + "allow-plugins": { + "cweagans/composer-patches": true + } + } +} diff --git a/tests/_data/fixtures/freeform-patcher/composer.json b/tests/_data/fixtures/freeform-patcher/composer.json new file mode 100644 index 00000000..1e1f6972 --- /dev/null +++ b/tests/_data/fixtures/freeform-patcher/composer.json @@ -0,0 +1,38 @@ +{ + "name": "cweagans/composer-patches-test-project", + "description": "Project for use in cweagans/composer-patches acceptance tests.", + "type": "project", + "license": "BSD-3-Clause", + "repositories": [ + { + "type": "path", + "url": "../../../../" + } + ], + "require": { + "cweagans/composer-patches": "*@dev", + "cweagans/composer-patches-testrepo": "~1.0" + }, + "extra": { + "patches": { + "cweagans/composer-patches-testrepo": [ + { + "description": "a new file", + "url": "https://raw.githubusercontent.com/cweagans/composer-patches-testrepo/main/src/OneMoreTest.php", + "depth": 123, + "extra": { + "freeform": { + "executable": "./kind-of-a-patcher.sh", + "args": "%s %s %s" + } + } + } + ] + } + }, + "config": { + "allow-plugins": { + "cweagans/composer-patches": true + } + } +} diff --git a/tests/_data/fixtures/freeform-patcher/kind-of-a-patcher.sh b/tests/_data/fixtures/freeform-patcher/kind-of-a-patcher.sh new file mode 100755 index 00000000..35c73eb9 --- /dev/null +++ b/tests/_data/fixtures/freeform-patcher/kind-of-a-patcher.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +depth=$1 +path=$2 +file=$3 + +echo "not doing anything with the depth, but it was set to ${depth}" + +echo "copying file into place" +cp $file ${path}/src/OneMoreTest.php diff --git a/tests/_data/fixtures/no-patchers-available/composer.json b/tests/_data/fixtures/no-patchers-available/composer.json index 923a279b..c0555c9f 100644 --- a/tests/_data/fixtures/no-patchers-available/composer.json +++ b/tests/_data/fixtures/no-patchers-available/composer.json @@ -18,6 +18,7 @@ "disable-patchers": [ "cweagans\\Composer\\Patcher\\BsdPatchPatcher", "cweagans\\Composer\\Patcher\\GitPatcher", + "cweagans\\Composer\\Patcher\\GitInitPatcher", "cweagans\\Composer\\Patcher\\GnuGPatchPatcher", "cweagans\\Composer\\Patcher\\GnuPatchPatcher" ] diff --git a/tests/_data/testtools/broken-bsd-patch.sh b/tests/_data/testtools/broken-bsd-patch.sh deleted file mode 100755 index 9f66fb03..00000000 --- a/tests/_data/testtools/broken-bsd-patch.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -echo "patch (not really though)" -exit 1 diff --git a/tests/_data/testtools/broken-gnu-patch.sh b/tests/_data/testtools/broken-gnu-patch.sh deleted file mode 100755 index b6539fea..00000000 --- a/tests/_data/testtools/broken-gnu-patch.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -echo "GNU patch (not really though)" -exit 1 diff --git a/tests/_data/testtools/gnu-patch.sh b/tests/_data/testtools/gnu-patch.sh deleted file mode 100755 index 73a1e131..00000000 --- a/tests/_data/testtools/gnu-patch.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -echo "GNU patch (not really though)" -exit 0 diff --git a/tests/_data/testtools/patch.sh b/tests/_data/testtools/patch.sh deleted file mode 100755 index c52d3c26..00000000 --- a/tests/_data/testtools/patch.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -exit 0 diff --git a/tests/acceptance/ApplyGitPatchFromWebUsingInitCept.php b/tests/acceptance/ApplyGitPatchFromWebUsingInitCept.php new file mode 100644 index 00000000..6bcec090 --- /dev/null +++ b/tests/acceptance/ApplyGitPatchFromWebUsingInitCept.php @@ -0,0 +1,13 @@ +wantTo('modify a package using a patch downloaded from the internet (exercising Git init patcher)'); +$I->amInPath(codecept_data_dir('fixtures/apply-git-patch-from-web-using-init')); +$I->runComposerCommand('install', ['-vvv']); +$I->canSeeFileFound('./vendor/cweagans/composer-patches-testrepo/src/OneMoreTest.php'); diff --git a/tests/acceptance/FreeformPatcherCept.php b/tests/acceptance/FreeformPatcherCept.php new file mode 100644 index 00000000..10c54ba4 --- /dev/null +++ b/tests/acceptance/FreeformPatcherCept.php @@ -0,0 +1,13 @@ +wantTo('exercise the freeform patcher'); +$I->amInPath(codecept_data_dir('fixtures/freeform-patcher')); +$I->runComposerCommand('install', ['-vvv']); +$I->canSeeFileFound('./vendor/cweagans/composer-patches-testrepo/src/OneMoreTest.php'); diff --git a/tests/unit/CoreDownloaderProviderTest.php b/tests/unit/CoreDownloaderProviderTest.php index 00261497..9e067228 100644 --- a/tests/unit/CoreDownloaderProviderTest.php +++ b/tests/unit/CoreDownloaderProviderTest.php @@ -10,6 +10,7 @@ use Composer\Plugin\PluginInterface; use cweagans\Composer\Capability\Downloader\CoreDownloaderProvider; use cweagans\Composer\Downloader\ComposerDownloader; +use cweagans\Composer\Downloader\DownloaderInterface; class CoreDownloaderProviderTest extends Unit { @@ -27,6 +28,6 @@ public function testGetDownloaders() $downloaders = $downloaderProvider->getDownloaders(); $this->assertCount(1, $downloaders); - $this->assertInstanceOf(ComposerDownloader::class, $downloaders[0]); + $this->assertContainsOnlyInstancesOf(DownloaderInterface::class, $downloaders); } } diff --git a/tests/unit/CorePatcherProviderTest.php b/tests/unit/CorePatcherProviderTest.php index 9267ef39..fc2fcc04 100644 --- a/tests/unit/CorePatcherProviderTest.php +++ b/tests/unit/CorePatcherProviderTest.php @@ -8,10 +8,7 @@ use Composer\IO\NullIO; use Composer\Plugin\PluginInterface; use cweagans\Composer\Capability\Patcher\CorePatcherProvider; -use cweagans\Composer\Patcher\BsdPatchPatcher; -use cweagans\Composer\Patcher\GitPatcher; -use cweagans\Composer\Patcher\GnuGPatchPatcher; -use cweagans\Composer\Patcher\GnuPatchPatcher; +use cweagans\Composer\Patcher\PatcherInterface; class CorePatcherProviderTest extends Unit { @@ -25,10 +22,7 @@ public function testGetPatchers() $patchers = $patcherProvider->getPatchers(); - $this->assertCount(4, $patchers); - $this->assertInstanceOf(GitPatcher::class, $patchers[0]); - $this->assertInstanceOf(GnuPatchPatcher::class, $patchers[1]); - $this->assertInstanceOf(GnuGPatchPatcher::class, $patchers[2]); - $this->assertInstanceOf(BsdPatchPatcher::class, $patchers[3]); + $this->assertCount(3, $patchers); + $this->assertContainsOnlyInstancesOf(PatcherInterface::class, $patchers); } } diff --git a/tests/unit/CoreResolverProviderTest.php b/tests/unit/CoreResolverProviderTest.php index 716c7153..913e8040 100644 --- a/tests/unit/CoreResolverProviderTest.php +++ b/tests/unit/CoreResolverProviderTest.php @@ -9,6 +9,7 @@ use Composer\Plugin\PluginInterface; use cweagans\Composer\Capability\Resolver\CoreResolverProvider; use cweagans\Composer\Resolver\PatchesFile; +use cweagans\Composer\Resolver\ResolverInterface; use cweagans\Composer\Resolver\RootComposer; class CoreResolverProviderTest extends Unit @@ -24,7 +25,6 @@ public function testGetResolvers() $resolvers = $resolverProvider->getResolvers(); $this->assertCount(2, $resolvers); - $this->assertInstanceOf(RootComposer::class, $resolvers[0]); - $this->assertInstanceOf(PatchesFile::class, $resolvers[1]); + $this->assertContainsOnlyInstancesOf(ResolverInterface::class, $resolvers); } } diff --git a/tests/unit/PatcherAvailabilityTest.php b/tests/unit/PatcherAvailabilityTest.php index ad287cce..4394e005 100644 --- a/tests/unit/PatcherAvailabilityTest.php +++ b/tests/unit/PatcherAvailabilityTest.php @@ -28,30 +28,6 @@ public function testMissingOrBrokenToolBehaviors($patcher, $expected) public function missingOrBrokenToolBehaviorsDataProvider() { - $patcher = new BsdPatchPatcher(new Composer(), new NullIO()); - $patcher->toolPathOverride = codecept_data_dir('testtools/intentionally-missing-executable'); - yield 'missing bsd patch' => [$patcher, false]; - - $patcher = new BsdPatchPatcher(new Composer(), new NullIO()); - $patcher->toolPathOverride = codecept_data_dir('testtools/broken-bsd-patch.sh'); - yield 'broken bsd patch' => [$patcher, false]; - - $patcher = new BsdPatchPatcher(new Composer(), new NullIO()); - $patcher->toolPathOverride = codecept_data_dir('testtools/patch.sh'); - yield 'working bsd patch' => [$patcher, true]; - - $patcher = new GnuPatchPatcher(new Composer(), new NullIO()); - $patcher->toolPathOverride = codecept_data_dir('testtools/intentionally-missing-executable'); - yield 'missing gnu patch' => [$patcher, false]; - - $patcher = new GnuPatchPatcher(new Composer(), new NullIO()); - $patcher->toolPathOverride = codecept_data_dir('testtools/broken-gnu-patch.sh'); - yield 'broken gnu patch' => [$patcher, false]; - - $patcher = new GnuPatchPatcher(new Composer(), new NullIO()); - $patcher->toolPathOverride = codecept_data_dir('testtools/gnu-patch.sh'); - yield 'working gnu patch' => [$patcher, true]; - $patcher = new GitPatcher(new Composer(), new NullIO()); $patcher->toolPathOverride = codecept_data_dir('testtools/intentionally-missing-executable'); yield 'missing git' => [$patcher, false];