Merge branch 'pacman-strict' into 'master'

Add a strict mode for package installs

See merge request pacman/pacman!108
This commit is contained in:
Edmund Smith 2025-06-22 02:29:57 +00:00
commit 802e813319
11 changed files with 244 additions and 19 deletions

View file

@ -24,6 +24,7 @@ Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg = #IgnorePkg =
#IgnoreGroup = #IgnoreGroup =
#DependencyStrategy = Default
#NoUpgrade = #NoUpgrade =
#NoExtract = #NoExtract =

View file

@ -563,6 +563,22 @@ typedef enum _alpm_fileconflicttype_t {
ALPM_FILECONFLICT_FILESYSTEM ALPM_FILECONFLICT_FILESYSTEM
} alpm_fileconflicttype_t; } alpm_fileconflicttype_t;
/**
* Dependency strategy type.
* The strategy changes the details of how dependency names are
* matched up against existing packages when requested.
*/
typedef enum _alpm_depstrategy_t {
/** Prefer packages with a name matching a dependency over
packages that provide that name, regardless of database
order. */
ALPM_DEPSTRATEGY_DEFAULT = 1,
/** Prefer packages in higher priority databases over packages
in lower priority databases, regardless of whether their
names match the dependency or they just provide it. */
ALPM_DEPSTRATEGY_STRICT
} alpm_depstrategy_t;
/** The basic dependency type. /** The basic dependency type.
* *
* This type is used throughout libalpm, not just for dependencies * This type is used throughout libalpm, not just for dependencies
@ -637,7 +653,7 @@ alpm_list_t *alpm_checkdeps(alpm_handle_t *handle, alpm_list_t *pkglist,
*/ */
alpm_pkg_t *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring); alpm_pkg_t *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring);
/** Find a package satisfying a specified dependency. /** Find a package satisfying a specified dependency with the default strategy.
* First look for a literal, going through each db one by one. Then look for * First look for a literal, going through each db one by one. Then look for
* providers. The first satisfyer that belongs to an installed package is * providers. The first satisfyer that belongs to an installed package is
* returned. If no providers belong to an installed package then an * returned. If no providers belong to an installed package then an
@ -652,6 +668,22 @@ alpm_pkg_t *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring);
alpm_pkg_t *alpm_find_dbs_satisfier(alpm_handle_t *handle, alpm_pkg_t *alpm_find_dbs_satisfier(alpm_handle_t *handle,
alpm_list_t *dbs, const char *depstring); alpm_list_t *dbs, const char *depstring);
/** Find a package satisfying a specified dependency.
* First look for a literal, going through each db one by one. Then look for
* providers. The first satisfyer that belongs to an installed package is
* returned. If no providers belong to an installed package then an
* alpm_question_select_provider_t is created to select the provider.
* The dependency can include versions with depmod operators.
*
* @param handle the context handle
* @param dbs an alpm_list_t* of alpm_db_t where the satisfyer will be searched
* @param depstrategy the dependency strategy to use
* @param depstring package or provision name, versioned or not
* @return a alpm_pkg_t* satisfying depstring
*/
alpm_pkg_t *alpm_find_dbs_satisfier_ex(alpm_handle_t *handle,
alpm_list_t *dbs, alpm_depstrategy_t depstrategy, const char *depstring);
/** Check the package conflicts in a database /** Check the package conflicts in a database
* *
* @param handle the context handle * @param handle the context handle
@ -2854,7 +2886,7 @@ alpm_list_t *alpm_trans_get_remove(alpm_handle_t *handle);
*/ */
int alpm_trans_init(alpm_handle_t *handle, int flags); int alpm_trans_init(alpm_handle_t *handle, int flags);
/** Prepare a transaction. /** Prepare a transaction with the default dependency strategy.
* @param handle the context handle * @param handle the context handle
* @param data the address of an alpm_list where a list * @param data the address of an alpm_list where a list
* of alpm_depmissing_t objects is dumped (conflicting packages) * of alpm_depmissing_t objects is dumped (conflicting packages)
@ -2862,6 +2894,15 @@ int alpm_trans_init(alpm_handle_t *handle, int flags);
*/ */
int alpm_trans_prepare(alpm_handle_t *handle, alpm_list_t **data); int alpm_trans_prepare(alpm_handle_t *handle, alpm_list_t **data);
/** Prepare a transaction specifying the dependency strategy.
* @param handle the context handle
* @param data the address of an alpm_list where a list
* of alpm_depmissing_t objects is dumped (conflicting packages)
* @param depstrategy the dependency resolution strategy to use.
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
int alpm_trans_prepare_ex(alpm_handle_t *handle, alpm_depstrategy_t depstrategy, alpm_list_t **data);
/** Commit a transaction. /** Commit a transaction.
* @param handle the context handle * @param handle the context handle
* @param data the address of an alpm_list where detailed description * @param data the address of an alpm_list where detailed description

View file

@ -622,7 +622,9 @@ int _alpm_recursedeps(alpm_db_t *db, alpm_list_t **targs, int include_explicit)
} }
/** /**
* helper function for resolvedeps: search for dep satisfier in dbs * helper function for resolvedep: search for dep satisfier in dbs
* this version applies the "default" logic that puts name matching
* ahead of db ordering.
* *
* @param handle the context handle * @param handle the context handle
* @param dep is the dependency to search for * @param dep is the dependency to search for
@ -633,7 +635,7 @@ int _alpm_recursedeps(alpm_db_t *db, alpm_list_t **targs, int include_explicit)
* packages. * packages.
* @return the resolved package * @return the resolved package
**/ **/
static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep, static alpm_pkg_t *resolvedep_default(alpm_handle_t *handle, alpm_depend_t *dep,
alpm_list_t *dbs, alpm_list_t *excluding, int prompt) alpm_list_t *dbs, alpm_list_t *excluding, int prompt)
{ {
alpm_list_t *i, *j; alpm_list_t *i, *j;
@ -748,8 +750,169 @@ static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep,
return NULL; return NULL;
} }
/**
* helper function for resolvedep: search for dep satisfier in dbs
* this version applies the "strict" logic that puts db order before
* exact matching.
*
* @param handle the context handle
* @param dep is the dependency to search for
* @param dbs are the databases to search
* @param excluding are the packages to exclude from the search
* @param prompt if true, ask an alpm_question_install_ignorepkg_t to decide
* if ignored packages should be installed; if false, skip ignored
* packages.
* @return the resolved package
**/
static alpm_pkg_t *resolvedep_strict(alpm_handle_t *handle, alpm_depend_t *dep,
alpm_list_t *dbs, alpm_list_t *excluding, int prompt)
{
alpm_list_t *i, *j;
int ignored = 0;
alpm_list_t *providers = NULL;
int count;
for(i = dbs; i; i = i->next) {
alpm_pkg_t *pkg;
alpm_db_t *db = i->data;
if(!(db->usage & (ALPM_DB_USAGE_INSTALL|ALPM_DB_USAGE_UPGRADE))) {
continue;
}
/* 1. literals */
pkg = _alpm_db_get_pkgfromcache(db, dep->name);
if(pkg && _alpm_depcmp_literal(pkg, dep)
&& !alpm_pkg_find(excluding, pkg->name)) {
if(alpm_pkg_should_ignore(handle, pkg)) {
alpm_question_install_ignorepkg_t question = {
.type = ALPM_QUESTION_INSTALL_IGNOREPKG,
.install = 0,
.pkg = pkg
};
if(prompt) {
QUESTION(handle, &question);
} else {
_alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package %s-%s\n"),
pkg->name, pkg->version);
}
if(!question.install) {
ignored = 1;
continue;
}
}
if(_alpm_db_get_pkgfromcache(handle->db_local, pkg->name)) {
alpm_list_free(providers);
return pkg;
}
providers = alpm_list_add(providers, pkg);
}
/* 2. satisfiers (skip literals here) */
for(j = _alpm_db_get_pkgcache(db); j; j = j->next) {
pkg = j->data;
if((pkg->name_hash != dep->name_hash || strcmp(pkg->name, dep->name) != 0)
&& _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg))
&& !alpm_pkg_find(excluding, pkg->name)) {
if(alpm_pkg_should_ignore(handle, pkg)) {
alpm_question_install_ignorepkg_t question = {
.type = ALPM_QUESTION_INSTALL_IGNOREPKG,
.install = 0,
.pkg = pkg
};
if(prompt) {
QUESTION(handle, &question);
} else {
_alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package %s-%s\n"),
pkg->name, pkg->version);
}
if(!question.install) {
ignored = 1;
continue;
}
}
_alpm_log(handle, ALPM_LOG_DEBUG, "provider found (%s provides %s)\n",
pkg->name, dep->name);
/* provide is already installed so return early instead of prompting later */
if(_alpm_db_get_pkgfromcache(handle->db_local, pkg->name)) {
alpm_list_free(providers);
return pkg;
}
providers = alpm_list_add(providers, pkg);
/* keep looking for other providers in the all dbs */
}
}
}
count = alpm_list_count(providers);
if(count >= 1) {
alpm_question_select_provider_t question = {
.type = ALPM_QUESTION_SELECT_PROVIDER,
/* default to first provider if there is no QUESTION callback */
.use_index = 0,
.providers = providers,
.depend = dep
};
if(count > 1) {
/* if there is more than one provider, we ask the user */
QUESTION(handle, &question);
}
if(question.use_index >= 0 && question.use_index < count) {
alpm_list_t *nth = alpm_list_nth(providers, question.use_index);
alpm_pkg_t *pkg = nth->data;
alpm_list_free(providers);
return pkg;
}
alpm_list_free(providers);
providers = NULL;
}
if(ignored) { /* resolvedeps will override these */
handle->pm_errno = ALPM_ERR_PKG_IGNORED;
} else {
handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND;
}
return NULL;
}
/**
* helper function for resolvedeps: search for dep satisfier in dbs
*
* @param handle the context handle
* @param dep is the dependency to search for
* @param depstrategy is the depstrategy to apply when searching
* @param dbs are the databases to search
* @param excluding are the packages to exclude from the search
* @param prompt if true, ask an alpm_question_install_ignorepkg_t to decide
* if ignored packages should be installed; if false, skip ignored
* packages.
* @return the resolved package
**/
static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep,
alpm_depstrategy_t depstrategy, alpm_list_t *dbs, alpm_list_t *excluding, int prompt)
{
switch(depstrategy) {
case ALPM_DEPSTRATEGY_DEFAULT:
return resolvedep_default(handle, dep, dbs, excluding, prompt);
case ALPM_DEPSTRATEGY_STRICT:
return resolvedep_strict(handle, dep, dbs, excluding, prompt);
default:
/* We should never reach here */
return NULL;
}
}
alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle, alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle,
alpm_list_t *dbs, const char *depstring) alpm_list_t *dbs, const char *depstring)
{
return alpm_find_dbs_satisfier_ex(handle, dbs, ALPM_DEPSTRATEGY_DEFAULT, depstring);
}
alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier_ex(alpm_handle_t *handle,
alpm_list_t *dbs, alpm_depstrategy_t depstrategy, const char *depstring)
{ {
alpm_depend_t *dep; alpm_depend_t *dep;
alpm_pkg_t *pkg; alpm_pkg_t *pkg;
@ -759,7 +922,7 @@ alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle,
dep = alpm_dep_from_string(depstring); dep = alpm_dep_from_string(depstring);
ASSERT(dep, return NULL); ASSERT(dep, return NULL);
pkg = resolvedep(handle, dep, dbs, NULL, 1); pkg = resolvedep(handle, dep, depstrategy, dbs, NULL, 1);
alpm_dep_free(dep); alpm_dep_free(dep);
return pkg; return pkg;
} }
@ -771,6 +934,8 @@ alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle,
* @param handle the context handle * @param handle the context handle
* @param localpkgs is the list of local packages * @param localpkgs is the list of local packages
* @param pkg is the package to resolve * @param pkg is the package to resolve
* @param depstrategy is the strategy to follow (one of
ALPM_DEPSTRATEGY_DEFAULT, ALPM_DEPSTRATEGY_STRICT)
* @param preferred packages to prefer when resolving * @param preferred packages to prefer when resolving
* @param packages is a pointer to a list of packages which will be * @param packages is a pointer to a list of packages which will be
* searched first for any dependency packages needed to complete the * searched first for any dependency packages needed to complete the
@ -786,8 +951,8 @@ alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle,
* unmodified by this function * unmodified by this function
*/ */
int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,
alpm_pkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_pkg_t *pkg, alpm_depstrategy_t depstrategy, alpm_list_t *preferred,
alpm_list_t *rem, alpm_list_t **data) alpm_list_t **packages, alpm_list_t *rem, alpm_list_t **data)
{ {
int ret = 0; int ret = 0;
alpm_list_t *j; alpm_list_t *j;
@ -826,14 +991,14 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,
alpm_pkg_t *spkg = find_dep_satisfier(preferred, missdep); alpm_pkg_t *spkg = find_dep_satisfier(preferred, missdep);
if(!spkg) { if(!spkg) {
/* find a satisfier package in the given repositories */ /* find a satisfier package in the given repositories */
spkg = resolvedep(handle, missdep, handle->dbs_sync, *packages, 0); spkg = resolvedep(handle, missdep, depstrategy, handle->dbs_sync, *packages, 0);
} }
if(spkg && _alpm_resolvedeps(handle, localpkgs, spkg, preferred, packages, rem, data) == 0) { if(spkg && _alpm_resolvedeps(handle, localpkgs, spkg, depstrategy, preferred, packages, rem, data) == 0) {
_alpm_log(handle, ALPM_LOG_DEBUG, _alpm_log(handle, ALPM_LOG_DEBUG,
"pulling dependency %s (needed by %s)\n", "pulling dependency %s (needed by %s)\n",
spkg->name, pkg->name); spkg->name, pkg->name);
alpm_depmissing_free(miss); alpm_depmissing_free(miss);
} else if(resolvedep(handle, missdep, (targ = alpm_list_add(NULL, handle->db_local)), rem, 0)) { } else if(resolvedep(handle, missdep, depstrategy, (targ = alpm_list_add(NULL, handle->db_local)), rem, 0)) {
alpm_depmissing_free(miss); alpm_depmissing_free(miss);
} else { } else {
handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS; handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS;

View file

@ -32,8 +32,8 @@ alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle,
alpm_list_t *targets, alpm_list_t *ignore, int reverse); alpm_list_t *targets, alpm_list_t *ignore, int reverse);
int _alpm_recursedeps(alpm_db_t *db, alpm_list_t **targs, int include_explicit); int _alpm_recursedeps(alpm_db_t *db, alpm_list_t **targs, int include_explicit);
int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t *pkg, int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t *pkg,
alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_depstrategy_t depstrategy, alpm_list_t *preferred, alpm_list_t **packages,
alpm_list_t **data); alpm_list_t *remove, alpm_list_t **data);
int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep);
int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions);
int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep);

