-
Notifications
You must be signed in to change notification settings - Fork 24
/
mediated-links.txt
269 lines (202 loc) · 11.6 KB
/
mediated-links.txt
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
Problem Statement
=================
It's common to want multiple versions of a component installed on a system.
In order for this to work, each version must have no coincident pathnames.
For most pathnames, it's easy to put them in a versioned directory or give
them a versioned name. But for some frequently used pathnames (an
executable expected to be in $PATH, or a man page), it's highly convenient
to provide an unversioned path (possibly as a link to a versioned path) for
casual use.
This of course leads to a conflict when multiple component versions all
want to provide the same unversioned path. We need a mechanism by which we
can manage these paths.
The most typical desired behavior for these paths is that they refer to the
latest version available; that is, if component foo has versions 1.2, 1.3,
and 1.4 installed, then unversioned pathnames for foo should refer to the
1.4 version. However, there may be reasons that the package vendor, the
site administrator, or even the local system administrator may want to
override this choice. Since properly written code uses the versioned
pathnames, the reference should be allowed to switch at arbitrary times.
Another related problem is the delivery of different components which
provide similar functionality. This differs from the previously stated
problem in that the components don't share the same versioning space, and
so need a different namespace from which the desired component can be
chosen.
Finally, a versioned component may also have different implementations
(indeed, there may be multiple implementation axes), so we need to handle
both problems at once.
Proposal
========
We assert that this problem can be restricted to pathnames which can be
replaced by symbolic links. Although a solution could apply to other
filesystem entry types, the implementations would be significantly more
difficult, and likely wouldn't provide any real benefit.
To that, we introduce the notion of "mediated links", being symlinks or
hardlinks which are subject -- when necessary -- to mediation in the case of
conflict. Mediated links are link or hardlink actions with some extra metadata
that allows the packaging system to treat conflicts specially.
The one required attribute is "mediator", whose value denotes the entry in
the namespace shared by all the pathnames participating in a given
mediation group. For instance, the mediator attribute value for all
/usr/bin/python and /usr/share/man/man1/python.1 links might be "python".
The value of this attribute must be an alphanumeric string.
For a link mediated solely by version, the "mediator-version" attribute is
required. This is the version (expressed as a dot-separated sequence of
nonnegative integers) of the interface described by the "mediator"
attribute, and not necessarily related to the version of the implementation
delivered by the package, or by the version in the package FMRI. For
instance, links participating in the "python" mediation might have
"mediator-version" set to "2.4", "2.6", "3.2", etc.
When resolving the conflict in mediated links, pkg(5) will normally choose
the link with the greatest value of "mediator-version". The package vendor
may override this selection by adding the attribute "mediator-priority"
with the value "vendor" to its preferred link in a package it delivers.
Similarly, site administrators may override the selection by version or the
vendor override by adding the attribute "mediator-priority" with the value
"site" to its preferred link. The local system administrator may override
this selection with the commandline specified below.
Mediation may be performed by implementation in addition to or instead of
by version. In this case, the attribute is "mediator-implementation" and
the value must be a string containing only alphanumeric characters and '-'
(preferably short and descriptive). Implementation strings are not considered
to be ordered, and so one must be chosen explicitly, or the system will choose
arbitrarily (first in lexical order). As with versioned mediation,
"mediator-priority=vendor" and "mediator-priority=site" can be used to override
the default behavior, and the local administrator can set the preference
explicitly.
If the implementation itself can be or is versioned, then the value may
have a '@' and a version appended to it. If multiple versions of an
implementation exist, the default will be to choose the greatest as defined
by those versions, similarly to the purely version-mediated scenario.
By default, every time a package operation is performed, the "best" mediation
will be selected and then applied to all packages. However, the local
administrator may explicitly set both the version and implementation for a
mediation, or only one of them, in which case the system will select the "best"
mediation with the matching component.
All links delivered to a given pathname must participate in mediation or not
at all. If some links delivered to a given pathname are mediated, and some
are not, package operations will fail with a conflicting error message. Likewise,
all mediated links delivered to a given pathname must share the same mediator.
However, not all mediator versions and implementations need to provide a link at
a given path. If a version and/or implementation doesn't provide a link, then the
link is removed when that version is selected.
The commandline used for locally administering mediated links is as
follows:
- pkg set-mediator [-V <version>] [-I <implementation>] mediator ...
Sets the mediator <mediator> to a given version and/or implementation.
- pkg unset-mediator [-V] [-I] mediator ...
Reverts the mediator <mediator> to the system default. If the -V option is
supplied, revert the version-mediated aspect to the system default, but leave
the implementation mediation in place. If the -I option is supplied,
revert the implementation-mediated aspect to the system default, but
leave the version mediation in place. If neither -V or -I are specified,
both the version and implementation will be reverted to the system default.
- pkg mediator [<mediator> ...]
Display information about the mediators on the system. When one or
more mediators are specified, display information only about the specified
mediators. The information should include the mediator name, selected
version and implementation, and how each component was chosen by the system.
Examples
========
Mediation by version
--------------------
The canonical case for version mediation is a language platform. In this
case, we'll investigate Python. Two paths that might be mediated are the
python interpreter executable and its manpage. The runtime/python-26
package would deliver
file path=usr/bin/python2.6 ...
file path=usr/share/man/man1/python2.6.1 ...
link path=usr/bin/python target=python2.6 mediator=python \
mediator-version=2.6
link path=usr/share/man/man1/python.1 target=python2.6.1 mediator=python \
mediator-version=2.6
and the runtime/python-24 package would deliver
file path=usr/bin/python2.4 ...
file path=usr/share/man/man1/python2.4.1 ...
link path=usr/bin/python target=python2.4 mediator=python \
mediator-version=2.4
link path=usr/share/man/man1/python.1 target=python2.4.1 mediator=python \
mediator-version=2.4
If only runtime/python-26 were installed, then /usr/bin/python would be
linked to python2.6. Likewise, if only runtime/python-24 were installed,
then /usr/bin/python would be linked to python2.4. If both were installed,
then by default, 2.6 would be found to be greater than 2.4, and the link
would point to python2.6.
If the vendor of the two packages wished, they could deliver a package
"runtime/python" which would simply have a dependency on the desired
default version.
If the local administrator preferred /usr/bin/python to be version 2.4,
then she could run
pkg set-mediator -V 2.4 python
after which running "python" would run the 2.4 interpreter, and "man
python" would display the manual for the 2.4 interpreter.
Vendor override
---------------
If, in the above scenario, the vendor of runtime/python-26 and
runtime/python-24 wished to override the default behavior and have the 2.4
interpreter be the default, then the runtime/python-24 package would
deliver
file path=usr/bin/python2.4 ...
file path=usr/share/man/man1/python2.4.1 ...
link path=usr/bin/python target=python2.4 mediator=python \
mediator-version=2.4 mediator-priority=vendor
link path=usr/share/man/man1/python.1 target=python2.4.1 mediator=python \
mediator-version=2.4 mediator-priority=vendor
Thus in the case where both runtime/python-26 and runtime/python-24 were
installed, /usr/bin/python would point to python2.4, despite 2.6 being
greater than 2.4. The "runtime/python" package would likely then contain a
a dependency on "runtime/python-24". The local administrator could
override this choice to 2.6 by running
pkg set-mediator -V 2.6 python
Mediation by implementation
---------------------------
The canonical case for implementation mediation is the editor vi. There
are multiple implementations of vi, but there is no versioned specification
which each implements. We will examine vim, nvi, and the legacy Solaris
vi.
In the package editor/vim, we deliver
file path=usr/bin/vim
link path=usr/bin/vi target=vim mediator=vi mediator-implementation=vim
In the package editor/svr4-vi, we deliver
file path=usr/has/bin/vi
link path=usr/bin/vi target=../has/bin/vi mediator=vi mediator-implementation=svr4
And in the package editor/nvi, we deliver
file path=usr/bin/nvi
link path=usr/bin/vi target=nvi mediator=vi mediator-implementation=nvi
If editor/vim were installed on the system without either of the others,
then /usr/bin/vi would point to vim. If either of the other packages were
later added, the /usr/bin/vi would continue to run vim, until the local
administrator were to run
pkg set-mediator -I svr4 vi
which would switch the link to run legacy Solaris vi. If the packages were
all installed simultaneously, the link would be chosen arbitrarily. The
vendor ought to deliver a vendor priority tag:
link path=usr/bin/vi target=vim mediator=vi mediator-implementation=vim \
mediator-priority=vendor
so that the desired default is always chosen.
Mediation with multiple implementations
---------------------------------------
Vim can be configured with a handful of different compile-time options.
For this example, we'll focus on --with-features=tiny (the minimal
configuration) and --with-features=huge (the maximal configuration, sans
GUI and external languages).
As before, we deliver the package editor/svr4-vi:
file path=usr/has/bin/vi
link path=usr/bin/vi target=../has/bin/vi mediator=vi mediator-implementation=svr4
We deliver two vim packages -- one for tiny, one for huge -- with a new
"vim" implementation-based mediator, set to "tiny" for the tiny package and
"huge" for the huge package. In addition, an implementation-based mediated
link is delivered to /usr/bin/vi which targets vim if the vi mediator is
set to vim. Since these two actions are identical, there is no conflict.
Here is vim-tiny:
file path=usr/bin/vim-tiny
link path=usr/bin/vim target=vim-tiny mediator=vim mediator-implementation=tiny
link path=usr/bin/vi target=vim mediator=vi mediator-implementation=vim
and editor/vim-huge:
file path=usr/bin/vim-huge
link path=usr/bin/vim target=vim-huge mediator=vim mediator-implementation=huge
link path=usr/bin/vi target=vim mediator=vi mediator-implementation=vim
Thus to ensure that /usr/bin/vi is the huge vim, the administrator would
have to run
pkg set-mediator -I huge vim
pkg set-mediator -I vim vi