Fixing the Code

Introduction: Patches Welcome

Most open source communities are very welcoming to people who are interested in fixing bugs or adding new features to a project. Patches are not only welcome, they are encouraged! It’s important, however, to know how to create a proper patch and how to submit a patch to a community for possible integration into the code base.

This chapter introduces the patch file format and shows how to create and apply patches. It covers patches created both with and without a source code management (SCM) system, and introduces best practices to follow when creating patches and submitting those patches to a FOSS project.

What is a Patch?

A patch (also sometimes referred to as a diff) is a text file that shows changes to a file (or multiple files) as compared to a previous version. Typically, a patch shows line-by-line changes delineated with a ‘+’ (plus sign) or ‘-‘ (minus sign) to represent additions and removals in the code, respectively. Certain patch formats also include surrounding lines of code to provide context and line numbers associated with the changes.

Patches are the preferred method for submitting changes to a FOSS project. This is because patches are a standard format and can be easily read and understood by developers familiar with the code base. A patch can include descriptions of multiple changes to multiple files, and this makes patches a great format for representing bug fixes or code enhancements that may touch many files within the larger project.

Example of a Simple Patch

In this example you generate a small change to a source code file to see how to create a patch. The file you start with is a simple Hello, World program hello.c written in C.

/* hello.c - a simple program to print out hello
* to the screen
*/

#include <stdio.h>

int main() {
    printf("Hello, World.\n");
    return 0;

}

That output is not too exciting — instead change the punctuation to an exclamation point to really get some enthusiasm! The first step in making a change is to create a copy of the file you are working on. If you are working on code that is in a revision control system this step won’t be necessary. For now, assume this code is not checked out from a repository (you practice creating patches using Subversion later in this chapter.)

Next, create a backup copy of the file hello.c and name it hello.c.punct so that you know the file is related to your punctuation change.

$ cp hello.c hello.c.punct

Next edit hello.c and leave the backup copy hello.c.punct as-is. Using your favorite editor, open hello.c and change the '.' in the printf statement to be a '?'. Save the file and exit out of the editor. Now generate a patch showing the change that was made. To do this, use the diff command. Since the unified diff format is considered by many to be easier to read, generate a patch in that format by passing the -u flag to the diff command. Run the following command to have the patch printed out to your screen:

$ diff -u hello.c.punct hello.c
--- hello.c.punct       2010-03-11 07:57:04.000000000 -0800
+++ hello.c     2010-03-11 07:58:54.000000000 -0800
@@ -5,6 +5,6 @@
#include <stdio.h>

int main() {
-    printf("Hello, World.\n");
+    printf("Hello, World?\n");
     return 0;
}

Examine the output from the diff command.

  • The first two lines represent the files that are being compared — showing the file name as well as the last modified date.
  • Next are one or more hunks (pieces of a file) showing the differences between the files. In this case, you only have one change, so only one hunk is shown. Each hunk starts with the @@ text and numbers that represent the line numbers displayed in the change for the old (marked with a '-') and new (marked with a '+') files, respectively.
  • It then outputs the differences between the files. Since you used the -u flag to set the output to unified format, there are a number of lines shown that have not changed; these are output with a space in front of them.
  • Lines with a - in front of them have been removed from the first file.
  • Lines with a + in front of them are additions to the first file.

Notice that your one-line change is actually shown as the removal of an entire line and then an addition of a new, modified line.

When you ran the diff command you had it output to the screen. This can be useful when comparing things locally, but in order to share changes with others you should capture that output to a patch file. Use a simple shell redirect (>) to achieve this. In order to save the patch as hello-excitement.patch, the following command is used:

$ diff -u hello.c.punct hello.c > hello-excitement.patch

Exercise – Compare diff formats

Run the diff command again, this time without the -u flag and compare the output to the output when the -u flag is used.

Naming Conventions

Patch files are most often created using the .patch file extension, although .diff is also common. Our recommendation is to use .patch as the file extension unless the project you are working on has a different naming convention. For the actual file name, it is best to use something descriptive without being too long. Spaces should be replaced with a dash (-) or an underscore (_) — choose one and be consistent. It can also be helpful to include any applicable bug or ticket numbers should the patch fix something described in the project’s bug tracking system. Look at the following example to get a better idea about how best to name a patch file.

