]>
Commit | Line | Data |
---|---|---|
221cc3ce MT |
1 | /*############################################################################# |
2 | # # | |
3 | # Pakfire - The IPFire package management system # | |
4 | # Copyright (C) 2013 Pakfire development team # | |
5 | # # | |
6 | # This program is free software: you can redistribute it and/or modify # | |
7 | # it under the terms of the GNU General Public License as published by # | |
8 | # the Free Software Foundation, either version 3 of the License, or # | |
9 | # (at your option) any later version. # | |
10 | # # | |
11 | # This program is distributed in the hope that it will be useful, # | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
14 | # GNU General Public License for more details. # | |
15 | # # | |
16 | # You should have received a copy of the GNU General Public License # | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
18 | # # | |
19 | #############################################################################*/ | |
20 | ||
21 | #include <assert.h> | |
22 | ||
23 | #include <solv/pool.h> | |
24 | #include <solv/queue.h> | |
25 | #include <solv/solver.h> | |
26 | ||
27 | #include <pakfire/errno.h> | |
28 | #include <pakfire/filter.h> | |
4347c271 | 29 | #include <pakfire/logging.h> |
221cc3ce MT |
30 | #include <pakfire/package.h> |
31 | #include <pakfire/packagelist.h> | |
cbed1552 | 32 | #include <pakfire/pakfire.h> |
9f953e68 | 33 | #include <pakfire/private.h> |
221cc3ce MT |
34 | #include <pakfire/selector.h> |
35 | #include <pakfire/types.h> | |
36 | #include <pakfire/util.h> | |
37 | ||
4347c271 | 38 | struct _PakfireSelector { |
cbed1552 | 39 | Pakfire pakfire; |
4347c271 MT |
40 | PakfireFilter f_name; |
41 | PakfireFilter f_provides; | |
42 | PakfireFilter f_evr; | |
43 | PakfireFilter f_arch; | |
44 | int nrefs; | |
45 | }; | |
46 | ||
443d79d5 | 47 | PAKFIRE_EXPORT PakfireSelector pakfire_selector_create(Pakfire pakfire) { |
221cc3ce | 48 | PakfireSelector selector = pakfire_calloc(1, sizeof(*selector)); |
4347c271 MT |
49 | if (selector) { |
50 | DEBUG("Allocated Selector at %p\n", selector); | |
51 | selector->nrefs = 1; | |
52 | ||
443d79d5 | 53 | selector->pakfire = pakfire_ref(pakfire); |
4347c271 MT |
54 | |
55 | selector->f_arch = NULL; | |
56 | selector->f_name = NULL; | |
57 | selector->f_evr = NULL; | |
58 | selector->f_provides = NULL; | |
59 | } | |
60 | ||
61 | return selector; | |
62 | } | |
221cc3ce | 63 | |
4347c271 MT |
64 | PAKFIRE_EXPORT PakfireSelector pakfire_selector_ref(PakfireSelector selector) { |
65 | selector->nrefs++; | |
221cc3ce MT |
66 | |
67 | return selector; | |
68 | } | |
69 | ||
4347c271 | 70 | static void pakfire_selector_free(PakfireSelector selector) { |
443d79d5 | 71 | pakfire_unref(selector->pakfire); |
221cc3ce | 72 | pakfire_free(selector); |
4347c271 MT |
73 | |
74 | DEBUG("Released Selector at %p\n", selector); | |
75 | } | |
76 | ||
77 | PAKFIRE_EXPORT PakfireSelector pakfire_selector_unref(PakfireSelector selector) { | |
78 | if (!selector) | |
79 | return NULL; | |
80 | ||
81 | if (--selector->nrefs > 0) | |
82 | return selector; | |
83 | ||
84 | pakfire_selector_free(selector); | |
85 | return NULL; | |
221cc3ce MT |
86 | } |
87 | ||
88 | static int pakfire_selector_valid_setting(int keyname, int cmp_type) { | |
89 | switch (keyname) { | |
90 | case PAKFIRE_PKG_ARCH: | |
91 | case PAKFIRE_PKG_EVR: | |
92 | case PAKFIRE_PKG_VERSION: | |
93 | case PAKFIRE_PKG_PROVIDES: | |
94 | return cmp_type == PAKFIRE_EQ; | |
95 | ||
96 | case PAKFIRE_PKG_NAME: | |
97 | return (cmp_type == PAKFIRE_EQ || cmp_type == PAKFIRE_GLOB); | |
98 | ||
99 | default: | |
100 | return 0; | |
101 | } | |
102 | } | |
103 | ||
104 | static void pakfire_selector_replace_filter(PakfireFilter* filter, int keyname, int cmp_type, const char* match) { | |
105 | if (*filter) | |
106 | pakfire_filter_free(*filter); | |
107 | ||
108 | PakfireFilter f = pakfire_filter_create(); | |
109 | ||
110 | f->keyname = keyname; | |
111 | f->cmp_type = cmp_type; | |
112 | f->match = pakfire_strdup(match); | |
113 | ||
114 | *filter = f; | |
115 | } | |
116 | ||
9f953e68 | 117 | PAKFIRE_EXPORT int pakfire_selector_set(PakfireSelector selector, int keyname, int cmp_type, const char* match) { |
221cc3ce MT |
118 | if (!pakfire_selector_valid_setting(keyname, cmp_type)) |
119 | return PAKFIRE_E_SELECTOR; | |
120 | ||
121 | PakfireFilter* filter = NULL; | |
122 | ||
123 | switch (keyname) { | |
124 | case PAKFIRE_PKG_ARCH: | |
125 | filter = &selector->f_arch; | |
126 | break; | |
127 | ||
128 | case PAKFIRE_PKG_EVR: | |
129 | case PAKFIRE_PKG_VERSION: | |
130 | filter = &selector->f_evr; | |
131 | break; | |
132 | ||
133 | case PAKFIRE_PKG_NAME: | |
134 | if (selector->f_provides) | |
135 | return PAKFIRE_E_SELECTOR; | |
136 | ||
137 | filter = &selector->f_name; | |
138 | break; | |
139 | ||
140 | case PAKFIRE_PKG_PROVIDES: | |
141 | if (selector->f_name) | |
142 | return PAKFIRE_E_SELECTOR; | |
143 | ||
144 | filter = &selector->f_provides; | |
145 | break; | |
146 | ||
147 | default: | |
148 | return PAKFIRE_E_SELECTOR; | |
149 | } | |
150 | ||
151 | assert(filter); | |
152 | ||
153 | pakfire_selector_replace_filter(filter, keyname, cmp_type, match); | |
154 | ||
155 | return 0; | |
156 | } | |
157 | ||
9f953e68 | 158 | PAKFIRE_EXPORT PakfirePackageList pakfire_selector_providers(PakfireSelector selector) { |
221cc3ce MT |
159 | Queue q; |
160 | queue_init(&q); | |
161 | ||
162 | pakfire_selector2queue(selector, &q, 0); | |
163 | ||
cbed1552 | 164 | PakfirePackageList list = pakfire_packagelist_from_queue(selector->pakfire, &q); |
221cc3ce MT |
165 | |
166 | queue_free(&q); | |
167 | ||
168 | return list; | |
169 | } | |
170 | ||
171 | static int queue_has(Queue* queue, Id what, Id id) { | |
172 | for (int i = 0; i < queue->count; i += 2) { | |
173 | if (queue->elements[i] == what && queue->elements[i + 1] == id) | |
174 | return 1; | |
175 | } | |
176 | ||
177 | return 0; | |
178 | } | |
179 | ||
180 | static Id str2archid(Pool* pool, const char* arch) { | |
181 | // originally from libsolv/examples/solv.c:str2archid() | |
182 | ||
183 | if (!*arch) | |
184 | return 0; | |
185 | ||
186 | Id id = pool_str2id(pool, arch, 0); | |
187 | if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH) | |
188 | return id; | |
189 | ||
190 | if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id])) | |
191 | return 0; | |
192 | ||
193 | return id; | |
194 | } | |
195 | ||
443d79d5 | 196 | static int filter_arch2queue(Pakfire pakfire, const PakfireFilter f, Queue* queue) { |
221cc3ce MT |
197 | if (f == NULL) |
198 | return 0; | |
199 | ||
200 | assert(f->cmp_type == PAKFIRE_EQ); | |
201 | ||
443d79d5 MT |
202 | Pool* pool = pakfire_get_solv_pool(pakfire); |
203 | Id archid = str2archid(pool, f->match); | |
221cc3ce MT |
204 | if (archid == 0) |
205 | return PAKFIRE_E_ARCH; | |
206 | ||
207 | for (int i = 0; i < queue->count; i += 2) { | |
221cc3ce | 208 | Id dep = queue->elements[i + 1]; |
443d79d5 MT |
209 | |
210 | queue->elements[i + 1] = pool_rel2id(pool, dep, archid, REL_ARCH, 1); | |
221cc3ce MT |
211 | queue->elements[i] |= SOLVER_SETARCH; |
212 | } | |
213 | ||
214 | return 0; | |
215 | } | |
216 | ||
443d79d5 | 217 | static int filter_evr2queue(Pakfire pakfire, const PakfireFilter f, Queue* queue) { |
221cc3ce MT |
218 | if (f == NULL) |
219 | return 0; | |
220 | ||
221 | assert(f->cmp_type == PAKFIRE_EQ); | |
222 | ||
443d79d5 MT |
223 | Pool* pool = pakfire_get_solv_pool(pakfire); |
224 | Id evr = pool_str2id(pool, f->match, 1); | |
221cc3ce MT |
225 | |
226 | for (int i = 0; i < queue->count; i += 2) { | |
221cc3ce | 227 | Id dep = queue->elements[i + 1]; |
443d79d5 | 228 | queue->elements[i + 1] = pool_rel2id(pool, dep, evr, REL_EQ, 1); |
221cc3ce MT |
229 | queue->elements[i] |= PAKFIRE_PKG_VERSION ? SOLVER_SETEV : SOLVER_SETEVR; |
230 | } | |
231 | ||
232 | return 0; | |
233 | } | |
234 | ||
443d79d5 | 235 | static int filter_name2queue(Pakfire pakfire, const PakfireFilter f, Queue* queue) { |
221cc3ce MT |
236 | if (f == NULL) |
237 | return 0; | |
238 | ||
443d79d5 | 239 | Pool* pool = pakfire_get_solv_pool(pakfire); |
221cc3ce MT |
240 | const char* name = f->match; |
241 | Id id; | |
242 | Dataiterator di; | |
243 | ||
244 | switch (f->cmp_type) { | |
245 | case PAKFIRE_EQ: | |
443d79d5 | 246 | id = pool_str2id(pool, name, 0); |
221cc3ce MT |
247 | if (id) |
248 | queue_push2(queue, SOLVER_SOLVABLE_NAME, id); | |
249 | break; | |
250 | ||
251 | case PAKFIRE_GLOB: | |
443d79d5 | 252 | dataiterator_init(&di, pool, 0, 0, SOLVABLE_NAME, name, SEARCH_GLOB); |
221cc3ce MT |
253 | |
254 | while (dataiterator_step(&di)) { | |
221cc3ce MT |
255 | Id id = *di.idp; |
256 | ||
257 | if (queue_has(queue, SOLVABLE_NAME, id)) | |
258 | continue; | |
259 | ||
260 | queue_push2(queue, SOLVER_SOLVABLE_NAME, id); | |
261 | } | |
262 | ||
263 | dataiterator_free(&di); | |
264 | break; | |
265 | ||
266 | default: | |
221cc3ce MT |
267 | return 1; |
268 | } | |
269 | ||
270 | return 0; | |
271 | } | |
272 | ||
443d79d5 | 273 | static int filter_provides2queue(Pakfire pakfire, const PakfireFilter f, Queue* queue) { |
221cc3ce MT |
274 | if (f == NULL) |
275 | return 0; | |
276 | ||
443d79d5 | 277 | Pool* pool = pakfire_get_solv_pool(pakfire); |
221cc3ce MT |
278 | Id id; |
279 | ||
280 | switch (f->cmp_type) { | |
281 | case PAKFIRE_EQ: | |
443d79d5 | 282 | id = pool_str2id(pool, f->match, 0); |
221cc3ce MT |
283 | if (id) |
284 | queue_push2(queue, SOLVER_SOLVABLE_PROVIDES, id); | |
285 | break; | |
286 | ||
287 | default: | |
221cc3ce MT |
288 | return 1; |
289 | } | |
290 | ||
291 | return 0; | |
292 | } | |
293 | ||
9f953e68 | 294 | PAKFIRE_EXPORT int pakfire_selector2queue(const PakfireSelector selector, Queue* queue, int solver_action) { |
221cc3ce MT |
295 | int ret = 0; |
296 | ||
297 | Queue queue_selector; | |
298 | queue_init(&queue_selector); | |
299 | ||
300 | if (selector->f_name == NULL && selector->f_provides == NULL) { | |
301 | // no name or provides in the selector is an erro | |
302 | ret = PAKFIRE_E_SELECTOR; | |
303 | goto finish; | |
304 | } | |
305 | ||
cbed1552 | 306 | pakfire_pool_apply_changes(selector->pakfire); |
221cc3ce | 307 | |
443d79d5 | 308 | ret = filter_name2queue(selector->pakfire, selector->f_name, &queue_selector); |
221cc3ce MT |
309 | if (ret) |
310 | goto finish; | |
311 | ||
443d79d5 | 312 | ret = filter_provides2queue(selector->pakfire, selector->f_provides, &queue_selector); |
221cc3ce MT |
313 | if (ret) |
314 | goto finish; | |
315 | ||
443d79d5 | 316 | ret = filter_arch2queue(selector->pakfire, selector->f_arch, &queue_selector); |
221cc3ce MT |
317 | if (ret) |
318 | goto finish; | |
319 | ||
443d79d5 | 320 | ret = filter_evr2queue(selector->pakfire, selector->f_evr, &queue_selector); |
221cc3ce MT |
321 | if (ret) |
322 | goto finish; | |
323 | ||
324 | for (int i = 0; i < queue_selector.count; i += 2) { | |
325 | queue_push2(queue, | |
326 | queue_selector.elements[i] | solver_action, | |
327 | queue_selector.elements[i + 1] | |
328 | ); | |
329 | } | |
330 | ||
331 | finish: | |
332 | if (ret) | |
333 | pakfire_errno = ret; | |
334 | ||
335 | queue_free(&queue_selector); | |
336 | ||
337 | return ret; | |
338 | } |