From 7586e9b910edf4bfc176417bf971a9d83243b139 Mon Sep 17 00:00:00 2001 From: Ciaran McCreesh Date: Sat, 26 Mar 2011 19:26:06 +0000 Subject: Move PackageDatabase into EnvironmentImplementation --- .gitignore | 2 +- paludis/environment_implementation.cc | 256 +++++++++++++++++++++++++++-- paludis/environment_implementation_TEST.cc | 183 +++++++++++++++++++++ paludis/files.m4 | 4 +- paludis/package_database_TEST.cc | 181 -------------------- 5 files changed, 424 insertions(+), 202 deletions(-) create mode 100644 paludis/environment_implementation_TEST.cc delete mode 100644 paludis/package_database_TEST.cc diff --git a/.gitignore b/.gitignore index 4bccc6c56..5a22b83b2 100644 --- a/.gitignore +++ b/.gitignore @@ -246,6 +246,7 @@ paludis-*.*.*.tar.bz2 /paludis/dep_spec_TEST /paludis/elike_dep_parser_TEST /paludis/elike_use_requirement_TEST +/paludis/environment_implementation_TEST /paludis/environments/adapted/adapted_environment_TEST /paludis/environments/no_config/no_config_environment_TEST /paludis/environments/paludis/paludis_environment_TEST @@ -263,7 +264,6 @@ paludis-*.*.*.tar.bz2 /paludis/host_tuple_name_TEST /paludis/ihateautomake.cc /paludis/name_TEST -/paludis/package_database_TEST /paludis/paludis.hh /paludis/repositories/accounts/accounts_repository_TEST /paludis/repositories/e/aa_visitor_TEST diff --git a/paludis/environment_implementation.cc b/paludis/environment_implementation.cc index d7f7f339b..910d278e6 100644 --- a/paludis/environment_implementation.cc +++ b/paludis/environment_implementation.cc @@ -20,12 +20,15 @@ #include #include #include -#include #include #include #include #include -#include +#include +#include +#include +#include +#include #include #include @@ -39,10 +42,15 @@ #include #include #include +#include +#include +#include +#include #include #include #include +#include #include "config.h" @@ -113,23 +121,24 @@ namespace paludis template <> struct WrappedForwardIteratorTraits { - typedef PackageDatabase::RepositoryConstIterator UnderlyingIterator; + typedef std::list >::const_iterator UnderlyingIterator; }; template <> struct Imp { - std::shared_ptr package_database; std::map notifier_callbacks; std::list > selection_caches; + std::list > repositories; + std::multimap >::iterator> repository_importances; + mutable Mutex sets_mutex; mutable bool loaded_sets; mutable std::shared_ptr set_names; mutable SetsStore sets; - Imp(const std::shared_ptr & d) : - package_database(d), + Imp() : loaded_sets(false) { } @@ -137,7 +146,7 @@ namespace paludis } EnvironmentImplementation::EnvironmentImplementation() : - _imp(std::shared_ptr(new PackageDatabase(this))) + _imp() { } @@ -369,50 +378,261 @@ EnvironmentImplementation::set_always_exists(const SetName & s) const void EnvironmentImplementation::add_repository(int importance, const std::shared_ptr & repository) { - _imp->package_database->add_repository(importance, repository); + Context c("When adding a repository named '" + stringify(repository->name()) + "':"); + + for (IndirectIterator r_c(begin_repositories()), r_end(end_repositories()) ; + r_c != r_end ; ++r_c) + if (r_c->name() == repository->name()) + throw DuplicateRepositoryError(stringify(repository->name())); + + std::list >::iterator q(_imp->repositories.end()); + for (std::multimap >::iterator>::iterator + p(_imp->repository_importances.begin()), p_end(_imp->repository_importances.end()) ; + p != p_end ; ++p) + if (p->first > importance) + { + q = p->second; + break; + } + + _imp->repository_importances.insert(std::make_pair(importance, _imp->repositories.insert(q, repository))); } const std::shared_ptr EnvironmentImplementation::fetch_repository(const RepositoryName & name) const { - return _imp->package_database->fetch_repository(name); + for (RepositoryConstIterator r(begin_repositories()), r_end(end_repositories()) ; + r != r_end ; ++r) + if ((*r)->name() == name) + return *r; + + throw NoSuchRepositoryError(name); } const std::shared_ptr EnvironmentImplementation::fetch_repository(const RepositoryName & name) { - return _imp->package_database->fetch_repository(name); + for (RepositoryConstIterator r(begin_repositories()), r_end(end_repositories()) ; + r != r_end ; ++r) + if ((*r)->name() == name) + return *r; + + throw NoSuchRepositoryError(name); } bool EnvironmentImplementation::has_repository_named(const RepositoryName & name) const { - return _imp->package_database->has_repository_named(name); + for (RepositoryConstIterator r(begin_repositories()), r_end(end_repositories()) ; + r != r_end ; ++r) + if ((*r)->name() == name) + return true; + + return false; +} + +namespace +{ + typedef std::map > QPNIMap; + + struct CategoryRepositoryNamePairComparator + { + bool operator() (const std::pair & a, + const std::pair & b) const + { + if (a.first != b.first) + return a.first < b.first; + return a.second < b.second; + } + }; + + struct IsInstalled + { + const Environment * const _env; + + IsInstalled(const Environment * e) : + _env(e) + { + } + + typedef QualifiedPackageName argument_type; + typedef bool result_type; + + bool operator() (const QualifiedPackageName & qpn) const + { + return ! (*_env)[selection::SomeArbitraryVersion(generator::Package(qpn) | + filter::InstalledAtRoot(_env->preferred_root_key()->value()))]->empty(); + } + }; + + struct IsImportant + { + typedef QualifiedPackageName argument_type; + typedef bool result_type; + + const std::shared_ptr _map; + + IsImportant(const std::shared_ptr & m) : + _map(m) + { + } + + bool operator() (const QualifiedPackageName & qpn) const + { + return _map->find(qpn)->second.first; + } + }; + + struct IsInUnimportantRepo + { + typedef QualifiedPackageName argument_type; + typedef bool result_type; + + const std::shared_ptr _map; + + IsInUnimportantRepo(const std::shared_ptr & m) : + _map(m) + { + } + + bool operator() (const QualifiedPackageName & qpn) const + { + return ! _map->find(qpn)->second.second; + } + }; } QualifiedPackageName -EnvironmentImplementation::fetch_unique_qualified_package_name(const PackageNamePart & name, - const Filter & filter, const bool disambiguate) const +EnvironmentImplementation::fetch_unique_qualified_package_name(const PackageNamePart & p, + const Filter & f, const bool disambiguate) const { - return _imp->package_database->fetch_unique_qualified_package_name(name, filter, disambiguate); + Context context("When disambiguating package name '" + stringify(p) + "':"); + + // Map matching QualifiedPackageNames with a pair of flags specifying + // respectively that at least one repository containing the package thinks + // the category is important and that the package is in a repository + // that reports it is important itself + std::shared_ptr result(new QPNIMap); + std::set, CategoryRepositoryNamePairComparator> checked; + + std::shared_ptr pkgs((*this)[selection::AllVersionsUnsorted( + generator::Matches(make_package_dep_spec({ }).package_name_part(p), make_null_shared_ptr(), { }) | f)]); + + for (IndirectIterator it(pkgs->begin()), + it_end(pkgs->end()); it_end != it; ++it) + { + Context local_context("When checking category '" + stringify(it->name().category()) + "' in repository '" + + stringify(it->repository_name()) + "':"); + + if (! checked.insert(std::make_pair(it->name().category(), it->repository_name())).second) + continue; + + auto repo(fetch_repository(it->repository_name())); + std::shared_ptr unimportant_cats(repo->unimportant_category_names({ })); + bool is_important(unimportant_cats->end() == unimportant_cats->find(it->name().category())); + bool is_in_important_repo(! repo->is_unimportant()); + QPNIMap::iterator i(result->insert(std::make_pair(it->name(), std::make_pair(is_important, is_in_important_repo))).first); + i->second.first = i->second.first || is_important; + i->second.second = i->second.second || is_in_important_repo; + } + + if (result->empty()) + throw NoSuchPackageError(stringify(p)); + if (result->size() > 1) + { + using namespace std::placeholders; + + std::list qpns; + + do + { + const IsImportant is_important(result); + const IsInstalled is_installed(this); + const IsInUnimportantRepo is_in_unimportant_repo(result); + + std::remove_copy_if(first_iterator(result->begin()), first_iterator(result->end()), + std::front_inserter(qpns), + std::bind(std::logical_and(), + std::bind(std::not1(is_important), _1), + std::bind(std::not1(is_installed), _1))); + + if (! qpns.empty() && next(qpns.begin()) == qpns.end()) + break; + + qpns.remove_if(std::bind(is_in_unimportant_repo, _1)); + + if (! qpns.empty() && next(qpns.begin()) == qpns.end()) + break; + + qpns.remove_if(std::bind(std::logical_and(), + std::bind(is_important, _1), + std::bind(std::not1(is_installed), _1))); + + if (! qpns.empty() && next(qpns.begin()) == qpns.end()) + break; + + qpns.remove_if(std::bind(std::logical_and(), + std::bind(std::not1(is_important), _1), + std::bind(is_installed, _1))); + + if (! qpns.empty() && next(qpns.begin()) == qpns.end()) + break; + + auto candidates(std::make_shared >()); + std::transform(first_iterator(result->begin()), first_iterator(result->end()), candidates->back_inserter(), + &stringify); + throw AmbiguousPackageNameError(stringify(p), candidates); + } while (false); + + if (! disambiguate) + { + auto candidates(std::make_shared >()); + std::transform(first_iterator(result->begin()), first_iterator(result->end()), candidates->back_inserter(), + &stringify); + throw AmbiguousPackageNameError(stringify(p), candidates); + } + + Log::get_instance()->message("environment.ambiguous_name", ll_warning, lc_context) + << "Package name '" << p << "' is ambiguous, assuming you meant '" << *qpns.begin() + << "' (candidates were '" + << join(first_iterator(result->begin()), first_iterator(result->end()), "', '") << "')"; + + return *qpns.begin(); + } + else + return result->begin()->first; } bool -EnvironmentImplementation::more_important_than(const RepositoryName & a, const RepositoryName & b) const +EnvironmentImplementation::more_important_than(const RepositoryName & lhs, const RepositoryName & rhs) const { - return _imp->package_database->more_important_than(a, b); + std::map rank; + int x(0); + for (auto r(begin_repositories()), r_end(end_repositories()) ; + r != r_end ; ++r) + rank.insert(std::make_pair(stringify((*r)->name()), ++x)); + + std::map::const_iterator l(rank.find(stringify(lhs))); + if (l == rank.end()) + throw InternalError(PALUDIS_HERE, "lhs.repository '" + stringify(lhs) + "' not in rank"); + + std::map::const_iterator r(rank.find(stringify(rhs))); + if (r == rank.end()) + throw InternalError(PALUDIS_HERE, "rhs.repository '" + stringify(rhs) + "' not in rank"); + + return l->second > r->second; } EnvironmentImplementation::RepositoryConstIterator EnvironmentImplementation::begin_repositories() const { - return _imp->package_database->begin_repositories(); + return RepositoryConstIterator(_imp->repositories.begin()); } EnvironmentImplementation::RepositoryConstIterator EnvironmentImplementation::end_repositories() const { - return _imp->package_database->end_repositories(); + return RepositoryConstIterator(_imp->repositories.end()); } DuplicateSetError::DuplicateSetError(const SetName & s) throw () : diff --git a/paludis/environment_implementation_TEST.cc b/paludis/environment_implementation_TEST.cc new file mode 100644 index 000000000..a982fa25a --- /dev/null +++ b/paludis/environment_implementation_TEST.cc @@ -0,0 +1,183 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Ciaran McCreesh + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace paludis; + +TEST(EnvironmentImplementation, Repositories) +{ + TestEnvironment e; + + const std::shared_ptr r1(std::make_shared(make_named_values( + n::environment() = &e, + n::name() = RepositoryName("repo1") + ))); + const std::shared_ptr r2(std::make_shared(make_named_values( + n::environment() = &e, + n::name() = RepositoryName("repo2") + ))); + + EXPECT_THROW(e.fetch_repository(RepositoryName("repo1")), NoSuchRepositoryError); + EXPECT_THROW(e.fetch_repository(RepositoryName("repo2")), NoSuchRepositoryError); + + e.add_repository(10, r1); + ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo1")))); + EXPECT_EQ(RepositoryName("repo1"), e.fetch_repository(RepositoryName("repo1"))->name()); + EXPECT_THROW(e.fetch_repository(RepositoryName("repo2")), NoSuchRepositoryError); + + EXPECT_THROW(e.add_repository(10, r1), DuplicateRepositoryError); + + e.add_repository(11, r2); + ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo1")))); + EXPECT_EQ(RepositoryName("repo1"), e.fetch_repository(RepositoryName("repo1"))->name()); + ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo2")))); + EXPECT_EQ(RepositoryName("repo2"), e.fetch_repository(RepositoryName("repo2"))->name()); + + EXPECT_THROW(e.add_repository(10, r1), DuplicateRepositoryError); + EXPECT_THROW(e.add_repository(5, r2), DuplicateRepositoryError); + + ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo1")))); + EXPECT_EQ(RepositoryName("repo1"), e.fetch_repository(RepositoryName("repo1"))->name()); + ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo2")))); + EXPECT_EQ(RepositoryName("repo2"), e.fetch_repository(RepositoryName("repo2"))->name()); + + EXPECT_TRUE(! e.more_important_than(RepositoryName("repo1"), RepositoryName("repo2"))); + EXPECT_TRUE(e.more_important_than(RepositoryName("repo2"), RepositoryName("repo1"))); + EXPECT_TRUE(! e.more_important_than(RepositoryName("repo2"), RepositoryName("repo2"))); + EXPECT_TRUE(! e.more_important_than(RepositoryName("repo1"), RepositoryName("repo1"))); +} + +namespace +{ + struct CoolFakeRepository : + FakeRepository + { + CoolFakeRepository(const Environment * const e, const RepositoryName & rn) : + FakeRepository(make_named_values( + n::environment() = e, + n::name() = rn + )) + { + } + + std::shared_ptr unimportant_category_names(const RepositoryContentMayExcludes &) const + { + std::shared_ptr result(std::make_shared()); + result->insert(CategoryNamePart("bad-cat1")); + result->insert(CategoryNamePart("bad-cat2")); + return result; + } + }; +} + +TEST(EnvironmentImplementation, Disambiguation) +{ + TestEnvironment e; + + std::shared_ptr r1(std::make_shared(make_named_values( + n::environment() = &e, + n::name() = RepositoryName("repo1")))); + r1->add_version(CategoryNamePart("cat-one") + PackageNamePart("pkg-one"), VersionSpec("0", { })); + r1->add_version(CategoryNamePart("cat-one") + PackageNamePart("pkg-two"), VersionSpec("0", { })); + r1->add_version(CategoryNamePart("cat-two") + PackageNamePart("pkg-two"), VersionSpec("0", { })); + r1->add_version(CategoryNamePart("cat-two") + PackageNamePart("pkg-three"), VersionSpec("0", { })); + e.add_repository(10, r1); + + std::shared_ptr r2(std::make_shared(make_named_values( + n::environment() = &e, + n::name() = RepositoryName("repo2")))); + r2->add_version(CategoryNamePart("cat-three") + PackageNamePart("pkg-three"), VersionSpec("0", { })); + r2->add_version(CategoryNamePart("cat-three") + PackageNamePart("pkg-four"), VersionSpec("0", { })); + e.add_repository(10, r2); + + std::shared_ptr r3(std::make_shared(&e, RepositoryName("repo3"))); + r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-important"), VersionSpec("0", { })); + r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-important"), VersionSpec("0", { })); + + r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-installed"), VersionSpec("0", { })); + r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-installed"), VersionSpec("0", { })); + + r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail1"), VersionSpec("0", { })); + r3->add_version(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail1"), VersionSpec("0", { })); + + r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail2"), VersionSpec("0", { })); + r3->add_version(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail2"), VersionSpec("0", { })); + + r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail3"), VersionSpec("0", { })); + r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail3"), VersionSpec("0", { })); + + r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); + r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); + + r3->add_version(CategoryNamePart("avail-cat") + PackageNamePart("pkg-foo"), VersionSpec("0", { })); + e.add_repository(10, r3); + + std::shared_ptr r4(std::make_shared( + make_named_values( + n::environment() = &e, + n::name() = RepositoryName("repo4"), + n::suitable_destination() = true, + n::supports_uninstall() = true + ))); + r4->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-installed"), VersionSpec("0", { })); + r4->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); + r4->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); + r4->add_version(CategoryNamePart("inst-cat") + PackageNamePart("pkg-foo"), VersionSpec("0", { })); + e.add_repository(10, r4); + + EXPECT_EQ("cat-one/pkg-one", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-one")))); + EXPECT_EQ("cat-three/pkg-four", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-four")))); + EXPECT_EQ("good-cat1/pkg-important", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-important")))); + EXPECT_EQ("good-cat1/pkg-installed", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-installed")))); + + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-two")), AmbiguousPackageNameError); + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-three")), AmbiguousPackageNameError); + + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail1")), AmbiguousPackageNameError); + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail2")), AmbiguousPackageNameError); + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail3")), AmbiguousPackageNameError); + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail4")), AmbiguousPackageNameError); + + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-five")), NoSuchPackageError); + + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-one"), + filter::SupportsAction()), NoSuchPackageError); + EXPECT_EQ("inst-cat/pkg-foo", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo")))); + EXPECT_EQ("avail-cat/pkg-foo", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo"), filter::SupportsAction()))); + EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo"), filter::All(), false), AmbiguousPackageNameError); +} + diff --git a/paludis/files.m4 b/paludis/files.m4 index 1e37fdde1..635003c9f 100644 --- a/paludis/files.m4 +++ b/paludis/files.m4 @@ -42,7 +42,7 @@ add(`elike_slot_requirement', `hh', `cc', `fwd') add(`elike_use_requirement', `hh', `cc', `fwd', `se', `gtest') add(`environment', `hh', `fwd', `cc') add(`environment_factory', `hh', `fwd', `cc') -add(`environment_implementation', `hh', `cc') +add(`environment_implementation', `hh', `cc', `gtest') add(`file_output_manager', `hh', `cc', `fwd') add(`filter', `hh', `cc', `fwd', `test') add(`filter_handler', `hh', `cc', `fwd') @@ -75,7 +75,7 @@ add(`notifier_callback', `hh', `cc', `fwd') add(`output_manager', `hh', `fwd', `cc', `se') add(`output_manager_factory', `hh', `fwd', `cc') add(`output_manager_from_environment', `hh', `fwd', `cc') -add(`package_database', `hh', `cc', `fwd', `gtest') +add(`package_database', `hh', `cc', `fwd') add(`package_dep_spec_collection', `hh', `cc', `fwd') add(`package_dep_spec_properties', `hh', `cc', `fwd') add(`package_id', `hh', `cc', `fwd', `se') diff --git a/paludis/package_database_TEST.cc b/paludis/package_database_TEST.cc deleted file mode 100644 index effe522d4..000000000 --- a/paludis/package_database_TEST.cc +++ /dev/null @@ -1,181 +0,0 @@ -/* vim: set sw=4 sts=4 et foldmethod=syntax : */ - -/* - * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Ciaran McCreesh - * - * This file is part of the Paludis package manager. Paludis is free software; - * you can redistribute it and/or modify it under the terms of the GNU General - * Public License version 2, as published by the Free Software Foundation. - * - * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -using namespace paludis; - -TEST(PackageDatabase, Repositories) -{ - TestEnvironment e; - - const std::shared_ptr r1(std::make_shared(make_named_values( - n::environment() = &e, - n::name() = RepositoryName("repo1") - ))); - const std::shared_ptr r2(std::make_shared(make_named_values( - n::environment() = &e, - n::name() = RepositoryName("repo2") - ))); - - EXPECT_THROW(e.fetch_repository(RepositoryName("repo1")), NoSuchRepositoryError); - EXPECT_THROW(e.fetch_repository(RepositoryName("repo2")), NoSuchRepositoryError); - - e.add_repository(10, r1); - ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo1")))); - EXPECT_EQ(RepositoryName("repo1"), e.fetch_repository(RepositoryName("repo1"))->name()); - EXPECT_THROW(e.fetch_repository(RepositoryName("repo2")), NoSuchRepositoryError); - - EXPECT_THROW(e.add_repository(10, r1), DuplicateRepositoryError); - - e.add_repository(11, r2); - ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo1")))); - EXPECT_EQ(RepositoryName("repo1"), e.fetch_repository(RepositoryName("repo1"))->name()); - ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo2")))); - EXPECT_EQ(RepositoryName("repo2"), e.fetch_repository(RepositoryName("repo2"))->name()); - - EXPECT_THROW(e.add_repository(10, r1), DuplicateRepositoryError); - EXPECT_THROW(e.add_repository(5, r2), DuplicateRepositoryError); - - ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo1")))); - EXPECT_EQ(RepositoryName("repo1"), e.fetch_repository(RepositoryName("repo1"))->name()); - ASSERT_TRUE(bool(e.fetch_repository(RepositoryName("repo2")))); - EXPECT_EQ(RepositoryName("repo2"), e.fetch_repository(RepositoryName("repo2"))->name()); - - EXPECT_TRUE(! e.more_important_than(RepositoryName("repo1"), RepositoryName("repo2"))); - EXPECT_TRUE(e.more_important_than(RepositoryName("repo2"), RepositoryName("repo1"))); - EXPECT_TRUE(! e.more_important_than(RepositoryName("repo2"), RepositoryName("repo2"))); - EXPECT_TRUE(! e.more_important_than(RepositoryName("repo1"), RepositoryName("repo1"))); -} - -namespace -{ - struct CoolFakeRepository : - FakeRepository - { - CoolFakeRepository(const Environment * const e, const RepositoryName & rn) : - FakeRepository(make_named_values( - n::environment() = e, - n::name() = rn - )) - { - } - - std::shared_ptr unimportant_category_names(const RepositoryContentMayExcludes &) const - { - std::shared_ptr result(std::make_shared()); - result->insert(CategoryNamePart("bad-cat1")); - result->insert(CategoryNamePart("bad-cat2")); - return result; - } - }; -} - -TEST(PackageDatabase, Disambiguation) -{ - TestEnvironment e; - - std::shared_ptr r1(std::make_shared(make_named_values( - n::environment() = &e, - n::name() = RepositoryName("repo1")))); - r1->add_version(CategoryNamePart("cat-one") + PackageNamePart("pkg-one"), VersionSpec("0", { })); - r1->add_version(CategoryNamePart("cat-one") + PackageNamePart("pkg-two"), VersionSpec("0", { })); - r1->add_version(CategoryNamePart("cat-two") + PackageNamePart("pkg-two"), VersionSpec("0", { })); - r1->add_version(CategoryNamePart("cat-two") + PackageNamePart("pkg-three"), VersionSpec("0", { })); - e.add_repository(10, r1); - - std::shared_ptr r2(std::make_shared(make_named_values( - n::environment() = &e, - n::name() = RepositoryName("repo2")))); - r2->add_version(CategoryNamePart("cat-three") + PackageNamePart("pkg-three"), VersionSpec("0", { })); - r2->add_version(CategoryNamePart("cat-three") + PackageNamePart("pkg-four"), VersionSpec("0", { })); - e.add_repository(10, r2); - - std::shared_ptr r3(std::make_shared(&e, RepositoryName("repo3"))); - r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-important"), VersionSpec("0", { })); - r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-important"), VersionSpec("0", { })); - - r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-installed"), VersionSpec("0", { })); - r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-installed"), VersionSpec("0", { })); - - r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail1"), VersionSpec("0", { })); - r3->add_version(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail1"), VersionSpec("0", { })); - - r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail2"), VersionSpec("0", { })); - r3->add_version(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail2"), VersionSpec("0", { })); - - r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail3"), VersionSpec("0", { })); - r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail3"), VersionSpec("0", { })); - - r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); - r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); - - r3->add_version(CategoryNamePart("avail-cat") + PackageNamePart("pkg-foo"), VersionSpec("0", { })); - e.add_repository(10, r3); - - std::shared_ptr r4(std::make_shared( - make_named_values( - n::environment() = &e, - n::name() = RepositoryName("repo4"), - n::suitable_destination() = true, - n::supports_uninstall() = true - ))); - r4->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-installed"), VersionSpec("0", { })); - r4->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); - r4->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail4"), VersionSpec("0", { })); - r4->add_version(CategoryNamePart("inst-cat") + PackageNamePart("pkg-foo"), VersionSpec("0", { })); - e.add_repository(10, r4); - - EXPECT_EQ("cat-one/pkg-one", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-one")))); - EXPECT_EQ("cat-three/pkg-four", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-four")))); - EXPECT_EQ("good-cat1/pkg-important", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-important")))); - EXPECT_EQ("good-cat1/pkg-installed", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-installed")))); - - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-two")), AmbiguousPackageNameError); - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-three")), AmbiguousPackageNameError); - - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail1")), AmbiguousPackageNameError); - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail2")), AmbiguousPackageNameError); - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail3")), AmbiguousPackageNameError); - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-fail4")), AmbiguousPackageNameError); - - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-five")), NoSuchPackageError); - - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-one"), - filter::SupportsAction()), NoSuchPackageError); - EXPECT_EQ("inst-cat/pkg-foo", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo")))); - EXPECT_EQ("avail-cat/pkg-foo", stringify(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo"), filter::SupportsAction()))); - EXPECT_THROW(e.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo"), filter::All(), false), AmbiguousPackageNameError); -} - -- cgit v1.2.3