Example: Fixing a bug that caused the date to be output in an incorrect format. This is bug #1517 in the project’s bug tracking system.

Bad:   date.patch
Good:  format-date-output.patch
Best:  format-date-output-bug1517.patch

Comparing Multiple Files

The above example contained a relatively simple patch. In general, patches you encounter are likely to be much larger — representing bigger changes to the code such as the addition of a new feature, or a bug or security fix that may touch multiple files within multiple directories of the code. These larger patches are still generated in the same manner by using the diff command. Instead of comparing two files, diff can be used to compare two directories and all of the files contained within.

Extend the example above by working with a directory, hello/, that contains two files: the hello.c program you started with in the first example plus a README file that describes the program. The directory contents and the README file contents are shown below:

$ ls hello/
hello.c  README
$ cat hello/README
This is a simple program which outputs "hello" to the screen.

You are going to be making changes to each of these files, so instead of making a backup of each file within the hello/ directory, copy the entire directory:

$ cp -r hello hello.orig

Now edit the files in the hello/ directory to include the exclamation point in the printf statement in hello.c and to update the README file to contain:

This is a simple program which outputs "hello" to the screen in an enthusiastic manner.

To create a patch file showing the changes, pass it the directory names rather than the file names:

$ diff -u hello.orig hello
diff -u hello.orig/hello.c hello/hello.c
--- hello.orig/hello.c  2010-03-11 09:11:29.612888467 -0800
+++ hello/hello.c   2010-03-11 09:14:39.406763357 -0800
@@ -5,6 +5,6 @@
#include <stdio.h>

int main() {
-    printf("Hello, World.\n");
+    printf("Hello, World?\n");
     return 0;
}
diff -u hello.orig/README hello/README
--- hello.orig/README   2010-03-11 09:11:29.612888467 -0800
+++ hello/README    2010-03-11 09:14:58.175763807 -0800
@@ -1 +1 @@
-This is a simple program which outputs "hello" to the screen.
+This is a simple program which outputs "hello" to the screen in an enthusiastic manner.

The output is similar to the previous example, however there are now multiple hunks shown — one for each change. In this manner, you can create large changes that touch multiple files and encapsulate all of those changes in a single patch file to easily share with others.

$ diff -u hello.orig hello > hello-excitement-exercise-X.Y.patch

Patches Generated with Subversion

If you read Getting the Code about source control management, you may recall seeing a similar diff displayed by using the svn diff command. If you make changes to your working copy of a Subversion repository, you are able to see those changes compared to the latest revision you have checked out by running the svn diff command. The format output by svn is similar to what the diff -u command generates, however, svn is comparing revisions of the same file instead of two different files. If you were using Subversion in the first example above, the output from svn diff would look similar to this:

$ svn diff
Index: hello.c
===================================================================
--- hello.c (revision 1)
+++ hello.c (working copy)
@@ -5,6 +5,6 @@
#include <stdio.h>

int main() {
-    printf("Hello, World.\n");
+    printf("Hello, World?\n");
return 0;
}

Notice that the lines representing the file names in the svn diff output appear slightly different than what you saw from the diff -u command. In this case, you are comparing your current working copy to revision 1 of the repository. Other than that, the output should look very similar. As with the diff command, you can redirect the output of svn diff to create a patch file.

$ svn diff > hello-excitement.patch

When using Subversion or another SCM, you generally want to create patches against the latest HEAD code from the repository. This means that you should run svn update or similar before creating your patch. This makes it easier for the project’s maintainers to include your patch once you submit it.

Applying a Patch

You’ve looked at one side of the patch process, creating a patch to describe changes to a code base. The other side of patching is being able to apply a patch to an unchanged (also known as pristine or vanilla) code base. Patches are created using the diff command and are applied using the patch command. In the simplest form, a patch can be applied by feeding the input of a patch file into the patch command:

$ patch < new-feature.patch

The above command assumes that the files to be patched are located in the same directory in which you are running the patch command. Another common way to run patch is using the -p flag followed by a number indicating the number of directory layers to strip off of the filenames specified in the patch. This makes sense when running patch from the root directory of the code in question. Using -p0 passes patch the entire filename unmodified. This is generally the standard for submitted patches.

