How it works
In this chapter, we'll try to explain how autoepatch works, and how to extend it
to patch and fix new problems. Specifically, this chapter is intended to make
maintaining autoepatch much simpler, especially for newcomers, who shouldn't
have to read all the code to understand how it works.
Requirements
Being a package that is going to be in the system set, and used by every user as
a Portage component, autoepatch needs to have the minimum impact over the
dependencies of that set. For this reason, the script is written in bash. As the
targets for Gentoo software are less wide than the general GNU or Open Source
targets, there's no need to use a portable subset of sh (as we already consider
bash present), and it can depend on a few GNU tools, or at least tools that can
support an acceptable subset of GNU parameters.
There are basically two Gentoo-specific dependencies that are needed for
autoepatch: the first is baselayout, as autoepatch loads /sbin/functions.sh to
get functions like ebegin and eend; the other is Portage, as autoepatch uses the
portageq command, and allows the patchsets to use it.
First of all, as most of the patchsets are expected to be actual patch files,
the patch(1) command is supposed to be the GNU patch. While FreeBSD uses Larry
Wall's patch(1) command that supports most of the options that GNU patch
supports, there are some tricky behaviours on fuzzyness of patches. If patch(1)
is not a GNU-compatible implementation, you can provide a GNU patch command
named gpatch that will be prioritised over the normal
patch(1).
Another command on which behaviour the script relies more than just a bit is
find(1). Considering the frequency of execution of the script itself, and thus
of the targeting logic, the script tries to reduce as much as possible the
processes spawned, so instead of using the xargs(1) command to transform the
find(1) output to input arguments to other commands, autoepatch relies on
find(1) to support the -exec cmd {} + syntax.
Fortunately, FreeBSD, Darwin and NetBSD find(1) implementations support the GNU
findutils syntax. OpenBSD on the other hand does not, so to allow autoepatch to
work on that operating system, a special handling for the find command was
written: by replacing the string @findcmd@ with the path,
or the name, of a compatible find implementation (most likely GNU find), you can
tell autoepatch to run an alternative command.
As there is often the need to get a temporary file, either for log or debugging
purposes, or to store intermediate results, the mktemp utility is also required.
Unfortunately, the mktemp utility found on most Linux implementations (Gentoo
Linux included) comes from debianutils package, and has a syntax incompatible
with the original BSD mktemp utility. As the autoepatch script does not get the
USERLAND variable from Portage (and tries to be entirely transparent), the
choice between the two implementations is done at runtime by checking the
outcome of calling mktemp -V. On Debian implementation,
this reports the version of the command itself, while it simply fails on BSD
implementation. The emktemp wrapper is picked up from eutils.eclass.
Concepts
Autoepatch is, basically, a simple set of scripts. The definitions that will be
given here are not even proper "concepts," but this section is intended to clear
up the terminology used, to prevent any misunderstanding in the next sections
and chapters.
patchset
This is a set of scripts and actual patches, and is the base element handled
by autoepatch itself. Despite the name, it's possible that a "patchset" has
no actual ".patch" file, and instead consists of a single shell script that
describes the changes to will be applied to the targets.
The patchsets can be found in the repository inside the patches/ directory,
or for the installed copy in /usr/share/autoepatch/patches.
For alternative prefixes support, see .
target
This is a file or a directory on which the patchset applies. When the target
is a directory, and the patchset contains actual patches, the paths inside
the patches should refer to the direct name of the files starting from the
target directory (-p0 option to gpatch). When the target is a file, the
patch will apply directly over the file. When instead the patchset consist
of a function (or a series of functions), the target is passed as parameter,
whichever the type it is.
For more informations about target, look at .
Whitespaces handling and safety
While there are currently some limitations in ebuilds and in Portage
code that disallow using paths with spaces for important directories
like the merge root, the temporary directory and the portage tree
directory, autoepatch was supposed not to break even if all of them had
all kind of special characters. Unfortunately this is not always
possible, because of limitations in the tools and the language used.
The biggest limitation is provided by bash itself: variables cannot
contain the NULL character, which means that the targets cannot be
passed with the output of find -print0 or grep -Z, so the targets
have to be separated by the \n sequence (new line).
To try minimising the possibility of problems during piping throught
different commands (find, grep and so on), it is suggested to use the
option find $dir -exec cmd {} + rather than using
-print and xargs (this also avoids one process spawn), and if you need
to pass the result of grep -l, also add the --null parameter.
For reasons far from our understanding, FreeBSD people decided to
use the -Z option to GNU grep to support running grep over
gzip-compressed files. For compatibility and portability, rather
than using the -Z option, you should use the --null option in
autoepatch patchsets, which would behave consistently on both Linux
and non-Linux systems.
Alternative prefixes support
At the time of writing, Portage does not officially support a way to install
packages on an alternate prefix (such as /usr/local). However, autoepatch has
been designed from the beginning to support being installed in an arbitrary
prefix.
To install autoepatch on a different prefix, you should just replace
the string @PREFIX@ with the prefix the package
is installed in the file autoepatch.sh.