Handling Patch Rejects

From eLinux.org
Revision as of 20:05, 26 April 2007 by Tim Bird (Talk | contribs) (add stuff about finding and editing rejects)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Here is the response I sent to someone on the Linux-tiny mailing list when they had a question about how to handle reject files.

This is for very new beginners.


Fernando de Francisco Cano wrote:
> Sure I have some rejects, but I don't know what to do with them....
> Until now I 've only recompiled distro kernels, so it's my first time
> patching
> 
> Is there any problem patching  mandrake 10.0?


OK. If you're new to patching, maybe a brief explanation is needed. Pardon me if this is too remedial, but I wanted to write low level since I don't know your experience. Sorry in advance for the length.

Patches are created by diff'ing two source bases against each other. A patch is like a set of instructions for converting one source base into the other. Inside the patch are both the changes themselves, and context information which helps patch to identify the correct place to make each change.

If you try to apply a patch to a different version of software than it was originally created from, you may encounter problems. Patch may not find the correct place to make a change. When this happens, it leaves a reject file, showing the change that it could not make.

The Linux-tiny patches were created based on a kernel.org version of Linux (I'm not sure which one you are using, so I don't know the specific version). The Mandake kernel (and indeed almost all kernels shipped by the major Linux distribution vendors) is significantly different from the kernel.org version of Linux. Distribution vendors add many (often hundreds) of patches to their kernels, in order to provide extra features to their products. This includes drivers, protocols, filesystems, and other enhancements.

Since Linux-tiny is a fairly big patchset, it is very likely that there will be overlap between some of the changes it makes and some of the changes made by Mandrake.

If you get rejects while patching, it means that not all of the patch could apply. It is possible that the rejects don't matter, but you can't know that without looking at them. Basically, any time you get rejects you need to examine them and either 1) fix them or 2) decide they can be ignored, before proceeding.

Many times, rejects can be fixed pretty easily. A common cause of rejects is multiple additions to the beginning or end of something. Often, in these cases, the changes themselves don't really interfere with each other. But the change in text from one patch causes the patch program to be unable to match the context for a change from another patch.

For example, take the following text and patches. Starting with a simple text file describing a fish, there are two patches, one of which adds stuff about a dog and one adds stuff about a cat. Semantically, these patches don't interfere with each other, and there is no harm in applying both changes to the file. However, patch has problems with them.

Text (file 'A'):

I have a fish, named Charlie.
He swims in a fishbowl.
He doesn't eat much.


1.patch:

--- A   2004-10-21 10:49:53.547578239 -0700
+++ B   2004-10-21 10:50:40.395525796 -0700
@@ -1,3 +1,5 @@
 I have a fish, named Charlie.
 He swims in a fishbowl.
 He doesn't eat much.
+My dog is named Spot.
+Spot is friendly and wags his tail.


2.patch:

--- A   2004-10-21 10:49:53.547578239 -0700
+++ C   2004-10-21 10:51:05.435687319 -0700
@@ -1,3 +1,5 @@
 I have a fish, named Charlie.
 He swims in a fishbowl.
 He doesn't eat much.
+My cat is named cleo.
+Cleo scratches the couch.

}

Each of these patches could be applied succesfully to file A, individually. However, if you try to apply these patches in sequence, like so:

  • cp A D
  • patch D <1.patch
  • patch D <2.patch

You get a reject on the second patch. The place where the description of the cat is supposed to be is now different, and patch gives up.

To fix this, you need to add the rejected changes manually, taking into account the differences caused by the other changes. (Think of 1.patch as the Mandrake changes and 2.patch as the linux-tiny patch set.)

Doing this is usually pretty easy. You look at the rejected hunks, and compare the lines they intended to patch from the original file with the lines in your source base. (In your case, compare a kernel.org version of Linux, with Mandrake Linux, for the file and lines mentioned in the reject file.) In the example above, I would have to decide if I wanted the description of the dog to come before or after the description of the cat. I would make the change manually. (If this were source, I would then recompile and test extensively... :)

For extra credit, once you have made your changes, you can create a new linux-tiny patch set by diffing your Mandrake-tiny with your original Mandrake (which you should have saved off earlier). Mandrake users may appreciate having such a "Mandrake-tiny" patch set to work with.

Some more notes

If you do this regularly, here are a few tips for working through rejects quickly.

To find reject files in a source tree, at the top of the source tree type:

find . -name "*.rej"

If you find a reject file, it is often useful to examine the reject file and edit the file it applies to, simultaneously. You can do this using shell wildcards pretty easily. For example, if you see the reject arch/arm/kernel/time.c.rej, you can edit both the reject file and the original file with:

vi arch/arm/kernel/time.c*

Now split your 'vi' window with ":split", get the reject file in one of the windows, and go through it and the original file fixing any problems found.