1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
<chapter id="howitworks">
<title>How it works</title>
<para>
In this chapter, we'll try to explain how autoepatch works, and how to
extend it to patch and fix new problems. The reason to provide a
throughout documentation about this is to make the maintainership of
autoepatch simpler, so that if the developers currently involved in
its writing would not be available, newcomers won't have to read all
the code to find how it actually works.
</para>
<sect1 id="requirements">
<title>Requirements</title>
<para>
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 a bash script. 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.
</para>
<para>
There are basically two Gentoo specific softwares that are needed for
autoepatch: the first is baselayout, as autoepatch loads
/sbin/functions.sh to get functions like ebegin and eend, and
similar; the other is Portage, as autoepatch uses the portageq
command, and allows to the patchsets to use it.
</para>
<para>
First of all, as most of the patchsets are expected to be actual patch
files, the patch(1) command is supposed to be coming from GNU
project. 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 <emphasis>gpatch</emphasis> that will be prioritised over the
normal patch(1).
</para>
<para>
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 targetting logic, the script tries to reduce
as much as possible the processes spawn, so instead of using xargs(1)
command to transform the find(1) output to input arguments to other
commands, autoepatch relies on find(1) to support the <emphasis>-exec
cmd {} +</emphasis> syntax.
</para>
<para>
Luckily not only GNU findutils, but also FreeBSD, Darwin and NetBSD find(1)
implementations support that 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 <emphasis>@findcmd@</emphasis> with the path, or the name, of a
compatible find implementation (most likely GNU find), you can tell
autoepatch to run an alternative command.
</para>
<para>
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 to that
matter, the choice between the two implementations is done at runtime
by checking the outcome of calling <emphasis>mktemp -V</emphasis>; 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.
</para>
</sect1>
<sect1 id="concepts">
<title>Concepts</title>
<para>
There aren't many concepts to describe on autoepatch because it is,
basically, a simple set of scripts. The definitions that will be given
here are not even proper "concepts" but this section is intented to
clear up the terminology used, so that there can't be misunderstanding
in the next sections and chapters.
</para>
<variablelist>
<varlistentry>
<term>patchset</term>
<listitem>
<para>
With this term, the documentation will refer to a set of scripts
and actual patches, the base element handled by autoepatch itself.
Despite the name used seem to limit a patchset to just patches,
it's well possible that a patchset has no actual ".patch" file,
and instead consist of a single shell script that describes the
changes to apply to targets.
</para>
<para>
The patchsets can be found in the repository inside the patches
directory, or for the installed copy in
/usr/share/autoepatch/patches
<footnote><para>
For alternative prefixes support, see <xref
linkend="prefixsupport" />.
</para></footnote>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>target</term>
<listitem>
<para>
Under this name we consider a file, or a directory, on which the
patchset applies. When the target is a directory, ad 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 instead, 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.
</para>
<para>
For more informations about target, look at <xref
linkend="writingpatchsets" />.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect1>
<sect1 id="whitespaces">
<title>Whitespaces handling and safety</title>
<para>
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.
</para>
<para>
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).
</para>
<para>
To try minimising the possibility of problems during piping throught
different commands (find, grep and so on), it is suggested to use the
option <emphasis>find $dir -exec cmd {} +</emphasis> 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.
</para>
<warning>
<para>
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.
</para>
</warning>
</sect1>
<sect1 id="prefixsupport">
<title>Alternative prefixes support</title>
<para>
Although Portage, at the time of writing, it's limited to work as a
primary package manager and does not support officially a way to
install packages on an alternate prefix (like /usr/local or something
else), autoepatch is designed to support being installed in an
arbitrary prefix from day one.
</para>
<para>
To install autoepatch on a different prefix, you should just replace
the string <emphasis>@PREFIX@</emphasis> with the prefix the package
is installed in the file autoepatch.sh.
</para>
</sect1>
</chapter>
|