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,
34 #include "alpm_list.h"
48 pmtrans_t
*_alpm_trans_new()
54 if((trans
= (pmtrans_t
*)malloc(sizeof(pmtrans_t
))) == NULL
) {
55 _alpm_log(PM_LOG_ERROR
, _("malloc failure: could not allocate %d bytes"), sizeof(pmtrans_t
));
59 trans
->targets
= NULL
;
60 trans
->packages
= NULL
;
61 trans
->skip_add
= NULL
;
62 trans
->skip_remove
= NULL
;
65 trans
->cb_event
= NULL
;
66 trans
->cb_conv
= NULL
;
67 trans
->cb_progress
= NULL
;
68 trans
->state
= STATE_IDLE
;
73 void _alpm_trans_free(void *data
)
75 pmtrans_t
*trans
= data
;
83 FREELIST(trans
->targets
);
84 if(trans
->type
== PM_TRANS_TYPE_SYNC
) {
86 for(i
= trans
->packages
; i
; i
= i
->next
) {
89 FREELIST(trans
->packages
);
91 FREELISTPKGS(trans
->packages
);
94 FREELIST(trans
->skip_add
);
95 FREELIST(trans
->skip_remove
);
100 int _alpm_trans_init(pmtrans_t
*trans
, pmtranstype_t type
, pmtransflag_t flags
,
101 alpm_trans_cb_event event
, alpm_trans_cb_conv conv
,
102 alpm_trans_cb_progress progress
)
107 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
110 trans
->flags
= flags
;
111 trans
->cb_event
= event
;
112 trans
->cb_conv
= conv
;
113 trans
->cb_progress
= progress
;
114 trans
->state
= STATE_INITIALIZED
;
119 int _alpm_trans_sysupgrade(pmtrans_t
*trans
)
124 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
126 return(_alpm_sync_sysupgrade(trans
, handle
->db_local
, handle
->dbs_sync
));
129 int _alpm_trans_addtarget(pmtrans_t
*trans
, char *target
)
134 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
135 ASSERT(target
!= NULL
, RET_ERR(PM_ERR_WRONG_ARGS
, -1));
137 if(alpm_list_find_str(trans
->targets
, target
)) {
139 //RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
142 switch(trans
->type
) {
143 case PM_TRANS_TYPE_ADD
:
144 case PM_TRANS_TYPE_UPGRADE
:
145 if(_alpm_add_loadtarget(trans
, handle
->db_local
, target
) == -1) {
146 /* pm_errno is set by _alpm_add_loadtarget() */
150 case PM_TRANS_TYPE_REMOVE
:
151 if(_alpm_remove_loadtarget(trans
, handle
->db_local
, target
) == -1) {
152 /* pm_errno is set by remove_loadtarget() */
156 case PM_TRANS_TYPE_SYNC
:
157 if(_alpm_sync_addtarget(trans
, handle
->db_local
, handle
->dbs_sync
, target
) == -1) {
158 /* pm_errno is set by sync_loadtarget() */
164 trans
->targets
= alpm_list_add(trans
->targets
, strdup(target
));
169 int _alpm_trans_prepare(pmtrans_t
*trans
, alpm_list_t
**data
)
176 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
178 /* If there's nothing to do, return without complaining */
179 if(trans
->packages
== NULL
) {
183 switch(trans
->type
) {
184 case PM_TRANS_TYPE_ADD
:
185 case PM_TRANS_TYPE_UPGRADE
:
186 if(_alpm_add_prepare(trans
, handle
->db_local
, data
) == -1) {
187 /* pm_errno is set by _alpm_add_prepare() */
191 case PM_TRANS_TYPE_REMOVE
:
192 if(_alpm_remove_prepare(trans
, handle
->db_local
, data
) == -1) {
193 /* pm_errno is set by _alpm_remove_prepare() */
197 case PM_TRANS_TYPE_SYNC
:
198 if(_alpm_sync_prepare(trans
, handle
->db_local
, handle
->dbs_sync
, data
) == -1) {
199 /* pm_errno is set by _alpm_sync_prepare() */
205 trans
->state
= STATE_PREPARED
;
210 int _alpm_trans_commit(pmtrans_t
*trans
, alpm_list_t
**data
)
218 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
220 /* If there's nothing to do, return without complaining */
221 if(trans
->packages
== NULL
) {
225 trans
->state
= STATE_COMMITING
;
227 switch(trans
->type
) {
228 case PM_TRANS_TYPE_ADD
:
229 case PM_TRANS_TYPE_UPGRADE
:
230 if(_alpm_add_commit(trans
, handle
->db_local
) == -1) {
231 /* pm_errno is set by _alpm_add_prepare() */
235 case PM_TRANS_TYPE_REMOVE
:
236 if(_alpm_remove_commit(trans
, handle
->db_local
) == -1) {
237 /* pm_errno is set by _alpm_remove_prepare() */
241 case PM_TRANS_TYPE_SYNC
:
242 if(_alpm_sync_commit(trans
, handle
->db_local
, data
) == -1) {
243 /* pm_errno is set by _alpm_sync_commit() */
249 trans
->state
= STATE_COMMITED
;
254 int _alpm_trans_update_depends(pmtrans_t
*trans
, pmpkg_t
*pkg
)
257 alpm_list_t
*depends
= NULL
;
264 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
265 ASSERT(pkg
!= NULL
, RET_ERR(PM_ERR_PKG_INVALID
, -1));
267 pkgname
= alpm_pkg_get_name(pkg
);
268 depends
= alpm_pkg_get_depends(pkg
);
271 _alpm_log(PM_LOG_DEBUG
, _("updating dependency packages 'requiredby' fields for %s-%s"),
272 pkgname
, pkg
->version
);
274 _alpm_log(PM_LOG_DEBUG
, _("package has no dependencies, no other packages to update"));
277 localdb
= alpm_option_get_localdb();
278 for(i
= depends
; i
; i
= i
->next
) {
279 pmdepend_t
* dep
= alpm_splitdep(i
->data
);
284 if(trans
->packages
&& trans
->type
== PM_TRANS_TYPE_REMOVE
) {
285 if(_alpm_pkg_find(dep
->name
, handle
->trans
->packages
)) {
290 pmpkg_t
*deppkg
= _alpm_db_get_pkgfromcache(localdb
, dep
->name
);
292 int found_provides
= 0;
293 /* look for a provides package */
294 alpm_list_t
*provides
= _alpm_db_whatprovides(localdb
, dep
->name
);
295 for(j
= provides
; j
; j
= j
->next
) {
299 pmpkg_t
*provpkg
= j
->data
;
300 deppkg
= _alpm_db_get_pkgfromcache(localdb
, alpm_pkg_get_name(provpkg
));
308 /* this is cheating... we call this function to populate the package */
309 alpm_list_t
*rqdby
= alpm_pkg_get_requiredby(deppkg
);
311 _alpm_log(PM_LOG_DEBUG
, _("updating 'requiredby' field for package '%s'"),
312 alpm_pkg_get_name(deppkg
));
313 if(trans
->type
== PM_TRANS_TYPE_REMOVE
) {
315 rqdby
= alpm_list_remove(rqdby
, pkgname
, _alpm_str_cmp
, &data
);
317 deppkg
->requiredby
= rqdby
;
319 if(!alpm_list_find_str(rqdby
, pkgname
)) {
320 rqdby
= alpm_list_add(rqdby
, strdup(pkgname
));
321 deppkg
->requiredby
= rqdby
;
325 if(_alpm_db_write(localdb
, deppkg
, INFRQ_DEPENDS
)) {
326 _alpm_log(PM_LOG_ERROR
, _("could not update 'requiredby' database entry %s-%s"),
327 alpm_pkg_get_name(deppkg
), alpm_pkg_get_version(deppkg
));
330 FREELISTPTR(provides
);
332 if(!found_provides
) {
333 _alpm_log(PM_LOG_DEBUG
, _("could not find dependency '%s'"), dep
->name
);
338 /* this is cheating... we call this function to populate the package */
339 alpm_list_t
*rqdby
= alpm_pkg_get_requiredby(deppkg
);
341 _alpm_log(PM_LOG_DEBUG
, _("updating 'requiredby' field for package '%s'"),
342 alpm_pkg_get_name(deppkg
));
343 if(trans
->type
== PM_TRANS_TYPE_REMOVE
) {
345 rqdby
= alpm_list_remove(rqdby
, pkgname
, _alpm_str_cmp
, &data
);
347 deppkg
->requiredby
= rqdby
;
349 if(!alpm_list_find_str(rqdby
, pkgname
)) {
350 rqdby
= alpm_list_add(rqdby
, strdup(pkgname
));
351 deppkg
->requiredby
= rqdby
;
355 if(_alpm_db_write(localdb
, deppkg
, INFRQ_DEPENDS
)) {
356 _alpm_log(PM_LOG_ERROR
, _("could not update 'requiredby' database entry %s-%s"),
357 alpm_pkg_get_name(deppkg
), alpm_pkg_get_version(deppkg
));
365 pmtranstype_t
alpm_trans_get_type()
368 ASSERT(handle
!= NULL
, return(-1));
369 ASSERT(handle
->trans
!= NULL
, return(-1));
371 return handle
->trans
->type
;
374 unsigned int SYMEXPORT
alpm_trans_get_flags()
377 ASSERT(handle
!= NULL
, return(-1));
378 ASSERT(handle
->trans
!= NULL
, return(-1));
380 return handle
->trans
->flags
;
383 alpm_list_t
* alpm_trans_get_targets()
386 ASSERT(handle
!= NULL
, return(NULL
));
387 ASSERT(handle
->trans
!= NULL
, return(NULL
));
389 return handle
->trans
->targets
;
392 alpm_list_t SYMEXPORT
* alpm_trans_get_pkgs()
395 ASSERT(handle
!= NULL
, return(NULL
));
396 ASSERT(handle
->trans
!= NULL
, return(NULL
));
398 return handle
->trans
->packages
;
400 /* vim: set ts=2 sw=2 noet: */