Add support for multiple 'Architecture' values
This allows architecture to be multivalued. On x86-64 machines, this could be something like: Architecture = x86-64-v3 x86-64 We use the first specified Architecture value in mirrorlist $arch variable replacement, as this is backwards-compatible and sane. Original-patch-by: Dan McGee <dan@archlinux.org> Patch-updated-by: Allan McRae <allan@archlinux.org> Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
parent
abdb4d7fa6
commit
3179db108a
12 changed files with 127 additions and 41 deletions
|
@ -113,9 +113,9 @@ Options
|
|||
general configuration options. Wildcards in the specified paths will get
|
||||
expanded based on linkman:glob[7] rules.
|
||||
|
||||
*Architecture =* auto | i686 | x86_64 | ...::
|
||||
If set, pacman will only allow installation of packages of the given
|
||||
architecture (e.g. 'i686', 'x86_64', etc). The special value 'auto' will
|
||||
*Architecture =* auto &| i686 &| x86_64 | ...::
|
||||
If set, pacman will only allow installation of packages with the given
|
||||
architectures (e.g. 'i686', 'x86_64', etc). The special value 'auto' will
|
||||
use the system architecture, provided via ``uname -m''. If unset, no
|
||||
architecture checks are made. *NOTE*: Packages with the special
|
||||
architecture 'any' can always be installed, as they are meant to be
|
||||
|
@ -252,8 +252,8 @@ number.
|
|||
During parsing, pacman will define the `$repo` variable to the name of the
|
||||
current section. This is often utilized in files specified using the 'Include'
|
||||
directive so all repositories can use the same mirrorfile. pacman also defines
|
||||
the `$arch` variable to the value of `Architecture`, so the same mirrorfile can
|
||||
even be used for different architectures.
|
||||
the `$arch` variable to the first (or only) value of the `Architecture` option,
|
||||
so the same mirrorfile can even be used for different architectures.
|
||||
|
||||
*SigLevel =* ...::
|
||||
Set the signature verification level for this repository. For more
|
||||
|
|
|
@ -2016,25 +2016,37 @@ int alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const alpm_depend_
|
|||
/** @} */
|
||||
|
||||
|
||||
/** @name Accessors for the configured architecture
|
||||
*
|
||||
* libalpm will only install packages that match the configured architecture.
|
||||
* The architecture does not need to match the physical architecture.
|
||||
* It can just be treated as a label.
|
||||
/** @name Accessors to the list of allowed architectures.
|
||||
* libalpm will only install packages that match one of the configured
|
||||
* architectures. The architectures do not need to match the physical
|
||||
architecture. They can just be treated as a label.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Returns the allowed package architecture.
|
||||
* @param handle the context handle
|
||||
* @return the configured package architecture
|
||||
* @return the configured package architectures
|
||||
*/
|
||||
const char *alpm_option_get_arch(alpm_handle_t *handle);
|
||||
alpm_list_t *alpm_option_get_architectures(alpm_handle_t *handle);
|
||||
|
||||
/** Sets the allowed package architecture.
|
||||
/** Adds an allowed package architecture.
|
||||
* @param handle the context handle
|
||||
* @param arch the architecture to set
|
||||
*/
|
||||
int alpm_option_set_arch(alpm_handle_t *handle, const char *arch);
|
||||
int alpm_option_add_architecture(alpm_handle_t *handle, const char *arch);
|
||||
|
||||
/** Sets the allowed package architecture.
|
||||
* @param handle the context handle
|
||||
* @param arches the architecture to set
|
||||
*/
|
||||
int alpm_option_set_architectures(alpm_handle_t *handle, alpm_list_t *arches);
|
||||
|
||||
/** Removes an allowed package architecture.
|
||||
* @param handle the context handle
|
||||
* @param arch the architecture to remove
|
||||
*/
|
||||
int alpm_option_remove_architecture(alpm_handle_t *handle, const char *arch);
|
||||
|
||||
/* End of arch accessors */
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ void _alpm_handle_free(alpm_handle_t *handle)
|
|||
FREELIST(handle->hookdirs);
|
||||
FREE(handle->logfile);
|
||||
FREE(handle->lockfile);
|
||||
FREE(handle->arch);
|
||||
FREELIST(handle->architectures);
|
||||
FREE(handle->gpgdir);
|
||||
FREELIST(handle->noupgrade);
|
||||
FREELIST(handle->noextract);
|
||||
|
@ -276,10 +276,10 @@ alpm_list_t SYMEXPORT *alpm_option_get_assumeinstalled(alpm_handle_t *handle)
|
|||
return handle->assumeinstalled;
|
||||
}
|
||||
|
||||
const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle)
|
||||
alpm_list_t SYMEXPORT *alpm_option_get_architectures(alpm_handle_t *handle)
|
||||
{
|
||||
CHECK_HANDLE(handle, return NULL);
|
||||
return handle->arch;
|
||||
return handle->architectures;
|
||||
}
|
||||
|
||||
int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)
|
||||
|
@ -720,11 +720,29 @@ int SYMEXPORT alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const al
|
|||
return 0;
|
||||
}
|
||||
|
||||
int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)
|
||||
int SYMEXPORT alpm_option_add_architecture(alpm_handle_t *handle, const char *arch)
|
||||
{
|
||||
handle->architectures = alpm_list_add(handle->architectures, strdup(arch));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SYMEXPORT alpm_option_set_architectures(alpm_handle_t *handle, alpm_list_t *arches)
|
||||
{
|
||||
CHECK_HANDLE(handle, return -1);
|
||||
if(handle->arch) FREE(handle->arch);
|
||||
STRDUP(handle->arch, arch, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
|
||||
if(handle->architectures) FREELIST(handle->architectures);
|
||||
handle->architectures = alpm_list_strdup(arches);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SYMEXPORT alpm_option_remove_architecture(alpm_handle_t *handle, const char *arch)
|
||||
{
|
||||
char *vdata = NULL;
|
||||
CHECK_HANDLE(handle, return -1);
|
||||
handle->architectures = alpm_list_remove_str(handle->architectures, arch, &vdata);
|
||||
if(vdata != NULL) {
|
||||
FREE(vdata);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ struct __alpm_handle_t {
|
|||
alpm_list_t *assumeinstalled; /* List of virtual packages used to satisfy dependencies */
|
||||
|
||||
/* options */
|
||||
char *arch; /* Architecture of packages we should allow */
|
||||
alpm_list_t *architectures; /* Architectures of packages we should allow */
|
||||
int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
|
||||
int checkspace; /* Check disk space before installing */
|
||||
char *dbext; /* Sync DB extension */
|
||||
|
|
|
@ -71,14 +71,29 @@ static alpm_list_t *check_arch(alpm_handle_t *handle, alpm_list_t *pkgs)
|
|||
alpm_list_t *i;
|
||||
alpm_list_t *invalid = NULL;
|
||||
|
||||
const char *arch = handle->arch;
|
||||
if(!arch) {
|
||||
if(!handle->architectures) {
|
||||
_alpm_log(handle, ALPM_LOG_DEBUG, "skipping architecture checks\n");
|
||||
return NULL;
|
||||
}
|
||||
for(i = pkgs; i; i = i->next) {
|
||||
alpm_pkg_t *pkg = i->data;
|
||||
alpm_list_t *j;
|
||||
int found = 0;
|
||||
const char *pkgarch = alpm_pkg_get_arch(pkg);
|
||||
if(pkgarch && strcmp(pkgarch, arch) && strcmp(pkgarch, "any")) {
|
||||
|
||||
/* always allow non-architecture packages and those marked "any" */
|
||||
if(!pkgarch || strcmp(pkgarch, "any") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(j = handle->architectures; j; j = j->next) {
|
||||
if(strcmp(pkgarch, j->data) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
char *string;
|
||||
const char *pkgname = pkg->name;
|
||||
const char *pkgver = pkg->version;
|
||||
|
|
|
@ -159,7 +159,7 @@ int config_free(config_t *oldconfig)
|
|||
FREELIST(oldconfig->cachedirs);
|
||||
free(oldconfig->xfercommand);
|
||||
free(oldconfig->print_format);
|
||||
free(oldconfig->arch);
|
||||
FREELIST(oldconfig->architectures);
|
||||
wordsplit_free(oldconfig->xfercommand_argv);
|
||||
free(oldconfig);
|
||||
|
||||
|
@ -394,16 +394,19 @@ cleanup:
|
|||
}
|
||||
|
||||
|
||||
int config_set_arch(const char *arch)
|
||||
int config_add_architecture(char *arch)
|
||||
{
|
||||
if(strcmp(arch, "auto") == 0) {
|
||||
struct utsname un;
|
||||
char *newarch;
|
||||
uname(&un);
|
||||
config->arch = strdup(un.machine);
|
||||
} else {
|
||||
config->arch = strdup(arch);
|
||||
newarch = strdup(un.machine);
|
||||
free(arch);
|
||||
arch = newarch;
|
||||
}
|
||||
pm_printf(ALPM_LOG_DEBUG, "config: arch: %s\n", config->arch);
|
||||
|
||||
pm_printf(ALPM_LOG_DEBUG, "config: arch: %s\n", arch);
|
||||
config->architectures = alpm_list_add(config->architectures, arch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -638,9 +641,12 @@ static int _parse_options(const char *key, char *value,
|
|||
} else if(strcmp(key, "HookDir") == 0) {
|
||||
setrepeatingoption(value, "HookDir", &(config->hookdirs));
|
||||
} else if(strcmp(key, "Architecture") == 0) {
|
||||
if(!config->arch) {
|
||||
config_set_arch(value);
|
||||
alpm_list_t *i, *arches = NULL;
|
||||
setrepeatingoption(value, "Architecture", &arches);
|
||||
for(i = arches; i; i = alpm_list_next(i)) {
|
||||
config_add_architecture(i->data);
|
||||
}
|
||||
alpm_list_free(arches);
|
||||
} else if(strcmp(key, "DBPath") == 0) {
|
||||
/* don't overwrite a path specified on the command line */
|
||||
if(!config->dbpath) {
|
||||
|
@ -751,17 +757,20 @@ static int _parse_options(const char *key, char *value,
|
|||
|
||||
static char *replace_server_vars(config_t *c, config_repo_t *r, const char *s)
|
||||
{
|
||||
if(c->arch == NULL && strstr(s, "$arch")) {
|
||||
if(c->architectures == NULL && strstr(s, "$arch")) {
|
||||
pm_printf(ALPM_LOG_ERROR,
|
||||
_("mirror '%s' contains the '%s' variable, but no '%s' is defined.\n"),
|
||||
s, "$arch", "Architecture");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(c->arch) {
|
||||
/* use first specified architecture */
|
||||
if(c->architectures) {
|
||||
char *temp, *replaced;
|
||||
alpm_list_t *i = config->architectures;
|
||||
const char *arch = i->data;
|
||||
|
||||
replaced = strreplace(s, "$arch", c->arch);
|
||||
replaced = strreplace(s, "$arch", arch);
|
||||
|
||||
temp = replaced;
|
||||
replaced = strreplace(temp, "$repo", r->name);
|
||||
|
@ -893,7 +902,7 @@ static int setup_libalpm(void)
|
|||
pm_printf(ALPM_LOG_WARNING, _("no '%s' configured\n"), "XferCommand");
|
||||
}
|
||||
|
||||
alpm_option_set_arch(handle, config->arch);
|
||||
alpm_option_set_architectures(handle, config->architectures);
|
||||
alpm_option_set_checkspace(handle, config->checkspace);
|
||||
alpm_option_set_usesyslog(handle, config->usesyslog);
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ typedef struct __config_t {
|
|||
unsigned short usesyslog;
|
||||
unsigned short color;
|
||||
unsigned short disable_dl_timeout;
|
||||
char *arch;
|
||||
char *print_format;
|
||||
/* unfortunately, we have to keep track of paths both here and in the library
|
||||
* because they can come from both the command line or config file, and we
|
||||
|
@ -70,6 +69,7 @@ typedef struct __config_t {
|
|||
char *sysroot;
|
||||
alpm_list_t *hookdirs;
|
||||
alpm_list_t *cachedirs;
|
||||
alpm_list_t *architectures;
|
||||
|
||||
unsigned short op_q_isfile;
|
||||
unsigned short op_q_info;
|
||||
|
@ -244,7 +244,7 @@ int config_free(config_t *oldconfig);
|
|||
|
||||
void config_repo_free(config_repo_t *repo);
|
||||
|
||||
int config_set_arch(const char *arch);
|
||||
int config_add_architecture(char *arch);
|
||||
int parseconfig(const char *file);
|
||||
int parseconfigfile(const char *file);
|
||||
int setdefaults(config_t *c);
|
||||
|
|
|
@ -258,7 +258,7 @@ static void dump_config(void)
|
|||
show_list_str("NoUpgrade", config->noupgrade);
|
||||
show_list_str("NoExtract", config->noextract);
|
||||
|
||||
show_str("Architecture", config->arch);
|
||||
show_list_str("Architecture", config->architectures);
|
||||
show_str("XferCommand", config->xfercommand);
|
||||
|
||||
show_bool("UseSyslog", config->usesyslog);
|
||||
|
@ -364,7 +364,7 @@ static int list_directives(void)
|
|||
|
||||
|
||||
} else if(strcasecmp(i->data, "Architecture") == 0) {
|
||||
show_str("Architecture", config->arch);
|
||||
show_list_str("Architecture", config->architectures);
|
||||
} else if(strcasecmp(i->data, "XferCommand") == 0) {
|
||||
show_str("XferCommand", config->xfercommand);
|
||||
|
||||
|
|
|
@ -377,7 +377,7 @@ static int parsearg_global(int opt)
|
|||
{
|
||||
switch(opt) {
|
||||
case OP_ARCH:
|
||||
config_set_arch(optarg);
|
||||
config_add_architecture(strdup(optarg));
|
||||
break;
|
||||
case OP_ASK:
|
||||
config->noask = 1;
|
||||
|
|
|
@ -85,6 +85,8 @@ pacman_tests = [
|
|||
'tests/mode001.py',
|
||||
'tests/mode002.py',
|
||||
'tests/mode003.py',
|
||||
'tests/multiple-architectures01.py',
|
||||
'tests/multiple-architectures02.py',
|
||||
'tests/noupgrade-inverted.py',
|
||||
'tests/overwrite-files-match-negated.py',
|
||||
'tests/overwrite-files-match.py',
|
||||
|
|
14
test/pacman/tests/multiple-architectures01.py
Normal file
14
test/pacman/tests/multiple-architectures01.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
self.description = "Install a package (multiple Architecture options, wrong)"
|
||||
|
||||
p = pmpkg("dummy")
|
||||
p.files = ["bin/dummy",
|
||||
"usr/man/man1/dummy.1"]
|
||||
p.arch = 'i686'
|
||||
self.addpkg(p)
|
||||
|
||||
self.option["Architecture"] = ['i586', 'i486', 'i386']
|
||||
|
||||
self.args = "-U %s" % p.filename()
|
||||
|
||||
self.addrule("PACMAN_RETCODE=1")
|
||||
self.addrule("!PKG_EXIST=dummy")
|
16
test/pacman/tests/multiple-architectures02.py
Normal file
16
test/pacman/tests/multiple-architectures02.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
self.description = "Install a package (multiple Architecture options)"
|
||||
|
||||
p = pmpkg("dummy")
|
||||
p.files = ["bin/dummy",
|
||||
"usr/man/man1/dummy.1"]
|
||||
p.arch = 'i486'
|
||||
self.addpkg(p)
|
||||
|
||||
self.option["Architecture"] = ['i586', 'i486', 'i386']
|
||||
|
||||
self.args = "-U %s" % p.filename()
|
||||
|
||||
self.addrule("PACMAN_RETCODE=0")
|
||||
self.addrule("PKG_EXIST=dummy")
|
||||
for f in p.files:
|
||||
self.addrule("FILE_EXIST=%s" % f)
|
Loading…
Add table
Reference in a new issue