Skip to content

Commit

Permalink
Merge pull request #496 from cweagans/dedupe-patch-collection
Browse files Browse the repository at this point in the history
Deduplicate patch collection as patches are added
  • Loading branch information
cweagans authored Feb 27, 2023
2 parents b6d1859 + 58778d7 commit 472139e
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 4 deletions.
7 changes: 7 additions & 0 deletions docs/usage/defining-patches.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ If you're defining patches in `patches.json` (or some other separate patches fil
}
```

## Duplicate patches

If the same patch is defined in multiple places, the first one added to the patch collection "wins". Subsequent definitions of the same patch will be ignored without emitting an error. The criteria used for determining whether two patches are the same are:

* They have the same URL
* They have the same sha256 hash

## `patches.lock.json`

If `patches.lock.json` does not exist the first time you run `composer install` with this plugin enabled, one will be created for you. Generally, you shouldn't need to do anything with this file: commit it to your project repository alongside your `composer.json` and `composer.lock`, and commit any changes when you change your patch definitions.
Expand Down
16 changes: 16 additions & 0 deletions src/PatchCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ class PatchCollection implements JsonSerializable
*/
public function addPatch(Patch $patch)
{
if (array_key_exists($patch->package, $this->patches)) {
foreach ($this->patches[$patch->package] as $existing_patch) {
$has_same_url = ($patch->url === $existing_patch->url);
$has_same_sha = (
isset($patch->sha256) &&
isset($existing_patch->sha256) &&
($patch->sha256 === $existing_patch->sha256)
);

if ($has_same_url || $has_same_sha) {
// If we already have the patch, don't try to add it again.
return;
}
}
}

$this->patches[$patch->package][] = $patch;
}

Expand Down
6 changes: 3 additions & 3 deletions tests/_data/dummyPatches.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
"description": "Test patch"
},
{
"url": "https://drupal.org",
"url": "https://drupal.org/foo",
"description": "Test patch"
}
],
"test/package2": [
{
"url": "https://drupal.org",
"url": "https://drupal.org/bar",
"description": "Test patch"
},
{
"url": "https://drupal.org",
"url": "https://drupal.org/baz",
"description": "Test patch"
}
]
Expand Down
45 changes: 44 additions & 1 deletion tests/unit/PatchCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,25 @@ public function testPatchCollectionAddRetrieve()
$patch1 = new Patch();
$patch1->package = 'some/package';
$patch1->description = 'patch1';
$patch1->url = '1';
$collection->addPatch($patch1);

$patch2 = new Patch();
$patch2->package = 'some/package';
$patch2->description = 'patch2';
$patch2->url = '2';
$collection->addPatch($patch2);

$patch3 = new Patch();
$patch3->package = 'other/package';
$patch3->description = 'patch3';
$patch3->url = '3';
$collection->addPatch($patch3);

$patch4 = new Patch();
$patch4->package = 'other/package';
$patch4->description = 'patch4';
$patch4->url = '4';
$collection->addPatch($patch4);

foreach (['some/package', 'other/package'] as $package_name) {
Expand Down Expand Up @@ -64,6 +68,45 @@ public function testPatchCollectionAddRetrieve()
$this->assertContains('some/package', $packages);
}

public function testPatchDeduplication()
{
$collection = new PatchCollection();

// First, make sure that we don't get anything out of an empty collection.
$this->assertEmpty($collection->getPatchesForPackage('some/package'));

// Add two patches with the same URL.
$patch1 = new Patch();
$patch1->package = 'some/package';
$patch1->description = 'patch1';
$patch1->url = 'https://example.com';
$collection->addPatch($patch1);

$patch2 = new Patch();
$patch2->package = 'some/package';
$patch2->description = 'patch2';
$patch2->url = 'https://example.com';
$collection->addPatch($patch2);

// We should only have one patch now.
$this->assertCount(1, $collection->getPatchedPackages('some/package'));
$this->assertEquals('patch1', $collection->getPatchesForPackage('some/package')[0]->description);

// Start over to test deduplication with sha256.
$collection = new PatchCollection();
$this->assertEmpty($collection->getPatchesForPackage('some/package'));

$patch1->sha256 = 'asdf';
$patch2->sha256 = 'asdf';
$patch2->url = 'https://example.com#something-different';

$collection->addPatch($patch1);
$collection->addPatch($patch2);

$this->assertCount(1, $collection->getPatchedPackages('some/package'));
$this->assertEquals('patch1', $collection->getPatchesForPackage('some/package')[0]->description);
}

public function testSerializeDeserialize()
{
$collection = new PatchCollection();
Expand All @@ -77,7 +120,7 @@ public function testSerializeDeserialize()
$patch2 = new Patch();
$patch2->package = 'another/package';
$patch2->description = 'patch2';
$patch2->url = 'https://example.com/test.patch';
$patch2->url = 'https://example.com/test2.patch';
$patch2->extra = [];

$collection->addPatch($patch1);
Expand Down

0 comments on commit 472139e

Please sign in to comment.