Patches
There is no fixed rule for patch naming. The following are guidelines only.
Small patches (less than, say, a few KBytes) should be added to
${FILESDIR}
. If you anticipate having several patches, it often
helps to create version numbered subdirectories — ${FILESDIR}/${PV}/
is conventional. Patches are best named ${P}-what-it-does.patch
(or
.diff
), where what-it-does
is a two or three word
description of what the patch is for. If the patch is to fix a
specific bug, it is often useful to add in the bug number — for
example, vim-7.0-cron-vars-79981.patch
. If the patch is pulled from
upstream's VCS repository, it can help to include the revision
number in the patch name as a suffix to the version part —
fluxbox-0.9.12-3860-menu-backups.patch
.
Larger patches should be
mirrored, preferably on the Gentoo Infrastructure. When
mirroring patches, choosing a name that will not cause conflicts is
important — the ${P}
prefix is highly recommended
here. Mirrored patches are often compressed with xz
or
bzip2
. Remember to list these patches in SRC_URI
. Please
see The files directory
for more information.
${FILESDIR}
should never be compressed.
-p1
.
Although it can be overridden with a eapply -p<strip_level>
command, it is highly recommended to adapt the patch itself to work
with the -p1
default.
If a package requires many patches, even if they are individually small, it is often best to create a patch tarball to avoid cluttering up the tree too much.
Patch descriptions
It is possible to include a description with a patch. This is often helpful when others come to work with your packages, or, indeed when you come back to take a look at your own package a few months later. Good things to include in comments are:
- What the patch actually does. Bug numbers are good here.
- Where the patch came from. For example, is it from an upstream VCS, something from Bugzilla, or something you wrote?
- Whether the patch has been sent upstream, if applicable.
To include the description, simply insert it at the top of the patch
file. The patch
tool will ignore leading text until it finds
something that looks like it might be a 'start patching' instruction,
so as long as each description line starts with letters (rather than
numbers, symbols or whitespace) there shouldn't be a
problem. Alternatively, prefix each description line with a hash
(that's #
, or 'pound' to the USians) sign. It's also best to
leave a single blank line after the description and before the main
patch.
Here's a simple example (023_all_vim-6.3-apache-83565.patch
)
from the vim
patch tarball:
# Detect Gentoo apache files properly. Gentoo bug 83565. --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -93,6 +93,9 @@ " Gentoo apache config file locations (Gentoo bug #76713) au BufNewFile,BufRead /etc/apache2/conf/*/* setf apache +" More Gentoo apache config file locations (Gentoo bug #83565) +au BufNewFile,BufRead /etc/apache2/{modules,vhosts}.d/*.conf setf apache + " XA65 MOS6510 cross assembler au BufNewFile,BufRead *.a65 setf a65
Conditional patching
Patching is ideally only done to make the package in question build properly, and should not be done to modify the runtime behaviour of the package. This is what USE flags and features of the package are for. As such, it is preferable to apply patches unconditionally and avoid conditional patching.
There are a number of reasons to avoid conditional patching:
- It may go unnoticed that a patch fails to apply, if a package is not being tested with a given flag
- More variance is introduced and problems with a package can become much more difficult to debug
- Patches should preferably be upstreamed, but conditional patches cannot
Consider the following example src_prepare()
implementation:
src_prepare() {
if use threads; then
PATCHES+=( "${FILESDIR}"/${P}-mt.patch )
fi
default
}
As this patch is only applied when USE="threads"
is set, any developer
creating new versions of this package might not detect whether the patch applies
successfully if they don't test with the same flag.
Although conditional patching is discouraged it can be unavoidable and as such, it is not considered a banned practice, but, to the extent possible, patches should be written such that they affect behaviour correctly based on e.g. build time definitions and configuration options rather than USE flags directly. This allows them to be applied unconditionally.
Clean patch howto
"Clean patch" does not refer to the patch itself (as in the changes it makes to the source code). It refers to all the metadata that exists in the patch to make it "maintainable".
Why
This may take more effort "up front", but the amount of effort that it saves for everyone else in the future more than makes up for it. This refers to other distributions or upstream maintainers who read the patch, or future Gentoo maintainers. By keeping all patches "clean", people can quickly and easily assess a patch without searching through many other files.
File naming
Your patch name should be short and to the point. When doing a file listing
(e.g., ls files/
), it's a lot easier to be able to scan for relevant
patches when they have good keywords in their file names.
It should also include the package name and the version it was written against.
This way, people searching for patches or who happen to just stumble across the
file itself have a clue as to what it's for. Stripping out the ${PN}
(and to a lesser extent, the ${PV}
) makes the filename significantly
less useful. The fact the files are typically stored in
${CATEGORY}/${PN}/files/
is irrelevant, because the patch may be used
outside Gentoo.
How
Here's a check list of things to keep in the patch header:
-
External references
- Upstream mailing archives
- Upstream bug reports
- Upstream commit links
- Upstream ChangeLog entries
- Gentoo bug reports
-
Short/medium explanation
- Why is the patch needed?
- What is it fixing?
- Why is it fixing it the way it is?
- Proposal for better fixes in the future?
- Is it a stop gap measure (workaround)?
- How was it regression tested?
-
Examples of before/after behaviour
- How to reproduce bug without patch
- How to show bug is fixed after patch
- Maybe upstream fixed it in a different way, so this test can be used to show that the patch is no longer needed with newer versions
-
Status
- Was it merged/rejected/postponed/etc. upstream?
- Is it distribution-specific?
-
Attribution
- Who found the bug?
- Who fixed the bug?
- Who wrote the patch?
- Who tested the patch?
- Who gave advice on the patch?
All this information should be in the patch itself. It should never be found in something like the ebuild. If you really want to put a comment next to a patch in an ebuild, then this is about the only thing that is OK (where 93671 is the Gentoo bug number):
PATCHES=(
"${FILESDIR}"/${P}-dont-umask.patch #93671
)
When documenting these things, it might be useful to use RFC822/Git-style tags to format the metadata. So when documenting the author, use:
From: Nice Person <[email protected]>
Or when documenting relevant URLs, use something like:
Bug: https://upstream.example.com/12345 Bug: https://bugs.gentoo.org/9889
And if you want to note your copyright signoff, slap on a Signed-off-by tag:
Signed-off-by: Diligent Developer <[email protected]>
Finally, your patch should be clear of useless cruft. If it was not taken
straight from an upstream SCM (git format-patch
or svn diff -r #
or cvs diff -r 1.123 -r 1.124
), then the metadata is useless. So delete
it. This refers to things like the diff command used to produce the patch,
or the timestamps on the files, local revision info, or other similar spam.
Note that the context info (the stuff that comes after the @@
) should
be left, as that can be invaluable when applying patches to later versions.
For example:
@@ -80,6 +82,7 @@ case $sys in ^^^^^^^^^^^^ keep this part
Extra points if you make the filename in the ---
/+++
section
consistent and sane. That is, remove different leading backup/paths/
and .orig
/.new
suffixes. Your patch should be in the -p1
format because this tends to be much more standard than any other -p#
.
It is also what eapply
understands by default. A good suggestion is to
use either a/
and b/
(as in git format-patch
) or the
package name/version as the leading portion that gets stripped.
Also note that patch
uses the timestamp info in order to remove empty
files automatically. Alternatively, you can specify the -E
option with
eapply
if you want to remove an empty file.
Removed lines should not appear in the patch because they are commented —
just remove them entirely. Patches show removed lines by prefixing them with
a -
, so no information is lost by simply deleting lines rather than
commenting them out (which adds noise). This makes the patch shorter and
more readable.
The following function (for your interactive shell, not for the ebuild) will help deleting these things:
scrub_patch() {
sed -i \
-e '/^index /d' \
-e '/^new file mode /d' \
-e '/^Index:/d' \
-e '/^=========/d' \
-e '/^RCS file:/d' \
-e '/^retrieving/d' \
-e '/^diff/d' \
-e '/^Files .* differ$/d' \
-e '/^Only in /d' \
-e '/^Common subdirectories/d' \
-e '/^deleted file mode [0-9]*$/d' \
-e '/^+++/s:\t.*::' \
-e '/^---/s:\t.*::' \
"$@"
}
scrub_patch some-patch-you-found.patch
Examples
This shows a simple explanation and a URL for more info (this patch could do
with some attribution however). No metadata exists from running the diff
command (timestamps, etc.).
Fixes compilation in FreeBSD. https://bugs.gentoo.org/138123 --- man-1.6d/gencat/genlib.c +++ man-1.6d/gencat/genlib.c @@ -54,7 +54,7 @@ #include <unistd.h> #endif -#ifndef __linux__ +#if !defined(__linux__) && !defined(__FreeBSD__) #include <memory.h> static int bcopy(src, dst, length) char *src, *dst;
Don't force umask to 022 or the -o umask option doesn't work. Patch by Daniel Drake. https://bugs.gentoo.org/93671 --- mount/mount.c +++ mount/mount.c @@ -1491,8 +1491,6 @@ main(int argc, char *argv[]) { if ((p = strrchr(progname, '/')) != NULL) progname = p+1; - umask(022); - /* People report that a mount called from init without console writes error messages to /etc/mtab Let us try to avoid getting fd's 0,1,2 */
Don't let target flags bleed into build flags. Fix by Bertrand Jacquin. https://bugs.gentoo.org/226035 --- netem/Makefile +++ netem/Makefile @@ -2,6 +2,7 @@ DISTGEN = maketable normal pareto paretonormal DISTDATA = normal.dist pareto.dist paretonormal.dist experimental.dist HOSTCC ?= $(CC) +CCOPTS = $(CBUILD_CFLAGS) LDLIBS += -lm all: $(DISTGEN) $(DISTDATA)