]> git.ipfire.org Git - pakfire.git/blame - src/libpakfire/selector.c
libpakfire: Drop Pool
[pakfire.git] / src / libpakfire / selector.c
CommitLineData
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 38struct _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 47PAKFIRE_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
64PAKFIRE_EXPORT PakfireSelector pakfire_selector_ref(PakfireSelector selector) {
65 selector->nrefs++;
221cc3ce
MT
66
67 return selector;
68}
69
4347c271 70static 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
77PAKFIRE_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
88static 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
104static 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 117PAKFIRE_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 158PAKFIRE_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
171static 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
180static 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 196static 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 217static 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 235static 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 273static 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 294PAKFIRE_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
331finish:
332 if (ret)
333 pakfire_errno = ret;
334
335 queue_free(&queue_selector);
336
337 return ret;
338}