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
|
general configuration options. Wildcards in the specified paths will get
|
||||||
expanded based on linkman:glob[7] rules.
|
expanded based on linkman:glob[7] rules.
|
||||||
|
|
||||||
*Architecture =* auto | i686 | x86_64 | ...::
|
*Architecture =* auto &| i686 &| x86_64 | ...::
|
||||||
If set, pacman will only allow installation of packages of the given
|
If set, pacman will only allow installation of packages with the given
|
||||||
architecture (e.g. 'i686', 'x86_64', etc). The special value 'auto' will
|
architectures (e.g. 'i686', 'x86_64', etc). The special value 'auto' will
|
||||||
use the system architecture, provided via ``uname -m''. If unset, no
|
use the system architecture, provided via ``uname -m''. If unset, no
|
||||||
architecture checks are made. *NOTE*: Packages with the special
|
architecture checks are made. *NOTE*: Packages with the special
|
||||||
architecture 'any' can always be installed, as they are meant to be
|
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
|
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'
|
current section. This is often utilized in files specified using the 'Include'
|
||||||
directive so all repositories can use the same mirrorfile. pacman also defines
|
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
|
the `$arch` variable to the first (or only) value of the `Architecture` option,
|
||||||
even be used for different architectures.
|
so the same mirrorfile can even be used for different architectures.
|
||||||
|
|
||||||
*SigLevel =* ...::
|
*SigLevel =* ...::
|
||||||
Set the signature verification level for this repository. For more
|
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
|
/** @name Accessors to the list of allowed architectures.
|
||||||
*
|
* libalpm will only install packages that match one of the configured
|
||||||
* libalpm will only install packages that match the configured architecture.
|
* architectures. The architectures do not need to match the physical
|
||||||
* The architecture does not need to match the physical architecture.
|
architecture. They can just be treated as a label.
|
||||||
* It can just be treated as a label.
|
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Returns the allowed package architecture.
|
/** Returns the allowed package architecture.
|
||||||
* @param handle the context handle
|
* @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 handle the context handle
|
||||||
* @param arch the architecture to set
|
* @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 */
|
/* End of arch accessors */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ void _alpm_handle_free(alpm_handle_t *handle)
|
||||||
FREELIST(handle->hookdirs);
|
FREELIST(handle->hookdirs);
|
||||||
FREE(handle->logfile);
|
FREE(handle->logfile);
|
||||||
FREE(handle->lockfile);
|
FREE(handle->lockfile);
|
||||||
FREE(handle->arch);
|
FREELIST(handle->architectures);
|
||||||
FREE(handle->gpgdir);
|
FREE(handle->gpgdir);
|
||||||
FREELIST(handle->noupgrade);
|
FREELIST(handle->noupgrade);
|
||||||
FREELIST(handle->noextract);
|
FREELIST(handle->noextract);
|
||||||
|
@ -276,10 +276,10 @@ alpm_list_t SYMEXPORT *alpm_option_get_assumeinstalled(alpm_handle_t *handle)
|
||||||
return handle->assumeinstalled;
|
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);
|
CHECK_HANDLE(handle, return NULL);
|
||||||
return handle->arch;
|
return handle->architectures;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)
|
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;
|
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);
|
CHECK_HANDLE(handle, return -1);
|
||||||
if(handle->arch) FREE(handle->arch);
|
if(handle->architectures) FREELIST(handle->architectures);
|
||||||
STRDUP(handle->arch, arch, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ struct __alpm_handle_t {
|
||||||
alpm_list_t *assumeinstalled; /* List of virtual packages used to satisfy dependencies */
|
alpm_list_t *assumeinstalled; /* List of virtual packages used to satisfy dependencies */
|
||||||
|
|
||||||
/* options */
|
/* 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 usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
|
||||||
int checkspace; /* Check disk space before installing */
|
int checkspace; /* Check disk space before installing */
|
||||||
char *dbext; /* Sync DB extension */
|
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 *i;
|
||||||
alpm_list_t *invalid = NULL;
|
alpm_list_t *invalid = NULL;
|
||||||
|
|
||||||
const char *arch = handle->arch;
|
if(!handle->architectures) {
|
||||||
if(!arch) {
|
_alpm_log(handle, ALPM_LOG_DEBUG, "skipping architecture checks\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for(i = pkgs; i; i = i->next) {
|
for(i = pkgs; i; i = i->next) {
|
||||||
alpm_pkg_t *pkg = i->data;
|
alpm_pkg_t *pkg = i->data;
|
||||||
|
alpm_list_t *j;
|
||||||
|
int found = 0;
|
||||||
const char *pkgarch = alpm_pkg_get_arch(pkg);
|
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;
|
char *string;
|
||||||
const char *pkgname = pkg->name;
|
const char *pkgname = pkg->name;
|
||||||
const char *pkgver = pkg->version;
|
const char *pkgver = pkg->version;
|
||||||
|
|
|
@ -159,7 +159,7 @@ int config_free(config_t *oldconfig)
|
||||||
FREELIST(oldconfig->cachedirs);
|
FREELIST(oldconfig->cachedirs);
|
||||||
free(oldconfig->xfercommand);
|
free(oldconfig->xfercommand);
|
||||||
free(oldconfig->print_format);
|
free(oldconfig->print_format);
|
||||||
free(oldconfig->arch);
|
FREELIST(oldconfig->architectures);
|
||||||
wordsplit_free(oldconfig->xfercommand_argv);
|
wordsplit_free(oldconfig->xfercommand_argv);
|
||||||
free(oldconfig);
|
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) {
|
if(strcmp(arch, "auto") == 0) {
|
||||||
struct utsname un;
|
struct utsname un;
|
||||||
|
char *newarch;
|
||||||
uname(&un);
|
uname(&un);
|
||||||
config->arch = strdup(un.machine);
|
newarch = strdup(un.machine);
|
||||||
} else {
|
free(arch);
|
||||||
config->arch = strdup(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,9 +641,12 @@ static int _parse_options(const char *key, char *value,
|
||||||
} else if(strcmp(key, "HookDir") == 0) {
|
} else if(strcmp(key, "HookDir") == 0) {
|
||||||
setrepeatingoption(value, "HookDir", &(config->hookdirs));
|
setrepeatingoption(value, "HookDir", &(config->hookdirs));
|
||||||
} else if(strcmp(key, "Architecture") == 0) {
|
} else if(strcmp(key, "Architecture") == 0) {
|
||||||
if(!config->arch) {
|
alpm_list_t *i, *arches = NULL;
|
||||||
config_set_arch(value);
|
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) {
|
} else if(strcmp(key, "DBPath") == 0) {
|
||||||
/* don't overwrite a path specified on the command line */
|
/* don't overwrite a path specified on the command line */
|
||||||
if(!config->dbpath) {
|
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)
|
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,
|
pm_printf(ALPM_LOG_ERROR,
|
||||||
_("mirror '%s' contains the '%s' variable, but no '%s' is defined.\n"),
|
_("mirror '%s' contains the '%s' variable, but no '%s' is defined.\n"),
|
||||||
s, "$arch", "Architecture");
|
s, "$arch", "Architecture");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c->arch) {
|
/* use first specified architecture */
|
||||||
|
if(c->architectures) {
|
||||||
char *temp, *replaced;
|
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;
|
temp = replaced;
|
||||||
replaced = strreplace(temp, "$repo", r->name);
|
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");
|
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_checkspace(handle, config->checkspace);
|
||||||
alpm_option_set_usesyslog(handle, config->usesyslog);
|
alpm_option_set_usesyslog(handle, config->usesyslog);
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,6 @@ typedef struct __config_t {
|
||||||
unsigned short usesyslog;
|
unsigned short usesyslog;
|
||||||
unsigned short color;
|
unsigned short color;
|
||||||
unsigned short disable_dl_timeout;
|
unsigned short disable_dl_timeout;
|
||||||
char *arch;
|
|
||||||
char *print_format;
|
char *print_format;
|
||||||
/* unfortunately, we have to keep track of paths both here and in the library
|
/* 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
|
* because they can come from both the command line or config file, and we
|
||||||
|
@ -70,6 +69,7 @@ typedef struct __config_t {
|
||||||
char *sysroot;
|
char *sysroot;
|
||||||
alpm_list_t *hookdirs;
|
alpm_list_t *hookdirs;
|
||||||
alpm_list_t *cachedirs;
|
alpm_list_t *cachedirs;
|
||||||
|
alpm_list_t *architectures;
|
||||||
|
|
||||||
unsigned short op_q_isfile;
|
unsigned short op_q_isfile;
|
||||||
unsigned short op_q_info;
|
unsigned short op_q_info;
|
||||||
|
@ -244,7 +244,7 @@ int config_free(config_t *oldconfig);
|
||||||
|
|
||||||
void config_repo_free(config_repo_t *repo);
|
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 parseconfig(const char *file);
|
||||||
int parseconfigfile(const char *file);
|
int parseconfigfile(const char *file);
|
||||||
int setdefaults(config_t *c);
|
int setdefaults(config_t *c);
|
||||||
|
|
|
@ -258,7 +258,7 @@ static void dump_config(void)
|
||||||
show_list_str("NoUpgrade", config->noupgrade);
|
show_list_str("NoUpgrade", config->noupgrade);
|
||||||
show_list_str("NoExtract", config->noextract);
|
show_list_str("NoExtract", config->noextract);
|
||||||
|
|
||||||
show_str("Architecture", config->arch);
|
show_list_str("Architecture", config->architectures);
|
||||||
show_str("XferCommand", config->xfercommand);
|
show_str("XferCommand", config->xfercommand);
|
||||||
|
|
||||||
show_bool("UseSyslog", config->usesyslog);
|
show_bool("UseSyslog", config->usesyslog);
|
||||||
|
@ -364,7 +364,7 @@ static int list_directives(void)
|
||||||
|
|
||||||
|
|
||||||
} else if(strcasecmp(i->data, "Architecture") == 0) {
|
} 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) {
|
} else if(strcasecmp(i->data, "XferCommand") == 0) {
|
||||||
show_str("XferCommand", config->xfercommand);
|
show_str("XferCommand", config->xfercommand);
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,7 @@ static int parsearg_global(int opt)
|
||||||
{
|
{
|
||||||
switch(opt) {
|
switch(opt) {
|
||||||
case OP_ARCH:
|
case OP_ARCH:
|
||||||
config_set_arch(optarg);
|
config_add_architecture(strdup(optarg));
|
||||||
break;
|
break;
|
||||||
case OP_ASK:
|
case OP_ASK:
|
||||||
config->noask = 1;
|
config->noask = 1;
|
||||||
|
|
|
@ -85,6 +85,8 @@ pacman_tests = [
|
||||||
'tests/mode001.py',
|
'tests/mode001.py',
|
||||||
'tests/mode002.py',
|
'tests/mode002.py',
|
||||||
'tests/mode003.py',
|
'tests/mode003.py',
|
||||||
|
'tests/multiple-architectures01.py',
|
||||||
|
'tests/multiple-architectures02.py',
|
||||||
'tests/noupgrade-inverted.py',
|
'tests/noupgrade-inverted.py',
|
||||||
'tests/overwrite-files-match-negated.py',
|
'tests/overwrite-files-match-negated.py',
|
||||||
'tests/overwrite-files-match.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