diff options
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r-- | lib/libalpm/sync.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c new file mode 100644 index 00000000..8a049c74 --- /dev/null +++ b/lib/libalpm/sync.c @@ -0,0 +1,248 @@ +/* + * sync.c + * + * Copyright (c) 2002-2005 by Judd Vinet <jvinet@zeroflux.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "config.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +/* pacman */ +#include "log.h" +#include "util.h" +#include "list.h" +#include "package.h" +#include "db.h" +#include "cache.h" +#include "deps.h" +#include "trans.h" +#include "sync.h" +#include "rpmvercmp.h" +#include "handle.h" + +extern pmhandle_t *handle; + +pmsync_t *sync_new(int type, pmpkg_t *lpkg, pmpkg_t *spkg) +{ + pmsync_t *sync; + + if((sync = (pmsync_t *)malloc(sizeof(pmsync_t))) == NULL) { + return(NULL); + } + + sync->type = type; + sync->lpkg = lpkg; + sync->spkg = spkg; + + return(sync); +} + +int sync_sysupgrade(PMList **data) +{ + PMList *i, *j, *k; + PMList *targets = NULL; + + *data = NULL; + + /* check for "recommended" package replacements */ + for(i = handle->dbs_sync; i; i = i->next) { + PMList *j; + + for(j = db_get_pkgcache(i->data); j; j = j->next) { + pmpkg_t *spkg = j->data; + + for(k = spkg->replaces; k; k = k->next) { + PMList *m; + + for(m = db_get_pkgcache(handle->db_local); m; m = m->next) { + pmpkg_t *lpkg = m->data; + + if(!strcmp(k->data, lpkg->name)) { + if(pm_list_is_strin(lpkg->name, handle->ignorepkg)) { + _alpm_log(PM_LOG_WARNING, "%s-%s: ignoring package upgrade (to be replaced by %s-%s)", + lpkg->name, lpkg->version, spkg->name, spkg->version); + } else { + pmsync_t *sync = sync_new(PM_SYSUPG_REPLACE, lpkg, spkg); + + if(sync == NULL) { + pm_errno = PM_ERR_MEMORY; + goto error; + } + + targets = pm_list_add(targets, sync); + } + } + } + } + } + } + + /* match installed packages with the sync dbs and compare versions */ + for(i = db_get_pkgcache(handle->db_local); i; i = i->next) { + int cmp; + pmpkg_t *local = i->data; + pmpkg_t *spkg = NULL; + pmsync_t *sync; + + for(j = handle->dbs_sync; !spkg && j; j = j->next) { + + for(k = db_get_pkgcache(j->data); !spkg && k; k = k->next) { + pmpkg_t *sp = k->data; + + if(!strcmp(local->name, sp->name)) { + spkg = sp; + } + } + } + if(spkg == NULL) { + /*fprintf(stderr, "%s: not found in sync db. skipping.", local->name);*/ + continue; + } + + /* compare versions and see if we need to upgrade */ + cmp = rpmvercmp(local->version, spkg->version); + if(cmp > 0 && !spkg->force) { + /* local version is newer */ + _alpm_log(PM_LOG_FLOW1, "%s-%s: local version is newer", + local->name, local->version); + continue; + } else if(cmp == 0) { + /* versions are identical */ + continue; + } else if(pm_list_is_strin(i->data, handle->ignorepkg)) { + /* package should be ignored (IgnorePkg) */ + _alpm_log(PM_LOG_FLOW1, "%s-%s: ignoring package upgrade (%s)", + local->name, local->version, spkg->version); + continue; + } + + sync = sync_new(PM_SYSUPG_UPGRADE, local, spkg); + if(sync == NULL) { + pm_errno = PM_ERR_MEMORY; + goto error; + } + + targets = pm_list_add(targets, sync); + } + + *data = targets; + + return(0); + +error: + FREELIST(targets); + return(-1); +} + +int sync_resolvedeps(PMList **syncs) +{ + return(0); +} + +int sync_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data) +{ + PMList *i; + PMList *trail = NULL; + + /* Resolve targets dependencies */ + for(i = trans->targets; i; i = i->next) { + if(resolvedeps(handle->db_local, handle->dbs_sync, i->data, trans->targets, trail, data) == -1) { + /* pm_errno is set by resolvedeps */ + goto error; + } + } + + /* ORE + check for inter-conflicts and whatnot */ + + /* ORE + any packages in rmtargs need to be removed from final. + rather than ripping out nodes from final, we just copy over + our "good" nodes to a new list and reassign. */ + + /* ORE + Check dependencies of packages in rmtargs and make sure + we won't be breaking anything by removing them. + If a broken dep is detected, make sure it's not from a + package that's in our final (upgrade) list. */ + + return(0); + +error: + return(-1); +} + +int sync_commit(pmdb_t *db, pmtrans_t *trans) +{ + PMList *i, *files = NULL; + PMList *final = NULL; + PMList *data; + pmtrans_t *tr; + + /* remove any conflicting packages (WITHOUT dep checks) */ + + /* remove to-be-replaced packages */ + + /* install targets */ + tr = trans_new(PM_TRANS_TYPE_UPGRADE, 0); + for(i = files; i; i = i->next) { + trans_addtarget(tr, i->data); + } + + trans_prepare(tr, &data); + + trans_commit(tr); + + trans_free(tr); + + /* propagate replaced packages' requiredby fields to their new owners */ + for(i = final; i; i = i->next) { + /*syncpkg_t *sync = (syncpkg_t*)i->data; + if(sync->replaces) { + pkginfo_t *new = db_scan(db, sync->pkg->name, INFRQ_DEPENDS); + for(j = sync->replaces; j; j = j->next) { + pkginfo_t *old = (pkginfo_t*)j->data; + // merge lists + for(k = old->requiredby; k; k = k->next) { + if(!is_in(k->data, new->requiredby)) { + // replace old's name with new's name in the requiredby's dependency list + PMList *m; + pkginfo_t *depender = db_scan(db, k->data, INFRQ_DEPENDS); + for(m = depender->depends; m; m = m->next) { + if(!strcmp(m->data, old->name)) { + FREE(m->data); + m->data = strdup(new->name); + } + } + db_write(db, depender, INFRQ_DEPENDS); + + // add the new requiredby + new->requiredby = list_add(new->requiredby, strdup(k->data)); + } + } + } + db_write(db, new, INFRQ_DEPENDS); + FREEPKG(new); + }*/ + } + + return(0); +} + +/* vim: set ts=2 sw=2 noet: */ |