Quick intro to "patch" (Was Re: [SATLUG] patching gcc's source
code?)
Daniel DiPaolo
ddipaolo at strike.homelinux.org
Thu Aug 29 12:53:01 CDT 2002
On Thu, 2002-08-29 at 05:34, _zip wrote:
> I'm in need of help applying a patch to a gcc compiler's source code
>
> I'm doing a gentoo install where the gcc compiler and everything will be
> compiled from source. And I have a patch for gcc that I would like to
> add before compiling it.
>
It comes as a bit of a shock to me that someone would distribute a patch
without having some sort of documentation available (either in the patch
tarball itself or on the site where it is available).
> These are the files in the patch protector-2.95.3-9.tar.gz
>
> protector.dif
> protectonly.dif
> protector.c
> protector.h
>
Rather than explicitly explain how to use patch for this problem I'm
just going to go through a completely trivial example that the "viewers
at home" can follow along with if they want, to sort of give you a feel
for how diff and patch work together.
For starters I just create two files, foo and foobar:
---
echo "foo" > foo
echo -e "foo\nbar" > foobar
---
So foo contains just "foo" and foobar contains a line with "foo" and one
with "bar". Now, to generate the patch to apply to foo in order to make
it like bar, I just use diff:
---
diff -u foo bar > foo.patch
---
The "-u" format performs what is known as a "unidiff", or a "unified
diff", which provides enough context for a program like patch to know
what to do. Most patches are to more than just one file, however, and
some even create/remove files and even patch non-text files. As such,
the usual usage is:
---
diff -Naur gcc-old gcc-new > gcc.patch
---
-N for being able to create new files, -a for patching non-text files,
and the -r for recursing through directories.
Now, assuming the diff files you have are set up properly, you simply
need to run patch with them in the appropriate place. Luckily, patch
has the "--dry-run" option so that you can make sure the patch will
apply cleanly before making modifications to anything. So, let's
examine what a patch file looks like so that you can find out where to
apply it. Here's what my foo.patch contains:
---
[ddipaolo at strike ~/temp]% cat foo.patch
--- foo 2002-08-29 11:31:41.000000000 -0500
+++ foobar 2002-08-29 11:31:54.000000000 -0500
@@ -1 +1,2 @@
foo
+bar
---
The "---" line indicates the original file name and modification time,
and the "+++" line indicates the new file name and modification time.
The "@@" line details what lines they are talking about (I think the
"-1" is the number of different lines, and the "+1,2" is the line range,
but I'm not sure). And lastly the text below is the actual stuff to be
patched. Lines without a "+" or "-" in front are just to assure that
the patch is being applied in the right place.
So, as you expect, the only difference is to add a line that says "bar"
to the file, and that's readily apparent from the patch file contents.
However, what is particularly germane to this discussion is the "---"
file name line because this will help you find _where_ you need to be
when you apply your patch. The filename here will usually contain some
sort of relative path. You need to get to a point in the source where
this relative path applies (normally that's just the root of the source
directory, or right above it). Since they didn't make just one diff
that patches all the files, you may have to descend into the source tree
somewhere to apply the patch more directly.
Once you find the place you want to be, you apply your patch like so
(continuing with the foo->foobar example), first checking the
cleanliness of the patch by using the "--dry-run" option:
---
[ddipaolo at strike ~/temp]% patch --dry-run < foo.patch
patching file foo
[ddipaolo at strike ~/temp]%
---
Getting nothing back is, in true *nix fashion, a Good Thing(TM). It
means it applies cleanly. I'll show you waht it looks like for an
unclean patch by changing the "foo" in foo.patch to "bar" (i.e. giving
it the wrong context).
---
[ddipaolo at strike ~/temp]% patch --dry-run < foo.patch
patching file foo
Hunk #1 succeeded at 1 with fuzz 1.
[ddipaolo at strike ~/temp]%
---
This is deceptive because the actual patch part applied cleanly, though
it seemed to be out of context. For all intents and purposes, for
patches you don't make yourself, this is more or less a failure to apply
since it doesn't apply cleanly (but with "fuzz"). With a bit of
trickery, I've come up with a failed message as well:
---
[ddipaolo at strike ~/temp]% patch --dry-run < foo.patch
patching file foo
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED -- saving rejects to file foo.rej
---
This is an out and out failure, it couldn't even apply the patch (even
with "fuzz"). I just included it so you know what the message looks
like.
So, hopefully you can find out how to apply your patch now (and are
hopefully a bit more enlightened about the diff and patch utils, I know
they can be confusing).
--
Daniel DiPaolo <ddipaolo at strike.homelinux.org>
GnuPG key ID: 0xB2F23FC2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://www.satlug.org/pipermail/satlug/attachments/20020829/0c51c270/attachment-0001.bin
More information about the Satlug
mailing list