View file

@ -364,7 +364,7 @@ finish:
return ret; return ret;
} }
int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) int _alpm_sync_prepare(alpm_handle_t *handle, alpm_depstrategy_t depstrategy, alpm_list_t **data)
{ {
alpm_list_t *i, *j; alpm_list_t *i, *j;
alpm_list_t *deps = NULL; alpm_list_t *deps = NULL;
@ -426,7 +426,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
building up a list of packages which could not be resolved. */ building up a list of packages which could not be resolved. */
for(i = trans->add; i; i = i->next) { for(i = trans->add; i; i = i->next) {
alpm_pkg_t *pkg = i->data; alpm_pkg_t *pkg = i->data;
if(_alpm_resolvedeps(handle, localpkgs, pkg, trans->add, if(_alpm_resolvedeps(handle, localpkgs, pkg, depstrategy, trans->add,
&resolved, remove, data) == -1) { &resolved, remove, data) == -1) {
unresolvable = alpm_list_add(unresolvable, pkg); unresolvable = alpm_list_add(unresolvable, pkg);
} }

View file

@ -24,7 +24,7 @@
#include "alpm.h" #include "alpm.h"
int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data); int _alpm_sync_prepare(alpm_handle_t *handle, alpm_depstrategy_t depstrategy, alpm_list_t **data);
int _alpm_sync_load(alpm_handle_t *handle, alpm_list_t **data); int _alpm_sync_load(alpm_handle_t *handle, alpm_list_t **data);
int _alpm_sync_check(alpm_handle_t *handle, alpm_list_t **data); int _alpm_sync_check(alpm_handle_t *handle, alpm_list_t **data);
int _alpm_sync_commit(alpm_handle_t *handle); int _alpm_sync_commit(alpm_handle_t *handle);

View file

@ -108,6 +108,10 @@ static alpm_list_t *check_arch(alpm_handle_t *handle, alpm_list_t *pkgs)
int SYMEXPORT alpm_trans_prepare(alpm_handle_t *handle, alpm_list_t **data) int SYMEXPORT alpm_trans_prepare(alpm_handle_t *handle, alpm_list_t **data)
{ {
return alpm_trans_prepare_ex(handle, ALPM_DEPSTRATEGY_DEFAULT, data);
}
int SYMEXPORT alpm_trans_prepare_ex(alpm_handle_t *handle, alpm_depstrategy_t depstrategy, alpm_list_t **data) {
alpm_trans_t *trans; alpm_trans_t *trans;
/* Sanity checks */ /* Sanity checks */
@ -138,7 +142,7 @@ int SYMEXPORT alpm_trans_prepare(alpm_handle_t *handle, alpm_list_t **data)
return -1; return -1;
} }
} else { } else {
if(_alpm_sync_prepare(handle, data) == -1) { if(_alpm_sync_prepare(handle, depstrategy, data) == -1) {
/* pm_errno is set by _alpm_sync_prepare() */ /* pm_errno is set by _alpm_sync_prepare() */
return -1; return -1;
} }

View file

@ -115,6 +115,7 @@ config_t *config_new(void)
newconfig->remotefilesiglevel = ALPM_SIG_USE_DEFAULT; newconfig->remotefilesiglevel = ALPM_SIG_USE_DEFAULT;
} }
newconfig->depstrategy = ALPM_DEPSTRATEGY_DEFAULT;
/* by default use 1 download stream */ /* by default use 1 download stream */
newconfig->parallel_downloads = 1; newconfig->parallel_downloads = 1;
newconfig->colstr.colon = ":: "; newconfig->colstr.colon = ":: ";
@ -762,6 +763,17 @@ static int _parse_options(const char *key, char *value,
} }
config->parallel_downloads = number; config->parallel_downloads = number;
} else if(strcmp(key, "DependencyStrategy") == 0) {
if(strcmp(value, "Default") == 0) {
config->depstrategy = ALPM_DEPSTRATEGY_DEFAULT;
} else if(strcmp(value, "Strict") == 0) {
config->depstrategy = ALPM_DEPSTRATEGY_STRICT;
} else {
pm_printf(ALPM_LOG_ERROR,
_("config file %s, line %d: invalid value for '%s': '%s'\n"),
file, linenum, "DependencyStrategy", value);
return 1;
}
} else { } else {
pm_printf(ALPM_LOG_WARNING, pm_printf(ALPM_LOG_WARNING,
_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),

View file

@ -130,6 +130,7 @@ typedef struct __config_t {
char *xfercommand; char *xfercommand;
char **xfercommand_argv; char **xfercommand_argv;
size_t xfercommand_argc; size_t xfercommand_argc;
alpm_depstrategy_t depstrategy;
/* our connection to libalpm */ /* our connection to libalpm */
alpm_handle_t *handle; alpm_handle_t *handle;

View file

@ -107,7 +107,7 @@ int pacman_remove(alpm_list_t *targets)
} }
/* Step 2: prepare the transaction based on its type, targets and flags */ /* Step 2: prepare the transaction based on its type, targets and flags */
if(alpm_trans_prepare(config->handle, &data) == -1) { if(alpm_trans_prepare_ex(config->handle, ALPM_DEPSTRATEGY_DEFAULT, &data) == -1) {
alpm_errno_t err = alpm_errno(config->handle); alpm_errno_t err = alpm_errno(config->handle);
pm_printf(ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), pm_printf(ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"),
alpm_strerror(err)); alpm_strerror(err));

View file

@ -632,7 +632,8 @@ cleanup:
static int process_targname(alpm_list_t *dblist, const char *targname, static int process_targname(alpm_list_t *dblist, const char *targname,
int error) int error)
{ {
alpm_pkg_t *pkg = alpm_find_dbs_satisfier(config->handle, dblist, targname); alpm_pkg_t *pkg = alpm_find_dbs_satisfier_ex(config->handle, dblist,
config->depstrategy, targname);
/* skip ignored packages when user says no */ /* skip ignored packages when user says no */
if(alpm_errno(config->handle) == ALPM_ERR_PKG_IGNORED) { if(alpm_errno(config->handle) == ALPM_ERR_PKG_IGNORED) {
@ -765,7 +766,7 @@ int sync_prepare_execute(void)
int retval = 0; int retval = 0;
/* Step 2: "compute" the transaction based on targets and flags */ /* Step 2: "compute" the transaction based on targets and flags */
if(alpm_trans_prepare(config->handle, &data) == -1) { if(alpm_trans_prepare_ex(config->handle, config->depstrategy, &data) == -1) {
alpm_errno_t err = alpm_errno(config->handle); alpm_errno_t err = alpm_errno(config->handle);
pm_printf(ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), pm_printf(ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"),
alpm_strerror(err)); alpm_strerror(err));