how to make a patch – the explained way

Upload: garytiedeman

Post on 30-May-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/14/2019 How to make a patch the explained way

    1/4

    How to make a patch the explained wayJune 27, 2008 by sergiosdj

    Hi everybody,

    if you just want to learn something new and interesting, keep reading :-).

    I ll try to organize this post in a few topics so you ll feel more comfortable in

    reading it. Let s start.

    1) A little introduction

    The patch utility is considered to be one of the most useful programs ever written. Together with diff , they are the dynamic duo for the most majority of the FLOSS projects.

    Basically, what it does is simple: you have to feed it with a text pre-formatted(we ll see how to generate this pre-formatted text later) to represent differences between two versions of the same file (say, YOUR_FILE and YOUR_FILE_MODIFIED ). Then, patch modifies YOUR_FILE so it can be an exactly copy of YOUR_FILE_MODIFIED . These differences are generated by a program called

    diff .

    The patch tool was written by Larry Wall (creator of the Perl programming language) in 1985, and the diff tool was written by Douglas Mcllroy, in the 70 s. They are the basis for almost every open-source project since they provide a smart and cheap way to represent modifications in a file.

    2) Why patching files?

    Patching files, as said above, is the smarter and cheaper way to deal withmodifications in a file. Think about a file that has, say, 4 KB in size (can be aC program, doesn t matter). Now, imagine that you modified just 2 lines in it,

    totalizing 10 bytes (i.e., these 2 lines are 10 bytes long). If you try torepresent this difference without using diff and patch , you ll have (in the worst case) to send your entire 4-KB-file to all your friends/colleagues that areworking on this file with you. Now if you suppose you have 100 people working with(a large open-source project), you would have to send almost 400 KB (4 KB x 100 =400 KB) through your network! Ok, nowadays it may be an irrisory value due to ourDSL connections, but imagine doing this 10 times a day

    Now, try to enlight your world and think that you do have diff and patch ! The diff program would represent this modification using approximately 30 bytes (10 bytes to represent the excluded lines, 10 bytes to represent the added lines, andanother 10 bytes for the header). Ok, now doing some math again, you would have tosend almost 3 KB (30 bytes x 100 = 3000 bytes), which is way too lower than the

    previous value! You have a great decreasement of network usage, and the mostimportant, you improved the readibility of your modification! Now you don t have to tell your friends hey, take a look at lines X and Y because I modified something there to fix the problem Z . You just have to say that s the modification I ve done to fix the problem Z . Got it? :-)

    3) How to make your own patch

    Finally, now that you have understood what a patch is, let s try to make our own. First, let s write something in a file. I ll assume that you know C, but even if you don t you can keep reading because I ll not focus on the code.

  • 8/14/2019 How to make a patch the explained way

    2/4

    sergio@miki /tmp/patch_howto $ cat ourfile.c#include

    void print_hello (void){

    printf ("Hello, World!\n");}

    int main (int argc, char **argv){

    print_hello ();return 0;

    }Ok, so here we are with our beautiful Hello World. But you re still not happy with it. You want it to print someting else! Maybe a longer sentence? Maybe youwant to remove that comma between the two words! Doesn t matter. I myself prefer it to say something else, like Hello, World! This is a post about patching files!So I ll do the modification, but as I want to make a patch, I ll create a

    backup version of the original file so that I can take the differences later.

    sergio@miki /tmp/patch_howto $ cp ourfile.c ourfile.c.originalIt also doesn t matter how you choose your backup s name, but it s kind of a convention to name it

    like file.orig or file.original . Now, we can modify our code and include that other phrase that we want it to say. Did it? Good. Now comes the cool stuff :-).Go one directory down (cd ..), and type:

    sergio@miki /tmp $ diff -u patch_howto/ourfile.c.originalpatch_howto/ourfile.c(Obviously, you should change the path used in the exampleabove to reflect your directory s name and file s name).

    You should see something pretty much like:

    --- patch_howto/ourfile.c.original 2008-06-27 22:22:25.000000000 -0300+++ patch_howto/ourfile.c 2008-06-27 22:25:32.000000000 -0300@@ -2,7 +2,7 @@

    void print_hello (void){- printf ("Hello, World!\n");+ printf ("Hello, World! This is a post about patching files!\n");}

    int main (int argc, char **argv)Wow! My first patch! Yeap :-). Now, save it to a file:

    sergio@miki /tmp $ diff -u patch_howto/ourfile.c.original patch_howto/ourfile.c >myfirstpatch.patchAnd you re done :-). Now you have your first patch in your hands. So let s see

    what we just did in the line above.

    First, you invoked the diff program passing two arguments to it: your original file, and your modified file (be aware that the order of these arguments domatter). You also passed one modifier to it, namely -u. This modifier means thatyou want diff to generate the differences in a unified format (this is the pre-formatted text that I mentioned earlier). This unified format allows the patch tool to recognize and apply correctly your modifications, and has the advantage to be more human-readable than other formats that diff can output (as an exercise, try to run this diff command without using the -u and see what happens).

  • 8/14/2019 How to make a patch the explained way

    3/4

    Also, it s good to notice that it s a convention to generate your patch outside your code s directory tree. Some people also prefer to keep two directories (one original and another modified ), and to run diff against those dirs. I won t tell you to do this or that, because it depends on your needs. But it is certainlya good idea to make some tests and find out what s your preferred way to work with patching :-).

    4) Applying someone s patch into your code

    You know how to generate the patch, but you still don t know how to apply it? Now problem :-). For this lesson, let s assume that you still have the old ourfile.c code, which prints only Hello, World! . As you re not satisfied with it too, you decide to apply the patch that makes the program print Hello, World! This is a post about patching files! . Remember, your patch is named myfirstpatch.patch .

    So first make sure you have the old version of the code:

    sergio@miki /tmp/patch_howto $ rm ourfile.csergio@miki /tmp/patch_howto $ mv ourfile.c.original ourfile.cNow, everything you have to do is:

    sergio@miki /tmp/patch_howto $ patch -p1 < ../myfirstpatch.patchpatching file ourfile.cWow again! Try opening your file and see what happened. Now the full messageshould be there as expected. But wait what did we do this time?

    Now, you invoked patch without arguments, but you provided data through its standard input. That s the right way to do it: redirect the output of you patch to the input of the program. Now, you may notice that we passed one modifier to thetool: the -p1. Do you remember that we generated our patch from one directoryunder the file s dir? And do you remember that in the patch s header there were information about its relative path? That s why we must provide the -p1 option: because we are telling patch to remove the first directory (left) from this

    relative path, and start applying the patch from the current directory. As therelative path was patch_howto/FILENAME, it removed the patch_howto part andapplied the patch to FILENAME (which, in our case, is ourfile.c).

    It s also good to notice that it s a very common practice in open-source projects to make/apply patches like that. Always go 1 directory below when making, andalways provide the -p1 modifier when applying.

    5) Extra modifiers for diff

    There are also good modifiers for the diff command. You ll find something like -pruN. They mean:

    -p: Show the C function that has changed in the header of the diff file. It s useful when dealing with large files and lots of modifications.

    -r: Go recursive (used when you have that schema with 2 directories that I toldabove).

    -u: See above :-)

    -N: Treat absent files as empty, so if you have new files in your modified directory they are included in the diff (and you don t get error messages).

  • 8/14/2019 How to make a patch the explained way

    4/4

    Well, that s it for now :-). As usual, take a look at the manpages for both commands; it should help you more than this post!

    Bye!