The following commit has been merged in the master branch: commit 61b3201ddbd1fc5b8683309138d5482c95716f88 Author: Guillem Jover <guil...@debian.org> Date: Tue Nov 15 21:59:17 2011 +0100
dpkg: Switch from foreign arch option to add and remove commands The --foreign-architecture option is not a good interface, the problem with it comes from the fact that the architectures supported by the database are not configuration, they are state. This shows up in several ways. When a front-end needs to load the list of architectures, it needs to get someone to parse dpkg.cfg files, this is currently done by dpkg itself, and the list can be retrieved with --print-foreign-architectures, the problem appears when wanting a front-end to load them through libdpkg. Making the latter have to execute «dpkg --print-foreign-architectures» would be suboptimal, and making libdpkg have to load dpkg.cfg would be distasteful. Another issue is that if the list of foreign architectures is on the configuration files it makes it slightly more tricky to cross-grade dpkg, and it makes it fairly easy to accidentally remove architectures required by the database. Replace the option with two new commands --add-architecture and --remove-architecture which will perform sanity checks and store and load the architecture list (including the native arch) in an internal db file under /var/lib/dpkg/. diff --git a/lib/dpkg/dbmodify.c b/lib/dpkg/dbmodify.c index 6981511..8922e46 100644 --- a/lib/dpkg/dbmodify.c +++ b/lib/dpkg/dbmodify.c @@ -276,6 +276,8 @@ modstatdb_open(enum modstatdb_rw readwritereq) internerr("unknown modstatdb_rw '%d'", readwritereq); } + dpkg_arch_load_list(); + if (cstatus != msdbrw_needsuperuserlockonly) { cleanupdates(); if (cflags >= msdbrw_available_readonly) diff --git a/man/dpkg.1 b/man/dpkg.1 index a01ae42..390a478 100644 --- a/man/dpkg.1 +++ b/man/dpkg.1 @@ -231,6 +231,19 @@ deinstall any packages not in list given to \-\-set\-selections. Searches for packages selected for installation, but which for some reason still haven't been installed. .TP +.B \-\-add\-architecture \fIarchitecture\fP +Add \fIarchitecture\fP to the list of architectures for which packages can +be installed without using \fB\-\-force\-architecture\fP. The architecture +\fBdpkg\fP is built for (i.e. the output of \fB\-\-print\-architecture\fP) +is always part of that list. +.TP +.B \-\-remove\-architecture \fIarchitecture\fP +Remove \fIarchitecture\fP from the list of architectures for which packages +can be installed without using \fB\-\-force\-architecture\fP. If the +architecture is currently in use in the database then the operation will +be refused, except if \fB\-\-force\-architecture\fP is specified. The +architecture \fBdpkg\fP is built for (i.e. the output of +\fB\-\-print\-architecture\fP) can never be removed from that list. .TP .B \-\-print\-architecture Print architecture of packages \fBdpkg\fP installs (for example, "i386"). @@ -572,12 +585,6 @@ each other. Both are processed in the given order, with the last rule that matches a file name making the decision. .RE .TP -.B \-\-foreign\-architecture \fIarchitecture\fP -Add \fIarchitecture\fP to the list of architectures for which packages can -be installed without using \fB\-\-force\-architecture\fP, in addition to -the architecture \fBdpkg\fP is built for (i.e.: the output of -\fB\-\-print\-architecture\fP). -.TP \fB\-\-status\-fd \fR\fIn\fR Send machine-readable package status and progress information to file descriptor \fIn\fP. This option can be specified multiple times. The diff --git a/src/enquiry.c b/src/enquiry.c index 0eebf11..5b661b5 100644 --- a/src/enquiry.c +++ b/src/enquiry.c @@ -484,6 +484,8 @@ print_foreign_arches(const char *const *argv) if (*argv) badusage(_("--%s takes no arguments"), cipaction->olong); + dpkg_arch_load_list(); + for (arch = dpkg_arch_get_list(); arch; arch = arch->next) { if (arch->type != arch_foreign) continue; diff --git a/src/main.c b/src/main.c index 27924cf..4ed6ee1 100644 --- a/src/main.c +++ b/src/main.c @@ -104,6 +104,8 @@ usage(const struct cmdinfo *ci, const char *value) " -l|--list [<pattern> ...] List packages concisely.\n" " -S|--search <pattern> ... Find package(s) owning file(s).\n" " -C|--audit Check for broken package(s).\n" +" --add-architecture <arch> Add <arch> to the list of architectures.\n" +" --remove-architecture <arch> Remove <arch> from the list of architectures.\n" " --print-architecture Print dpkg architecture.\n" " --print-foreign-architectures Print allowed foreign architectures.\n" " --compare-versions <a> <op> <b> Compare version numbers - see below.\n" @@ -133,8 +135,6 @@ usage(const struct cmdinfo *ci, const char *value) " --instdir=<directory> Change installation dir without changing admin dir.\n" " --path-exclude=<pattern> Do not install paths which match a shell pattern.\n" " --path-include=<pattern> Re-include a pattern after a previous exclusion.\n" -" --foreign-architecture=<arch>\n" -" Add <arch> to the list of foreign architectures.\n" " -O|--selected-only Skip packages not selected for install/upgrade.\n" " -E|--skip-same-version Skip packages whose same version is installed.\n" " -G|--refuse-downgrade Skip packages with earlier version than installed.\n" @@ -473,22 +473,74 @@ run_status_loggers(struct invoke_hook *hook_head) } } -static void -set_foreign_arch(const struct cmdinfo *cip, const char *value) +static int +arch_add(const char *const *argv) { struct dpkg_arch *arch; + const char *archname = *argv++; + + if (archname == NULL) + badusage(_("--%s takes one argument"), cipaction->olong); + + dpkg_arch_load_list(); + + arch = dpkg_arch_add(archname); + switch (arch->type) { + case arch_native: + case arch_foreign: + break; + case arch_illegal: + ohshit(_("architecture '%s' is illegal: %s"), archname, + dpkg_arch_name_is_illegal(archname)); + default: + ohshit(_("architecture '%s' is reserved and cannot be added"), archname); + } + + dpkg_arch_save_list(); + + return 0; +} + +static int +arch_remove(const char *const *argv) +{ + const char *archname = *argv++; + struct dpkg_arch *arch; + struct pkgiterator *iter; + struct pkginfo *pkg; + + if (archname == NULL) + badusage(_("--%s takes one argument"), cipaction->olong); + + modstatdb_open(msdbrw_readonly); + + arch = dpkg_arch_find(archname); + if (arch->type != arch_foreign) { + warning(_("cannot remove non-foreign architecture '%s'"), arch->name); + return 0; + } + + /* Check if it's safe to remove the architecture from the db. */ + iter = pkg_db_iter_new(); + while ((pkg = pkg_db_iter_next_pkg(iter))) { + if (pkg->installed.arch == arch) { + if (fc_architecture) + warning(_("removing architecture '%s' currently in use by database"), + arch->name); + else + ohshit(_("cannot remove architecture '%s' currently in use by the database"), + arch->name); + break; + } + } + pkg_db_iter_free(iter); + + dpkg_arch_remove(arch); + dpkg_arch_save_list(); + + modstatdb_shutdown(); - arch = dpkg_arch_find(value); - if (arch->type == arch_foreign) - return; - else if (arch->type == arch_unknown) - arch->type = arch_foreign; - else if (arch->type == arch_illegal) - warning(_("ignoring option --%s=%s: %s"), cip->olong, value, - dpkg_arch_name_is_illegal(value)); - else - warning(_("ignoring option --%s=%s: %s"), cip->olong, value, - _("this architecture cannot be foreign")); + return 0; } static void setforce(const struct cmdinfo *cip, const char *value) { @@ -574,6 +626,8 @@ static const struct cmdinfo cmdinfos[]= { ACTION( "assert-working-epoch", 0, act_assertepoch, assertepoch ), ACTION( "assert-long-filenames", 0, act_assertlongfilenames, assertlongfilenames ), ACTION( "assert-multi-conrep", 0, act_assertmulticonrep, assertmulticonrep ), + ACTION( "add-architecture", 0, act_arch_add, arch_add ), + ACTION( "remove-architecture", 0, act_arch_remove, arch_remove ), ACTION( "print-architecture", 0, act_printarch, printarch ), ACTION( "print-installation-architecture", 0, act_printinstarch, printinstarch ), ACTION( "print-foreign-architectures", 0, act_printforeignarches, print_foreign_arches ), @@ -587,7 +641,6 @@ static const struct cmdinfo cmdinfos[]= { { "post-invoke", 0, 1, NULL, NULL, set_invoke_hook, 0, &post_invoke_hooks_tail }, { "path-exclude", 0, 1, NULL, NULL, setfilter, 0 }, { "path-include", 0, 1, NULL, NULL, setfilter, 1 }, - { "foreign-architecture", 0, 1, NULL, NULL, set_foreign_arch, 0 }, { "status-logger", 0, 1, NULL, NULL, set_invoke_hook, 0, &status_loggers_tail }, { "status-fd", 0, 1, NULL, NULL, setpipe, 0 }, { "log", 0, 1, NULL, &log_file, NULL, 0 }, diff --git a/src/main.h b/src/main.h index c6807be..583dedd 100644 --- a/src/main.h +++ b/src/main.h @@ -78,6 +78,8 @@ enum action { act_cmpversions, + act_arch_add, + act_arch_remove, act_printarch, act_printinstarch, act_printforeignarches, -- dpkg's main repository -- To UNSUBSCRIBE, email to debian-dpkg-cvs-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org