Game Development Community

dev|Pro Game Development Curriculum

How To Make Patches (Cygwin/Unix)

by Kyle Carter · 08/08/2002 (10:33 am) · 2 comments

One of the best ways to help the Torque community is to contribute back to it. Many of you have - there are a lot of really useful code snippets; the CVS is updating regularly; and we've an extensive list of resources and thoughtful forum threads.

Code is the lifeblood of the Torque engine; were it not for all the work people have done in modifying and extending it, Garage Games would be a faint, dead memory among Tribes enthusiasts, regardless of how good the resources, or how helpful the forums.

But not very many people seem aware of how many great tools there are to work with source code (or any text file), especially on Unix. (For those of you running Windows, you can either find the equivalent tools in your development environment, or get Cygwin from www.cygwin.com/. It's fast, free, and powerful.) Two of the most powerful tools for sharing changes to source files are diff and patch.

How many code snippets have you seen that have screens and screens of changes listed like this?

After line 180:

//----------------------------------------------------------

Insert these lines:

if(m_active) {
	target.DoThing();
}

After line 203:

// Now to frobzan the dooflerps:

Remove the 4 lines that read:

frobzan * fptr;
dooflerp * dptr;
for(int i=0; i<NUM_DOOFLERPS; i++) {
	fptr = get_frobzan();
	dptr = get_dooflerp(i);
	frobzan_dooflerp(fptr, dptr);
}

It's pretty boring to read and follow, and even more boring to write... And there's always the possibility of forgetting something important! ("Whoops, I forgot to mention these variable definitions." or "Why isn't this working? I think I made all the changes...")

That layout works pretty well for things that require changing very little code, but if you start making complex changes (for instance, making Torque support space environments), it quickly becomes gargantuan and ugly. A headache to maintain and follow.

Is there hope? Are we stuck forever dealing with these kinds of problems? Maybe we should write some sort of program to extract changes automatically...

In fact, programmers have been fighting with this problem for the last twenty years, and the solution they've come up with is called diff. Originally developed for Unix, most IDEs come with graphical versions.

diff works very simply. You give it two files, and it tells you the differences between 'em. Here's some example output for a file I changed one line in:

$ diff rev0.c rev1.c
4c4
<       printf("Hello world\n");
---
>       printf("Goodbye, world\n");

What does this gobbledygook mean? The first line shows me typing the command in; I told diff to compare rev0.c and rev1.c. Now a line by line analysis:

4c4                                   This is a marker; it says where in the file the change is.
<       printf("Hello world\n");      The line in the original file
---                                   A seperator
>       printf("Goodbye, world\n");   And what the line was changed to.

What if I had change the file and added several lines? No worries; diff handles that just fine. It would have multiple lines after the seperator - for instance:

4c4,6
<       printf("Hello world\n");
---
>       printf("Goodbye, world\n");
>       // Wring pity from user.
>       printf("You done broke my heart.\n");

If there are multiple changed portions in the file, then diff will generate multiple chunks like that as output. So if you want to compare the changes between two chunks of source, you can just run diff on it straight and see what's happening.

Notice that diff is doing the same thing you'd do by hand - but it won't make typos or miss lines, and its format is a lot easier to follow (or skip over!).

What if you have a whole hierarchy of files (like the Torque source tree), and you've made some changes in different places, you're not sure where?

Well, that's pretty easy, too. Here's how you do it. Say you've made some changes for your Monkey Island clone that add fur rendering. Pretty cool feature, huh? And because you're just as cool, you decide to make your fur changes available to all those nice people on the GG site.

The first thing you do is you get a fresh copy of the Torque source from CVS (or wherever else you might like). In fact, you want two copies - an untouched copy and a modified copy with your fur stuff in it. Put 'em in a subdirectory, so that you can readily get to either.

Ok, now go and get your fur changes in. You'll end up with the two copies described above. If you applied any other patches to the modified copy (say, to add suport for that undocumented glFur function you found), note them down and apply them to the untouched copy, too.

You should now have two copies of the Torque source - one ready for the fur stuff, and one with the fur stuff in it. We'll say that the one with fur stuff is in a directory called furry and the one without is in a directory called shaved. Go to the subdirectory the two copies are in, and type:

diff -rd shaved furry

You'll experience deja vu, because every change you made for the furry stuff will go scrolling by. You probably want to save this; go run:

diff -rd shave furry > furry_patch
[code]

And voila! A new file called furry_patch will appear in the subdirectory that has _all_ the information needed for someone to add your fur rendering code.

Well, almost. There's one more step. You need to open furry_patch and look at the top, where you may find lines that look like:

[code]
Only in shaved: render_bumpy.cc
Only in furry: custom/render_fur.cc

This means that diff found files that were only in one branch or the other; you need to include all the "Only in furry" files, and mention to the end user they should consider removing the "Only in shaved" files.

Now you have made it very easy for anyone to see exactly what changes they have to make to get the same l33t fur rendering code you had!

To summarize, you need to give the person applying the patch the following information: what version of the Torque source you started with, what patches you applied first, what files need to be created entirely, and the output of a diff -rd on those two source trees.

Still, it'll be a big pain for them to go and make all those changes by hand... Wouldn't it be nice if there was a tool that could take the output of a [diff]diff[/diff] and apply it to an existing source tree?

There is! It's called patch, and it's pretty bright tool. Here's how to use it:

You first get a body of code roughly equivalent to what the patch-maker started with. For best results, get the exact same version of Torque they started with, apply the same patches, then add their files and apply their patches. That'd be best. Of course, most of the time you want to add the patch after you've done extensive development on a source tree - in that case, make sure you've got all the stuff they depend on (ie, you've either installed the patches already, or you hand-added it).

Then add the files they've given you, and finally run (for our example):

patch -p3 < furry_patch

What does that -p3 do? Well, the file names in the patch file sometimes have big, long paths that don't match up with your system. -pN lets you say, "Trim the first N slashes from all the paths in the patch." For instance, if the paths in the patch file all started with /home/jeff/ (because you want to include some high quality Jeff code in your project), you would say -p3 and it would trim the first three slashes - getting rid of /home/jeff/ entirely.

And there you go. That's how to make and apply patches. I hope it's useful; if you need more knowledge, go check out:

www.gnu.org/manual/diffutils/html_node/index.html - the GNU Foundation docs. Extensive.
unix.about.com/library/weekly/aa040102a.htm - About.com's explanation.
www.cs.ucsb.edu/facilities/software/diff-info/Top.shtml - And UCSB's thoughts on how to use diff and patch.

Also note that diff is integrated into CVS.

Happy patching!

#1
01/03/2005 (3:29 am)
The above links are (mostly) broken, and general "non-linux style human" understanding of the contents of patch files can be a bit difficult when you want to manually apply one, so I added a thread on Manually Applying Patches (HowTo).