summaryrefslogtreecommitdiff
path: root/lib/libalpm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm')
-rw-r--r--lib/libalpm/add.c229
-rw-r--r--lib/libalpm/add.h4
-rw-r--r--lib/libalpm/alpm.h29
-rw-r--r--lib/libalpm/be_files.c42
-rw-r--r--lib/libalpm/conflict.c26
-rw-r--r--lib/libalpm/conflict.h3
-rw-r--r--lib/libalpm/db.c61
-rw-r--r--lib/libalpm/db.h8
-rw-r--r--lib/libalpm/delta.c67
-rw-r--r--lib/libalpm/deps.c2
-rw-r--r--lib/libalpm/dload.c53
-rw-r--r--lib/libalpm/error.c4
-rw-r--r--lib/libalpm/handle.c12
-rw-r--r--lib/libalpm/handle.h2
-rw-r--r--lib/libalpm/package.c18
-rw-r--r--lib/libalpm/remove.c220
-rw-r--r--lib/libalpm/remove.h5
-rw-r--r--lib/libalpm/sync.c339
-rw-r--r--lib/libalpm/sync.h3
-rw-r--r--lib/libalpm/trans.c308
-rw-r--r--lib/libalpm/trans.h9
-rw-r--r--lib/libalpm/util.c45
-rw-r--r--lib/libalpm/util.h1
23 files changed, 648 insertions, 842 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 1d143c6f..c6751a49 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -50,21 +50,30 @@
#include "remove.h"
#include "handle.h"
-int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
+/** Add a file target to the transaction.
+ * @param target the name of the file target to add
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_add_target(char *target)
{
pmpkg_t *pkg = NULL;
const char *pkgname, *pkgver;
alpm_list_t *i;
+ pmtrans_t *trans;
ALPM_LOG_FUNC;
+ /* Sanity checks */
+ ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ trans = handle->trans;
+ ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+ ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- ASSERT(name != NULL && strlen(name) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
- _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", name);
+ _alpm_log(PM_LOG_DEBUG, "loading target '%s'\n", target);
- if(alpm_pkg_load(name, 1, &pkg) != 0) {
+ if(alpm_pkg_load(target, 1, &pkg) != 0) {
goto error;
}
pkgname = alpm_pkg_get_name(pkg);
@@ -72,17 +81,19 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
/* check if an older version of said package is already in transaction
* packages. if so, replace it in the list */
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *transpkg = i->data;
if(strcmp(transpkg->name, pkgname) == 0) {
if(alpm_pkg_vercmp(transpkg->version, pkgver) < 0) {
- _alpm_log(PM_LOG_WARNING, _("replacing older version %s-%s by %s in target list\n"),
- transpkg->name, transpkg->version, pkgver);
+ _alpm_log(PM_LOG_WARNING,
+ _("replacing older version %s-%s by %s in target list\n"),
+ transpkg->name, transpkg->version, pkgver);
_alpm_pkg_free(i->data);
i->data = pkg;
} else {
- _alpm_log(PM_LOG_WARNING, _("skipping %s-%s because newer version %s is in target list\n"),
- pkgname, pkgver, transpkg->version);
+ _alpm_log(PM_LOG_WARNING,
+ _("skipping %s-%s because newer version %s is in target list\n"),
+ pkgname, pkgver, transpkg->version);
_alpm_pkg_free(pkg);
}
return(0);
@@ -90,7 +101,7 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
}
/* add the package to the transaction */
- trans->packages = alpm_list_add(trans->packages, pkg);
+ trans->add = alpm_list_add(trans->add, pkg);
return(0);
@@ -99,176 +110,6 @@ error:
return(-1);
}
-int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
-{
- alpm_list_t *lp = NULL;
-
- ALPM_LOG_FUNC;
-
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
-
- /* Check dependencies
- */
- if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
- EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL);
-
- /* look for unsatisfied dependencies */
- _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n");
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, NULL, trans->packages);
- if(lp != NULL) {
- if(data) {
- *data = lp;
- } else {
- alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
- alpm_list_free(lp);
- }
- RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1);
- }
-
- /* no unsatisfied deps, so look for conflicts */
- _alpm_log(PM_LOG_DEBUG, "looking for conflicts\n");
- alpm_list_t *inner = _alpm_innerconflicts(trans->packages);
- alpm_list_t *outer = _alpm_outerconflicts(db, trans->packages);
- lp = alpm_list_join(inner, outer);
-
- /* TODO : factorize the conflict resolving code from sync.c to use it here (FS#3492) */
-
- if(lp != NULL) {
- if(data) {
- *data = lp;
- } else {
- alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_conflict_free);
- alpm_list_free(lp);
- }
- if(inner) {
- _alpm_log(PM_LOG_ERROR, _("conflicting packages were found in target list\n"));
- _alpm_log(PM_LOG_ERROR, _("you cannot install two conflicting packages at the same time\n"));
- }
- if(outer) {
- _alpm_log(PM_LOG_ERROR, _("replacing packages with -U is not supported yet\n"));
- _alpm_log(PM_LOG_ERROR, _("you can replace packages manually using -Rd and -U\n"));
- }
- RET_ERR(PM_ERR_CONFLICTING_DEPS, -1);
- }
-
- /* re-order w.r.t. dependencies */
- _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n");
- lp = _alpm_sortbydeps(trans->packages, 0);
- /* free the old alltargs */
- alpm_list_free(trans->packages);
- trans->packages = lp;
-
- EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);
- }
-
- /* Check for file conflicts */
- if(!(trans->flags & PM_TRANS_FLAG_FORCE)) {
- EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL);
-
- _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n");
- lp = _alpm_db_find_fileconflicts(db, trans, trans->packages, NULL);
- if(lp != NULL) {
- if(data) {
- *data = lp;
- } else {
- alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_fileconflict_free);
- alpm_list_free(lp);
- }
- RET_ERR(PM_ERR_FILE_CONFLICTS, -1);
- }
-
- EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL);
- }
-
- return(0);
-}
-
-static int upgrade_remove(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans, pmdb_t *db) {
- /* this is kinda odd. If the old package exists, at this point we make a
- * NEW transaction, unrelated to handle->trans, and instantiate a "remove"
- * with the type PM_TRANS_TYPE_REMOVEUPGRADE. TODO: kill this weird
- * behavior. */
- pmtrans_t *tr = _alpm_trans_new();
-
- ALPM_LOG_FUNC;
-
- _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n",
- oldpkg->name, oldpkg->version);
-
- if(!tr) {
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- if(_alpm_trans_init(tr, PM_TRANS_TYPE_REMOVEUPGRADE, trans->flags,
- NULL, NULL, NULL) == -1) {
- _alpm_trans_free(tr);
- tr = NULL;
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- if(_alpm_remove_loadtarget(tr, db, newpkg->name) == -1) {
- _alpm_trans_free(tr);
- tr = NULL;
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- /* copy the remove skiplist over */
- tr->skip_remove = alpm_list_strdup(trans->skip_remove);
- const alpm_list_t *b;
-
- /* Add files in the NEW backup array to the NoUpgrade array
- * so this removal operation doesn't kill them */
- alpm_list_t *old_noupgrade = alpm_list_strdup(handle->noupgrade);
- /* old package backup list */
- alpm_list_t *filelist = alpm_pkg_get_files(newpkg);
- for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) {
- char *backup = _alpm_backup_file(b->data);
- /* safety check (fix the upgrade026 pactest) */
- if(!alpm_list_find_str(filelist, backup)) {
- FREE(backup);
- continue;
- }
- _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n",
- backup);
- handle->noupgrade = alpm_list_add(handle->noupgrade,
- backup);
- }
-
- /* TODO: we could also add files in the OLD backup array, but this would
- * change the backup handling behavior, and break several pactests, and we
- * can't do this just before 3.1 release.
- * The unlink_file function in remove.c would also need to be reviewed. */
-#if 0
- /* new package backup list */
- for(b = alpm_pkg_get_backup(oldpkg); b; b = b->next) {
- char *backup = _alpm_backup_file(b->data);
- /* make sure we don't add duplicate entries */
- if(!alpm_list_find_ptr(handle->noupgrade, backup)) {
- _alpm_log(PM_LOG_DEBUG, "adding %s to the NoUpgrade array temporarily\n",
- backup);
- handle->noupgrade = alpm_list_add(handle->noupgrade,
- backup);
- }
- }
-#endif
-
- int ret = _alpm_remove_commit(tr, db);
-
- _alpm_trans_free(tr);
- tr = NULL;
-
- /* restore our "NoUpgrade" list to previous state */
- FREELIST(handle->noupgrade);
- handle->noupgrade = old_noupgrade;
-
- if(ret == -1) {
- RET_ERR(PM_ERR_TRANS_ABORT, -1);
- }
-
- return(0);
-}
-
static int extract_single_file(struct archive *archive,
struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg,
pmtrans_t *trans, pmdb_t *db)
@@ -291,13 +132,13 @@ static int extract_single_file(struct archive *archive,
if(strcmp(entryname, ".INSTALL") == 0) {
/* the install script goes inside the db */
- snprintf(filename, PATH_MAX, "%s%s-%s/install", db->path,
- newpkg->name, newpkg->version);
+ snprintf(filename, PATH_MAX, "%s%s-%s/install",
+ _alpm_db_path(db), newpkg->name, newpkg->version);
archive_entry_set_perm(entry, 0644);
} else if(strcmp(entryname, ".CHANGELOG") == 0) {
/* the changelog goes inside the db */
- snprintf(filename, PATH_MAX, "%s%s-%s/changelog", db->path,
- newpkg->name, newpkg->version);
+ snprintf(filename, PATH_MAX, "%s%s-%s/changelog",
+ _alpm_db_path(db), newpkg->name, newpkg->version);
archive_entry_set_perm(entry, 0644);
} else if(*entryname == '.') {
/* for now, ignore all files starting with '.' that haven't
@@ -642,8 +483,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
ALPM_LOG_FUNC;
- snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path,
- alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg));
+ snprintf(scriptlet, PATH_MAX, "%s%s-%s/install",
+ _alpm_db_path(db), alpm_pkg_get_name(newpkg),
+ alpm_pkg_get_version(newpkg));
/* see if this is an upgrade. if so, remove the old package first */
pmpkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name);
@@ -691,8 +533,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
if(oldpkg) {
/* set up fake remove transaction */
- int ret = upgrade_remove(oldpkg, newpkg, trans, db);
- if(ret != 0) {
+ if(_alpm_upgraderemove_package(oldpkg, newpkg, trans) == -1) {
+ pm_errno = PM_ERR_TRANS_ABORT;
+ ret = -1;
goto cleanup;
}
}
@@ -858,7 +701,7 @@ cleanup:
return(ret);
}
-int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
+int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db)
{
int pkg_count, pkg_current;
alpm_list_t *targ;
@@ -868,15 +711,15 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- if(trans->packages == NULL) {
+ if(trans->add == NULL) {
return(0);
}
- pkg_count = alpm_list_count(trans->packages);
+ pkg_count = alpm_list_count(trans->add);
pkg_current = 1;
/* loop through our package list adding/upgrading one at a time */
- for(targ = trans->packages; targ; targ = targ->next) {
+ for(targ = trans->add; targ; targ = targ->next) {
if(handle->trans->state == STATE_INTERRUPTED) {
return(0);
}
diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h
index 6983de9e..b0467507 100644
--- a/lib/libalpm/add.h
+++ b/lib/libalpm/add.h
@@ -24,9 +24,7 @@
#include "alpm_list.h"
#include "trans.h"
-int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name);
-int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data);
-int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db);
+int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db);
#endif /* _ALPM_ADD_H */
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index ce8c6919..e9fadca2 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -151,8 +151,9 @@ void alpm_option_add_ignoregrp(const char *grp);
void alpm_option_set_ignoregrps(alpm_list_t *ignoregrps);
int alpm_option_remove_ignoregrp(const char *grp);
-unsigned short alpm_option_get_nopassiveftp();
-void alpm_option_set_nopassiveftp(unsigned short nopasv);
+const char *alpm_option_get_arch();
+void alpm_option_set_arch(const char *arch);
+
void alpm_option_set_usedelta(unsigned short usedelta);
pmdb_t *alpm_option_get_localdb();
@@ -224,7 +225,6 @@ alpm_list_t *alpm_pkg_get_deltas(pmpkg_t *pkg);
alpm_list_t *alpm_pkg_get_replaces(pmpkg_t *pkg);
alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg);
alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg);
-alpm_list_t *alpm_pkg_get_removes(pmpkg_t *pkg);
pmdb_t *alpm_pkg_get_db(pmpkg_t *pkg);
void *alpm_pkg_changelog_open(pmpkg_t *pkg);
size_t alpm_pkg_changelog_read(void *ptr, size_t size,
@@ -262,13 +262,6 @@ pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync);
* Transactions
*/
-/* Types */
-typedef enum _pmtranstype_t {
- PM_TRANS_TYPE_UPGRADE = 1,
- PM_TRANS_TYPE_REMOVE,
- PM_TRANS_TYPE_REMOVEUPGRADE,
- PM_TRANS_TYPE_SYNC
-} pmtranstype_t;
/* Flags */
typedef enum _pmtransflag_t {
@@ -402,19 +395,23 @@ typedef void (*alpm_trans_cb_conv)(pmtransconv_t, void *, void *,
/* Transaction Progress callback */
typedef void (*alpm_trans_cb_progress)(pmtransprog_t, const char *, int, int, int);
-pmtranstype_t alpm_trans_get_type();
unsigned int alpm_trans_get_flags();
-alpm_list_t * alpm_trans_get_pkgs();
-int alpm_trans_init(pmtranstype_t type, pmtransflag_t flags,
+alpm_list_t * alpm_trans_get_add();
+alpm_list_t * alpm_trans_get_remove();
+int alpm_trans_init(pmtransflag_t flags,
alpm_trans_cb_event cb_event, alpm_trans_cb_conv conv,
alpm_trans_cb_progress cb_progress);
-int alpm_trans_sysupgrade(int enable_downgrade);
-int alpm_trans_addtarget(char *target);
int alpm_trans_prepare(alpm_list_t **data);
int alpm_trans_commit(alpm_list_t **data);
int alpm_trans_interrupt(void);
int alpm_trans_release(void);
+int alpm_sync_sysupgrade(int enable_downgrade);
+int alpm_sync_target(char *target);
+int alpm_sync_dbtarget(char *db, char *target);
+int alpm_add_target(char *target);
+int alpm_remove_target(char *target);
+
/*
* Dependencies and conflicts
*/
@@ -441,6 +438,7 @@ alpm_list_t *alpm_checkconflicts(alpm_list_t *pkglist);
const char *alpm_conflict_get_package1(pmconflict_t *conflict);
const char *alpm_conflict_get_package2(pmconflict_t *conflict);
+const char *alpm_conflict_get_reason(pmconflict_t *conflict);
pmdepmod_t alpm_dep_get_mod(const pmdepend_t *dep);
const char *alpm_dep_get_name(const pmdepend_t *dep);
@@ -509,6 +507,7 @@ enum _pmerrno_t {
PM_ERR_PKG_OPEN,
PM_ERR_PKG_CANT_REMOVE,
PM_ERR_PKG_INVALID_NAME,
+ PM_ERR_PKG_INVALID_ARCH,
PM_ERR_PKG_REPO_NOT_FOUND,
/* Deltas */
PM_ERR_DLT_INVALID,
diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c
index bfe10867..21533ef2 100644
--- a/lib/libalpm/be_files.c
+++ b/lib/libalpm/be_files.c
@@ -51,10 +51,11 @@
* Return the last update time as number of seconds from the epoch.
* Returns 0 if the value is unknown or can't be read.
*/
-static time_t getlastupdate(const pmdb_t *db)
+static time_t getlastupdate(pmdb_t *db)
{
FILE *fp;
char *file;
+ const char *dbpath;
time_t ret = 0;
ALPM_LOG_FUNC;
@@ -63,9 +64,10 @@ static time_t getlastupdate(const pmdb_t *db)
return(ret);
}
- /* db->path + '.lastupdate' + NULL */
- MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret));
- sprintf(file, "%s.lastupdate", db->path);
+ dbpath = _alpm_db_path(db);
+ /* dbpath + '.lastupdate' + NULL */
+ MALLOC(file, strlen(dbpath) + 12, RET_ERR(PM_ERR_MEMORY, ret));
+ sprintf(file, "%s.lastupdate", dbpath);
/* get the last update time, if it's there */
if((fp = fopen(file, "r")) == NULL) {
@@ -85,10 +87,11 @@ static time_t getlastupdate(const pmdb_t *db)
/*
* writes the dbpath/.lastupdate file with the value in time
*/
-static int setlastupdate(const pmdb_t *db, time_t time)
+static int setlastupdate(pmdb_t *db, time_t time)
{
FILE *fp;
char *file;
+ const char *dbpath;
int ret = 0;
ALPM_LOG_FUNC;
@@ -97,9 +100,10 @@ static int setlastupdate(const pmdb_t *db, time_t time)
return(-1);
}
- /* db->path + '.lastupdate' + NULL */
- MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret));
- sprintf(file, "%s.lastupdate", db->path);
+ dbpath = _alpm_db_path(db);
+ /* dbpath + '.lastupdate' + NULL */
+ MALLOC(file, strlen(dbpath) + 12, RET_ERR(PM_ERR_MEMORY, ret));
+ sprintf(file, "%s.lastupdate", dbpath);
if((fp = fopen(file, "w")) == NULL) {
free(file);
@@ -116,7 +120,7 @@ static int setlastupdate(const pmdb_t *db, time_t time)
static int checkdbdir(pmdb_t *db)
{
struct stat buf;
- char *path = db->path;
+ const char *path = _alpm_db_path(db);
if(stat(path, &buf) != 0) {
_alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n",
@@ -148,7 +152,7 @@ static int checkdbdir(pmdb_t *db)
* pmdb_t *db;
* int result;
* db = alpm_list_getdata(alpm_option_get_syncdbs());
- * if(alpm_trans_init(PM_TRANS_TYPE_SYNC, 0, NULL, NULL, NULL) == 0) {
+ * if(alpm_trans_init(0, NULL, NULL, NULL) == 0) {
* result = alpm_db_update(0, db);
* alpm_trans_release();
*
@@ -191,7 +195,6 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
*/
ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
- ASSERT(handle->trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1));
if(!alpm_list_find_ptr(handle->dbs_sync, db)) {
RET_ERR(PM_ERR_DB_NOT_FOUND, -1);
@@ -225,8 +228,9 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
_alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast());
return(-1);
} else {
+ const char *syncdbpath = _alpm_db_path(db);
/* remove the old dir */
- if(_alpm_rmrf(db->path) != 0) {
+ if(_alpm_rmrf(syncdbpath) != 0) {
_alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename);
RET_ERR(PM_ERR_DB_REMOVE, -1);
}
@@ -241,7 +245,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
/* uncompress the sync database */
checkdbdir(db);
- ret = _alpm_unpack(dbfilepath, db->path, NULL);
+ ret = _alpm_unpack(dbfilepath, syncdbpath, NULL);
if(ret) {
free(dbfilepath);
RET_ERR(PM_ERR_SYSTEM, -1);
@@ -306,13 +310,15 @@ int _alpm_db_populate(pmdb_t *db)
struct dirent *ent = NULL;
struct stat sbuf;
char path[PATH_MAX];
+ const char *dbpath;
DIR *dbdir;
ALPM_LOG_FUNC;
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- dbdir = opendir(db->path);
+ dbpath = _alpm_db_path(db);
+ dbdir = opendir(dbpath);
if(dbdir == NULL) {
return(0);
}
@@ -324,7 +330,7 @@ int _alpm_db_populate(pmdb_t *db)
continue;
}
/* stat the entry, make sure it's a directory */
- snprintf(path, PATH_MAX, "%s%s", db->path, name);
+ snprintf(path, PATH_MAX, "%s%s", dbpath, name);
if(stat(path, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) {
continue;
}
@@ -367,10 +373,12 @@ static char *get_pkgpath(pmdb_t *db, pmpkg_t *info)
{
size_t len;
char *pkgpath;
+ const char *dbpath;
- len = strlen(db->path) + strlen(info->name) + strlen(info->version) + 3;
+ dbpath = _alpm_db_path(db);
+ len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3;
MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL));
- sprintf(pkgpath, "%s%s-%s/", db->path, info->name, info->version);
+ sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version);
return(pkgpath);
}
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 07ef73cf..e934c01e 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -41,7 +41,7 @@
#include "cache.h"
#include "deps.h"
-pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2)
+pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason)
{
pmconflict_t *conflict;
@@ -51,6 +51,7 @@ pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2)
STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL));
STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(conflict->reason, reason, RET_ERR(PM_ERR_MEMORY, NULL));
return(conflict);
}
@@ -59,6 +60,7 @@ void _alpm_conflict_free(pmconflict_t *conflict)
{
FREE(conflict->package2);
FREE(conflict->package1);
+ FREE(conflict->reason);
FREE(conflict);
}
@@ -69,6 +71,7 @@ pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict)
STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL));
STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL));
+ STRDUP(newconflict->reason, conflict->reason, RET_ERR(PM_ERR_MEMORY, NULL));
return(newconflict);
}
@@ -122,9 +125,9 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2)
* @param pkg2 package causing conflict
*/
static void add_conflict(alpm_list_t **baddeps, const char *pkg1,
- const char *pkg2)
+ const char *pkg2, const char *reason)
{
- pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2);
+ pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2, reason);
if(conflict && !_alpm_conflict_isin(conflict, *baddeps)) {
*baddeps = alpm_list_add(*baddeps, conflict);
} else {
@@ -168,9 +171,9 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2,
if(does_conflict(pkg1, conflict, pkg2)) {
if(order >= 0) {
- add_conflict(baddeps, pkg1name, pkg2name);
+ add_conflict(baddeps, pkg1name, pkg2name, conflict);
} else {
- add_conflict(baddeps, pkg2name, pkg1name);
+ add_conflict(baddeps, pkg2name, pkg1name, conflict);
}
}
}
@@ -513,7 +516,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans,
/* skip removal of file, but not add. this will prevent a second
* package from removing the file when it was already installed
* by its new owner (whether the file is in backup array or not */
- trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(path));
+ trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(filestr));
_alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s\n", filestr);
resolved_conflict = 1;
}
@@ -578,6 +581,17 @@ const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict)
return conflict->package2;
}
+const char SYMEXPORT *alpm_conflict_get_reason(pmconflict_t *conflict)
+{
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(handle != NULL, return(NULL));
+ ASSERT(conflict != NULL, return(NULL));
+
+ return conflict->reason;
+}
+
const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict)
{
ALPM_LOG_FUNC;
diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h
index 149c728e..73a6e959 100644
--- a/lib/libalpm/conflict.h
+++ b/lib/libalpm/conflict.h
@@ -27,6 +27,7 @@
struct __pmconflict_t {
char *package1;
char *package2;
+ char *reason;
};
struct __pmfileconflict_t {
@@ -36,7 +37,7 @@ struct __pmfileconflict_t {
char *ctarget;
};
-pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2);
+pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason);
pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict);
void _alpm_conflict_free(pmconflict_t *conflict);
int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack);
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index 62c2e0a3..e57ff935 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -323,18 +323,15 @@ alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles)
/** @} */
-pmdb_t *_alpm_db_new(const char *dbpath, const char *treename)
+static pmdb_t *_alpm_db_new(const char *treename, unsigned short is_local)
{
pmdb_t *db;
- const size_t pathsize = strlen(dbpath) + strlen(treename) + 2;
ALPM_LOG_FUNC;
CALLOC(db, 1, sizeof(pmdb_t), RET_ERR(PM_ERR_MEMORY, NULL));
- CALLOC(db->path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));
-
- sprintf(db->path, "%s%s/", dbpath, treename);
STRDUP(db->treename, treename, RET_ERR(PM_ERR_MEMORY, NULL));
+ db->is_local = is_local;
return(db);
}
@@ -347,13 +344,44 @@ void _alpm_db_free(pmdb_t *db)
_alpm_db_free_pkgcache(db);
/* cleanup server list */
FREELIST(db->servers);
- FREE(db->path);
+ FREE(db->_path);
FREE(db->treename);
FREE(db);
return;
}
+const char *_alpm_db_path(pmdb_t *db)
+{
+ if(!db) {
+ return(NULL);
+ }
+ if(!db->_path) {
+ const char *dbpath;
+ size_t pathsize;
+
+ dbpath = alpm_option_get_dbpath();
+ if(!dbpath) {
+ _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
+ RET_ERR(PM_ERR_DB_OPEN, NULL);
+ }
+
+ if(db->is_local) {
+ pathsize = strlen(dbpath) + strlen(db->treename) + 2;
+ CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));
+ sprintf(db->_path, "%s%s/", dbpath, db->treename);
+ } else {
+ pathsize = strlen(dbpath) + 5 + strlen(db->treename) + 2;
+ CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));
+ /* all sync DBs now reside in the sync/ subdir of the dbpath */
+ sprintf(db->_path, "%ssync/%s/", dbpath, db->treename);
+ }
+ _alpm_log(PM_LOG_DEBUG, "database path for tree %s set to %s\n",
+ db->treename, db->_path);
+ }
+ return(db->_path);
+}
+
int _alpm_db_cmp(const void *d1, const void *d2)
{
pmdb_t *db1 = (pmdb_t *)d1;
@@ -440,7 +468,6 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles)
pmdb_t *_alpm_db_register_local(void)
{
pmdb_t *db;
- const char *dbpath;
ALPM_LOG_FUNC;
@@ -451,13 +478,7 @@ pmdb_t *_alpm_db_register_local(void)
_alpm_log(PM_LOG_DEBUG, "registering local database\n");
- dbpath = alpm_option_get_dbpath();
- if(!dbpath) {
- _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
- RET_ERR(PM_ERR_DB_OPEN, NULL);
- }
-
- db = _alpm_db_new(dbpath, "local");
+ db = _alpm_db_new("local", 1);
if(db == NULL) {
RET_ERR(PM_ERR_DB_CREATE, NULL);
}
@@ -469,8 +490,6 @@ pmdb_t *_alpm_db_register_local(void)
pmdb_t *_alpm_db_register_sync(const char *treename)
{
pmdb_t *db;
- const char *dbpath;
- char path[PATH_MAX];
alpm_list_t *i;
ALPM_LOG_FUNC;
@@ -485,15 +504,7 @@ pmdb_t *_alpm_db_register_sync(const char *treename)
_alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename);
- dbpath = alpm_option_get_dbpath();
- if(!dbpath) {
- _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
- RET_ERR(PM_ERR_DB_OPEN, NULL);
- }
- /* all sync DBs now reside in the sync/ subdir of the dbpath */
- snprintf(path, PATH_MAX, "%ssync/", dbpath);
-
- db = _alpm_db_new(path, treename);
+ db = _alpm_db_new(treename, 0);
if(db == NULL) {
RET_ERR(PM_ERR_DB_CREATE, NULL);
}
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index 950ace22..29816032 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -40,18 +40,20 @@ typedef enum _pmdbinfrq_t {
/* Database */
struct __pmdb_t {
- char *path;
char *treename;
+ /* do not access directly, use _alpm_db_path(db) for lazy access */
+ char *_path;
unsigned short pkgcache_loaded;
- alpm_list_t *pkgcache;
unsigned short grpcache_loaded;
+ unsigned short is_local;
+ alpm_list_t *pkgcache;
alpm_list_t *grpcache;
alpm_list_t *servers;
};
/* db.c, database general calls */
-pmdb_t *_alpm_db_new(const char *dbpath, const char *treename);
void _alpm_db_free(pmdb_t *db);
+const char *_alpm_db_path(pmdb_t *db);
int _alpm_db_cmp(const void *d1, const void *d2);
alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles);
pmdb_t *_alpm_db_register_local(void);
diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c
index 599a1b76..523968ec 100644
--- a/lib/libalpm/delta.c
+++ b/lib/libalpm/delta.c
@@ -71,34 +71,16 @@ off_t SYMEXPORT alpm_delta_get_size(pmdelta_t *delta)
/** @} */
-static alpm_list_t *delta_graph_init(alpm_list_t *deltas)
+static alpm_list_t *graph_init(alpm_list_t *deltas)
{
alpm_list_t *i, *j;
alpm_list_t *vertices = NULL;
/* create the vertices */
for(i = deltas; i; i = i->next) {
- char *fpath, *md5sum;
pmgraph_t *v = _alpm_graph_new();
pmdelta_t *vdelta = i->data;
vdelta->download_size = vdelta->delta_size;
v->weight = LONG_MAX;
-
- /* determine whether the delta file already exists */
- fpath = _alpm_filecache_find(vdelta->delta);
- md5sum = alpm_compute_md5sum(fpath);
- if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) {
- vdelta->download_size = 0;
- }
- FREE(fpath);
- FREE(md5sum);
-
- /* determine whether a base 'from' file exists */
- fpath = _alpm_filecache_find(vdelta->from);
- if(fpath) {
- v->weight = vdelta->download_size;
- }
- FREE(fpath);
-
v->data = vdelta;
vertices = alpm_list_add(vertices, v);
}
@@ -128,8 +110,36 @@ static alpm_list_t *delta_graph_init(alpm_list_t *deltas)
return(vertices);
}
-static off_t delta_vert(alpm_list_t *vertices,
- const char *to, alpm_list_t **path) {
+static void graph_init_size(alpm_list_t *vertices)
+{
+ alpm_list_t *i;
+
+ for(i = vertices; i; i = i->next) {
+ char *fpath, *md5sum;
+ pmgraph_t *v = i->data;
+ pmdelta_t *vdelta = v->data;
+
+ /* determine whether the delta file already exists */
+ fpath = _alpm_filecache_find(vdelta->delta);
+ md5sum = alpm_compute_md5sum(fpath);
+ if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) {
+ vdelta->download_size = 0;
+ }
+ FREE(fpath);
+ FREE(md5sum);
+
+ /* determine whether a base 'from' file exists */
+ fpath = _alpm_filecache_find(vdelta->from);
+ if(fpath) {
+ v->weight = vdelta->download_size;
+ }
+ FREE(fpath);
+ }
+}
+
+
+static void dijkstra(alpm_list_t *vertices)
+{
alpm_list_t *i;
pmgraph_t *v;
while(1) {
@@ -165,9 +175,14 @@ static off_t delta_vert(alpm_list_t *vertices,
}
}
+}
- v = NULL;
+static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t **path)
+{
+ alpm_list_t *i;
+ pmgraph_t *v = NULL;
off_t bestsize = 0;
+ alpm_list_t *rpath = NULL;
for(i = vertices; i; i = i->next) {
pmgraph_t *v_i = i->data;
@@ -181,7 +196,6 @@ static off_t delta_vert(alpm_list_t *vertices,
}
}
- alpm_list_t *rpath = NULL;
while(v != NULL) {
pmdelta_t *vdelta = v->data;
rpath = alpm_list_add(rpath, vdelta);
@@ -219,9 +233,10 @@ off_t _alpm_shortest_delta_path(alpm_list_t *deltas,
_alpm_log(PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to);
- vertices = delta_graph_init(deltas);
-
- bestsize = delta_vert(vertices, to, &bestpath);
+ vertices = graph_init(deltas);
+ graph_init_size(vertices);
+ dijkstra(vertices);
+ bestsize = shortest_path(vertices, to, &bestpath);
_alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize);
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index 02a4c7b6..46699ac6 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -605,7 +605,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *pkg,
ALPM_LOG_FUNC;
- if(local == NULL || dbs_sync == NULL) {
+ if(local == NULL) {
return(-1);
}
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 10be5e9d..8b3226bd 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -76,30 +76,6 @@ static char *get_tempfile(const char *path, const char *filename) {
return(tempfile);
}
-/* Build a 'struct url' from an url. */
-static struct url *url_for_string(const char *url)
-{
- struct url *ret = NULL;
- ret = fetchParseURL(url);
- if(!ret) {
- _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url);
- RET_ERR(PM_ERR_SERVER_BAD_URL, NULL);
- }
-
- /* if no URL scheme specified, assume HTTP */
- if(strlen(ret->scheme) == 0) {
- _alpm_log(PM_LOG_WARNING, _("url scheme not specified, assuming HTTP\n"));
- strcpy(ret->scheme, SCHEME_HTTP);
- }
- /* add a user & password for anonymous FTP */
- if(strcmp(ret->scheme,SCHEME_FTP) == 0 && strlen(ret->user) == 0) {
- strcpy(ret->user, "anonymous");
- strcpy(ret->pwd, "libalpm@guest");
- }
-
- return(ret);
-}
-
static const char *gethost(struct url *fileurl)
{
const char *host = _("disk");
@@ -120,17 +96,20 @@ static int download_internal(const char *url, const char *localpath,
ssize_t nread = 0;
char *tempfile, *destfile, *filename;
struct sigaction new_action, old_action;
- struct url *fileurl = url_for_string(url);
+ struct url *fileurl;
char buffer[PM_DLBUF_LEN];
- if(!fileurl) {
- return(-1);
- }
-
filename = get_filename(url);
if(!filename) {
return(-1);
}
+
+ fileurl = fetchParseURL(url);
+ if(!fileurl) {
+ _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url);
+ RET_ERR(PM_ERR_SERVER_BAD_URL, -1);
+ }
+
destfile = get_destfile(localpath, filename);
tempfile = get_tempfile(localpath, filename);
@@ -171,7 +150,7 @@ static int download_internal(const char *url, const char *localpath,
sigaction(SIGPIPE, NULL, &old_action);
sigaction(SIGPIPE, &new_action, NULL);
- dlf = fetchXGet(fileurl, &ust, (handle->nopassiveftp ? "i" : "pi"));
+ dlf = fetchXGet(fileurl, &ust, "i");
if(fetchLastErrCode == FETCH_UNCHANGED) {
_alpm_log(PM_LOG_DEBUG, "mtimes are identical, skipping %s\n", filename);
@@ -220,14 +199,12 @@ static int download_internal(const char *url, const char *localpath,
while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) {
size_t nwritten = 0;
- while(nwritten < nread) {
- nwritten += fwrite(buffer, 1, (nread - nwritten), localf);
- if(ferror(localf)) {
- _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"),
- destfile, strerror(errno));
- ret = -1;
- goto cleanup;
- }
+ nwritten = fwrite(buffer, 1, nread, localf);
+ if((nwritten != nread) || ferror(localf)) {
+ _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"),
+ destfile, strerror(errno));
+ ret = -1;
+ goto cleanup;
}
dl_thisfile += nread;
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index 81aaa8b1..ae19786e 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -117,8 +117,10 @@ const char SYMEXPORT *alpm_strerror(int err)
return _("cannot remove all files for package");
case PM_ERR_PKG_INVALID_NAME:
return _("package filename is not valid");
+ case PM_ERR_PKG_INVALID_ARCH:
+ return _("package architecture is not valid");
case PM_ERR_PKG_REPO_NOT_FOUND:
- return _("no such repository");
+ return _("could not find repository for target");
/* Deltas */
case PM_ERR_DLT_INVALID:
return _("invalid or corrupted delta");
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index d1a35ad9..012d4121 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -79,6 +79,7 @@ void _alpm_handle_free(pmhandle_t *handle)
FREELIST(handle->cachedirs);
FREE(handle->logfile);
FREE(handle->lockfile);
+ FREE(handle->arch);
FREELIST(handle->dbs_sync);
FREELIST(handle->noupgrade);
FREELIST(handle->noextract);
@@ -213,13 +214,13 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps()
return handle->ignoregrp;
}
-unsigned short SYMEXPORT alpm_option_get_nopassiveftp()
+const char SYMEXPORT *alpm_option_get_arch()
{
if (handle == NULL) {
pm_errno = PM_ERR_HANDLE_NULL;
- return -1;
+ return NULL;
}
- return handle->nopassiveftp;
+ return handle->arch;
}
pmdb_t SYMEXPORT *alpm_option_get_localdb()
@@ -529,9 +530,10 @@ int SYMEXPORT alpm_option_remove_ignoregrp(const char *grp)
return(0);
}
-void SYMEXPORT alpm_option_set_nopassiveftp(unsigned short nopasv)
+void SYMEXPORT alpm_option_set_arch(const char *arch)
{
- handle->nopassiveftp = nopasv;
+ if(handle->arch) FREE(handle->arch);
+ if(arch) handle->arch = strdup(arch);
}
void SYMEXPORT alpm_option_set_usedelta(unsigned short usedelta)
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index c7c262cf..a1eb1cde 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -58,7 +58,7 @@ typedef struct _pmhandle_t {
/* options */
unsigned short usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
- unsigned short nopassiveftp; /* Don't use PASV ftp connections */
+ char *arch; /* Architecture of packages we should allow */
unsigned short usedelta; /* Download deltas if possible */
} pmhandle_t;
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index 002b1c89..de171661 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -423,13 +423,6 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg)
return pkg->backup;
}
-alpm_list_t SYMEXPORT *alpm_pkg_get_removes(pmpkg_t *pkg)
-{
- ASSERT(pkg != NULL, return(NULL));
-
- return(pkg->removes);
-}
-
pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg)
{
/* Sanity checks */
@@ -858,7 +851,11 @@ void _alpm_pkg_free(pmpkg_t *pkg)
FREE(pkg);
}
-/* Free transaction specific fields */
+/* This function should be used when removing a target from upgrade/sync target list
+ * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed.
+ * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed,
+ * only the transaction specific fields of pkg will be freed.
+ */
void _alpm_pkg_free_trans(pmpkg_t *pkg)
{
ALPM_LOG_FUNC;
@@ -867,6 +864,11 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg)
return;
}
+ if(pkg->origin == PKG_FROM_FILE) {
+ _alpm_pkg_free(pkg);
+ return;
+ }
+
alpm_list_free(pkg->removes);
pkg->removes = NULL;
}
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 1e8f9156..f31fbfb0 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -47,35 +47,45 @@
#include "handle.h"
#include "alpm.h"
-int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
+int SYMEXPORT alpm_remove_target(char *target)
{
pmpkg_t *info;
- const char *targ;
+ pmtrans_t *trans;
+ pmdb_t *db_local;
+ alpm_list_t *p;
ALPM_LOG_FUNC;
- ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
+ /* Sanity checks */
+ ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ trans = handle->trans;
+ db_local = handle->db_local;
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
+ ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- targ = strchr(name, '/');
- if(targ && strncmp(name, "local", 5) == 0) {
- targ++;
- } else {
- targ = name;
- }
- if(_alpm_pkg_find(trans->packages, targ)) {
+ if(_alpm_pkg_find(trans->remove, target)) {
RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
}
- if((info = _alpm_db_get_pkgfromcache(db, targ)) == NULL) {
- _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", targ);
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ if((info = _alpm_db_get_pkgfromcache(db_local, target)) != NULL) {
+ _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", info->name);
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info));
+ return(0);
}
- _alpm_log(PM_LOG_DEBUG, "adding %s in target list\n", info->name);
- trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info));
+ _alpm_log(PM_LOG_DEBUG, "could not find %s in database\n", target);
+ pmgrp_t *grp = alpm_db_readgrp(db_local, target);
+ if(grp == NULL) {
+ RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ }
+ for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) {
+ pmpkg_t *pkg = alpm_list_getdata(p);
+ _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", pkg->name);
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(pkg));
+ }
return(0);
}
@@ -91,10 +101,10 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db,
pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target);
if(info) {
- if(!_alpm_pkg_find(trans->packages, alpm_pkg_get_name(info))) {
+ if(!_alpm_pkg_find(trans->remove, alpm_pkg_get_name(info))) {
_alpm_log(PM_LOG_DEBUG, "pulling %s in target list\n",
alpm_pkg_get_name(info));
- trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info));
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info));
}
} else {
_alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"),
@@ -103,7 +113,7 @@ static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db,
}
alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
alpm_list_free(lp);
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL);
+ lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL);
}
}
@@ -118,11 +128,11 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db,
for(i = lp; i; i = i->next) {
pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
void *vpkg;
- pmpkg_t *pkg = _alpm_pkg_find(trans->packages, miss->causingpkg);
+ pmpkg_t *pkg = _alpm_pkg_find(trans->remove, miss->causingpkg);
if(pkg == NULL) {
continue;
}
- trans->packages = alpm_list_remove(trans->packages, pkg, _alpm_pkg_cmp,
+ trans->remove = alpm_list_remove(trans->remove, pkg, _alpm_pkg_cmp,
&vpkg);
pkg = vpkg;
if(pkg) {
@@ -133,7 +143,7 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db,
}
alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
alpm_list_free(lp);
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL);
+ lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL);
}
}
@@ -146,21 +156,16 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- /* skip all checks if we are doing this removal as part of an upgrade */
- if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
- return(0);
- }
-
if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) {
_alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n");
- _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL);
+ _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n");
- lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->packages, NULL);
+ lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL);
if(lp != NULL) {
if(trans->flags & PM_TRANS_FLAG_CASCADE) {
@@ -183,15 +188,15 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
/* re-order w.r.t. dependencies */
_alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n");
- lp = _alpm_sortbydeps(trans->packages, 1);
+ lp = _alpm_sortbydeps(trans->remove, 1);
/* free the old alltargs */
- alpm_list_free(trans->packages);
- trans->packages = lp;
+ alpm_list_free(trans->remove);
+ trans->remove = lp;
/* -Rcs == -Rc then -Rs */
if((trans->flags & PM_TRANS_FLAG_CASCADE) && (trans->flags & PM_TRANS_FLAG_RECURSE)) {
_alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n");
- _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL);
+ _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
@@ -201,13 +206,13 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
return(0);
}
-static int can_remove_file(pmtrans_t *trans, const char *path)
+static int can_remove_file(const char *path, alpm_list_t *skip)
{
char file[PATH_MAX+1];
snprintf(file, PATH_MAX, "%s%s", handle->root, path);
- if(alpm_list_find_str(trans->skip_remove, file)) {
+ if(alpm_list_find_str(skip, file)) {
/* return success because we will never actually remove this file */
return(1);
}
@@ -228,7 +233,7 @@ static int can_remove_file(pmtrans_t *trans, const char *path)
/* Helper function for iterating through a package's file and deleting them
* Used by _alpm_remove_commit. */
-static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
+static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, int nosave)
{
struct stat buf;
char file[PATH_MAX+1];
@@ -237,13 +242,13 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
snprintf(file, PATH_MAX, "%s%s", handle->root, filename);
- if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
- /* check noupgrade */
- if(alpm_list_find_str(handle->noupgrade, filename)) {
- _alpm_log(PM_LOG_DEBUG, "Skipping removal of '%s' due to NoUpgrade\n",
- file);
- return;
- }
+ /* check the remove skip list before removing the file.
+ * see the big comment block in db_find_fileconflicts() for an
+ * explanation. */
+ if(alpm_list_find_str(skip_remove, filename)) {
+ _alpm_log(PM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n",
+ file);
+ return;
}
/* we want to do a lstat here, and not a _alpm_lstat.
@@ -263,19 +268,10 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
_alpm_log(PM_LOG_DEBUG, "removing directory %s\n", file);
}
} else {
- /* check the remove skip list before removing the file.
- * see the big comment block in db_find_fileconflicts() for an
- * explanation. */
- if(alpm_list_find_str(trans->skip_remove, file)) {
- _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_remove, skipping removal\n",
- file);
- return;
- }
-
/* if the file needs backup and has been modified, back it up to .pacsave */
char *pkghash = _alpm_needbackup(filename, alpm_pkg_get_backup(info));
if(pkghash) {
- if(trans->flags & PM_TRANS_FLAG_NOSAVE) {
+ if(nosave) {
_alpm_log(PM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file);
FREE(pkghash);
} else {
@@ -303,7 +299,69 @@ static void unlink_file(pmpkg_t *info, char *filename, pmtrans_t *trans)
}
}
-int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
+int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans)
+{
+ alpm_list_t *skip_remove, *b;
+ alpm_list_t *newfiles, *lp;
+ alpm_list_t *files = alpm_pkg_get_files(oldpkg);
+ const char *pkgname = alpm_pkg_get_name(oldpkg);
+
+ ALPM_LOG_FUNC;
+
+ _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n",
+ oldpkg->name, oldpkg->version);
+
+ /* copy the remove skiplist over */
+ skip_remove =
+ alpm_list_join(alpm_list_strdup(trans->skip_remove),alpm_list_strdup(handle->noupgrade));
+ /* Add files in the NEW backup array to the skip_remove array
+ * so this removal operation doesn't kill them */
+ /* old package backup list */
+ alpm_list_t *filelist = alpm_pkg_get_files(newpkg);
+ for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) {
+ char *backup = _alpm_backup_file(b->data);
+ /* safety check (fix the upgrade026 pactest) */
+ if(!alpm_list_find_str(filelist, backup)) {
+ FREE(backup);
+ continue;
+ }
+ _alpm_log(PM_LOG_DEBUG, "adding %s to the skip_remove array\n", backup);
+ skip_remove = alpm_list_add(skip_remove, backup);
+ }
+
+ for(lp = files; lp; lp = lp->next) {
+ if(!can_remove_file(lp->data, skip_remove)) {
+ _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n",
+ pkgname);
+ RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1);
+ }
+ }
+
+ /* iterate through the list backwards, unlinking files */
+ newfiles = alpm_list_reverse(files);
+ for(lp = newfiles; lp; lp = alpm_list_next(lp)) {
+ unlink_file(oldpkg, lp->data, skip_remove, 0);
+ }
+ alpm_list_free(newfiles);
+ FREELIST(skip_remove);
+
+ /* remove the package from the database */
+ _alpm_log(PM_LOG_DEBUG, "updating database\n");
+ _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname);
+ if(_alpm_db_remove(handle->db_local, oldpkg) == -1) {
+ _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"),
+ pkgname, alpm_pkg_get_version(oldpkg));
+ }
+ /* remove the package from the cache */
+ if(_alpm_db_remove_pkgfromcache(handle->db_local, oldpkg) == -1) {
+ _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"),
+ pkgname);
+ }
+
+ return(0);
+}
+
+int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db)
{
pmpkg_t *info;
alpm_list_t *targ, *lp;
@@ -314,12 +372,11 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- pkg_count = alpm_list_count(trans->packages);
+ pkg_count = alpm_list_count(trans->remove);
- for(targ = trans->packages; targ; targ = targ->next) {
+ for(targ = trans->remove; targ; targ = targ->next) {
int position = 0;
char scriptlet[PATH_MAX];
- alpm_list_t *files;
info = (pmpkg_t*)targ->data;
const char *pkgname = NULL;
@@ -329,26 +386,24 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
/* get the name now so we can use it after package is removed */
pkgname = alpm_pkg_get_name(info);
- snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path,
- pkgname, alpm_pkg_get_version(info));
-
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL);
- _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n",
- pkgname, alpm_pkg_get_version(info));
-
- /* run the pre-remove scriptlet if it exists */
- if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
- _alpm_runscriptlet(handle->root, scriptlet, "pre_remove",
- alpm_pkg_get_version(info), NULL, trans);
- }
+ snprintf(scriptlet, PATH_MAX, "%s%s-%s/install",
+ _alpm_db_path(db), pkgname, alpm_pkg_get_version(info));
+
+ EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL);
+ _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n",
+ pkgname, alpm_pkg_get_version(info));
+
+ /* run the pre-remove scriptlet if it exists */
+ if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
+ _alpm_runscriptlet(handle->root, scriptlet, "pre_remove",
+ alpm_pkg_get_version(info), NULL, trans);
}
- files = alpm_pkg_get_files(info);
if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) {
+ alpm_list_t *files = alpm_pkg_get_files(info);
for(lp = files; lp; lp = lp->next) {
- if(!can_remove_file(trans, lp->data)) {
+ if(!can_remove_file(lp->data, NULL)) {
_alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n",
pkgname);
RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1);
@@ -363,7 +418,7 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
/* iterate through the list backwards, unlinking files */
newfiles = alpm_list_reverse(files);
for(lp = newfiles; lp; lp = alpm_list_next(lp)) {
- unlink_file(info, lp->data, trans);
+ unlink_file(info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE);
/* update progress bar after each file */
percent = (double)position / (double)filenum;
@@ -379,12 +434,10 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, pkgname, 100,
pkg_count, (pkg_count - alpm_list_count(targ) + 1));
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- /* run the post-remove script if it exists */
- if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
- _alpm_runscriptlet(handle->root, scriptlet, "post_remove",
- alpm_pkg_get_version(info), NULL, trans);
- }
+ /* run the post-remove script if it exists */
+ if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
+ _alpm_runscriptlet(handle->root, scriptlet, "post_remove",
+ alpm_pkg_get_version(info), NULL, trans);
}
/* remove the package from the database */
@@ -400,16 +453,11 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
pkgname);
}
- /* call a done event if this isn't an upgrade */
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL);
- }
+ EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL);
}
/* run ldconfig if it exists */
- if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
- _alpm_ldconfig(handle->root);
- }
+ _alpm_ldconfig(handle->root);
return(0);
}
diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h
index 716fbf72..fbbaa169 100644
--- a/lib/libalpm/remove.h
+++ b/lib/libalpm/remove.h
@@ -24,9 +24,10 @@
#include "alpm_list.h"
#include "trans.h"
-int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name);
int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data);
-int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db);
+int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db);
+
+int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans);
#endif /* _ALPM_REMOVE_H */
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 47639248..a1a6ea7c 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -43,11 +43,13 @@
#include "deps.h"
#include "conflict.h"
#include "trans.h"
+#include "add.h"
#include "util.h"
#include "handle.h"
#include "alpm.h"
#include "dload.h"
#include "delta.h"
+#include "remove.h"
/** Check for new version of pkg in sync repos
* (only the first occurrence is considered in sync)
@@ -80,17 +82,30 @@ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync)
return(NULL);
}
-int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade)
+/** Search for packages to upgrade and add them to the transaction.
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade)
{
alpm_list_t *i, *j, *k;
+ pmtrans_t *trans;
+ pmdb_t *db_local;
+ alpm_list_t *dbs_sync;
ALPM_LOG_FUNC;
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ trans = handle->trans;
+ db_local = handle->db_local;
+ dbs_sync = handle->dbs_sync;
+ ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+ ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
+
_alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n");
for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) {
pmpkg_t *lpkg = i->data;
- if(_alpm_pkg_find(trans->packages, lpkg->name)) {
+ if(_alpm_pkg_find(trans->add, lpkg->name)) {
_alpm_log(PM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name);
continue;
}
@@ -113,7 +128,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
} else {
_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
spkg->name, spkg->version);
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
}
} else if(cmp < 0) {
if(enable_downgrade) {
@@ -124,7 +139,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
} else {
_alpm_log(PM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"),
lpkg->name, lpkg->version, spkg->version);
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
}
} else {
_alpm_log(PM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"),
@@ -152,7 +167,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
}
/* If spkg is already in the target list, we append lpkg to spkg's removes list */
- pmpkg_t *tpkg = _alpm_pkg_find(trans->packages, spkg->name);
+ pmpkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name);
if(tpkg) {
/* sanity check, multiple repos can contain spkg->name */
if(tpkg->origin_data.db != sdb) {
@@ -173,7 +188,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
spkg->removes = alpm_list_add(NULL, lpkg);
_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
spkg->name, spkg->version);
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
}
}
}
@@ -187,57 +202,18 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_s
return(0);
}
-int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name)
+int _alpm_sync_pkg(pmpkg_t *spkg)
{
- char *targline;
- char *targ;
- alpm_list_t *j;
- pmpkg_t *local, *spkg;
- pmdepend_t *dep; /* provisions and dependencies are also allowed */
+ pmtrans_t *trans;
+ pmdb_t *db_local;
+ pmpkg_t *local;
ALPM_LOG_FUNC;
- ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
-
- STRDUP(targline, name, RET_ERR(PM_ERR_MEMORY, -1));
- targ = strchr(targline, '/');
- if(targ) {
- /* we are looking for a package in a specific database */
- alpm_list_t *dbs = NULL;
- *targ = '\0';
- targ++;
- _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", targ, targline);
- for(j = dbs_sync; j; j = j->next) {
- pmdb_t *db = j->data;
- if(strcmp(db->treename, targline) == 0) {
- dbs = alpm_list_add(NULL, db);
- break;
- }
- }
- if(dbs == NULL) {
- _alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline);
- FREE(targline);
- RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1);
- }
- dep = _alpm_splitdep(targ);
- spkg = _alpm_resolvedep(dep, dbs, NULL, 1);
- _alpm_dep_free(dep);
- alpm_list_free(dbs);
- } else {
- dep = _alpm_splitdep(targline);
- spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1);
- _alpm_dep_free(dep);
- }
- FREE(targline);
-
- if(spkg == NULL) {
- /* pm_errno is set by _alpm_resolvedep */
- return(-1);
- }
+ trans = handle->trans;
+ db_local = handle->db_local;
- if(_alpm_pkg_find(trans->packages, alpm_pkg_get_name(spkg))) {
+ if(_alpm_pkg_find(trans->add, alpm_pkg_get_name(spkg))) {
RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
}
@@ -267,11 +243,108 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
spkg->reason = PM_PKG_REASON_EXPLICIT;
_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg));
- trans->packages = alpm_list_add(trans->packages, spkg);
+ trans->add = alpm_list_add(trans->add, spkg);
return(0);
}
+int _alpm_sync_target(alpm_list_t *dbs_sync, char *target)
+{
+ alpm_list_t *i, *j;
+ pmpkg_t *spkg;
+ pmdepend_t *dep; /* provisions and dependencies are also allowed */
+ pmgrp_t *grp;
+ int found = 0;
+
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+
+ dep = _alpm_splitdep(target);
+ spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1);
+ _alpm_dep_free(dep);
+
+ if(spkg != NULL) {
+ return(_alpm_sync_pkg(spkg));
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "%s package not found, searching for group...\n", target);
+ for(i = dbs_sync; i; i = i->next) {
+ pmdb_t *db = i->data;
+ grp = alpm_db_readgrp(db, target);
+ if(grp) {
+ found = 1;
+ for(j = alpm_grp_get_pkgs(grp); j; j = j->next) {
+ pmpkg_t *pkg = j->data;
+ if(_alpm_sync_pkg(pkg) == -1) {
+ if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) {
+ /* just skip duplicate or ignored targets */
+ continue;
+ } else {
+ return(-1);
+ }
+ }
+ }
+ }
+ }
+
+ if(!found) {
+ RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ }
+
+ return(0);
+}
+
+/** Add a sync target to the transaction.
+ * @param target the name of the sync target to add
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_sync_dbtarget(char *dbname, char *target)
+{
+ alpm_list_t *i;
+ alpm_list_t *dbs_sync;
+
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ dbs_sync = handle->dbs_sync;
+
+ /* we are looking for a package in a specific database */
+ alpm_list_t *dbs = NULL;
+ _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", target, dbname);
+ for(i = dbs_sync; i; i = i->next) {
+ pmdb_t *db = i->data;
+ if(strcmp(db->treename, dbname) == 0) {
+ dbs = alpm_list_add(NULL, db);
+ break;
+ }
+ }
+ if(dbs == NULL) {
+ RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1);
+ }
+ return(_alpm_sync_target(dbs, target));
+}
+
+/** Add a sync target to the transaction.
+ * @param target the name of the sync target to add
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_sync_target(char *target)
+{
+ alpm_list_t *dbs_sync;
+
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ dbs_sync = handle->dbs_sync;
+
+ return(_alpm_sync_target(dbs_sync,target));
+}
+
/** Compute the size of the files that will be downloaded to install a
* package.
* @param newpkg the new package to upgrade to
@@ -282,6 +355,11 @@ static int compute_download_size(pmpkg_t *newpkg)
char *fpath;
off_t size = 0;
+ if(newpkg->origin == PKG_FROM_FILE) {
+ newpkg->download_size = 0;
+ return(0);
+ }
+
fname = alpm_pkg_get_filename(newpkg);
ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1));
fpath = _alpm_filecache_find(fname);
@@ -323,8 +401,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
alpm_list_t *deps = NULL;
alpm_list_t *preferred = NULL;
alpm_list_t *unresolvable = NULL;
- alpm_list_t *remove = NULL; /* allow checkdeps usage with trans->packages */
alpm_list_t *i, *j;
+ alpm_list_t *remove = NULL;
int ret = 0;
ALPM_LOG_FUNC;
@@ -345,7 +423,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
_alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n");
/* build remove list and preferred list for resolvedeps */
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
for(j = spkg->removes; j; j = j->next) {
remove = alpm_list_add(remove, j->data);
@@ -355,7 +433,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* Resolve packages in the transaction one at a time, in addtion
building up a list of packages which could not be resolved. */
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *pkg = i->data;
if(_alpm_resolvedeps(db_local, dbs_sync, pkg, preferred,
&resolved, remove, data) == -1) {
@@ -392,21 +470,21 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
}
}
- /* Unresolvable packages will be removed from the target list, so
- we free the transaction specific fields */
- alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans);
-
/* Set DEPEND reason for pulled packages */
for(i = resolved; i; i = i->next) {
pmpkg_t *pkg = i->data;
- if(!_alpm_pkg_find(trans->packages, pkg->name)) {
+ if(!_alpm_pkg_find(trans->add, pkg->name)) {
pkg->reason = PM_PKG_REASON_DEPEND;
}
}
+ /* Unresolvable packages will be removed from the target list, so
+ we free the transaction specific fields */
+ alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans);
+
/* re-order w.r.t. dependencies */
- alpm_list_free(trans->packages);
- trans->packages = _alpm_sortbydeps(resolved, 0);
+ alpm_list_free(trans->add);
+ trans->add = _alpm_sortbydeps(resolved, 0);
alpm_list_free(resolved);
EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL);
@@ -420,15 +498,15 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* 1. check for conflicts in the target list */
_alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
- deps = _alpm_innerconflicts(trans->packages);
+ deps = _alpm_innerconflicts(trans->add);
for(i = deps; i; i = i->next) {
pmconflict_t *conflict = i->data;
pmpkg_t *rsync, *sync, *sync1, *sync2;
/* have we already removed one of the conflicting targets? */
- sync1 = _alpm_pkg_find(trans->packages, conflict->package1);
- sync2 = _alpm_pkg_find(trans->packages, conflict->package2);
+ sync1 = _alpm_pkg_find(trans->add, conflict->package1);
+ sync2 = _alpm_pkg_find(trans->add, conflict->package2);
if(!sync1 || !sync2) {
continue;
}
@@ -468,8 +546,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
_alpm_log(PM_LOG_WARNING,
_("removing '%s' from target list because it conflicts with '%s'\n"),
rsync->name, sync->name);
+ trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL);
_alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */
- trans->packages = alpm_list_remove(trans->packages, rsync, _alpm_pkg_cmp, NULL);
continue;
}
@@ -479,7 +557,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* 2. we check for target vs db conflicts (and resolve)*/
_alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n");
- deps = _alpm_outerconflicts(db_local, trans->packages);
+ deps = _alpm_outerconflicts(db_local, trans->add);
for(i = deps; i; i = i->next) {
pmconflict_t *conflict = i->data;
@@ -487,7 +565,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* if conflict->package2 (the local package) is not elected for removal,
we ask the user */
int found = 0;
- for(j = trans->packages; j && !found; j = j->next) {
+ for(j = trans->add; j && !found; j = j->next) {
pmpkg_t *spkg = j->data;
if(_alpm_pkg_find(spkg->removes, conflict->package2)) {
found = 1;
@@ -500,11 +578,11 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
_alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
conflict->package1, conflict->package2);
- pmpkg_t *sync = _alpm_pkg_find(trans->packages, conflict->package1);
+ pmpkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1);
pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
int doremove = 0;
QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
- conflict->package2, NULL, &doremove);
+ conflict->package2, conflict->reason, &doremove);
if(doremove) {
/* append to the removes list */
_alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2);
@@ -532,16 +610,16 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
/* rebuild remove list */
alpm_list_free(remove);
- remove = NULL;
- for(i = trans->packages; i; i = i->next) {
+ trans->remove = NULL;
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
for(j = spkg->removes; j; j = j->next) {
- remove = alpm_list_add(remove, j->data);
+ trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(j->data));
}
}
_alpm_log(PM_LOG_DEBUG, "checking dependencies\n");
- deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, remove, trans->packages);
+ deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, trans->remove, trans->add);
if(deps) {
pm_errno = PM_ERR_UNSATISFIED_DEPS;
ret = -1;
@@ -554,7 +632,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
goto cleanup;
}
}
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
/* update download size field */
pmpkg_t *spkg = i->data;
if(compute_download_size(spkg) != 0) {
@@ -564,7 +642,6 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
}
cleanup:
- alpm_list_free(remove);
alpm_list_free(unresolvable);
return(ret);
@@ -601,7 +678,7 @@ static int apply_deltas(pmtrans_t *trans)
int ret = 0;
const char *cachedir = _alpm_filecache_setup();
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
alpm_list_t *delta_path = spkg->delta_path;
alpm_list_t *dlts = NULL;
@@ -711,7 +788,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
{
alpm_list_t *i, *j, *files = NULL;
alpm_list_t *deltas = NULL;
- pmtrans_t *tr_remove = NULL, *tr_upgrade = NULL;
int replaces = 0;
int errors = 0;
const char *cachedir = NULL;
@@ -730,7 +806,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
if(handle->totaldlcb) {
off_t total_size = (off_t)0;
/* sum up the download size for each package and store total */
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
total_size += spkg->download_size;
}
@@ -741,11 +817,10 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
for(i = handle->dbs_sync; i; i = i->next) {
pmdb_t *current = i->data;
- for(j = trans->packages; j; j = j->next) {
+ for(j = trans->add; j; j = j->next) {
pmpkg_t *spkg = j->data;
- pmdb_t *dbs = spkg->origin_data.db;
- if(current == dbs) {
+ if(spkg->origin == PKG_FROM_CACHE && current == spkg->origin_data.db) {
const char *fname = NULL;
fname = alpm_pkg_get_filename(spkg);
@@ -835,15 +910,36 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL);
errors = 0;
- for(i = trans->packages; i; i = i->next) {
+ for(i = trans->add; i; i = i->next) {
pmpkg_t *spkg = i->data;
+ if(spkg->origin == PKG_FROM_FILE) {
+ continue; /* pkg_load() has been already called, this package is valid */
+ }
+
const char *filename = alpm_pkg_get_filename(spkg);
const char *md5sum = alpm_pkg_get_md5sum(spkg);
if(test_md5sum(trans, filename, md5sum) != 0) {
errors++;
*data = alpm_list_add(*data, strdup(filename));
+ continue;
+ }
+ /* load the package file and replace pkgcache entry with it in the target list */
+ /* TODO: alpm_pkg_get_db() will not work on this target anymore */
+ _alpm_log(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name);
+ char *filepath = _alpm_filecache_find(filename);
+ pmpkg_t *pkgfile;
+ if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) {
+ _alpm_pkg_free(pkgfile);
+ errors++;
+ *data = alpm_list_add(*data, strdup(filename));
+ FREE(filepath);
+ continue;
}
+ FREE(filepath);
+ pkgfile->reason = spkg->reason; /* copy over install reason */
+ i->data = pkgfile;
+ _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */
}
if(errors) {
pm_errno = PM_ERR_PKG_INVALID;
@@ -856,71 +952,15 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
trans->state = STATE_COMMITING;
- /* Create remove and upgrade transactions */
- tr_remove = _alpm_trans_new();
- if(tr_remove == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n"));
- goto error;
- }
- tr_upgrade = _alpm_trans_new();
- if(tr_upgrade == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not create transaction\n"));
- goto error;
- }
-
- if(_alpm_trans_init(tr_remove, PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, NULL, NULL, NULL) == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not initialize the removal transaction\n"));
- goto error;
- }
- if(_alpm_trans_init(tr_upgrade, PM_TRANS_TYPE_UPGRADE, trans->flags, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not initialize transaction\n"));
- goto error;
- }
-
- /* adding targets */
- for(i = trans->packages; i; i = i->next) {
- pmpkg_t *spkg = i->data;
- alpm_list_t *j;
- /* remove transaction */
- for(j = spkg->removes; j; j = j->next) {
- pmpkg_t *pkg = j->data;
- if(!_alpm_pkg_find(tr_remove->packages, pkg->name)) {
- if(_alpm_trans_addtarget(tr_remove, pkg->name) == -1) {
- goto error;
- }
- replaces++;
- }
- }
- /* upgrade transaction */
- const char *fname;
- char *fpath;
-
- fname = alpm_pkg_get_filename(spkg);
- if(fname == NULL) {
- goto error;
- }
- /* Loop through the cache dirs until we find a matching file */
- fpath = _alpm_filecache_find(fname);
-
- if(_alpm_trans_addtarget(tr_upgrade, fpath) == -1) {
- FREE(fpath);
- goto error;
- }
- FREE(fpath);
-
- /* using alpm_list_last() is ok because addtarget() adds the new target at the
- * end of the tr->packages list */
- pmpkg_t *ipkg = alpm_list_last(tr_upgrade->packages)->data;
- ipkg->reason = spkg->reason;
- }
+ replaces = alpm_list_count(trans->remove);
/* fileconflict check */
if(!(trans->flags & PM_TRANS_FLAG_FORCE)) {
EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n");
- alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, tr_upgrade,
- tr_upgrade->packages, tr_remove->packages);
+ alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans,
+ trans->add, trans->remove);
if(conflict) {
pm_errno = PM_ERR_FILE_CONFLICTS;
if(data) {
@@ -938,14 +978,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
/* remove conflicting and to-be-replaced packages */
if(replaces) {
_alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n");
- if(_alpm_trans_prepare(tr_remove, data) == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not prepare removal transaction\n"));
- goto error;
- }
/* we want the frontend to be aware of commit details */
- tr_remove->cb_event = trans->cb_event;
- tr_remove->cb_progress = trans->cb_progress;
- if(_alpm_trans_commit(tr_remove, NULL) == -1) {
+ if(_alpm_remove_packages(trans, handle->db_local) == -1) {
_alpm_log(PM_LOG_ERROR, _("could not commit removal transaction\n"));
goto error;
}
@@ -953,8 +987,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
/* install targets */
_alpm_log(PM_LOG_DEBUG, "installing packages\n");
- /* add_prepare is not needed */
- if(_alpm_trans_commit(tr_upgrade, NULL) == -1) {
+ if(_alpm_upgrade_packages(trans, handle->db_local) == -1) {
_alpm_log(PM_LOG_ERROR, _("could not commit transaction\n"));
goto error;
}
@@ -963,8 +996,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
error:
FREELIST(files);
alpm_list_free(deltas);
- _alpm_trans_free(tr_remove);
- _alpm_trans_free(tr_upgrade);
return(ret);
}
diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h
index c2905a45..b432b69e 100644
--- a/lib/libalpm/sync.h
+++ b/lib/libalpm/sync.h
@@ -24,9 +24,6 @@
#include "alpm.h"
-int _alpm_sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, int enable_downgrade);
-
-int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name);
int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data);
int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data);
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index 6e847e64..c99f5964 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -52,17 +52,18 @@
*/
/** Initialize the transaction.
- * @param type type of the transaction
* @param flags flags of the transaction (like nodeps, etc)
* @param event event callback function pointer
* @param conv question callback function pointer
* @param progress progress callback function pointer
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags,
+int SYMEXPORT alpm_trans_init(pmtransflag_t flags,
alpm_trans_cb_event event, alpm_trans_cb_conv conv,
alpm_trans_cb_progress progress)
{
+ pmtrans_t *trans;
+
ALPM_LOG_FUNC;
/* Sanity checks */
@@ -78,38 +79,53 @@ int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags,
}
}
- handle->trans = _alpm_trans_new();
- if(handle->trans == NULL) {
+ trans = _alpm_trans_new();
+ if(trans == NULL) {
RET_ERR(PM_ERR_MEMORY, -1);
}
- return(_alpm_trans_init(handle->trans, type, flags, event, conv, progress));
-}
-
-/** Search for packages to upgrade and add them to the transaction.
- * @return 0 on success, -1 on error (pm_errno is set accordingly)
- */
-int SYMEXPORT alpm_trans_sysupgrade(int enable_downgrade)
-{
- pmtrans_t *trans;
+ trans->flags = flags;
+ trans->cb_event = event;
+ trans->cb_conv = conv;
+ trans->cb_progress = progress;
+ trans->state = STATE_INITIALIZED;
- ALPM_LOG_FUNC;
+ handle->trans = trans;
- ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+ return(0);
+}
- trans = handle->trans;
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
- ASSERT(trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1));
+static alpm_list_t *check_arch(alpm_list_t *pkgs)
+{
+ alpm_list_t *i;
+ alpm_list_t *invalid = NULL;
- return(_alpm_sync_sysupgrade(trans, handle->db_local, handle->dbs_sync, enable_downgrade));
+ const char *arch = alpm_option_get_arch();
+ if(!arch) {
+ return(NULL);
+ }
+ for(i = pkgs; i; i = i->next) {
+ pmpkg_t *pkg = i->data;
+ const char *pkgarch = alpm_pkg_get_arch(pkg);
+ if(strcmp(pkgarch,arch) && strcmp(pkgarch,"any")) {
+ char *string;
+ const char *pkgname = alpm_pkg_get_name(pkg);
+ const char *pkgver = alpm_pkg_get_version(pkg);
+ size_t len = strlen(pkgname) + strlen(pkgver) + strlen(pkgarch) + 3;
+ MALLOC(string, len, RET_ERR(PM_ERR_MEMORY, invalid));
+ sprintf(string, "%s-%s-%s", pkgname, pkgver, pkgarch);
+ invalid = alpm_list_add(invalid, string);
+ }
+ }
+ return(invalid);
}
-/** Add a target to the transaction.
- * @param target the name of the target to add
+/** Prepare a transaction.
+ * @param data the address of an alpm_list where detailed description
+ * of an error can be dumped (ie. list of conflicting files)
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_trans_addtarget(char *target)
+int SYMEXPORT alpm_trans_prepare(alpm_list_t **data)
{
pmtrans_t *trans;
@@ -117,32 +133,41 @@ int SYMEXPORT alpm_trans_addtarget(char *target)
/* Sanity checks */
ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
- ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
trans = handle->trans;
+
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
- return(_alpm_trans_addtarget(trans, target));
-}
+ /* If there's nothing to do, return without complaining */
+ if(trans->add == NULL && trans->remove == NULL) {
+ return(0);
+ }
-/** Prepare a transaction.
- * @param data the address of an alpm_list where detailed description
- * of an error can be dumped (ie. list of conflicting files)
- * @return 0 on success, -1 on error (pm_errno is set accordingly)
- */
-int SYMEXPORT alpm_trans_prepare(alpm_list_t **data)
-{
- ALPM_LOG_FUNC;
+ alpm_list_t *invalid = check_arch(trans->add);
+ if(invalid) {
+ if(data) {
+ *data = invalid;
+ }
+ RET_ERR(PM_ERR_PKG_INVALID_ARCH, -1);
+ }
- /* Sanity checks */
- ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
- ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ if(trans->add == NULL) {
+ if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) {
+ /* pm_errno is set by _alpm_remove_prepare() */
+ return(-1);
+ }
+ } else {
+ if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) {
+ /* pm_errno is set by _alpm_sync_prepare() */
+ return(-1);
+ }
+ }
- ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
+ trans->state = STATE_PREPARED;
- return(_alpm_trans_prepare(handle->trans, data));
+ return(0);
}
/** Commit a transaction.
@@ -152,17 +177,42 @@ int SYMEXPORT alpm_trans_prepare(alpm_list_t **data)
*/
int SYMEXPORT alpm_trans_commit(alpm_list_t **data)
{
+ pmtrans_t *trans;
+
ALPM_LOG_FUNC;
/* Sanity checks */
ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
- ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(handle->trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1));
+ trans = handle->trans;
- ASSERT(!(handle->trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1));
+ ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+ ASSERT(trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1));
+
+ ASSERT(!(trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1));
+
+ /* If there's nothing to do, return without complaining */
+ if(trans->add == NULL && trans->remove == NULL) {
+ return(0);
+ }
+
+ trans->state = STATE_COMMITING;
+
+ if(trans->add == NULL) {
+ if(_alpm_remove_packages(trans, handle->db_local) == -1) {
+ /* pm_errno is set by _alpm_remove_commit() */
+ return(-1);
+ }
+ } else {
+ if(_alpm_sync_commit(trans, handle->db_local, data) == -1) {
+ /* pm_errno is set by _alpm_sync_commit() */
+ return(-1);
+ }
+ }
- return(_alpm_trans_commit(handle->trans, data));
+ trans->state = STATE_COMMITED;
+
+ return(0);
}
/** Interrupt a transaction.
@@ -247,12 +297,10 @@ void _alpm_trans_free(pmtrans_t *trans)
return;
}
- if(trans->type == PM_TRANS_TYPE_SYNC) {
- alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free_trans);
- } else {
- alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free);
- }
- alpm_list_free(trans->packages);
+ alpm_list_free_inner(trans->add, (alpm_list_fn_free)_alpm_pkg_free_trans);
+ alpm_list_free(trans->add);
+ alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free);
+ alpm_list_free(trans->remove);
FREELIST(trans->skip_add);
FREELIST(trans->skip_remove);
@@ -260,150 +308,6 @@ void _alpm_trans_free(pmtrans_t *trans)
FREE(trans);
}
-int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags,
- alpm_trans_cb_event event, alpm_trans_cb_conv conv,
- alpm_trans_cb_progress progress)
-{
- ALPM_LOG_FUNC;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
- trans->type = type;
- trans->flags = flags;
- trans->cb_event = event;
- trans->cb_conv = conv;
- trans->cb_progress = progress;
- trans->state = STATE_INITIALIZED;
-
- return(0);
-}
-
-/** Add a target to the transaction.
- * @param trans the current transaction
- * @param target the name of the target to add
- * @return 0 on success, -1 on error (pm_errno is set accordingly)
- */
-int _alpm_trans_addtarget(pmtrans_t *trans, char *target)
-{
- ALPM_LOG_FUNC;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
- ASSERT(target != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
-
- switch(trans->type) {
- case PM_TRANS_TYPE_UPGRADE:
- if(_alpm_add_loadtarget(trans, handle->db_local, target) == -1) {
- /* pm_errno is set by _alpm_add_loadtarget() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_REMOVE:
- case PM_TRANS_TYPE_REMOVEUPGRADE:
- if(_alpm_remove_loadtarget(trans, handle->db_local, target) == -1) {
- /* pm_errno is set by _alpm_remove_loadtarget() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_SYNC:
- if(_alpm_sync_addtarget(trans, handle->db_local, handle->dbs_sync, target) == -1) {
- /* pm_errno is set by _alpm_sync_loadtarget() */
- return(-1);
- }
- break;
- }
-
- return(0);
-}
-
-int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data)
-{
- if(data) {
- *data = NULL;
- }
-
- ALPM_LOG_FUNC;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
- /* If there's nothing to do, return without complaining */
- if(trans->packages == NULL) {
- return(0);
- }
-
- switch(trans->type) {
- case PM_TRANS_TYPE_UPGRADE:
- if(_alpm_add_prepare(trans, handle->db_local, data) == -1) {
- /* pm_errno is set by _alpm_add_prepare() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_REMOVE:
- case PM_TRANS_TYPE_REMOVEUPGRADE:
- if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) {
- /* pm_errno is set by _alpm_remove_prepare() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_SYNC:
- if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) {
- /* pm_errno is set by _alpm_sync_prepare() */
- return(-1);
- }
- break;
- }
-
- trans->state = STATE_PREPARED;
-
- return(0);
-}
-
-int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data)
-{
- ALPM_LOG_FUNC;
-
- if(data!=NULL)
- *data = NULL;
-
- /* Sanity checks */
- ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
- /* If there's nothing to do, return without complaining */
- if(trans->packages == NULL) {
- return(0);
- }
-
- trans->state = STATE_COMMITING;
-
- switch(trans->type) {
- case PM_TRANS_TYPE_UPGRADE:
- if(_alpm_add_commit(trans, handle->db_local) == -1) {
- /* pm_errno is set by _alpm_add_commit() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_REMOVE:
- case PM_TRANS_TYPE_REMOVEUPGRADE:
- if(_alpm_remove_commit(trans, handle->db_local) == -1) {
- /* pm_errno is set by _alpm_remove_commit() */
- return(-1);
- }
- break;
- case PM_TRANS_TYPE_SYNC:
- if(_alpm_sync_commit(trans, handle->db_local, data) == -1) {
- /* pm_errno is set by _alpm_sync_commit() */
- return(-1);
- }
- break;
- }
-
- trans->state = STATE_COMMITED;
-
- return(0);
-}
-
/* A cheap grep for text files, returns 1 if a substring
* was found in the text file fn, 0 if it wasn't
*/
@@ -503,30 +407,30 @@ cleanup:
return(retval);
}
-pmtranstype_t SYMEXPORT alpm_trans_get_type()
+unsigned int SYMEXPORT alpm_trans_get_flags()
{
/* Sanity checks */
ASSERT(handle != NULL, return(-1));
ASSERT(handle->trans != NULL, return(-1));
- return handle->trans->type;
+ return handle->trans->flags;
}
-unsigned int SYMEXPORT alpm_trans_get_flags()
+alpm_list_t SYMEXPORT * alpm_trans_get_add()
{
/* Sanity checks */
- ASSERT(handle != NULL, return(-1));
- ASSERT(handle->trans != NULL, return(-1));
+ ASSERT(handle != NULL, return(NULL));
+ ASSERT(handle->trans != NULL, return(NULL));
- return handle->trans->flags;
+ return handle->trans->add;
}
-alpm_list_t SYMEXPORT * alpm_trans_get_pkgs()
+alpm_list_t SYMEXPORT * alpm_trans_get_remove()
{
/* Sanity checks */
ASSERT(handle != NULL, return(NULL));
ASSERT(handle->trans != NULL, return(NULL));
- return handle->trans->packages;
+ return handle->trans->remove;
}
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h
index 0537bc72..ca1e141a 100644
--- a/lib/libalpm/trans.h
+++ b/lib/libalpm/trans.h
@@ -37,10 +37,10 @@ typedef enum _pmtransstate_t {
/* Transaction */
struct __pmtrans_t {
- pmtranstype_t type;
pmtransflag_t flags;
pmtransstate_t state;
- alpm_list_t *packages; /* list of (pmpkg_t *) */
+ alpm_list_t *add; /* list of (pmpkg_t *) */
+ alpm_list_t *remove; /* list of (pmpkg_t *) */
alpm_list_t *skip_add; /* list of (char *) */
alpm_list_t *skip_remove; /* list of (char *) */
alpm_trans_cb_event cb_event;
@@ -69,12 +69,9 @@ do { \
pmtrans_t *_alpm_trans_new(void);
void _alpm_trans_free(pmtrans_t *trans);
-int _alpm_trans_init(pmtrans_t *trans, pmtranstype_t type, pmtransflag_t flags,
+int _alpm_trans_init(pmtrans_t *trans, pmtransflag_t flags,
alpm_trans_cb_event event, alpm_trans_cb_conv conv,
alpm_trans_cb_progress progress);
-int _alpm_trans_addtarget(pmtrans_t *trans, char *target);
-int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data);
-int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data);
int _alpm_runscriptlet(const char *root, const char *installfn,
const char *script, const char *ver,
const char *oldver, pmtrans_t *trans);
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 082c095b..f78d193a 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -196,51 +196,6 @@ char *_alpm_strtrim(char *str)
return(str);
}
-/* Helper function for _alpm_strreplace */
-static void _strnadd(char **str, const char *append, unsigned int count)
-{
- if(*str) {
- *str = realloc(*str, strlen(*str) + count + 1);
- } else {
- *str = calloc(count + 1, sizeof(char));
- }
-
- strncat(*str, append, count);
-}
-
-/* Replace all occurances of 'needle' with 'replace' in 'str', returning
- * a new string (must be free'd) */
-char *_alpm_strreplace(const char *str, const char *needle, const char *replace)
-{
- const char *p, *q;
- p = q = str;
-
- char *newstr = NULL;
- unsigned int needlesz = strlen(needle),
- replacesz = strlen(replace);
-
- while (1) {
- q = strstr(p, needle);
- if(!q) { /* not found */
- if(*p) {
- /* add the rest of 'p' */
- _strnadd(&newstr, p, strlen(p));
- }
- break;
- } else { /* found match */
- if(q > p){
- /* add chars between this occurance and last occurance, if any */
- _strnadd(&newstr, p, q - p);
- }
- _strnadd(&newstr, replace, replacesz);
- p = q + needlesz;
- }
- }
-
- return newstr;
-}
-
-
/* Create a lock file */
int _alpm_lckmk()
{
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 4bc8b92f..ccf169d3 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -60,7 +60,6 @@ int _alpm_makepath(const char *path);
int _alpm_makepath_mode(const char *path, mode_t mode);
int _alpm_copyfile(const char *src, const char *dest);
char *_alpm_strtrim(char *str);
-char *_alpm_strreplace(const char *str, const char *needle, const char *replace);
int _alpm_lckmk();
int _alpm_lckrm();
int _alpm_unpack(const char *archive, const char *prefix, const char *fn);