Skip to content

Commit

Permalink
Merge pull request jamescowie#6 from nevvermind/wee-refactoring
Browse files Browse the repository at this point in the history
Wee refactoring
  • Loading branch information
James Cowie committed May 7, 2015
2 parents 5d693ca + fd68571 commit acd6e01
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 30 deletions.
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
# Patcher
Applying generic patches using the `patch` tool using Composer's `script` feature.
The patching is idempotent as much as the `patch` tool is, meaning patches will _not_ be applied if `patch` decides not to.
The patching is idempotent as much as the `patch` tool is, meaning patches will _not_ be re-applied if `patch` decides not to.

## Project setup

a) Patches need to be declared in the `extra` config area of Composer (root package only):
```json
"extra": {
"patches": {
"magento": {
"autoloader-patch": {
"name": "Autoloader-patcher",
"title": "Allow composer autoloader to be applied to Mage.php",
"url": "https://raw.githubusercontent.com/inviqa/magento-patches/magento-composer-autoloader-patch/composer-autoloader/0001-Adding-Composer-autoloader-to-Mage.patch?token=token"
}
"extra": {
"patches": {
"patch-group-1": {
"patch-name-1": {
"title": "Allow composer autoloader to be applied to Mage.php",
"url": "https://url/to/file1.patch"
}
},
"patch-group-2": {
"patch-name-1": {
"title": "Fixes Windows 8.1",
"url": "https://url/to/file2.patch"
}
}
}
}
}
}
```
A patch's _group_ and _name_ will create its ID, used internally (i.e. `patch-group-1/patch-name-1`), so make sure you follow these 2 rules:
- `patch-group-1` MUST be unique in the `patches` object literal
- `patch-name-1` MUST be unique in its patch _group_

Examples of patch groups: "magento", "drupal", "security".
Examples of patch names: "CVS-1", "composer-autoloader".

b) Additional scripts callbacks need to be added for automatic patching on `install` or `update` (root package only):
```json
Expand Down
48 changes: 29 additions & 19 deletions src/Inviqa/Patcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
use \Symfony\Component\Process\ProcessUtils;

class Patcher
{
Expand All @@ -14,42 +15,51 @@ class Patcher
/** @var ConsoleOutput */
private $output;

/** @var \Composer\Script\Event */
private $event;

public function patch(\Composer\Script\Event $event)
{
$this->output = new ConsoleOutput();
$this->event = $event;

$extra = $event->getComposer()->getPackage()->getExtra();
$this->fetchPatches();
$this->applyPatches();
}

foreach ($extra['patches']['magento'] as $option) {
$this->output->writeln("<info>Downloading patch: " . $option['name'] . "</info>");
$downloader = new composerDownloader();
$this->patchFiles[] = $downloader->getContents($option['url'], $option['name']);
}
private function fetchPatches()
{
$downloader = new composerDownloader();
$extra = $this->event->getComposer()->getPackage()->getExtra();

$this->applyPatch();
foreach ($extra['patches'] as $patchGroupName => $patchGroup) {
foreach ($patchGroup as $patchName => $patchInfo) {
$patchNamespace = $patchGroupName . '/' . $patchName;
$this->output->writeln("<info>Fetching patch $patchNamespace</info>");
$patchContent = $downloader->getContents($patchInfo['url'], $patchGroupName . '_' . $patchName);
$this->patchFiles[$patchNamespace] = $patchContent;
}
}
}

private function applyPatch()
private function applyPatches()
{
$this->output->writeln("<info>Applying Patch</info>");
$this->output->writeln("<info>Applying patches...</info>");

foreach ($this->patchFiles as $filesToPatch)
{
foreach ($this->patchFiles as $patchNamespace => $filesToPatch) {
if (!$this->canApplyPatch($filesToPatch)) {
$this->output->writeln('<comment>Patch skipped. Patch was already applied?</comment>');
continue;
}

$process = new Process("patch -p 1 < " . $filesToPatch);
$process = new Process("patch -p 1 < " . ProcessUtils::escapeArgument($filesToPatch));
try {
$process->mustRun();

echo $process->getOutput();
} catch (ProcessFailedException $e) {
echo $e->getMessage();
$this->output->writeln("<info>Patch $patchNamespace successfully applied.</info>");
} catch (\Exception $e) {
$this->output->getErrorOutput()->writeln("<error>Error applying patch $patchNamespace:</error>");
$this->output->getErrorOutput()->writeln("<error>{$e->getMessage()}</error>");
}

$this->output->writeln("<info>File successfully patched.</info>");
}
}

Expand All @@ -59,7 +69,7 @@ private function applyPatch()
*/
private function canApplyPatch($filesToPatch)
{
$process = new Process("patch --dry-run -p 1 < " . $filesToPatch);
$process = new Process("patch --dry-run -p 1 < " . ProcessUtils::escapeArgument($filesToPatch));
try {
$process->mustRun();
return $process->getExitCode() === 0;
Expand Down

0 comments on commit acd6e01

Please sign in to comment.