Problem/Motivation

DiffEngine is a fork of a library from 17 years ago. It is obviously stable to some extent, but it's code is extremely non-Drupal and it only ever gets the bare minimum attention to port. It seems likely that eventually we're going to hit bigger issues with PHP version compatibility.

Every so often it fails a new code quality check. The most recent example of it showing up in an issue is #3274474: Fix 'Access to an undefined property' PHPStan L0 errors. It also is not PHP 8.2 compatible and triggers PHPStan L0 errors.

Proposed resolution

Deprecate DiffEngine and replace it with https://github.com/sebastianbergmann/diff

Remaining tasks

1. Decide which one (if any) to use
1a. Dependency evaluation
2. Patch.

Evaluated options (considered in D9), then left out when the D10 proposal was formulated

1. Fix the 8.2 compatibility (possibly by adding phpcs-ignore/phpstan-ignore to the entire file so we don't have to rewrite the entire file to do so), then deprecate it in 10.1.x for 11.x for one of the alternatives
2. Fix the 8.2 compatibility and deprecate it in 9.5.x for 11.x
3. Don't fix the 8.2 compatiblity, and deprecate it in 9.5.x for removal in 10.0.x, but with a patch ready against diff module to switch over.
4. Don't fix the 8.2 compatibility and deprecate it in 9.5.x for 11.x (basically diff module would have to switch over to get PHP 8.2 compatibility but without a hard deadline).

User interface changes

API changes

Data model changes

Release notes snippet

Dependency evaluation

This package is already in use indirectly on Drupal test environments as it is a dependency of PHPUnit, used to report diff of actuals vs expectations. It has over 450 million downloads (Feb 2023) total, over 300k downloads daily.

Maintainership: Maintained by Sebastian Bergmann and the PHPUnit community.

Security policy: https://github.com/sebastianbergmann/diff/blob/main/SECURITY.md

Release cycle: No schedule, it appears to be kept in synch with PHP evolution as needed by PHPUnit.

Other dependencies: None.

Issue fork drupal-3299678

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

catch created an issue. See original summary.

mondrake’s picture

Title: Consider replacing DiffEngine with phpdiff » PHP 8.2 - Consider replacing DiffEngine with phpdiff
Priority: Normal » Major
Issue tags: +PHP 8.2, +blocker

There's also sebastianbergmann/diff which is already a dependency of PHPUnit we're using in dev.

Disclaimer: I know nothing about the scope of usage here.

DiffEngine is making use of dynamic properties so it is in the blocker path for PHP 8.2 compatibility.

mondrake’s picture

Issue tags: +PHPStan-0
catch’s picture

Title: PHP 8.2 - Consider replacing DiffEngine with phpdiff » PHP 8.2 - Consider replacing DiffEngine with jfcherng/php-diff or sebastianbergmann/diff
Issue summary: View changes
longwave’s picture

I think this has been discussed before at least once, IIRC the issue is that if we are to retain BC then the interface we provide is very tied to the existing implementation. Alternatively we could just deprecate our diff component and reimplement where it is used - possibly only the config UI and some tests?

#1848264: Compare and merge PhpWiki diff*.php with MediaWiki's DairikiDiff.php and DiffEngine.php is related but can probably be closed as outdated now.

mondrake’s picture

Assigned: Unassigned » mondrake

I'm working on this

catch’s picture

Alternatively we could just deprecate our diff component and reimplement where it is used - possibly only the config UI and some tests?

That sounds like a good idea - means just a service + class deprecation and then providing the new ones.

larowlan’s picture

It looks like diff module in contrib uses it https://git.drupalcode.org/project/diff/-/blob/8.x-1.x/src/DiffEntityCom... - 41k installs of the 8.x-1.x version - so we need to be mindful of that

catch’s picture

Issue summary: View changes

Added some possible deprecation scenarios for the old service to the issue summary.

mondrake’s picture

Turns out we cannot deprecate easily Diff per se, but we can deprecate DiffEngine, and several methods of the component that are unused in core.
We can replace DiffEngine with sebastianbergmann/diff with a BC layer to transform its results into the DiffOp* value objects, that are kinda Drupal specific, and quite spread around, so not easy to replace.

mondrake’s picture

Assigned: mondrake » Unassigned
Status: Active » Needs review
StatusFileSize
new13.15 KB

Here's a patch, still quite rough around the edges, but illustrates the idea.

mondrake’s picture

Status: Needs review » Needs work

mondrake’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new150 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

mondrake’s picture

Status: Needs work » Needs review

Rebased.

spokje’s picture

Status: Needs review » Needs work

Unhappy PHPStan :/

longwave’s picture

Issue tags: +Needs issue summary update, +Needs dependency evaluation, +Needs change record

The proposed approach looks pretty neat while keeping us within the constraints of the interface to the existing Diff component.

Adding some tags for things that we still need; we also should add an explicit dependency on sebastian/diff to the core composer.json and also the component's composer.json.

mondrake’s picture

Added a draft CR and reflected in the deprecation messages, fixed PHPStan errors.

mondrake’s picture

Title: PHP 8.2 - Consider replacing DiffEngine with jfcherng/php-diff or sebastianbergmann/diff » Deprecate DiffEngine and replace with sebastianbergmann/diff
mondrake’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Updated IS and issue title

andypost’s picture

drupal:10.0.0 needs update to 10.1.0

mondrake’s picture

Title: Deprecate DiffEngine and replace with sebastianbergmann/diff » Deprecate DiffEngine and replace with sebastian/diff
Status: Needs work » Needs review
Issue tags: -blocker
longwave’s picture

Status: Needs review » Needs work

A comment that I think can be removed now, plus we also need to add the dependency to core/lib/Drupal/Component/Diff/composer.json.

mondrake’s picture

Status: Needs work » Needs review

Thanks for the review @longwave, commented inline.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record +Needs Review Queue Initiative

Removed change record as one was added.

This was a near perfect think I think. Issue summary was clear with problem, steps, and tasks.

Reviewing the PR everything looks good, not sure what more can be looked at.

longwave’s picture

Status: Reviewed & tested by the community » Needs work

The change record is only a placeholder and has no detail, also we need a dependency evaluation.

mondrake’s picture

Fleshed out the CR.

mondrake’s picture

Issue summary: View changes
Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs dependency evaluation

Added dependency evaluation

mondrake’s picture

Rebased.

catch’s picture

This looks good to me, we might want to look at the Diff component itself later, but no need to do that to make the switch here and the bc layer is tidy.

Since I opened this, probably better if another committer commits it, or at least will give it a few days if no-one else does.

longwave’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed ce28a42738 to 10.1.x. Thanks!

  • longwave committed ce28a427 on 10.1.x
    Issue #3299678 by mondrake, catch, longwave: Deprecate DiffEngine and...

mondrake’s picture

Published the CR

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

alexpott’s picture

Unfortunately this change has resulted in a regression in the update_helper module (and also the config_update module) see #3386482: DiffOpOutputBuilder does not correctly match the 10.0.x implementation and produces unexpected output.

alexpott’s picture

mstrelan’s picture

This has also introduced a regression in the diff contrib module when content in revisions have different line endings.

#3389010: Old content with different line endings can break diff entirely
#3389715: Diffs with different line endings leads to Invalid $mode 3 specified