Recently, at Drupal Camp Costa Rica, I was pleased to discuss what I feel is a very important, and very fundamental, Drupal technique. Patching code is something many of us have done, but the Drupal community has evolved standards around when, why, and how it's appropriate to do so. I'd like to run through some of the highlights of that talk here.
What's a patch?
Let's start at the beginning. What do I mean by, "patch a module"? A patch is a small text file that contains a list of all the differences between the code as published (usually on drupal.org) and the code as you wish it to run on your site. You "apply" it to the original code, and the changes are made so that you can use the code the way you want it.
Why would I do that?
In the Drupal community, we DON’T HACK CORE! This is a commonly held tenet of Drupal development, and there are very good reasons not to hack core, or even contrib modules:
- Forward compatibility: If new features or changes, or most importantly, security releases, are made to the module, you can’t take advantage of them without losing your changes.
- Developer friendliness: If your changes introduce a bug down the road, other developers will not look in that module, because they will assume it hasn’t been changed. This will cost them time and frustration.
What's the difference?
What is the difference between a patch and a hack? Method. When I say I "hack" a module, I mean that I am changing the module code directly, putting it straight into my site repo or on my site server, and running it. Changes like this are usually pretty invisible to other developers. When I say I "patch" a module, it means that the changes that I've made are in a separate text file, which is applied to the module by when the site is built. These changes are also easily accessed and reviewed by other developers. This tiny methodology difference means a great deal in actual practice. A module that's been hacked is very difficult to use in the long term. Changes made to it are often not recorded anywhere (or anywhere anyone would look), and if the module is replaced, by say a new or updated version, then those changes are lost forever. It's ok to patch core or contrib, just don't hack it!
When would I patch a module?
- You’ve found a module that does most of what you need... but not quite everything.
- You’ve found a bug in the module.
- You need to integrate custom functionality into the module, but it doesn’t have the right API functions.
- You need a change right now and the module maintainer isn’t responding.
When would I not patch a module?
- The module provides hooks or alter functions that will allow you to do what you need.
- The module only does a little of what you need, and you probably can build a custom module for the same effort.
- The dev version of the module has what you need, or there’s already a patch in the issue queue.
Please note this last point - work smarter! Spend some time before you get to coding to make sure that someone else hasn't already done the work for you! That's open source, folks - use it!
So, how do I do it?
Step 1: Check out the module
The easiest way to generate a patch file is by using git; this means you need to check out the module. See the screenshot here for instructions on checking out a Drupal module. Note, if you are running a development site, you can check this module out into your sites/all/modules directory; git is smart enough to handle it even if your full site directory is a git repo, too. (Though I don't recommend that methodology, and you'll see why later.)
Be sure to check out the dev version of the module; it's going to be the most up-to-date, and module maintainers want to have your code apply to the latest version of what they're working on.
Step 2: Hack away!
This is where you have the opportunity to make and test the changes you need to make in the code.
Step 3: Make the Patch
There's two ways of doing this: on the command line, or via a GUI. Command line is actually pretty easy. Once you've made your changes in the checked-out module directory, you run this simple command:
[php]git diff > patch_demo.patch[/php]
This will put all modified files into the patch. As with most command line tools, there are complicated options to only include certain files, or to compare different directories, etc. However, I personally favor a different way... Sourcetree. It's no secret that we here at Phase2 are huge Atlassian fans. This is another product by them, a GUI interface for management of your repositories, and it is awesome. It’s also free. It can manage your repos, help you keep them organized, and provides a visual interface for branching, git flow, and - of course - generating patches. Personally, while I can work with git on the command line, I don't. Because I use this instead. Did I mention it's free? (Disclaimer: I didn't get anything for this recommendation, except a free copy of Sourcetree). Congratulations! You've written a patch for a module! Now what?
Step 4: Submit your work
Create a new issue in the issue queue of the module you're working on. Fill out the form, but don't attach your file just yet. You'll need to rename it, and the Drupal community has a specific formula for doing so. [module name] - [short description] - [issue number] - [comment number] . patch That's the module name, followed by a one to two word description of what the patch does, followed by the nid of the issue queue node, and the number of the comment, dot patch. Let me show you where to find those numbers.
The issue number is the nid of the issue node, and can be found in the url. The comment number is not the cid of a comment; it's the visual display number of the comment - see the second screenshot on the right. However, it's the number of the comment you're about to add, so when you rename your patch, rename it the number of the last comment, plus one. So, let's make an example. For the module patch_demo, you need to add an additional field to the database table for "job roles". The nid of the issue node is 2313551. There are currently two comments on that thread. So, you could title your patch:
Now, make that comment and attach your patch! Be sure to set the issue "Status" to "Needs Review", as this will trigger drupal.org to automatically inspect and attempt to apply the patch.
Step 5: Bring it all together
Drush make is an amazing tool. It allows you to specify modules, themes, libraries, site structure... everything for building a site. While the use of it is pretty involved, and beyond the scope of this tutorial, I will touch on one thing - the ability to add a patch to your site build - automatically.
This is a very basic drush .make file. It tells drush to download drupal core, the features module, and the patch_demo module from my drupal.org sandbox. The last line, outlined in orange, tells drush to grab that patch file from the drupal file server, and apply it to the patch_demo module. Note that part of the array specification includes the issue queue nid - this is important, as it allows future developers to easily find that issue queue and see why you are patching the module. The naming convention on the patch file itself tells future devs which patch to look for, and in what comment. Running drush make on this make file will download drupal, the features module, and my patch_demo module. It will assemble the site, then apply the patch to the patch_demo module, making the changes we specified much earlier in the process.
Since the patch only needs to be accessible to drush via the web, it could be anywhere - like, on a file server, or your company’s web site download directory, or Github, or Dropbox. Why contribute in the Drupal issue queue? Because each of you, no matter how new, or inexperienced, or totally ninja, can help make Drupal better. Communities work best when everyone contributes. Your patch may not be accepted, or it may, or it may spark a discussion that leads to a better way of doing what you need. This is good for Drupal, which means in the long run it's good for you too! Also - even it it isn’t accepted, it’s in the issue queue file system, so it never goes away - meaning you can continue to use it. I’ve submitted many patches I knew would never get accepted, because I needed something to work in a particular unique way. That’s OK. Finally, on a more personal note, contributing in the issue queues helps get you known in the Drupal community. This is great for your career. Help make Drupal better. Save the kittens. Get yourself a better job. Contribute!
Here are a number of really good resources I drew on to write this presentation and tutorial.
- Drupal Patch Contributor Guide
- Joshua Brauer: Don't hack core and don't hack contrib (unless you have to)
- Git Diff definitions
Last word: Thanks to the Drupal Camp Costa Rica team for giving me time to present such an important topic to their devs. ¡Pura Vida!