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];