]>
Commit | Line | Data |
---|---|---|
d04baaba JV |
1 | /* |
2 | * deps.c | |
3 | * | |
4 | * Copyright (c) 2002-2005 by Judd Vinet <jvinet@zeroflux.org> | |
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 2 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, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
19 | * USA. | |
20 | */ | |
21 | ||
22 | #include <stdlib.h> | |
23 | #include <stdio.h> | |
24 | #include <string.h> | |
25 | /* pacman */ | |
26 | #include "util.h" | |
27 | #include "log.h" | |
4d21e4f7 | 28 | #include "error.h" |
d04baaba JV |
29 | #include "list.h" |
30 | #include "package.h" | |
31 | #include "db.h" | |
32 | #include "cache.h" | |
33 | #include "provide.h" | |
34 | #include "deps.h" | |
35 | #include "rpmvercmp.h" | |
36 | ||
37 | /* Re-order a list of target packages with respect to their dependencies. | |
38 | * | |
7c847fd7 | 39 | * Example (PM_TRANS_TYPE_ADD): |
d04baaba JV |
40 | * A depends on C |
41 | * B depends on A | |
42 | * Target order is A,B,C,D | |
43 | * | |
44 | * Should be re-ordered to C,A,B,D | |
45 | * | |
7c847fd7 AF |
46 | * mode should be either PM_TRANS_TYPE_ADD or PM_TRANS_TYPE_REMOVE. This |
47 | * affects the dependency order sortbydeps() will use. | |
48 | * | |
d04baaba JV |
49 | * This function returns the new PMList* target list. |
50 | * | |
51 | */ | |
7c847fd7 | 52 | PMList *sortbydeps(PMList *targets, int mode) |
d04baaba JV |
53 | { |
54 | PMList *newtargs = NULL; | |
55 | PMList *i, *j, *k; | |
56 | int change = 1; | |
57 | int numscans = 0; | |
58 | int numtargs = 0; | |
59 | int clean = 0; | |
60 | ||
61 | if(targets == NULL) { | |
62 | return(NULL); | |
63 | } | |
64 | ||
65 | /* count the number of targets */ | |
66 | numtargs = pm_list_count(targets); | |
67 | ||
68 | while(change) { | |
69 | change = 0; | |
70 | if(numscans > numtargs) { | |
56917dc3 | 71 | _alpm_log(PM_LOG_WARNING, "possible dependency cycle detected"); |
d04baaba JV |
72 | change = 0; |
73 | continue; | |
74 | } | |
75 | newtargs = NULL; | |
76 | numscans++; | |
77 | /* run thru targets, moving up packages as necessary */ | |
78 | for(i = targets; i; i = i->next) { | |
79 | pmpkg_t *p = (pmpkg_t*)i->data; | |
80 | for(j = p->depends; j; j = j->next) { | |
81 | pmdepend_t dep; | |
82 | int found = 0; | |
83 | pmpkg_t *q = NULL; | |
84 | ||
85 | splitdep(j->data, &dep); | |
86 | /* look for dep.name -- if it's farther down in the list, then | |
87 | * move it up above p | |
88 | */ | |
89 | for(k = i->next; k && !found; k = k->next) { | |
90 | q = (pmpkg_t*)k->data; | |
91 | if(!strcmp(dep.name, q->name)) { | |
92 | found = 1; | |
93 | } | |
94 | } | |
95 | if(found) { | |
96 | if(!pkg_isin(q, newtargs)) { | |
97 | change = 1; | |
98 | newtargs = pm_list_add(newtargs, q); | |
99 | } | |
100 | } | |
101 | } | |
102 | if(!pkg_isin(p, newtargs)) { | |
103 | newtargs = pm_list_add(newtargs, p); | |
104 | } | |
105 | } | |
106 | if(clean && change) { | |
107 | /* free up targets -- it's local now */ | |
0ef95757 | 108 | FREELISTPTR(targets); |
d04baaba JV |
109 | } |
110 | targets = newtargs; | |
111 | clean = 1; | |
112 | } | |
7c847fd7 AF |
113 | if(mode == PM_TRANS_TYPE_REMOVE) { |
114 | /* we're removing packages, so reverse the order */ | |
115 | newtargs = _alpm_list_reverse(targets); | |
116 | /* free the old one */ | |
0ef95757 | 117 | FREELISTPTR(targets); |
7c847fd7 AF |
118 | targets = newtargs; |
119 | } | |
120 | ||
d04baaba JV |
121 | return(targets); |
122 | } | |
123 | ||
124 | /* Returns a PMList* of missing_t pointers. | |
125 | * | |
126 | * conflicts are always name only, but dependencies can include versions | |
127 | * with depmod operators. | |
128 | * | |
129 | */ | |
95ea99e1 | 130 | PMList *checkdeps(pmdb_t *db, unsigned char op, PMList *packages) |
d04baaba JV |
131 | { |
132 | pmpkg_t *info = NULL; | |
133 | pmdepend_t depend; | |
134 | PMList *i, *j, *k; | |
135 | int cmp; | |
136 | int found = 0; | |
137 | PMList *baddeps = NULL; | |
138 | pmdepmissing_t *miss = NULL; | |
139 | ||
140 | if(db == NULL) { | |
141 | return(NULL); | |
142 | } | |
143 | ||
144 | if(op == PM_TRANS_TYPE_UPGRADE) { | |
145 | /* PM_TRANS_TYPE_UPGRADE handles the backwards dependencies, ie, the packages | |
146 | * listed in the requiredby field. | |
147 | */ | |
148 | for(i = packages; i; i = i->next) { | |
406f3831 AF |
149 | pmpkg_t *tp = i->data; |
150 | pmpkg_t *oldpkg; | |
151 | if(tp == NULL) { | |
d04baaba JV |
152 | continue; |
153 | } | |
d04baaba | 154 | |
406f3831 | 155 | if((oldpkg = db_get_pkgfromcache(db, tp->name)) == NULL) { |
d04baaba JV |
156 | continue; |
157 | } | |
158 | for(j = oldpkg->requiredby; j; j = j->next) { | |
159 | char *ver; | |
160 | pmpkg_t *p; | |
161 | found = 0; | |
406f3831 | 162 | if((p = db_get_pkgfromcache(db, j->data)) == NULL) { |
d04baaba JV |
163 | /* hmmm... package isn't installed.. */ |
164 | continue; | |
165 | } | |
166 | if(pkg_isin(p, packages)) { | |
167 | /* this package is also in the upgrade list, so don't worry about it */ | |
168 | continue; | |
169 | } | |
170 | for(k = p->depends; k && !found; k = k->next) { | |
171 | /* find the dependency info in p->depends */ | |
172 | splitdep(k->data, &depend); | |
173 | if(!strcmp(depend.name, oldpkg->name)) { | |
174 | found = 1; | |
175 | } | |
176 | } | |
177 | if(found == 0) { | |
d04baaba JV |
178 | /* look for packages that list depend.name as a "provide" */ |
179 | PMList *provides = _alpm_db_whatprovides(db, depend.name); | |
180 | if(provides == NULL) { | |
181 | /* not found */ | |
182 | continue; | |
183 | } | |
184 | /* we found an installed package that provides depend.name */ | |
61231c9b | 185 | FREELISTPTR(provides); |
d04baaba JV |
186 | } |
187 | found = 0; | |
95ea99e1 | 188 | if(depend.mod == PM_DEP_MOD_ANY) { |
d04baaba JV |
189 | found = 1; |
190 | } else { | |
191 | /* note that we use the version from the NEW package in the check */ | |
192 | ver = strdup(tp->version); | |
193 | if(!index(depend.version,'-')) { | |
194 | char *ptr; | |
195 | for(ptr = ver; *ptr != '-'; ptr++); | |
196 | *ptr = '\0'; | |
197 | } | |
198 | cmp = rpmvercmp(ver, depend.version); | |
199 | switch(depend.mod) { | |
95ea99e1 AF |
200 | case PM_DEP_MOD_EQ: found = (cmp == 0); break; |
201 | case PM_DEP_MOD_GE: found = (cmp >= 0); break; | |
202 | case PM_DEP_MOD_LE: found = (cmp <= 0); break; | |
d04baaba JV |
203 | } |
204 | FREE(ver); | |
205 | } | |
206 | if(!found) { | |
207 | MALLOC(miss, sizeof(pmdepmissing_t)); | |
95ea99e1 | 208 | miss->type = PM_DEP_TYPE_REQUIRED; |
d04baaba | 209 | miss->depend.mod = depend.mod; |
6063424c AF |
210 | STRNCPY(miss->target, p->name, PKG_NAME_LEN); |
211 | STRNCPY(miss->depend.name, depend.name, PKG_NAME_LEN); | |
212 | STRNCPY(miss->depend.version, depend.version, PKG_VERSION_LEN); | |
348cb923 | 213 | if(!pm_list_is_in(miss, baddeps)) { |
d04baaba | 214 | baddeps = pm_list_add(baddeps, miss); |
b7d584fe AF |
215 | } else { |
216 | FREE(miss); | |
d04baaba JV |
217 | } |
218 | } | |
219 | } | |
d04baaba JV |
220 | } |
221 | } | |
222 | if(op == PM_TRANS_TYPE_ADD || op == PM_TRANS_TYPE_UPGRADE) { | |
223 | for(i = packages; i; i = i->next) { | |
224 | pmpkg_t *tp = i->data; | |
225 | if(tp == NULL) { | |
226 | continue; | |
227 | } | |
228 | ||
229 | /* CONFLICTS */ | |
230 | for(j = tp->conflicts; j; j = j->next) { | |
231 | /* check targets against database */ | |
232 | for(k = db_get_pkgcache(db); k; k = k->next) { | |
233 | pmpkg_t *dp = (pmpkg_t *)k->data; | |
234 | if(!strcmp(j->data, dp->name)) { | |
235 | MALLOC(miss, sizeof(pmdepmissing_t)); | |
95ea99e1 AF |
236 | miss->type = PM_DEP_TYPE_CONFLICT; |
237 | miss->depend.mod = PM_DEP_MOD_ANY; | |
d04baaba | 238 | miss->depend.version[0] = '\0'; |
6063424c AF |
239 | STRNCPY(miss->target, tp->name, PKG_NAME_LEN); |
240 | STRNCPY(miss->depend.name, dp->name, PKG_NAME_LEN); | |
348cb923 | 241 | if(!pm_list_is_in(miss, baddeps)) { |
d04baaba | 242 | baddeps = pm_list_add(baddeps, miss); |
b7d584fe AF |
243 | } else { |
244 | FREE(miss); | |
d04baaba JV |
245 | } |
246 | } | |
247 | } | |
248 | /* check targets against targets */ | |
249 | for(k = packages; k; k = k->next) { | |
250 | pmpkg_t *a = (pmpkg_t *)k->data; | |
251 | if(!strcmp(a->name, (char *)j->data)) { | |
252 | MALLOC(miss, sizeof(pmdepmissing_t)); | |
95ea99e1 AF |
253 | miss->type = PM_DEP_TYPE_CONFLICT; |
254 | miss->depend.mod = PM_DEP_MOD_ANY; | |
d04baaba | 255 | miss->depend.version[0] = '\0'; |
6063424c AF |
256 | STRNCPY(miss->target, tp->name, PKG_NAME_LEN); |
257 | STRNCPY(miss->depend.name, a->name, PKG_NAME_LEN); | |
348cb923 | 258 | if(!pm_list_is_in(miss, baddeps)) { |
d04baaba | 259 | baddeps = pm_list_add(baddeps, miss); |
b7d584fe AF |
260 | } else { |
261 | FREE(miss); | |
d04baaba JV |
262 | } |
263 | } | |
264 | } | |
265 | } | |
266 | /* check database against targets */ | |
267 | for(k = db_get_pkgcache(db); k; k = k->next) { | |
268 | info = k->data; | |
269 | for(j = info->conflicts; j; j = j->next) { | |
270 | if(!strcmp((char *)j->data, tp->name)) { | |
271 | MALLOC(miss, sizeof(pmdepmissing_t)); | |
95ea99e1 AF |
272 | miss->type = PM_DEP_TYPE_CONFLICT; |
273 | miss->depend.mod = PM_DEP_MOD_ANY; | |
d04baaba | 274 | miss->depend.version[0] = '\0'; |
6063424c AF |
275 | STRNCPY(miss->target, tp->name, PKG_NAME_LEN); |
276 | STRNCPY(miss->depend.name, info->name, PKG_NAME_LEN); | |
348cb923 | 277 | if(!pm_list_is_in(miss, baddeps)) { |
d04baaba | 278 | baddeps = pm_list_add(baddeps, miss); |
b7d584fe AF |
279 | } else { |
280 | FREE(miss); | |
d04baaba JV |
281 | } |
282 | } | |
283 | } | |
284 | } | |
285 | ||
286 | /* PROVIDES -- check to see if another package already provides what | |
287 | * we offer | |
288 | */ | |
289 | /* XXX: disabled -- we allow multiple packages to provide the same thing. | |
290 | * list packages in conflicts if they really do conflict. | |
291 | for(j = tp->provides; j; j = j->next) { | |
292 | PMList *provs = whatprovides(db, j->data); | |
293 | for(k = provs; k; k = k->next) { | |
294 | if(!strcmp(tp->name, k->data->name)) { | |
295 | // this is the same package -- skip it | |
296 | continue; | |
297 | } | |
298 | // we treat this just like a conflict | |
299 | MALLOC(miss, sizeof(pmdepmissing_t)); | |
95ea99e1 AF |
300 | miss->type = PM_DEP_TYPE_CONFLICT; |
301 | miss->depend.mod = PM_DEP_MOD_ANY; | |
d04baaba | 302 | miss->depend.version[0] = '\0'; |
6063424c AF |
303 | STRNCPY(miss->target, tp->name, PKG_NAME_LEN); |
304 | STRNCPY(miss->depend.name, k->data, PKG_NAME_LEN); | |
d04baaba JV |
305 | if(!pm_list_is_in(baddeps, miss)) { |
306 | baddeps = pm_list_add(baddeps, miss); | |
307 | } | |
308 | k->data = NULL; | |
309 | } | |
61231c9b | 310 | FREELIST(provs); |
d04baaba JV |
311 | }*/ |
312 | ||
313 | /* DEPENDENCIES -- look for unsatisfied dependencies */ | |
314 | for(j = tp->depends; j; j = j->next) { | |
315 | /* split into name/version pairs */ | |
316 | splitdep((char *)j->data, &depend); | |
317 | found = 0; | |
318 | /* check database for literal packages */ | |
319 | for(k = db_get_pkgcache(db); k && !found; k = k->next) { | |
320 | pmpkg_t *p = (pmpkg_t *)k->data; | |
321 | if(!strcmp(p->name, depend.name)) { | |
95ea99e1 | 322 | if(depend.mod == PM_DEP_MOD_ANY) { |
d04baaba JV |
323 | /* accept any version */ |
324 | found = 1; | |
325 | } else { | |
326 | char *ver = strdup(p->version); | |
327 | /* check for a release in depend.version. if it's | |
328 | * missing remove it from p->version as well. | |
329 | */ | |
330 | if(!index(depend.version,'-')) { | |
331 | char *ptr; | |
332 | for(ptr = ver; *ptr != '-'; ptr++); | |
333 | *ptr = '\0'; | |
334 | } | |
335 | cmp = rpmvercmp(ver, depend.version); | |
336 | switch(depend.mod) { | |
95ea99e1 AF |
337 | case PM_DEP_MOD_EQ: found = (cmp == 0); break; |
338 | case PM_DEP_MOD_GE: found = (cmp >= 0); break; | |
339 | case PM_DEP_MOD_LE: found = (cmp <= 0); break; | |
d04baaba JV |
340 | } |
341 | FREE(ver); | |
342 | } | |
343 | } | |
344 | } | |
345 | /* check other targets */ | |
346 | for(k = packages; k && !found; k = k->next) { | |
347 | pmpkg_t *p = (pmpkg_t *)k->data; | |
348 | /* see if the package names match OR if p provides depend.name */ | |
349 | if(!strcmp(p->name, depend.name) || pm_list_is_strin(depend.name, p->provides)) { | |
95ea99e1 | 350 | if(depend.mod == PM_DEP_MOD_ANY) { |
d04baaba JV |
351 | /* accept any version */ |
352 | found = 1; | |
353 | } else { | |
354 | char *ver = strdup(p->version); | |
355 | /* check for a release in depend.version. if it's | |
356 | * missing remove it from p->version as well. | |
357 | */ | |
358 | if(!index(depend.version,'-')) { | |
359 | char *ptr; | |
360 | for(ptr = ver; *ptr != '-'; ptr++); | |
361 | *ptr = '\0'; | |
362 | } | |
363 | cmp = rpmvercmp(ver, depend.version); | |
364 | switch(depend.mod) { | |
95ea99e1 AF |
365 | case PM_DEP_MOD_EQ: found = (cmp == 0); break; |
366 | case PM_DEP_MOD_GE: found = (cmp >= 0); break; | |
367 | case PM_DEP_MOD_LE: found = (cmp <= 0); break; | |
d04baaba JV |
368 | } |
369 | FREE(ver); | |
370 | } | |
371 | } | |
372 | } | |
373 | /* check database for provides matches */ | |
374 | if(!found){ | |
d04baaba JV |
375 | k = _alpm_db_whatprovides(db, depend.name); |
376 | if(k) { | |
377 | /* grab the first one (there should only really be one, anyway) */ | |
85203ff6 | 378 | pmpkg_t *p = k->data; |
95ea99e1 | 379 | if(depend.mod == PM_DEP_MOD_ANY) { |
d04baaba JV |
380 | /* accept any version */ |
381 | found = 1; | |
382 | } else { | |
383 | char *ver = strdup(p->version); | |
384 | /* check for a release in depend.version. if it's | |
385 | * missing remove it from p->version as well. | |
386 | */ | |
387 | if(!index(depend.version,'-')) { | |
388 | char *ptr; | |
389 | for(ptr = ver; *ptr != '-'; ptr++); | |
390 | *ptr = '\0'; | |
391 | } | |
392 | cmp = rpmvercmp(ver, depend.version); | |
393 | switch(depend.mod) { | |
95ea99e1 AF |
394 | case PM_DEP_MOD_EQ: found = (cmp == 0); break; |
395 | case PM_DEP_MOD_GE: found = (cmp >= 0); break; | |
396 | case PM_DEP_MOD_LE: found = (cmp <= 0); break; | |
d04baaba JV |
397 | } |
398 | FREE(ver); | |
399 | } | |
85203ff6 | 400 | FREELISTPTR(k); |
d04baaba | 401 | } |
d04baaba JV |
402 | } |
403 | /* else if still not found... */ | |
404 | if(!found) { | |
405 | MALLOC(miss, sizeof(pmdepmissing_t)); | |
95ea99e1 | 406 | miss->type = PM_DEP_TYPE_DEPEND; |
d04baaba | 407 | miss->depend.mod = depend.mod; |
6063424c AF |
408 | STRNCPY(miss->target, tp->name, PKG_NAME_LEN); |
409 | STRNCPY(miss->depend.name, depend.name, PKG_NAME_LEN); | |
410 | STRNCPY(miss->depend.version, depend.version, PKG_VERSION_LEN); | |
348cb923 | 411 | if(!pm_list_is_in(miss, baddeps)) { |
d04baaba | 412 | baddeps = pm_list_add(baddeps, miss); |
b7d584fe AF |
413 | } else { |
414 | FREE(miss); | |
d04baaba JV |
415 | } |
416 | } | |
417 | } | |
418 | } | |
419 | } else if(op == PM_TRANS_TYPE_REMOVE) { | |
420 | /* check requiredby fields */ | |
421 | for(i = packages; i; i = i->next) { | |
422 | pmpkg_t *tp; | |
423 | if(i->data == NULL) { | |
424 | continue; | |
425 | } | |
426 | tp = (pmpkg_t*)i->data; | |
427 | for(j = tp->requiredby; j; j = j->next) { | |
428 | if(!pm_list_is_strin((char *)j->data, packages)) { | |
429 | MALLOC(miss, sizeof(pmdepmissing_t)); | |
95ea99e1 AF |
430 | miss->type = PM_DEP_TYPE_REQUIRED; |
431 | miss->depend.mod = PM_DEP_MOD_ANY; | |
d04baaba | 432 | miss->depend.version[0] = '\0'; |
6063424c AF |
433 | STRNCPY(miss->target, tp->name, PKG_NAME_LEN); |
434 | STRNCPY(miss->depend.name, (char *)j->data, PKG_NAME_LEN); | |
348cb923 | 435 | if(!pm_list_is_in(miss, baddeps)) { |
d04baaba | 436 | baddeps = pm_list_add(baddeps, miss); |
b7d584fe AF |
437 | } else { |
438 | FREE(miss); | |
d04baaba JV |
439 | } |
440 | } | |
441 | } | |
442 | } | |
443 | } | |
444 | ||
445 | return(baddeps); | |
446 | } | |
447 | ||
d77f8be8 | 448 | int splitdep(char *depstr, pmdepend_t *depend) |
d04baaba JV |
449 | { |
450 | char *str = NULL; | |
451 | char *ptr = NULL; | |
452 | ||
bcfc1244 | 453 | if(depstr == NULL || depend == NULL) { |
d77f8be8 | 454 | return(-1); |
d04baaba JV |
455 | } |
456 | ||
bcfc1244 AF |
457 | depend->mod = 0; |
458 | depend->name[0] = 0; | |
459 | depend->version[0] = 0; | |
460 | ||
d04baaba JV |
461 | str = strdup(depstr); |
462 | ||
463 | if((ptr = strstr(str, ">="))) { | |
95ea99e1 | 464 | depend->mod = PM_DEP_MOD_GE; |
d04baaba | 465 | } else if((ptr = strstr(str, "<="))) { |
95ea99e1 | 466 | depend->mod = PM_DEP_MOD_LE; |
d04baaba | 467 | } else if((ptr = strstr(str, "="))) { |
95ea99e1 | 468 | depend->mod = PM_DEP_MOD_EQ; |
d04baaba JV |
469 | } else { |
470 | /* no version specified - accept any */ | |
95ea99e1 | 471 | depend->mod = PM_DEP_MOD_ANY; |
6063424c | 472 | STRNCPY(depend->name, str, PKG_NAME_LEN); |
d04baaba JV |
473 | } |
474 | ||
475 | if(ptr == NULL) { | |
476 | FREE(str); | |
d77f8be8 | 477 | return(0); |
d04baaba JV |
478 | } |
479 | *ptr = '\0'; | |
6063424c | 480 | STRNCPY(depend->name, str, PKG_NAME_LEN); |
d04baaba | 481 | ptr++; |
95ea99e1 | 482 | if(depend->mod != PM_DEP_MOD_EQ) { |
d04baaba JV |
483 | ptr++; |
484 | } | |
6063424c | 485 | STRNCPY(depend->version, ptr, PKG_VERSION_LEN); |
d04baaba JV |
486 | FREE(str); |
487 | ||
d77f8be8 | 488 | return(0); |
d04baaba JV |
489 | } |
490 | ||
491 | /* return a new PMList target list containing all packages in the original | |
492 | * target list, as well as all their un-needed dependencies. By un-needed, | |
493 | * I mean dependencies that are *only* required for packages in the target | |
494 | * list, so they can be safely removed. This function is recursive. | |
495 | */ | |
496 | PMList* removedeps(pmdb_t *db, PMList *targs) | |
497 | { | |
498 | PMList *i, *j, *k; | |
499 | PMList *newtargs = targs; | |
500 | ||
501 | if(db == NULL) { | |
502 | return(newtargs); | |
503 | } | |
504 | ||
505 | for(i = targs; i; i = i->next) { | |
506 | pmpkg_t *pkg = (pmpkg_t*)i->data; | |
507 | for(j = pkg->depends; j; j = j->next) { | |
508 | pmdepend_t depend; | |
509 | pmpkg_t *dep; | |
510 | int needed = 0; | |
511 | splitdep(j->data, &depend); | |
85203ff6 | 512 | dep = db_get_pkgfromcache(db, depend.name); |
d04baaba JV |
513 | if(pkg_isin(dep, targs)) { |
514 | continue; | |
515 | } | |
516 | /* see if it was explicitly installed */ | |
517 | if(dep->reason == PM_PKG_REASON_EXPLICIT) { | |
56917dc3 | 518 | _alpm_log(PM_LOG_FLOW2, "excluding %s -- explicitly installed", dep->name); |
d04baaba JV |
519 | needed = 1; |
520 | } | |
521 | /* see if other packages need it */ | |
522 | for(k = dep->requiredby; k && !needed; k = k->next) { | |
85203ff6 | 523 | pmpkg_t *dummy = db_get_pkgfromcache(db, k->data); |
d04baaba JV |
524 | if(!pkg_isin(dummy, targs)) { |
525 | needed = 1; | |
526 | } | |
527 | } | |
528 | if(!needed) { | |
85203ff6 AF |
529 | char *name; |
530 | asprintf(&name, "%s-%s", dep->name, dep->version); | |
d04baaba | 531 | /* add it to the target list */ |
85203ff6 | 532 | db_read(db, name, INFRQ_ALL, dep); |
d04baaba JV |
533 | newtargs = pm_list_add(newtargs, dep); |
534 | newtargs = removedeps(db, newtargs); | |
85203ff6 | 535 | FREE(name); |
d04baaba JV |
536 | } |
537 | } | |
538 | } | |
539 | ||
540 | return(newtargs); | |
541 | } | |
542 | ||
543 | /* populates *list with packages that need to be installed to satisfy all | |
3b49720e | 544 | * dependencies (recursive) for syncpkg |
d04baaba JV |
545 | * |
546 | * make sure *list and *trail are already initialized | |
547 | */ | |
4d21e4f7 | 548 | int resolvedeps(pmdb_t *local, PMList *dbs_sync, pmpkg_t *syncpkg, PMList *list, PMList *trail) |
d04baaba JV |
549 | { |
550 | PMList *i, *j; | |
61231c9b | 551 | PMList *targ; |
d04baaba JV |
552 | PMList *deps = NULL; |
553 | ||
c5418ebf AF |
554 | if(local == NULL || dbs_sync == NULL || syncpkg == NULL) { |
555 | return(-1); | |
556 | } | |
4d21e4f7 AF |
557 | |
558 | targ = pm_list_add(NULL, syncpkg); | |
d04baaba | 559 | deps = checkdeps(local, PM_TRANS_TYPE_ADD, targ); |
61231c9b | 560 | FREELISTPTR(targ); |
d04baaba JV |
561 | |
562 | if(deps == NULL) { | |
563 | return(0); | |
564 | } | |
565 | ||
566 | for(i = deps; i; i = i->next) { | |
567 | int found = 0; | |
568 | pmdepmissing_t *miss = i->data; | |
569 | ||
570 | /* XXX: conflicts are now treated specially in the _add and _sync functions */ | |
571 | ||
4d21e4f7 | 572 | /*if(miss->type == PM_DEP_TYPE_CONFLICT) { |
56917dc3 | 573 | _alpm_log(PM_LOG_ERROR, "cannot resolve dependencies for \"%s\" (it conflict with %s)", miss->target, miss->depend.name); |
c5418ebf | 574 | RET_ERR(???, -1); |
d04baaba JV |
575 | } else*/ |
576 | ||
95ea99e1 | 577 | if(miss->type == PM_DEP_TYPE_DEPEND) { |
4d21e4f7 | 578 | pmpkg_t *sync = NULL; |
d04baaba | 579 | /* find the package in one of the repositories */ |
d04baaba | 580 | /* check literals */ |
4d21e4f7 | 581 | for(j = dbs_sync; !sync && j; j = j->next) { |
d04baaba JV |
582 | PMList *k; |
583 | pmdb_t *dbs = j->data; | |
d04baaba JV |
584 | for(k = db_get_pkgcache(dbs); !sync && k; k = k->next) { |
585 | pmpkg_t *pkg = k->data; | |
d04baaba | 586 | if(!strcmp(miss->depend.name, pkg->name)) { |
c5418ebf | 587 | sync = pkg; |
d04baaba JV |
588 | } |
589 | } | |
590 | } | |
d04baaba | 591 | /* check provides */ |
4d21e4f7 | 592 | for(j = dbs_sync; !sync && j; j = j->next) { |
d04baaba | 593 | PMList *provides; |
4d21e4f7 AF |
594 | pmdb_t *dbs = j->data; |
595 | provides = _alpm_db_whatprovides(dbs, miss->depend.name); | |
d04baaba | 596 | if(provides) { |
c5418ebf | 597 | sync = provides->data; |
d04baaba | 598 | } |
4d21e4f7 | 599 | FREELISTPTR(provides); |
d04baaba | 600 | } |
4d21e4f7 AF |
601 | if(sync == NULL) { |
602 | _alpm_log(PM_LOG_ERROR, "cannot resolve dependencies for \"%s\" (\"%s\" is not in the package set", miss->target, miss->depend.name); | |
c5418ebf AF |
603 | pm_errno = PM_ERR_UNRESOLVABLE_DEPS; |
604 | goto error; | |
d04baaba | 605 | } |
d04baaba JV |
606 | found = 0; |
607 | for(j = list; j && !found; j = j->next) { | |
4d21e4f7 AF |
608 | pmpkg_t *tmp = j->data; |
609 | if(tmp && !strcmp(tmp->name, sync->name)) { | |
d04baaba JV |
610 | found = 1; |
611 | } | |
612 | } | |
d04baaba JV |
613 | if(found) { |
614 | /* this dep is already in the target list */ | |
d04baaba JV |
615 | continue; |
616 | } | |
c5418ebf | 617 | _alpm_log(PM_LOG_DEBUG, "resolving %s", sync->name); |
d04baaba JV |
618 | found = 0; |
619 | for(j = trail; j; j = j->next) { | |
4d21e4f7 AF |
620 | pmpkg_t *tmp = j->data; |
621 | if(tmp && !strcmp(tmp->name, sync->name)) { | |
d04baaba JV |
622 | found = 1; |
623 | } | |
624 | } | |
d04baaba | 625 | if(!found) { |
43f4505b AF |
626 | /* check pmo_ignorepkg and pmo_s_ignore to make sure we haven't pulled in |
627 | * something we're not supposed to. | |
628 | */ | |
56917dc3 | 629 | int usedep = 1; |
43f4505b AF |
630 | found = 0; |
631 | /* ORE | |
4d21e4f7 AF |
632 | for(j = handle->ignorepkg; j && !found; j = j->next) { |
633 | if(!strcmp(j->data, sync->name)) { | |
43f4505b AF |
634 | found = 1; |
635 | } | |
636 | } | |
637 | for(j = pmo_s_ignore; j && !found; j = j->next) { | |
638 | if(!strcmp(j->data, sync->pkg->name)) { | |
639 | found = 1; | |
640 | } | |
4d21e4f7 | 641 | }*/ |
43f4505b | 642 | if(found) { |
4d21e4f7 | 643 | /* ORE |
43f4505b | 644 | usedep = yesno("%s requires %s, but it is in IgnorePkg. Install anyway? [Y/n] ", |
4d21e4f7 AF |
645 | miss->target, sync->pkg->name);*/ |
646 | } | |
43f4505b AF |
647 | if(usedep) { |
648 | trail = pm_list_add(trail, sync); | |
4d21e4f7 | 649 | if(resolvedeps(local, dbs_sync, sync, list, trail)) { |
43f4505b AF |
650 | goto error; |
651 | } | |
a94c24c4 | 652 | _alpm_log(PM_LOG_FLOW2, "adding dependency %s-%s", sync->name, sync->version); |
43f4505b AF |
653 | list = pm_list_add(list, sync); |
654 | } else { | |
655 | _alpm_log(PM_LOG_ERROR, "cannot resolve dependencies for \"%s\"", miss->target); | |
656 | pm_errno = PM_ERR_UNRESOLVABLE_DEPS; | |
d04baaba JV |
657 | goto error; |
658 | } | |
d04baaba JV |
659 | } else { |
660 | /* cycle detected -- skip it */ | |
c5418ebf | 661 | _alpm_log(PM_LOG_DEBUG, "dependency cycle detected: %s", sync->name); |
d04baaba JV |
662 | } |
663 | } | |
664 | } | |
665 | ||
666 | FREELIST(deps); | |
667 | ||
d04baaba JV |
668 | return(0); |
669 | ||
670 | error: | |
671 | FREELIST(deps); | |
672 | return(-1); | |
673 | } | |
674 | ||
675 | /* vim: set ts=2 sw=2 noet: */ |