Patching info files with Composer

Applying patches can be dicey when there are untracked changes in the files being patched. Suppose you find a patch on Drupal.org that adds a dependency to a module along with some other changes. It should be pretty simple to apply, right? If you are using Composer to manage your modules and patches it might not be so simple.

Understanding the Problem

When Composer installs a Drupal module, it installs the module using the dist version by default, but this version includes project information to the bottom of the *.info.yml file which is added by Drupal’s packaging system.

# Information added by Drupal.org packaging script on 2019-05-03
version: '8.x-1.1'
core: '8.x'
project: 'module_name'
datestamp: 1556870888

When a patch also alters one of those lines near the end of the file, such as when a dependency is added, then the patch will fail to apply.

Preferred Install

Thankfully composer allows you to specify the installation method using the preferred-install setting.

There are two ways of downloading a package: source and dist. For stable versions Composer will use the dist by default. The source is a version control repository.

Installations that use the source install avoid the packaging step that alters the *.info.yml file, and thus allow patches to be applied cleanly (assuming there are no other conflicts).

With an understanding of the issue, the solution is quite easy. Simply denote the preferred installation method for the patched module and watch it work!

"config": {
...
"preferred-install": {
"drupal/module_name": "source",
"*": "auto"
}
},

Note: The flags --prefer-dist and --prefer-source are both available for composer install. Be sure to check your deployment and build scripts to prevent unexpected issues in the deployment pipeline.

Other Solutions

Unfortunately, this is the only viable solution at the moment. There is an issue on Drupal.org for this, but a fix does not sound simple or straightforward.

The long term fix would need changes both on the d.o side and in core itself (since core would have to know to look in *.version.yml (or whatever) for the version info, instead of looking in *.info.yml).

Until a solution is agreed upon and implemented, avoiding the issue is the best we can do. Thankfully the workaround can often be temporary, as the custom preferred-install setting override can be reverted as soon as the needed patch makes its way into a release. Then it’s back to clean dist installs and smooth sailing, at least until the next info file patch comes along!