diff options
-rw-r--r-- | apt-pkg/aptconfiguration.cc | 22 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 20 | ||||
-rw-r--r-- | apt-pkg/edsp.cc | 7 | ||||
-rw-r--r-- | apt-private/private-source.cc | 11 | ||||
-rw-r--r-- | doc/examples/configure-index | 1 | ||||
-rwxr-xr-x | test/integration/test-apt-get-build-dep-barbarian | 140 | ||||
-rwxr-xr-x | test/integration/test-apt-get-build-dep-file | 14 | ||||
-rw-r--r-- | test/libapt/getarchitectures_test.cc | 28 |
8 files changed, 219 insertions, 24 deletions
diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 671c3d553..00a97a0e7 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -315,13 +315,11 @@ bool Configuration::checkLanguage(std::string Lang, bool const All) { /*}}}*/ // getArchitectures - Return Vector of preferred Architectures /*{{{*/ std::vector<std::string> const Configuration::getArchitectures(bool const &Cached) { - using std::string; - - std::vector<string> static archs; + std::vector<std::string> static archs; if (likely(Cached == true) && archs.empty() == false) return archs; - string const arch = _config->Find("APT::Architecture"); + std::string const arch = _config->Find("APT::Architecture"); archs = _config->FindVector("APT::Architectures"); if (archs.empty() == true && _system != nullptr) @@ -331,15 +329,13 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache std::find(archs.begin(), archs.end(), arch) == archs.end()) archs.insert(archs.begin(), arch); - // erase duplicates and empty strings - for (std::vector<string>::reverse_iterator a = archs.rbegin(); - a != archs.rend(); ++a) { - if (a->empty() == true || std::find(a + 1, archs.rend(), *a) != archs.rend()) - archs.erase(a.base()-1); - if (a == archs.rend()) - break; - } - + // erase duplicates, empty strings and very foreign architectures + auto newend = std::remove_if(archs.begin(), archs.end(), [](auto const &a) { return a.empty(); }); + for (auto a = archs.begin(); a != newend; ++a) + newend = std::remove(std::next(a), newend, *a); + for (auto const &f : _config->FindVector("APT::BarbarianArchitectures")) + newend = std::remove(archs.begin(), newend, f); + archs.erase(newend, archs.end()); return archs; } /*}}}*/ diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index f24a5e79e..d78cea758 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -18,6 +18,7 @@ #include <algorithm> #include <map> +#include <optional> #include <sstream> #include <string> #include <utility> @@ -966,13 +967,13 @@ pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool con class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ { - static std::vector<std::string> getDefaultSetOf(std::string const &Name, - std::map<std::string, std::string> const &Options, std::vector<std::string> const &defaultValues) + static std::optional<std::vector<std::string>> getDefaultSetOf(std::string const &Name, + std::map<std::string, std::string> const &Options) { auto const val = Options.find(Name); if (val != Options.end()) return VectorizeString(val->second, ','); - return defaultValues; + return {}; } static std::vector<std::string> applyPlusMinusOptions(std::string const &Name, std::map<std::string, std::string> const &Options, std::vector<std::string> &&Values) @@ -997,12 +998,21 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ static std::vector<std::string> parsePlusMinusOptions(std::string const &Name, std::map<std::string, std::string> const &Options, std::vector<std::string> const &defaultValues) { - return applyPlusMinusOptions(Name, Options, getDefaultSetOf(Name, Options, defaultValues)); + return applyPlusMinusOptions(Name, Options, getDefaultSetOf(Name, Options).value_or(defaultValues)); } static std::vector<std::string> parsePlusMinusArchOptions(std::string const &Name, std::map<std::string, std::string> const &Options) { - auto Values = getDefaultSetOf(Name, Options, APT::Configuration::getArchitectures()); + std::vector<std::string> Values; + if (auto opt = getDefaultSetOf(Name, Options); opt.has_value()) + Values = opt.value(); + else + { + Values = APT::Configuration::getArchitectures(); + auto veryforeign = _config->FindVector("APT::BarbarianArchitectures"); + Values.reserve(Values.size() + veryforeign.size()); + std::move(veryforeign.begin(), veryforeign.end(), std::back_inserter(Values)); + } // all is a very special architecture users shouldn't be concerned with explicitly // but if the user does, do not override the choice auto const val = Options.find(Name + "-"); diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 5bf23044b..b7c0d28d2 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -208,7 +208,10 @@ static bool WriteScenarioLimitedDependency(FileFd &output, /*}}}*/ static bool checkKnownArchitecture(std::string const &arch) /*{{{*/ { - return APT::Configuration::checkArchitecture(arch); + if (APT::Configuration::checkArchitecture(arch)) + return true; + static auto const veryforeign = _config->FindVector("APT::BarbarianArchitectures"); + return std::find(veryforeign.begin(), veryforeign.end(), arch) != veryforeign.end(); } /*}}}*/ static bool WriteGenericRequestHeaders(FileFd &output, APT::StringView const head)/*{{{*/ @@ -217,6 +220,8 @@ static bool WriteGenericRequestHeaders(FileFd &output, APT::StringView const hea "Architectures:"); for (auto const &a : APT::Configuration::getArchitectures()) WriteOkay(Okay, output, " ", a); + for (auto const &a : _config->FindVector("APT::BarbarianArchitectures")) + WriteOkay(Okay, output, " ", a); return WriteOkay(Okay, output, "\n"); } /*}}}*/ diff --git a/apt-private/private-source.cc b/apt-private/private-source.cc index 7eb5a8f4a..db96cb17f 100644 --- a/apt-private/private-source.cc +++ b/apt-private/private-source.cc @@ -638,11 +638,14 @@ static void WriteBuildDependencyPackage(std::ostringstream &buildDepsPkgFile, bool DoBuildDep(CommandLine &CmdL) { std::string hostArch = _config->Find("APT::Get::Host-Architecture"); - if (hostArch.empty() == false) + if (not hostArch.empty()) { - std::vector<std::string> archs = APT::Configuration::getArchitectures(); - if (std::find(archs.begin(), archs.end(), hostArch) == archs.end()) - return _error->Error(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch.c_str()); + if (not APT::Configuration::checkArchitecture(hostArch)) + { + auto const veryforeign = _config->FindVector("APT::BarbarianArchitectures"); + if (std::find(veryforeign.begin(), veryforeign.end(), hostArch) == veryforeign.end()) + _error->Warning(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch.c_str()); + } } auto const nativeArch = _config->Find("APT::Architecture"); std::string const pseudoArch = hostArch.empty() ? nativeArch : hostArch; diff --git a/doc/examples/configure-index b/doc/examples/configure-index index 4eca100f5..f3f7f5ebc 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -49,6 +49,7 @@ APT { Architecture "<STRING>"; // debian architecture like amd64, i386, powerpc, armhf, mips, … Architectures "<LIST>"; // a list of (foreign) debian architectures, defaults to: dpkg --print-foreign-architectures + BarbarianArchitectures "<LIST>"; // a list of architectures considered too foreign to satisfy M-A:foreign Build-Essential "<LIST>"; // list of package names Build-Profiles "<STRING_OR_LIST>"; diff --git a/test/integration/test-apt-get-build-dep-barbarian b/test/integration/test-apt-get-build-dep-barbarian new file mode 100755 index 000000000..688f7a54b --- /dev/null +++ b/test/integration/test-apt-get-build-dep-barbarian @@ -0,0 +1,140 @@ +#!/bin/sh +set -e + +TESTDIR="$(readlink -f "$(dirname "$0")")" +. "$TESTDIR/framework" +setupenvironment +configarchitecture 'amd64' 'i386' 'armel' 'mipsel' + +insertinstalledpackage 'build-essential' 'all' '1' +insertpackage 'unstable' 'samey' 'amd64,i386,armel,mipsel' '1' 'Multi-Arch: same' +insertinstalledpackage 'samey' 'unknown' '1' 'Multi-Arch: same' + +insertsource 'unstable' 'cool-foo' 'any' '1' 'Build-Depends: foo, samey' +insertsource 'unstable' 'bad-amd64-foo' 'any' '1' 'Build-Depends: foo, samey +Build-Conflicts: foo:amd64' +insertsource 'unstable' 'bad-armel-foo' 'any' '1' 'Build-Depends: foo, samey +Build-Conflicts: foo:armel' +insertsource 'unstable' 'bad-amd64-armel-foo' 'any' '1' 'Build-Depends: foo, samey +Build-Conflicts: foo:amd64, foo:armel' +insertsource 'unstable' 'bad-amd64-i386-foo' 'any' '1' 'Build-Depends: foo, samey +Build-Conflicts: foo:amd64, foo:i386' +insertsource 'unstable' 'bad-amd64-i386-armel-foo' 'any' '1' 'Build-Depends: foo, samey +Build-Conflicts: foo:amd64, foo:i386, foo:armel' +insertpackage 'unstable' 'foo' 'amd64,i386,armel,mipsel' '1' 'Multi-Arch: foreign' + +setupaptarchive + +installsfoosamey() { + local FOO="foo:$1" + local SAMEY="samey:$2" + if [ "$1" = 'amd64' ]; then FOO='foo'; fi + if [ "$2" = 'amd64' ]; then SAMEY='samey'; fi + echo "Reading package lists... +Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + $FOO $SAMEY +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst $FOO (1 unstable [$1]) +Inst $SAMEY (1 unstable [$2]) +Conf $FOO (1 unstable [$1]) +Conf $SAMEY (1 unstable [$2])" +} + +testdpkginstalled 'samey:unknown' + +testsuccessequal "$(installsfoosamey 'amd64' 'amd64')" apt build-dep cool-foo -s +testsuccessequal "$(installsfoosamey 'amd64' 'amd64')" apt build-dep cool-foo -s -a amd64 +testsuccessequal "$(installsfoosamey 'amd64' 'i386')" apt build-dep cool-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'amd64' 'armel')" apt build-dep cool-foo -s -a armel + +testsuccessequal "$(installsfoosamey 'i386' 'amd64')" apt build-dep bad-amd64-foo -s +testsuccessequal "$(installsfoosamey 'i386' 'amd64')" apt build-dep bad-amd64-foo -s -a amd64 +testsuccessequal "$(installsfoosamey 'i386' 'i386')" apt build-dep bad-amd64-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'i386' 'armel')" apt build-dep bad-amd64-foo -s -a armel + +testsuccessequal "$(installsfoosamey 'amd64' 'amd64')" apt build-dep bad-armel-foo -s +testsuccessequal "$(installsfoosamey 'amd64' 'amd64')" apt build-dep bad-armel-foo -s -a amd64 +testsuccessequal "$(installsfoosamey 'amd64' 'i386')" apt build-dep bad-armel-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'amd64' 'armel')" apt build-dep bad-armel-foo -s -a armel + +testsuccessequal "$(installsfoosamey 'i386' 'amd64')" apt build-dep bad-amd64-armel-foo -s +testsuccessequal "$(installsfoosamey 'i386' 'amd64')" apt build-dep bad-amd64-armel-foo -s -a amd64 +testsuccessequal "$(installsfoosamey 'i386' 'i386')" apt build-dep bad-amd64-armel-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'i386' 'armel')" apt build-dep bad-amd64-armel-foo -s -a armel + +testsuccessequal "$(installsfoosamey 'armel' 'amd64')" apt build-dep bad-amd64-i386-foo -s +testsuccessequal "$(installsfoosamey 'armel' 'amd64')" apt build-dep bad-amd64-i386-foo -s -a amd64 +testsuccessequal "$(installsfoosamey 'armel' 'i386')" apt build-dep bad-amd64-i386-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'armel' 'armel')" apt build-dep bad-amd64-i386-foo -s -a armel + +testsuccessequal "$(installsfoosamey 'mipsel' 'amd64')" apt build-dep bad-amd64-i386-armel-foo -s +testsuccessequal "$(installsfoosamey 'mipsel' 'amd64')" apt build-dep bad-amd64-i386-armel-foo -s -a amd64 +testsuccessequal "$(installsfoosamey 'mipsel' 'i386')" apt build-dep bad-amd64-i386-armel-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'mipsel' 'armel')" apt build-dep bad-amd64-i386-armel-foo -s -a armel + + +msgmsg 'BarbarianArchitectures' 'config' +echo 'APT::BarbarianArchitectures { "mipsel"; "armel"; };' > rootdir/etc/apt/apt.conf.d/99barbarianarchs +testsuccess aptcache gencaches + +testsuccessequal "$(installsfoosamey 'amd64' 'i386')" apt build-dep cool-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'i386' 'i386')" apt build-dep bad-amd64-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'amd64' 'i386')" apt build-dep bad-armel-foo -s -a i386 +testsuccessequal "$(installsfoosamey 'i386' 'i386')" apt build-dep bad-amd64-armel-foo -s -a i386 +testfailureequal 'Reading package lists... +Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: + +The following packages have unmet dependencies: + builddeps:bad-amd64-i386-foo:i386 : Depends: foo:i386 +E: Unable to correct problems, you have held broken packages.' apt build-dep bad-amd64-i386-foo -s -a i386 +testfailureequal 'Reading package lists... +Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: + +The following packages have unmet dependencies: + builddeps:bad-amd64-i386-armel-foo:i386 : Depends: foo:i386 +E: Unable to correct problems, you have held broken packages.' apt build-dep bad-amd64-i386-armel-foo -s -a i386 + +testsuccessequal "$(installsfoosamey 'amd64' 'armel')" apt build-dep cool-foo -s -a armel +testsuccessequal "$(installsfoosamey 'i386' 'armel')" apt build-dep bad-amd64-foo -s -a armel +testsuccessequal "$(installsfoosamey 'amd64' 'armel')" apt build-dep bad-armel-foo -s -a armel +testsuccessequal "$(installsfoosamey 'i386' 'armel')" apt build-dep bad-amd64-armel-foo -s -a armel +testsuccessequal "$(installsfoosamey 'armel' 'armel')" apt build-dep bad-amd64-i386-foo -s -a armel +FAILURE='Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: + +The following packages have unmet dependencies: + builddeps:bad-amd64-i386-armel-foo:armel : Depends: foo:armel +E: Unable to correct problems, you have held broken packages.' +testfailureequal "Reading package lists... +$FAILURE" apt build-dep bad-amd64-i386-armel-foo -s -a armel + +msgmsg 'BarbarianArchitectures' 'cmdline options' +rm rootdir/etc/apt/apt.conf.d/99barbarianarchs +testsuccess aptcache gencaches + +testsuccessequal "$(installsfoosamey 'mipsel' 'armel')" apt build-dep bad-amd64-i386-armel-foo -s -a armel +testsuccess aptcache gencaches -o APT::BarbarianArchitectures::=armel +testsuccessequal "$(installsfoosamey 'mipsel' 'armel')" apt build-dep bad-amd64-i386-armel-foo -s -a armel -o APT::BarbarianArchitectures::=armel +testfailureequal "$FAILURE" apt build-dep bad-amd64-i386-armel-foo -s -a armel -o APT::BarbarianArchitectures::=mipsel +testfailureequal "$FAILURE" apt build-dep bad-amd64-i386-armel-foo -s -a armel -o APT::BarbarianArchitectures::=mipsel -o APT::BarbarianArchitectures::=armel +testfailureequal "Reading package lists... +$FAILURE" apt build-dep bad-amd64-i386-armel-foo -s -a armel -o APT::BarbarianArchitectures=mipsel,armel diff --git a/test/integration/test-apt-get-build-dep-file b/test/integration/test-apt-get-build-dep-file index c4b6947bf..88bf10b0f 100755 --- a/test/integration/test-apt-get-build-dep-file +++ b/test/integration/test-apt-get-build-dep-file @@ -158,7 +158,19 @@ testsuccess aptget build-dep --simulate '..' cd ../.. testfailureequal 'E: Must specify at least one package to check builddeps for' aptget build-dep -testfailureequal 'E: No architecture information available for armel. See apt.conf(5) APT::Architectures for setup' aptget build-dep --simulate ./foo-1.0 -a armel +testfailureequal "Note, using directory './foo-1.0' to get the build dependencies +Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: + +The following packages have unmet dependencies: + builddeps:./foo-1.0:armel : Depends: debhelper:armel (>= 7) but it is not installable +W: No architecture information available for armel. See apt.conf(5) APT::Architectures for setup +E: Unable to correct problems, you have held broken packages." aptget build-dep --simulate ./foo-1.0 -a armel testfailureequal 'Reading package lists... E: Unable to find a source package for foo' aptget build-dep --simulate foo diff --git a/test/libapt/getarchitectures_test.cc b/test/libapt/getarchitectures_test.cc index 57e9a5f2f..4f767226f 100644 --- a/test/libapt/getarchitectures_test.cc +++ b/test/libapt/getarchitectures_test.cc @@ -75,3 +75,31 @@ TEST(ArchitecturesTest,Duplicates) _config->Clear(); } +TEST(ArchitecturesTest,VeryForeign) +{ + _config->Clear(); + _config->Set("APT::Architectures::", "i386"); + _config->Set("APT::Architectures::", "amd64"); + _config->Set("APT::Architectures::", "armel"); + + auto vec = APT::Configuration::getArchitectures(false); + ASSERT_EQ(3u, vec.size()); + EXPECT_EQ("i386", vec[0]); + EXPECT_EQ("amd64", vec[1]); + EXPECT_EQ("armel", vec[2]); + + _config->Set("APT::BarbarianArchitectures::", "mipsel"); + vec = APT::Configuration::getArchitectures(false); + ASSERT_EQ(3u, vec.size()); + EXPECT_EQ("i386", vec[0]); + EXPECT_EQ("amd64", vec[1]); + EXPECT_EQ("armel", vec[2]); + + _config->Set("APT::BarbarianArchitectures::", "armel"); + vec = APT::Configuration::getArchitectures(false); + ASSERT_EQ(2u, vec.size()); + EXPECT_EQ("i386", vec[0]); + EXPECT_EQ("amd64", vec[1]); + + _config->Clear(); +} |