$ patch -p0 < fix-output-display.patch

Of course, whether you use -p0, -p1, or no -p flag at all depends on how the patch was created. The patch manual page (accessed by typing man patch on the command line of a Linux machine) contains a description of the -p and other options that can be used with the patch command.

Submitting a Patch

Once you have created a patch that you would like to see included in a FOSS project, it’s important to submit the patch in a manner appropriate for that project. In some cases, this may mean creating a patch with certain flags passed to the diff command; in other cases, it may mean writing an email to a development email list attaching your patch file and writing a description of the code change. When in doubt, ask a developer! Most developers would be very happy to help you submit your first patch as they know it may lead to you contributing even more to the project.

Here are some general guidelines to follow submitting a patch:

  • Read the developer documentation for the project. This may contain preferences for how patches are formatted, or other general coding guidelines. As an example, refer to the patch submission guidelines for the git project.
  • If your patch is related to an existing ticket or bug report, either update the ticket to include your patch or if the patch needs to be submitted externally, be sure to reference the bug or ticket number so that people are aware of the connection.
  • In most cases, you should create a patch against the current HEAD of the development tree. If your patch was created against another version of the code, be sure to make that known.

Don’t be surprised or offended if your patch is not accepted for inclusion into a project’s code. This can happen for a number of reasons:

  • Your code may not meet coding guidelines for the project. Don’t let this discourage you. This is a great opportunity to improve your coding skills by learning what is required for this particular project and then re-submit another patch.
  • One of the main developers on the project may think you’ve provided a useful idea, but that it may need to be implemented in a different way. Again, don’t get discouraged should this happen, but try to use it as a learning opportunity.

Exercise – Create a Patch for a New File

Create a patch file that represents a new file, foo being created with the contents bar. Hint: on Linux systems, the file /dev/null represents an empty file — use that as one of the files you are comparing.

Exercise – Patch echo

(Adapted from Make A Simple Patch under Creative Commons Attribution-ShareAlike 2.0 England & Wales Licence.)

Patch the echo command from the coreutils project so that it echoes out arguments in reverse order.

Download the latest coreutils compressed archive file (or tarball) (8.4 as of this writing) from http://ftp.gnu.org/gnu/coreutils/coreutils-8.4.tar.gz:

$ curl -O http://ftp.gnu.org/gnu/coreutils/coreutils-8.4.tar.gz

Open the tarball to create a coreutils-8.4 directory containing the source code:

$ tar zxf coreutils-8.4.tar.gz

Edit the file src/echo.c in order to modify the echo command. First, create a backup copy of that file:

$ cd coreutils-8.4/src
$ cp echo.c echo.c.reverse

Now, edit the file echo.c. The code to modify is near the very bottom of the file — go to line 261 and change the following block of code:

while (argc > 0)
{
fputs (argv[0], stdout);
argc--;
argv++;
if (argc > 0)
putchar (' ');
}

Update the code to be:

while (argc > 0)
{
argc--;
fputs (argv[argc], stdout);
if (argc > 0)
putchar (' ');
}

Create a patch to represent your change by changing in to the directory and running the following diff command:

$ cd coreutils-8.4
$ diff -u src/echo.c.reverse src/echo.c > echo-reverse-output.patch

Your patch file should look something like:

--- src/echo.c.reverse  2010-03-14 09:45:40.959888410 -0700
+++ src/echo.c  2010-03-14 09:51:58.189768045 -0700
@@ -260,9 +260,8 @@
{
while (argc > 0)
{
- fputs (argv[0], stdout);
argc--;
- argv++;
+ fputs (argv[0], stdout);
if (argc > 0)
putchar (' ');
}

If you want to test out your changes, run the following commands to build the code:

$ sudo ./configure
$ make

note: The sudo command runs the code with superuser rights, and it will prompt the user to type the system administrator’s password.

You should now have a working echo binary. You can run the following command to test it out:

$ src/echo is this reversed
reversed this is

Exercise – Fix a Real FOSS Bug

Look through the bug tracking system for a project that you are interested in and find a small bug to fix. Create a patch file for that bug and submit it to the project for inclusion in the code.