4 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
5 * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
6 * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
7 * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
33 #include <limits.h> /* PATH_MAX */
40 #include "alpm_list.h"
51 #include "versioncmp.h"
60 pmsyncpkg_t
*_alpm_sync_new(int type
, pmpkg_t
*spkg
, void *data
)
66 if((sync
= (pmsyncpkg_t
*)malloc(sizeof(pmsyncpkg_t
))) == NULL
) {
67 _alpm_log(PM_LOG_ERROR
, _("malloc failure: could not allocate %d bytes"), sizeof(pmsyncpkg_t
));
78 void _alpm_sync_free(void *data
)
80 pmsyncpkg_t
*sync
= data
;
88 if(sync
->type
== PM_SYNC_TYPE_REPLACE
) {
89 FREELISTPKGS(sync
->data
);
96 /* Find recommended replacements for packages during a sync.
97 * (refactored from _alpm_sync_prepare)
99 static int find_replacements(pmtrans_t
*trans
, pmdb_t
*db_local
,
100 alpm_list_t
*dbs_sync
)
102 alpm_list_t
*i
, *j
, *k
; /* wow */
106 /* check for "recommended" package replacements */
107 _alpm_log(PM_LOG_DEBUG
, _("checking for package replacements"));
108 for(i
= dbs_sync
; i
; i
= i
->next
) {
109 pmdb_t
*db
= i
->data
;
111 /* for each db, check each package's REPLACES list */
112 for(j
= _alpm_db_get_pkgcache(db
); j
; j
= j
->next
) {
113 pmpkg_t
*spkg
= j
->data
;
115 for(k
= alpm_pkg_get_replaces(spkg
); k
; k
= k
->next
) {
116 const char *replacement
= k
->data
;
118 pmpkg_t
*lpkg
= _alpm_db_get_pkgfromcache(db_local
, replacement
);
123 _alpm_log(PM_LOG_DEBUG
, _("checking replacement '%s' for package '%s'"), replacement
, spkg
->name
);
124 if(alpm_list_find_str(handle
->ignorepkg
, lpkg
->name
)) {
125 _alpm_log(PM_LOG_WARNING
, _("%s-%s: ignoring package upgrade (to be replaced by %s-%s)"),
126 alpm_pkg_get_name(lpkg
), alpm_pkg_get_version(lpkg
),
127 alpm_pkg_get_name(spkg
), alpm_pkg_get_version(spkg
));
129 /* get confirmation for the replacement */
131 QUESTION(trans
, PM_TRANS_CONV_REPLACE_PKG
, lpkg
, spkg
, db
->treename
, &doreplace
);
134 /* if confirmed, add this to the 'final' list, designating 'lpkg' as
135 * the package to replace.
138 pmpkg_t
*dummy
= _alpm_pkg_new(alpm_pkg_get_name(lpkg
), NULL
);
140 pm_errno
= PM_ERR_MEMORY
;
143 dummy
->requiredby
= alpm_list_strdup(alpm_pkg_get_requiredby(lpkg
));
144 /* check if spkg->name is already in the packages list. */
145 sync
= _alpm_sync_find(trans
->packages
, alpm_pkg_get_name(spkg
));
147 /* found it -- just append to the replaces list */
148 sync
->data
= alpm_list_add(sync
->data
, dummy
);
150 /* none found -- enter pkg into the final sync list */
151 sync
= _alpm_sync_new(PM_SYNC_TYPE_REPLACE
, spkg
, NULL
);
154 pm_errno
= PM_ERR_MEMORY
;
157 sync
->data
= alpm_list_add(NULL
, dummy
);
158 trans
->packages
= alpm_list_add(trans
->packages
, sync
);
160 _alpm_log(PM_LOG_DEBUG
, _("%s-%s elected for upgrade (to be replaced by %s-%s)"),
161 alpm_pkg_get_name(lpkg
), alpm_pkg_get_version(lpkg
),
162 alpm_pkg_get_name(spkg
), alpm_pkg_get_version(spkg
));
173 /* TODO reimplement this in terms of alpm_get_upgrades */
174 int _alpm_sync_sysupgrade(pmtrans_t
*trans
, pmdb_t
*db_local
, alpm_list_t
*dbs_sync
)
180 /* check for "recommended" package replacements */
181 if(find_replacements(trans
, db_local
, dbs_sync
) == 0) {
182 /* match installed packages with the sync dbs and compare versions */
183 _alpm_log(PM_LOG_DEBUG
, _("checking for package upgrades"));
184 for(i
= _alpm_db_get_pkgcache(db_local
); i
; i
= i
->next
) {
186 pmpkg_t
*local
= i
->data
;
187 pmpkg_t
*spkg
= NULL
;
190 for(j
= dbs_sync
; !spkg
&& j
; j
= j
->next
) {
191 spkg
= _alpm_db_get_pkgfromcache(j
->data
, alpm_pkg_get_name(local
));
194 _alpm_log(PM_LOG_DEBUG
, _("'%s' not found in sync db -- skipping"), alpm_pkg_get_name(local
));
198 /* we don't care about a to-be-replaced package's newer version */
199 for(j
= trans
->packages
; j
&& !replace
; j
=j
->next
) {
201 if(sync
->type
== PM_SYNC_TYPE_REPLACE
) {
202 if(_alpm_pkg_find(alpm_pkg_get_name(spkg
), sync
->data
)) {
208 _alpm_log(PM_LOG_DEBUG
, _("'%s' is already elected for removal -- skipping"),
209 alpm_pkg_get_name(local
));
213 /* compare versions and see if we need to upgrade */
214 if(alpm_pkg_compare_versions(local
, spkg
)) {
215 _alpm_log(PM_LOG_DEBUG
, _("%s-%s elected for upgrade (%s => %s)"),
216 alpm_pkg_get_name(local
), alpm_pkg_get_version(local
),
217 alpm_pkg_get_name(spkg
), alpm_pkg_get_version(spkg
));
218 if(!_alpm_sync_find(trans
->packages
, alpm_pkg_get_name(spkg
))) {
219 /* If package is in the ignorepkg list, ask before we add it to
221 if(alpm_list_find_str(handle
->ignorepkg
, alpm_pkg_get_name(local
))) {
223 QUESTION(trans
, PM_TRANS_CONV_INSTALL_IGNOREPKG
, local
, NULL
, NULL
, &resp
);
228 pmpkg_t
*tmp
= _alpm_pkg_dup(local
);
232 sync
= _alpm_sync_new(PM_SYNC_TYPE_UPGRADE
, spkg
, tmp
);
237 trans
->packages
= alpm_list_add(trans
->packages
, sync
);
245 /* if we're here, it's an error */
249 int _alpm_sync_addtarget(pmtrans_t
*trans
, pmdb_t
*db_local
, alpm_list_t
*dbs_sync
, char *name
)
251 char targline
[PKG_FULLNAME_LEN
];
255 pmpkg_t
*spkg
= NULL
;
261 ASSERT(db_local
!= NULL
, RET_ERR(PM_ERR_DB_NULL
, -1));
262 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
263 ASSERT(name
!= NULL
, RET_ERR(PM_ERR_WRONG_ARGS
, -1));
265 STRNCPY(targline
, name
, PKG_FULLNAME_LEN
);
266 targ
= strchr(targline
, '/');
270 _alpm_log(PM_LOG_DEBUG
, _("searching for target in repo '%s'"), targ
);
271 for(j
= dbs_sync
; j
&& !spkg
; j
= j
->next
) {
272 pmdb_t
*db
= j
->data
;
273 if(strcmp(db
->treename
, targline
) == 0) {
275 spkg
= _alpm_db_get_pkgfromcache(db
, targ
);
277 /* Search provides */
278 _alpm_log(PM_LOG_DEBUG
, _("target '%s' not found -- looking for provisions"), targ
);
279 alpm_list_t
*p
= _alpm_db_whatprovides(db
, targ
);
281 RET_ERR(PM_ERR_PKG_NOT_FOUND
, -1);
283 _alpm_log(PM_LOG_DEBUG
, _("found '%s' as a provision for '%s'"), p
->data
, targ
);
284 spkg
= _alpm_db_get_pkgfromcache(db
, p
->data
);
290 _alpm_log(PM_LOG_ERROR
, _("repository '%s' not found"), targline
);
291 RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND
, -1);
295 for(j
= dbs_sync
; j
&& !spkg
; j
= j
->next
) {
296 pmdb_t
*db
= j
->data
;
297 spkg
= _alpm_db_get_pkgfromcache(db
, targ
);
300 /* Search provides */
301 _alpm_log(PM_LOG_DEBUG
, _("target '%s' not found -- looking for provisions"), targ
);
302 for(j
= dbs_sync
; j
&& !spkg
; j
= j
->next
) {
303 pmdb_t
*db
= j
->data
;
304 alpm_list_t
*p
= _alpm_db_whatprovides(db
, targ
);
306 _alpm_log(PM_LOG_DEBUG
, _("found '%s' as a provision for '%s'"), p
->data
, targ
);
307 spkg
= _alpm_db_get_pkgfromcache(db
, p
->data
);
315 RET_ERR(PM_ERR_PKG_NOT_FOUND
, -1);
318 local
= _alpm_db_get_pkgfromcache(db_local
, alpm_pkg_get_name(spkg
));
320 if(alpm_pkg_compare_versions(local
, spkg
) == 0) {
321 /* spkg is NOT an upgrade, get confirmation before adding */
323 if(alpm_list_find_str(handle
->ignorepkg
, alpm_pkg_get_name(local
))) {
324 QUESTION(trans
, PM_TRANS_CONV_INSTALL_IGNOREPKG
, local
, NULL
, NULL
, &resp
);
328 } else if(!(trans
->flags
& PM_TRANS_FLAG_PRINTURIS
)) {
329 QUESTION(trans
, PM_TRANS_CONV_LOCAL_UPTODATE
, local
, NULL
, NULL
, &resp
);
331 _alpm_log(PM_LOG_WARNING
, _("%s-%s is up to date -- skipping"),
332 alpm_pkg_get_name(local
), alpm_pkg_get_version(local
));
339 /* add the package to the transaction */
340 if(!_alpm_sync_find(trans
->packages
, alpm_pkg_get_name(spkg
))) {
341 pmpkg_t
*dummy
= NULL
;
343 dummy
= _alpm_pkg_new(alpm_pkg_get_name(local
),
344 alpm_pkg_get_version(local
));
346 RET_ERR(PM_ERR_MEMORY
, -1);
349 sync
= _alpm_sync_new(PM_SYNC_TYPE_UPGRADE
, spkg
, dummy
);
352 RET_ERR(PM_ERR_MEMORY
, -1);
354 _alpm_log(PM_LOG_DEBUG
, _("adding target '%s' to the transaction set"),
355 alpm_pkg_get_name(spkg
));
356 trans
->packages
= alpm_list_add(trans
->packages
, sync
);
362 /* Helper functions for alpm_list_remove
364 static int syncpkg_cmp(const void *s1
, const void *s2
)
366 pmsyncpkg_t
*sp1
= (pmsyncpkg_t
*)s1
;
367 pmsyncpkg_t
*sp2
= (pmsyncpkg_t
*)s2
;
370 p1
= alpm_sync_get_pkg(sp1
);
371 p2
= alpm_sync_get_pkg(sp2
);
373 return(strcmp(alpm_pkg_get_name(p1
), alpm_pkg_get_name(p2
)));
376 int _alpm_sync_prepare(pmtrans_t
*trans
, pmdb_t
*db_local
, alpm_list_t
*dbs_sync
, alpm_list_t
**data
)
378 alpm_list_t
*deps
= NULL
;
379 alpm_list_t
*list
= NULL
; /* list allowing checkdeps usage with data from trans->packages */
380 alpm_list_t
*trail
= NULL
; /* breadcrumb list to avoid running into circles */
381 alpm_list_t
*asked
= NULL
;
382 alpm_list_t
*i
, *j
, *k
, *l
;
387 ASSERT(db_local
!= NULL
, RET_ERR(PM_ERR_DB_NULL
, -1));
388 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
394 for(i
= trans
->packages
; i
; i
= i
->next
) {
395 pmsyncpkg_t
*sync
= i
->data
;
396 list
= alpm_list_add(list
, sync
->pkg
);
399 if(!(trans
->flags
& PM_TRANS_FLAG_NODEPS
)) {
400 /* Resolve targets dependencies */
401 EVENT(trans
, PM_TRANS_EVT_RESOLVEDEPS_START
, NULL
, NULL
);
402 _alpm_log(PM_LOG_DEBUG
, _("resolving target's dependencies"));
403 for(i
= trans
->packages
; i
; i
= i
->next
) {
404 pmpkg_t
*spkg
= ((pmsyncpkg_t
*)i
->data
)->pkg
;
405 if(_alpm_resolvedeps(db_local
, dbs_sync
, spkg
, list
, trail
, trans
, data
) == -1) {
406 /* pm_errno is set by resolvedeps */
412 for(i
= list
; i
; i
= i
->next
) {
413 /* add the dependencies found by resolvedeps to the transaction set */
414 pmpkg_t
*spkg
= i
->data
;
415 if(!_alpm_sync_find(trans
->packages
, alpm_pkg_get_name(spkg
))) {
416 pmsyncpkg_t
*sync
= _alpm_sync_new(PM_SYNC_TYPE_DEPEND
, spkg
, NULL
);
421 trans
->packages
= alpm_list_add(trans
->packages
, sync
);
422 _alpm_log(PM_LOG_DEBUG
, _("adding package %s-%s to the transaction targets"),
423 alpm_pkg_get_name(spkg
), alpm_pkg_get_version(spkg
));
425 /* remove the original targets from the list if requested */
426 if((trans
->flags
& PM_TRANS_FLAG_DEPENDSONLY
)) {
431 pkgname
= alpm_pkg_get_name(spkg
);
432 _alpm_log(PM_LOG_DEBUG
, "removing package %s-%s from the transaction targets",
433 pkgname
, alpm_pkg_get_version(spkg
));
435 sync
= _alpm_sync_find(trans
->packages
, pkgname
);
436 trans
->packages
= alpm_list_remove(trans
->packages
, sync
, syncpkg_cmp
, &vpkg
);
442 /* re-order w.r.t. dependencies */
444 for(i
=trans
->packages
; i
; i
=i
->next
) {
445 pmsyncpkg_t
*s
= (pmsyncpkg_t
*)i
->data
;
446 k
= alpm_list_add(k
, s
->pkg
);
448 k
= _alpm_sortbydeps(k
, PM_TRANS_TYPE_ADD
);
449 for(i
=k
; i
; i
=i
->next
) {
450 for(j
=trans
->packages
; j
; j
=j
->next
) {
451 pmsyncpkg_t
*s
= (pmsyncpkg_t
*)j
->data
;
452 if(s
->pkg
==i
->data
) {
453 l
= alpm_list_add(l
, s
);
458 FREELISTPTR(trans
->packages
);
461 EVENT(trans
, PM_TRANS_EVT_RESOLVEDEPS_DONE
, NULL
, NULL
);
463 _alpm_log(PM_LOG_DEBUG
, _("looking for unresolvable dependencies"));
464 deps
= _alpm_checkdeps(trans
, db_local
, PM_TRANS_TYPE_UPGRADE
, list
);
470 pm_errno
= PM_ERR_UNSATISFIED_DEPS
;
478 /* We don't care about conflicts if we're just printing uris */
479 if(!(trans
->flags
& (PM_TRANS_FLAG_NOCONFLICTS
| PM_TRANS_FLAG_PRINTURIS
))) {
480 /* check for inter-conflicts and whatnot */
481 EVENT(trans
, PM_TRANS_EVT_INTERCONFLICTS_START
, NULL
, NULL
);
483 _alpm_log(PM_LOG_DEBUG
, _("looking for conflicts"));
484 deps
= _alpm_checkconflicts(db_local
, list
);
488 for(i
= deps
; i
&& !errorout
; i
= i
->next
) {
489 pmdepmissing_t
*miss
= i
->data
;
494 _alpm_log(PM_LOG_DEBUG
, _("package '%s' conflicts with '%s'"),
495 miss
->target
, miss
->depend
.name
);
497 /* check if the conflicting package is one that's about to be removed/replaced.
498 * if so, then just ignore it
500 for(j
= trans
->packages
; j
&& !found
; j
= j
->next
) {
502 if(sync
->type
== PM_SYNC_TYPE_REPLACE
) {
503 if(_alpm_pkg_find(miss
->depend
.name
, sync
->data
)) {
509 _alpm_log(PM_LOG_DEBUG
, _("'%s' is already elected for removal -- skipping"),
514 sync
= _alpm_sync_find(trans
->packages
, miss
->target
);
516 _alpm_log(PM_LOG_DEBUG
, _("'%s' not found in transaction set -- skipping"),
520 local
= _alpm_db_get_pkgfromcache(db_local
, miss
->depend
.name
);
521 /* check if this package also "provides" the package it's conflicting with
523 if(alpm_list_find_str(alpm_pkg_get_provides(sync
->pkg
), miss
->depend
.name
)) {
524 /* so just treat it like a "replaces" item so the REQUIREDBY
525 * fields are inherited properly.
527 _alpm_log(PM_LOG_DEBUG
, _("package '%s' provides its own conflict"), miss
->target
);
529 /* nothing to do for now: it will be handled later
530 * (not the same behavior as in pacman 2.x) */
534 /* hmmm, depend.name isn't installed, so it must be conflicting
535 * with another package in our final list. For example:
537 * pacman -S blackbox xfree86
539 * If no x-servers are installed and blackbox pulls in xorg, then
540 * xorg and xfree86 will conflict with each other. In this case,
541 * we should follow the user's preference and rip xorg out of final,
542 * opting for xfree86 instead.
545 /* figure out which one was requested in targets. If they both were,
546 * then it's still an unresolvable conflict. */
547 target
= alpm_list_find_str(trans
->targets
, miss
->target
);
548 depend
= alpm_list_find_str(trans
->targets
, miss
->depend
.name
);
549 if(depend
&& !target
) {
550 _alpm_log(PM_LOG_DEBUG
, _("'%s' is in the target list -- keeping it"),
552 /* remove miss->target */
553 rmpkg
= miss
->target
;
554 } else if(target
&& !depend
) {
555 _alpm_log(PM_LOG_DEBUG
, _("'%s' is in the target list -- keeping it"),
557 /* remove miss->depend.name */
558 rmpkg
= miss
->depend
.name
;
560 /* miss->depend.name is not needed, miss->target already provides
561 * it, let's resolve the conflict */
562 rmpkg
= miss
->depend
.name
;
565 pmsyncpkg_t
*rsync
= _alpm_sync_find(trans
->packages
, rmpkg
);
567 _alpm_log(PM_LOG_DEBUG
, _("removing '%s' from target list"), rsync
->pkg
->name
);
568 trans
->packages
= alpm_list_remove(trans
->packages
, rsync
, syncpkg_cmp
, &vpkg
);
574 /* It's a conflict -- see if they want to remove it
576 _alpm_log(PM_LOG_DEBUG
, _("resolving package '%s' conflict"), miss
->target
);
579 if(!alpm_list_find_str(asked
, miss
->depend
.name
)) {
580 QUESTION(trans
, PM_TRANS_CONV_CONFLICT_PKG
, miss
->target
, miss
->depend
.name
, NULL
, &doremove
);
581 asked
= alpm_list_add(asked
, strdup(miss
->depend
.name
));
583 pmsyncpkg_t
*rsync
= _alpm_sync_find(trans
->packages
, miss
->depend
.name
);
584 pmpkg_t
*q
= _alpm_pkg_new(miss
->depend
.name
, NULL
);
592 q
->requiredby
= alpm_list_strdup(alpm_pkg_get_requiredby(local
));
593 if(sync
->type
!= PM_SYNC_TYPE_REPLACE
) {
594 /* switch this sync type to REPLACE */
595 sync
->type
= PM_SYNC_TYPE_REPLACE
;
598 /* append to the replaces list */
599 _alpm_log(PM_LOG_DEBUG
, _("electing '%s' for removal"), miss
->depend
.name
);
600 sync
->data
= alpm_list_add(sync
->data
, q
);
602 /* remove it from the target list */
604 _alpm_log(PM_LOG_DEBUG
, _("removing '%s' from target list"), miss
->depend
.name
);
605 trans
->packages
= alpm_list_remove(trans
->packages
, rsync
, syncpkg_cmp
, &vpkg
);
610 _alpm_log(PM_LOG_ERROR
, _("unresolvable package conflicts detected"));
613 if((miss
= (pmdepmissing_t
*)malloc(sizeof(pmdepmissing_t
))) == NULL
) {
614 _alpm_log(PM_LOG_ERROR
, _("malloc failure: could not allocate %d bytes"), sizeof(pmdepmissing_t
));
616 pm_errno
= PM_ERR_MEMORY
;
620 *miss
= *(pmdepmissing_t
*)i
->data
;
621 *data
= alpm_list_add(*data
, miss
);
626 _alpm_log(PM_LOG_ERROR
, _("unresolvable package conflicts detected"));
629 if((miss
= (pmdepmissing_t
*)malloc(sizeof(pmdepmissing_t
))) == NULL
) {
630 _alpm_log(PM_LOG_ERROR
, _("malloc failure: could not allocate %d bytes"), sizeof(pmdepmissing_t
));
632 pm_errno
= PM_ERR_MEMORY
;
636 *miss
= *(pmdepmissing_t
*)i
->data
;
637 *data
= alpm_list_add(*data
, miss
);
642 pm_errno
= PM_ERR_CONFLICTING_DEPS
;
649 EVENT(trans
, PM_TRANS_EVT_INTERCONFLICTS_DONE
, NULL
, NULL
);
654 /* XXX: this fails for cases where a requested package wants
655 * a dependency that conflicts with an older version of
656 * the package. It will be removed from final, and the user
657 * has to re-request it to get it installed properly.
659 * Not gonna happen very often, but should be dealt with...
662 if(!(trans
->flags
& PM_TRANS_FLAG_NODEPS
)) {
663 /* Check dependencies of packages in rmtargs and make sure
664 * we won't be breaking anything by removing them.
665 * If a broken dep is detected, make sure it's not from a
666 * package that's in our final (upgrade) list.
668 /*EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);*/
669 for(i
= trans
->packages
; i
; i
= i
->next
) {
670 pmsyncpkg_t
*sync
= i
->data
;
671 if(sync
->type
== PM_SYNC_TYPE_REPLACE
) {
672 for(j
= sync
->data
; j
; j
= j
->next
) {
673 list
= alpm_list_add(list
, j
->data
);
678 _alpm_log(PM_LOG_DEBUG
, _("checking dependencies of packages designated for removal"));
679 deps
= _alpm_checkdeps(trans
, db_local
, PM_TRANS_TYPE_REMOVE
, list
);
682 for(i
= deps
; i
; i
= i
->next
) {
683 pmdepmissing_t
*miss
= i
->data
;
684 if(!_alpm_sync_find(trans
->packages
, miss
->depend
.name
)) {
687 /* If miss->depend.name depends on something that miss->target and a
688 * package in final both provide, then it's okay... */
689 pmpkg_t
*leavingp
= _alpm_db_get_pkgfromcache(db_local
, miss
->target
);
690 pmpkg_t
*conflictp
= _alpm_db_get_pkgfromcache(db_local
, miss
->depend
.name
);
691 if(!leavingp
|| !conflictp
) {
692 _alpm_log(PM_LOG_ERROR
, _("something has gone horribly wrong"));
696 /* Look through the upset package's dependencies and try to match one up
697 * to a provisio from the package we want to remove */
698 for(k
= alpm_pkg_get_depends(conflictp
); k
&& !pfound
; k
= k
->next
) {
700 for(m
= alpm_pkg_get_provides(leavingp
); m
&& !pfound
; m
= m
->next
) {
701 if(!strcmp(k
->data
, m
->data
)) {
702 /* Found a match -- now look through final for a package that
703 * provides the same thing. If none are found, then it truly
704 * is an unresolvable conflict. */
706 for(n
= trans
->packages
; n
&& !pfound
; n
= n
->next
) {
707 pmsyncpkg_t
*sp
= n
->data
;
708 pmpkg_t
*sppkg
= sp
->pkg
;
709 for(o
= alpm_pkg_get_provides(sppkg
); o
&& !pfound
; o
= o
->next
) {
710 if(!strcmp(m
->data
, o
->data
)) {
711 /* found matching provisio -- we're good to go */
712 _alpm_log(PM_LOG_DEBUG
, _("found '%s' as a provision for '%s' -- conflict aborted"),
713 alpm_pkg_get_name(sppkg
), (char *)o
->data
);
726 if((miss
= (pmdepmissing_t
*)malloc(sizeof(pmdepmissing_t
))) == NULL
) {
727 _alpm_log(PM_LOG_ERROR
, _("malloc failure: could not allocate %d bytes"), sizeof(pmdepmissing_t
));
729 pm_errno
= PM_ERR_MEMORY
;
733 *miss
= *(pmdepmissing_t
*)i
->data
;
734 *data
= alpm_list_add(*data
, miss
);
740 pm_errno
= PM_ERR_UNSATISFIED_DEPS
;
747 /*EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);*/
751 /* check for free space only in case the packages will be extracted */
752 if(!(trans
->flags
& PM_TRANS_FLAG_NOCONFLICTS
)) {
753 if(_alpm_check_freespace(trans
, data
) == -1) {
754 /* pm_errno is set by check_freespace */
769 int _alpm_sync_commit(pmtrans_t
*trans
, pmdb_t
*db_local
, alpm_list_t
**data
)
771 alpm_list_t
*i
, *j
, *files
= NULL
;
772 pmtrans_t
*tr
= NULL
;
773 int replaces
= 0, retval
= 0;
779 ASSERT(db_local
!= NULL
, RET_ERR(PM_ERR_DB_NULL
, -1));
780 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
782 trans
->state
= STATE_DOWNLOADING
;
783 /* group sync records by repository and download */
784 snprintf(ldir
, PATH_MAX
, "%s%s", handle
->root
, handle
->cachedir
);
786 for(i
= handle
->dbs_sync
; i
; i
= i
->next
) {
787 pmdb_t
*current
= i
->data
;
789 for(j
= trans
->packages
; j
; j
= j
->next
) {
790 pmsyncpkg_t
*sync
= j
->data
;
791 pmpkg_t
*spkg
= sync
->pkg
;
792 pmdb_t
*dbs
= spkg
->data
;
795 const char *fname
= NULL
;
798 fname
= alpm_pkg_get_filename(spkg
);
799 if(trans
->flags
& PM_TRANS_FLAG_PRINTURIS
) {
800 EVENT(trans
, PM_TRANS_EVT_PRINTURI
, (char *)alpm_db_get_url(current
), (char *)fname
);
803 snprintf(path
, PATH_MAX
, "%s/%s", ldir
, fname
);
804 if(stat(path
, &buf
)) {
805 /* file is not in the cache dir, so add it to the list */
806 files
= alpm_list_add(files
, strdup(fname
));
808 _alpm_log(PM_LOG_DEBUG
, _("%s is already in the cache\n"), fname
);
816 EVENT(trans
, PM_TRANS_EVT_RETRIEVE_START
, current
->treename
, NULL
);
817 if(stat(ldir
, &buf
)) {
818 /* no cache directory.... try creating it */
819 _alpm_log(PM_LOG_WARNING
, _("no %s cache exists, creating...\n"), ldir
);
820 alpm_logaction(_("warning: no %s cache exists, creating..."), ldir
);
821 if(_alpm_makepath(ldir
)) {
822 /* couldn't mkdir the cache directory, so fall back to /tmp and unlink
823 * the package afterwards.
825 _alpm_log(PM_LOG_WARNING
, _("couldn't create package cache, using /tmp instead\n"));
826 alpm_logaction(_("warning: couldn't create package cache, using /tmp instead"));
827 snprintf(ldir
, PATH_MAX
, "%stmp", alpm_option_get_root());
828 alpm_option_set_cachedir(ldir
);
832 if(_alpm_downloadfiles(current
->servers
, ldir
, files
)) {
833 _alpm_log(PM_LOG_WARNING
, _("failed to retrieve some files from %s\n"), current
->treename
);
834 RET_ERR(PM_ERR_RETRIEVE
, -1);
839 if(trans
->flags
& PM_TRANS_FLAG_PRINTURIS
) {
843 /* Check integrity of files */
844 EVENT(trans
, PM_TRANS_EVT_INTEGRITY_START
, NULL
, NULL
);
846 for(i
= trans
->packages
; i
; i
= i
->next
) {
847 pmsyncpkg_t
*sync
= i
->data
;
848 pmpkg_t
*spkg
= sync
->pkg
;
851 char *md5sum1
, *md5sum2
, *sha1sum1
, *sha1sum2
;
854 pkgname
= alpm_pkg_get_filename(spkg
);
855 md5sum1
= spkg
->md5sum
;
856 sha1sum1
= spkg
->sha1sum
;
858 if((md5sum1
== NULL
) && (sha1sum1
== NULL
)) {
859 /* TODO wtf is this? malloc'd strings for error messages? */
860 if((ptr
= (char *)malloc(512)) == NULL
) {
861 RET_ERR(PM_ERR_MEMORY
, -1);
863 snprintf(ptr
, 512, _("can't get md5 or sha1 checksum for package %s\n"), pkgname
);
864 *data
= alpm_list_add(*data
, ptr
);
868 snprintf(str
, PATH_MAX
, "%s%s%s", handle
->root
, handle
->cachedir
, pkgname
);
869 md5sum2
= _alpm_MDFile(str
);
870 sha1sum2
= _alpm_SHAFile(str
);
871 if(md5sum2
== NULL
&& sha1sum2
== NULL
) {
872 if((ptr
= (char *)malloc(512)) == NULL
) {
873 RET_ERR(PM_ERR_MEMORY
, -1);
875 snprintf(ptr
, 512, _("can't get md5 or sha1 checksum for package %s\n"), pkgname
);
876 *data
= alpm_list_add(*data
, ptr
);
880 if((strcmp(md5sum1
, md5sum2
) != 0) && (strcmp(sha1sum1
, sha1sum2
) != 0)) {
882 if((ptr
= (char *)malloc(512)) == NULL
) {
883 RET_ERR(PM_ERR_MEMORY
, -1);
885 if(trans
->flags
& PM_TRANS_FLAG_ALLDEPS
) {
888 QUESTION(trans
, PM_TRANS_CONV_CORRUPTED_PKG
, (char *)pkgname
, NULL
, NULL
, &doremove
);
892 snprintf(str
, PATH_MAX
, "%s%s%s", handle
->root
, handle
->cachedir
, pkgname
);
894 snprintf(ptr
, 512, _("archive %s was corrupted (bad MD5 or SHA1 checksum)\n"), pkgname
);
896 snprintf(ptr
, 512, _("archive %s is corrupted (bad MD5 or SHA1 checksum)\n"), pkgname
);
898 *data
= alpm_list_add(*data
, ptr
);
905 pm_errno
= PM_ERR_PKG_CORRUPTED
;
908 EVENT(trans
, PM_TRANS_EVT_INTEGRITY_DONE
, NULL
, NULL
);
909 if(trans
->flags
& PM_TRANS_FLAG_DOWNLOADONLY
) {
913 /* remove conflicting and to-be-replaced packages */
914 trans
->state
= STATE_COMMITING
;
915 tr
= _alpm_trans_new();
917 _alpm_log(PM_LOG_ERROR
, _("could not create removal transaction"));
918 pm_errno
= PM_ERR_MEMORY
;
922 if(_alpm_trans_init(tr
, PM_TRANS_TYPE_REMOVE
, PM_TRANS_FLAG_NODEPS
, NULL
, NULL
, NULL
) == -1) {
923 _alpm_log(PM_LOG_ERROR
, _("could not initialize the removal transaction"));
927 for(i
= trans
->packages
; i
; i
= i
->next
) {
928 pmsyncpkg_t
*sync
= i
->data
;
929 if(sync
->type
== PM_SYNC_TYPE_REPLACE
) {
931 for(j
= sync
->data
; j
; j
= j
->next
) {
932 pmpkg_t
*pkg
= j
->data
;
933 if(!_alpm_pkg_find(pkg
->name
, tr
->packages
)) {
934 if(_alpm_trans_addtarget(tr
, pkg
->name
) == -1) {
943 _alpm_log(PM_LOG_DEBUG
, _("removing conflicting and to-be-replaced packages"));
944 if(_alpm_trans_prepare(tr
, data
) == -1) {
945 _alpm_log(PM_LOG_ERROR
, _("could not prepare removal transaction"));
948 /* we want the frontend to be aware of commit details */
949 tr
->cb_event
= trans
->cb_event
;
950 if(_alpm_trans_commit(tr
, NULL
) == -1) {
951 _alpm_log(PM_LOG_ERROR
, _("could not commit removal transaction"));
957 /* install targets */
958 _alpm_log(PM_LOG_DEBUG
, _("installing packages"));
959 tr
= _alpm_trans_new();
961 _alpm_log(PM_LOG_ERROR
, _("could not create transaction"));
962 pm_errno
= PM_ERR_MEMORY
;
965 if(_alpm_trans_init(tr
, PM_TRANS_TYPE_UPGRADE
, trans
->flags
| PM_TRANS_FLAG_NODEPS
, trans
->cb_event
, trans
->cb_conv
, trans
->cb_progress
) == -1) {
966 _alpm_log(PM_LOG_ERROR
, _("could not initialize transaction"));
969 for(i
= trans
->packages
; i
; i
= i
->next
) {
970 pmsyncpkg_t
*sync
= i
->data
;
971 pmpkg_t
*spkg
= sync
->pkg
;
973 const char *fname
= NULL
;
976 fname
= alpm_pkg_get_filename(spkg
);
977 snprintf(str
, PATH_MAX
, "%s%s%s", handle
->root
, handle
->cachedir
, fname
);
978 if(_alpm_trans_addtarget(tr
, str
) == -1) {
981 /* using alpm_list_last() is ok because addtarget() adds the new target at the
982 * end of the tr->packages list */
983 spkg
= alpm_list_last(tr
->packages
)->data
;
984 if(sync
->type
== PM_SYNC_TYPE_DEPEND
) {
985 spkg
->reason
= PM_PKG_REASON_DEPEND
;
988 if(_alpm_trans_prepare(tr
, data
) == -1) {
989 _alpm_log(PM_LOG_ERROR
, _("could not prepare transaction"));
990 /* pm_errno is set by trans_prepare */
993 if(_alpm_trans_commit(tr
, NULL
) == -1) {
994 _alpm_log(PM_LOG_ERROR
, _("could not commit transaction"));
999 /* propagate replaced packages' requiredby fields to their new owners */
1001 _alpm_log(PM_LOG_DEBUG
, _("updating database for replaced packages' dependencies"));
1002 for(i
= trans
->packages
; i
; i
= i
->next
) {
1003 pmsyncpkg_t
*sync
= i
->data
;
1004 if(sync
->type
== PM_SYNC_TYPE_REPLACE
) {
1006 pmpkg_t
*new = _alpm_db_get_pkgfromcache(db_local
, alpm_pkg_get_name(sync
->pkg
));
1007 for(j
= sync
->data
; j
; j
= j
->next
) {
1009 pmpkg_t
*old
= j
->data
;
1011 for(k
= alpm_pkg_get_requiredby(old
); k
; k
= k
->next
) {
1012 if(!alpm_list_find_str(alpm_pkg_get_requiredby(new), k
->data
)) {
1013 /* replace old's name with new's name in the requiredby's dependency list */
1015 pmpkg_t
*depender
= _alpm_db_get_pkgfromcache(db_local
, k
->data
);
1016 if(depender
== NULL
) {
1017 /* If the depending package no longer exists in the local db,
1018 * then it must have ALSO conflicted with sync->pkg. If
1019 * that's the case, then we don't have anything to propagate
1023 for(m
= alpm_pkg_get_depends(depender
); m
; m
= m
->next
) {
1024 if(!strcmp(m
->data
, alpm_pkg_get_name(old
))) {
1026 m
->data
= strdup(alpm_pkg_get_name(new));
1029 if(_alpm_db_write(db_local
, depender
, INFRQ_DEPENDS
) == -1) {
1030 _alpm_log(PM_LOG_ERROR
, _("could not update requiredby for database entry %s-%s"),
1031 alpm_pkg_get_name(new), alpm_pkg_get_version(new));
1033 /* add the new requiredby */
1034 new->requiredby
= alpm_list_add(alpm_pkg_get_requiredby(new), strdup(k
->data
));
1038 if(_alpm_db_write(db_local
, new, INFRQ_DEPENDS
) == -1) {
1039 _alpm_log(PM_LOG_ERROR
, _("could not update new database entry %s-%s"),
1040 alpm_pkg_get_name(new), alpm_pkg_get_version(new));
1046 if(!varcache
&& !(trans
->flags
& PM_TRANS_FLAG_DOWNLOADONLY
)) {
1047 /* delete packages */
1048 for(i
= files
; i
; i
= i
->next
) {
1053 /* run ldconfig if it exists */
1054 if(handle
->trans
->state
!= STATE_INTERRUPTED
) {
1055 _alpm_log(PM_LOG_DEBUG
, _("running \"ldconfig -r %s\""), handle
->root
);
1056 _alpm_ldconfig(handle
->root
);
1063 /* commiting failed, so this is still just a prepared transaction */
1064 trans
->state
= STATE_PREPARED
;
1068 pmsyncpkg_t
*_alpm_sync_find(alpm_list_t
*syncpkgs
, const char* pkgname
)
1071 for(i
= syncpkgs
; i
; i
= i
->next
) {
1072 pmsyncpkg_t
*syncpkg
= i
->data
;
1077 pmpkg_t
*pkg
= alpm_sync_get_pkg(syncpkg
);
1078 if(strcmp(alpm_pkg_get_name(pkg
), pkgname
) == 0) {
1079 _alpm_log(PM_LOG_DEBUG
, _("found package '%s-%s' in sync"),
1080 alpm_pkg_get_name(pkg
), alpm_pkg_get_version(pkg
));
1085 _alpm_log(PM_LOG_DEBUG
, _("package '%s' not found in sync"), pkgname
);
1086 return(NULL
); /* not found */
1089 pmsynctype_t SYMEXPORT
alpm_sync_get_type(pmsyncpkg_t
*sync
)
1092 ASSERT(sync
!= NULL
, return(-1));
1097 pmpkg_t SYMEXPORT
*alpm_sync_get_pkg(pmsyncpkg_t
*sync
)
1100 ASSERT(sync
!= NULL
, return(NULL
));
1105 void SYMEXPORT
*alpm_sync_get_data(pmsyncpkg_t
*sync
)
1108 ASSERT(sync
!= NULL
, return(NULL
));
1113 /* vim: set ts=2 sw=2 noet: */