Getting Started with Patches

A patch is a specific file that outlines all the changes made between two sets of files.

(Photo by Fabian Grohs on Unsplash)

This past month at Outside, we went through the process of updating all of our environments from PHP 5.6 to PHP 7.1. This process was not an easy one and took some careful testing, inspection, and review to make sure that we didn't miss any code changes between the versions.

Along the way, we encountered an issue with the Bulk Media Upload module, where the summary was not displaying after a successful upload. This issue was actually logged by another user back in September 2016 with the title "Previous upload summary does not show last uploaded items in PHP 7 (2800897)". The reporter graciously provided a solution (array syntax change) to create a patch, but, in the process, instead of creating an actual patch file, the reporter uploaded the diff instead.

As the newest member of the team, I had actually never created or applied patches to any Drupal project, so the process became a learning experience for me and one that I wanted to share with you.

What Is a Patch?

A patch is a specific file that outlines all the changes made between two sets of files. For example, if I have file and I make some changes to it, I would create a patch file that showcases the differences that I have implemented, and then I would submit it so other developers can review and/or implement it. This way, when developers are contributing to Drupal core or contributed modules, they can easily submit patches for any fixes without sending over a completely new file.

What Do Patches Look Like?

A patch file looks very similar to when you run git diff on a file. It outlines all the added lines (+) and all the lines removed (-) in that specific file. Patches usually start out as diff files and then move to a patch file. Below is the output of a git diff for a file and we can see the added lines (+) and removed (-).

diff --git a/test_module.module b/test_module.module

index 17b9c77..9dc0261 100644

--- a/test_module.module

+++ b/test_module.module

@@ -13,7 +13,8 @@ function test_module_menu() {

  // Admin configuration group.

  $items['admin/config/services/test_module'] = array(

  -    'title' => 'Test Module Settings',

  +    'title' => 'Test Module Admin Settings',

  +    'description' => 'Configure the test module',

  'page callback' => 'drupal_get_form',

  'page arguments' => array('test_module_admin_settings_form'),

  'access arguments' => array('administer site configuration'), 

Creating a Patch File

When creating a patch file, there are two things to note before submitting it:

  • Make sure you are in the git repository for that one module. If you are creating a patch for a contrib module, download that contrib module from Drupal.org and apply it there, not your project specific repository.

  • The diff file is not what you upload to Drupal.org; make sure you have a .patch file.

Let's get started! If you would like to follow along with a code sample, download this custom module on Github.

  1. Inside of our test_module, we are going to create a simple patch to change the title of menu item and add a description. Go ahead and open up test_module.module in your favorite text editor.

  2. Inside of test_module_menu() update the 'title' to be "Test Module Admin Settings"

  3. Next update, add a 'description' to the menu item with the text 'Configure the test module'

  4. After following those steps, the test_module_menu() function should look like this:

/**

* Implements hook_menu().

*/

function test_module_menu() {

  $items = array();


  // Admin configuration group.

  $items['admin/config/services/test_module'] = array(

    'title' => 'Test Module Admin Settings',

    'description' => 'Configure the test module',

    'page callback' => 'drupal_get_form',

    'page arguments' => array('test_module_admin_settings_form'),

    'access arguments' => array('administer site configuration'),

  );

  return $items;

}
  1. Now that we have successfully updated our module, it is time to create the patch!

  2. Open up the terminal and move into the module folder.

  3. Inside the module folder in your terminal, go ahead and run git diff. You should see something very similar to this:

diff --git a/test_module.module b/test_module.module

index 17b9c77..9dc0261 100644

--- a/test_module.module

+++ b/test_module.module

@@ -13,7 +13,8 @@ function test_module_menu() {

  // Admin configuration group.

  $items['admin/config/services/test_module'] = array(

  -    'title' => 'Test Module Settings',

  +    'title' => 'Test Module Admin Settings',

  +    'description' => 'Configure the test module',

  'page callback' => 'drupal_get_form',

  'page arguments' => array('test_module_admin_settings_form'),

  'access arguments' => array('administer site configuration'),
  1. With the above output, we can now create a patch by running git diff > test_module_patch.patch

  2. This will create a file, test_module_patch.patch that has all of the outputs of the git diff command in it, but as a patch file!

  3. Success! You've officially created your first patch.

  4. Now we want to test to make sure our patch works correctly. If you run git status from the command line, you should see something similar to this:

On branch master

Changes not staged for commit:

(use "git add <file>..." to update what will be committed)

(use "git checkout -- <file>..." to discard changes in working directory)

    modified:   test_module.module

Untracked files:

    (use "git add <file>..." to include in what will be committed)

	test_module_patch.patch

	no changes added to commit (use "git add" and/or "git commit -a")

	 
  1. To test, we will undo the changes we made to test_module.module, apple the patch, and make sure the patch changes are applied to test_module.module. Run git checkout -- test_module.module. The module file will now be back to the original state before we made the changes. If we view the file test_module.module, you will see the that test_module_menu() function looks like it did originally:

// Admin configuration group.

$items['admin/config/services/test_module'] = array(

  'title' => 'Test Module Settings',

  'page callback' => 'drupal_get_form',

  'page arguments' => array('test_module_admin_settings_form'),

  'access arguments' => array('administer site configuration'),

);
  1. Next up, we can run git apply test_module_patch.patch. This will apply the patch to the files specified in the patch. So for us, it will apply the changes we made to test_module.module

  2. If we open test_module.module again, we can see the patch applied!

// Admin configuration group.

$items['admin/config/services/test_module'] = array(

  'title' => 'Test Module Admin Settings',

  'description' => 'Configure the test module',

  'page callback' => 'drupal_get_form',

  'page arguments' => array('test_module_admin_settings_form'),

  'access arguments' => array('administer site configuration'),

); 

That is all there is to it! Remember to make sure that you are creating a patch in the module specific git directory. You do not want any path specific files showing up in the patch file.

What's Next?

If you were contributing to a module on Drupal.org, there are a few other rules:

  • Make sure there’s an issue related to the patch you are creating.

  • Name your patch file appropriately - test_module_path is a bad name for contributed modules. The best way to do it is with the Issue Number and then a descriptive title. For example: bulk-media-upload-previous-upload-summary-php-7-2800897-12.patch. Look to follow the (unofficial) coding conventions of [project_name]-[short-description]-[issue-number]-[comment-number].patch

  • Make sure your patch follows all Drupal Coding Standards.

  • Make sure you follow all rules outlined by the module's coding standards.

Congratulations on making a patch! Now you can contribute back to Drupal and all of the contributed modules.

Filed To: Technology
More Magazine
Pinterest Icon