|
danw@157
|
1 |
We start with two razor_sets, system and upstream, and a list of
|
|
danw@157
|
2 |
requested installations and removals.
|
|
danw@157
|
3 |
|
|
danw@157
|
4 |
FIXME: what about multiple upstream repos? Having to deal with
|
|
danw@157
|
5 |
arbitrary numbers of razor_sets is possible, but will probably be
|
|
danw@157
|
6 |
messy... It might be easier to either store all upstream repo data
|
|
danw@157
|
7 |
in a single .repo file, or else merge all upstream .repo files
|
|
danw@157
|
8 |
together into a single razor_set at startup. (Or some combination
|
|
danw@157
|
9 |
of those.)
|
|
danw@157
|
10 |
|
|
danw@157
|
11 |
We create a bit array of the packages in each set, indicating which
|
|
danw@157
|
12 |
ones are installed; the system bitarray starts out all 1s, and the
|
|
danw@157
|
13 |
upstream bitarray all 0s. Each bit is only allowed to change state
|
|
danw@157
|
14 |
once during the transaction; an installed package can be removed, or
|
|
danw@157
|
15 |
an uninstalled package installed, but trying to reinstall a removed
|
|
danw@157
|
16 |
package, or uninstall a newly-installed package is an error. This
|
|
danw@157
|
17 |
means the packages break down into four categories:
|
|
danw@157
|
18 |
|
|
danw@157
|
19 |
- installed (1 bit in the system bit array)
|
|
danw@157
|
20 |
- to-be-removed (0 bit in the system bit array)
|
|
danw@157
|
21 |
- to-be-installed (1 bit in the upstream bit array)
|
|
danw@157
|
22 |
- installable (0 bit in the upstream bit array)
|
|
danw@157
|
23 |
|
|
danw@157
|
24 |
|
|
danw@157
|
25 |
The depsolver repeats the following three steps until there are no new
|
|
danw@157
|
26 |
requested installs or removals.
|
|
danw@157
|
27 |
|
|
danw@157
|
28 |
New packages phase. Walk the system and upstream package lists in
|
|
danw@157
|
29 |
parallel, and:
|
|
danw@157
|
30 |
|
|
danw@157
|
31 |
- For each package
|
|
danw@157
|
32 |
|
|
danw@157
|
33 |
- If it has newly been added to the requested-installs list,
|
|
danw@157
|
34 |
create a razor_transaction_package for it, and set the
|
|
danw@157
|
35 |
appropriate bit in the upstream bitarray; if it is an
|
|
danw@157
|
36 |
update, clear the appropriate bit in the system bitarray
|
|
danw@157
|
37 |
|
|
danw@157
|
38 |
- If it has newly been added to the requested-removals list,
|
|
danw@157
|
39 |
create a razor_transaction_package for it, and clear the
|
|
danw@157
|
40 |
appropriate bit in the system bitarray
|
|
danw@157
|
41 |
|
|
danw@157
|
42 |
Properties phase. Walk the system and upstream property lists in
|
|
danw@157
|
43 |
parallel, and:
|
|
danw@157
|
44 |
|
|
danw@157
|
45 |
- For each to-be-installed non-file REQUIRES:
|
|
danw@157
|
46 |
|
|
danw@157
|
47 |
- See if there's an installed or to-be-installed package that
|
|
danw@157
|
48 |
PROVIDES that property.
|
|
danw@157
|
49 |
|
|
danw@157
|
50 |
- If not, see if there's an installable package that PROVIDES
|
|
danw@157
|
51 |
that property, and add it to the requested-installs list if
|
|
danw@157
|
52 |
so.
|
|
danw@157
|
53 |
|
|
danw@157
|
54 |
- If not, see if there's a to-be-removed package that PROVIDES
|
|
danw@157
|
55 |
that property. (If we find such a package, we have a
|
|
danw@157
|
56 |
CONTRADICTION error.)
|
|
danw@157
|
57 |
|
|
danw@157
|
58 |
- If none of the above, then we have an UNSATISFIABLE error
|
|
danw@157
|
59 |
|
|
danw@157
|
60 |
- For each to-be-installed file REQUIRES:
|
|
danw@157
|
61 |
|
|
danw@157
|
62 |
- Same as for property REQUIRES, except that since we have to
|
|
danw@157
|
63 |
search the file tree, this is not O(1). (See below for more
|
|
danw@157
|
64 |
discussion.)
|
|
danw@157
|
65 |
|
|
danw@157
|
66 |
- For each to-be-installed PROVIDES:
|
|
danw@157
|
67 |
|
|
danw@157
|
68 |
- Check if the new PROVIDES conflicts with an installed
|
|
danw@157
|
69 |
CONFLICTS. If so, add the installed package to the
|
|
danw@157
|
70 |
requested-installs list, so we can try to upgrade it to a
|
|
danw@157
|
71 |
non-conflicting version.
|
|
danw@157
|
72 |
|
|
danw@157
|
73 |
- Check if the new PROVIDES conflicts with a to-be-installed
|
|
danw@157
|
74 |
CONFLICTS. If so, we have an OLD_CONFLICT error.
|
|
danw@157
|
75 |
|
|
danw@157
|
76 |
- For each to-be-installed CONFLICTS:
|
|
danw@157
|
77 |
|
|
danw@157
|
78 |
- Basically the reverse of the previous case: check if the new
|
|
danw@157
|
79 |
CONFLICTS conflicts with an installed PROVIDES. If so, add
|
|
danw@157
|
80 |
the installed package to the requested-installs list to try
|
|
danw@157
|
81 |
to upgrade it.
|
|
danw@157
|
82 |
|
|
danw@157
|
83 |
- Check if the new CONFLICTS conflicts with a to-be-installed
|
|
danw@157
|
84 |
PROVIDES. If so, we have an NEW_CONFLICT error.
|
|
danw@157
|
85 |
|
|
danw@157
|
86 |
- For each to-be-installed OBSOLETES:
|
|
danw@157
|
87 |
|
|
danw@157
|
88 |
- Check if there's an installed package that PROVIDES that
|
|
danw@157
|
89 |
property. If so, add that package to the requested-removals
|
|
danw@157
|
90 |
list, noting it should be marked obsolete. ("Obsolete" means
|
|
danw@157
|
91 |
that the to-be-removed PROVIDES step below will treat it
|
|
danw@157
|
92 |
like it was upgraded, not removed.)
|
|
danw@157
|
93 |
|
|
danw@157
|
94 |
- If not, check if there's a to-be-installed package that
|
|
danw@157
|
95 |
PROVIDES that property. If so, we have a CONTRADICTION
|
|
danw@157
|
96 |
error.
|
|
danw@157
|
97 |
|
|
danw@157
|
98 |
- For each to-be-removed PROVIDES:
|
|
danw@157
|
99 |
|
|
danw@157
|
100 |
- If there's also an identical to-be-installed PROVIDES, we're
|
|
danw@157
|
101 |
ok and can skip this
|
|
danw@157
|
102 |
|
|
danw@157
|
103 |
- Otherwise, for each installed REQUIRES of this property:
|
|
danw@157
|
104 |
|
|
danw@157
|
105 |
- Look for some other installed or to-be-installed package
|
|
danw@157
|
106 |
that satisfies the REQUIRES.
|
|
danw@157
|
107 |
|
|
danw@157
|
108 |
- If there isn't one, then for each installed package in
|
|
danw@157
|
109 |
this REQUIRES's package list:
|
|
danw@157
|
110 |
|
|
danw@157
|
111 |
- If the PROVIDES was lost because the old package was
|
|
danw@157
|
112 |
removed (not updated or obsoleted), then add the
|
|
danw@157
|
113 |
requiring package to the requested-removals list.
|
|
danw@157
|
114 |
|
|
danw@157
|
115 |
- Otherwise, add the requiring package to the
|
|
danw@157
|
116 |
requested-installs list so it can be updated as
|
|
danw@157
|
117 |
well.
|
|
danw@157
|
118 |
|
|
danw@157
|
119 |
- (We don't need to look at to-be-installed REQUIRES of this
|
|
danw@157
|
120 |
property, because if there are any, they will cause a
|
|
danw@157
|
121 |
CONTRADICTION error when we try to re-satisfy them the next
|
|
danw@157
|
122 |
time through.)
|
|
danw@157
|
123 |
|
|
danw@157
|
124 |
- For each installed file REQUIRES:
|
|
danw@157
|
125 |
|
|
danw@157
|
126 |
- Check that the file is still installed. If not, check if
|
|
danw@157
|
127 |
a to-be-installed package also provides it.
|
|
danw@157
|
128 |
|
|
danw@157
|
129 |
- If not:
|
|
danw@157
|
130 |
|
|
danw@157
|
131 |
- If the package originally providing it was removed (not
|
|
danw@157
|
132 |
updated or obsoleted), then add the requiring package to
|
|
danw@157
|
133 |
the requested-removals list.
|
|
danw@157
|
134 |
|
|
danw@157
|
135 |
- Otherwise, add the requiring package to the
|
|
danw@157
|
136 |
requested-installs list, in the hope that an upgrade
|
|
danw@157
|
137 |
will no longer require the file
|
|
danw@157
|
138 |
|
|
danw@157
|
139 |
(End)
|
|
danw@157
|
140 |
|
|
danw@157
|
141 |
|
|
danw@157
|
142 |
Note on file dependencies
|
|
danw@157
|
143 |
|
|
danw@157
|
144 |
- With this algorithm, the total time spent satisfying file
|
|
danw@157
|
145 |
dependencies is O(D * log F), where D is the total number of
|
|
danw@157
|
146 |
file dependencies being added or removed, and F is the total
|
|
danw@157
|
147 |
number of files.
|
|
danw@157
|
148 |
|
|
danw@157
|
149 |
- If we sorted the file list differently, we could walk it in
|
|
danw@157
|
150 |
parallel with the property lists, resulting in an overall
|
|
danw@157
|
151 |
file-require-satisfying time of O(F). However, F is likely to be
|
|
danw@157
|
152 |
much much greater than D * log F, so this would probably end up
|
|
danw@157
|
153 |
actually being a pessimization.
|
|
danw@157
|
154 |
|
|
danw@157
|
155 |
- A better solution (assuming that we do actually need an O(1)
|
|
danw@157
|
156 |
algorithm here) would be to add explicit file PROVIDES
|
|
danw@157
|
157 |
properties to the set as needed. That is, whenever we add a
|
|
danw@157
|
158 |
package containing a "REQUIRES /foo" property to a set, we also
|
|
danw@157
|
159 |
add a "PROVIDES /foo" property to the set, pointing to the
|
|
danw@157
|
160 |
correct provider packages. More than half of all file requires
|
|
danw@157
|
161 |
are on /bin/sh or /sbin/ldconfig, and of the 7263 file requires
|
|
danw@157
|
162 |
in 9306 packages currently in rawhide.repo, only 154 are not
|
|
danw@157
|
163 |
satisfied by my system.repo. So storing file provides in the
|
|
danw@157
|
164 |
property list as they are needed would eliminate the need to
|
|
danw@157
|
165 |
search through the file list 99% of the time.
|
|
danw@157
|
166 |
|
|
danw@157
|
167 |
(We might need a separate optimization for the
|
|
danw@157
|
168 |
building-the-system-up-from-empty case in the installer, since
|
|
danw@157
|
169 |
we'd be resolving the whole transaction without having explicit
|
|
danw@157
|
170 |
PROVIDES listed for /bin/sh, etc.)
|