/* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* * Copyright (c) 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 #include #include #include #include #include #include #include #include using namespace paludis; DidNotGetExactlyOneError::DidNotGetExactlyOneError(const std::string & s, const std::shared_ptr & r) throw () : Exception("Did not get unique result for '" + stringify(s) + "' (got { " + join(indirect_iterator(r->begin()), indirect_iterator(r->end()), ", ") + "})") { } namespace paludis { template <> struct Imp { std::shared_ptr handler; Imp(const std::shared_ptr & h) : handler(h) { } }; } Selection::Selection(const std::shared_ptr & h) : _imp(h) { } Selection::Selection(const Selection & other) : _imp(other._imp->handler) { } Selection::~Selection() { } Selection & Selection::operator= (const Selection & other) { if (this != &other) _imp->handler = other._imp->handler; return *this; } std::shared_ptr Selection::perform_select(const Environment * const env) const { Context context("When finding " + _imp->handler->as_string() + ":"); return _imp->handler->perform_select(env); } std::string Selection::as_string() const { return _imp->handler->as_string(); } namespace { std::string slot_as_string(const std::shared_ptr & id) { if (id->slot_key()) return stringify(id->slot_key()->parse_value()); else return "(none)"; } class SomeArbitraryVersionSelectionHandler : public SelectionHandler { public: SomeArbitraryVersionSelectionHandler(const FilteredGenerator & g) : SelectionHandler(g) { } virtual std::shared_ptr perform_select(const Environment * const env) const { std::shared_ptr result(std::make_shared()); RepositoryContentMayExcludes may_excludes(_fg.filter().may_excludes()); std::shared_ptr r(_fg.filter().repositories(env, _fg.generator().repositories(env, may_excludes))); if (r->empty()) return result; std::shared_ptr c(_fg.filter().categories(env, r, _fg.generator().categories(env, r, may_excludes))); if (c->empty()) return result; std::shared_ptr p(_fg.filter().packages(env, r, _fg.generator().packages(env, r, c, may_excludes))); if (p->empty()) return result; for (QualifiedPackageNameSet::ConstIterator q(p->begin()), q_end(p->end()) ; q != q_end ; ++q) { std::shared_ptr s(std::make_shared()); s->insert(*q); std::shared_ptr i(_fg.filter().ids(env, _fg.generator().ids(env, r, s, may_excludes))); if (! i->empty()) { result->push_back(*i->begin()); break; } } return result; } virtual std::string as_string() const { return "some arbitrary version from " + stringify(_fg); } }; class BestVersionOnlySelectionHandler : public SelectionHandler { public: BestVersionOnlySelectionHandler(const FilteredGenerator & g) : SelectionHandler(g) { } virtual std::shared_ptr perform_select(const Environment * const env) const { using namespace std::placeholders; std::shared_ptr result(std::make_shared()); RepositoryContentMayExcludes may_excludes(_fg.filter().may_excludes()); std::shared_ptr r(_fg.filter().repositories(env, _fg.generator().repositories(env, may_excludes))); if (r->empty()) return result; std::shared_ptr c(_fg.filter().categories(env, r, _fg.generator().categories(env, r, may_excludes))); if (c->empty()) return result; std::shared_ptr p(_fg.filter().packages(env, r, _fg.generator().packages(env, r, c, may_excludes))); if (p->empty()) return result; for (QualifiedPackageNameSet::ConstIterator q(p->begin()), q_end(p->end()) ; q != q_end ; ++q) { std::shared_ptr s(std::make_shared()); s->insert(*q); std::shared_ptr i(_fg.filter().ids(env, _fg.generator().ids(env, r, s, may_excludes))); if (! i->empty()) result->push_back(*std::max_element(i->begin(), i->end(), PackageIDComparator(env))); } return result; } virtual std::string as_string() const { return "best version of each package from " + stringify(_fg); } }; class AllVersionsSortedSelectionHandler : public SelectionHandler { public: AllVersionsSortedSelectionHandler(const FilteredGenerator & g) : SelectionHandler(g) { } virtual std::shared_ptr perform_select(const Environment * const env) const { using namespace std::placeholders; std::shared_ptr result(std::make_shared()); RepositoryContentMayExcludes may_excludes(_fg.filter().may_excludes()); std::shared_ptr r(_fg.filter().repositories(env, _fg.generator().repositories(env, may_excludes))); if (r->empty()) return result; std::shared_ptr c(_fg.filter().categories(env, r, _fg.generator().categories(env, r, may_excludes))); if (c->empty()) return result; std::shared_ptr p(_fg.filter().packages(env, r, _fg.generator().packages(env, r, c, may_excludes))); if (p->empty()) return result; std::shared_ptr i(_fg.filter().ids(env, _fg.generator().ids(env, r, p, may_excludes))); std::copy(i->begin(), i->end(), result->back_inserter()); result->sort(PackageIDComparator(env)); return result; } virtual std::string as_string() const { return "all versions sorted from " + stringify(_fg); } }; class AllVersionsUnsortedSelectionHandler : public SelectionHandler { public: AllVersionsUnsortedSelectionHandler(const FilteredGenerator & g) : SelectionHandler(g) { } virtual std::shared_ptr perform_select(const Environment * const env) const { using namespace std::placeholders; std::shared_ptr result(std::make_shared()); RepositoryContentMayExcludes may_excludes(_fg.filter().may_excludes()); std::shared_ptr r(_fg.filter().repositories(env, _fg.generator().repositories(env, may_excludes))); if (r->empty()) return result; std::shared_ptr c(_fg.filter().categories(env, r, _fg.generator().categories(env, r, may_excludes))); if (c->empty()) return result; std::shared_ptr p(_fg.filter().packages(env, r, _fg.generator().packages(env, r, c, may_excludes))); if (p->empty()) return result; std::shared_ptr i(_fg.filter().ids(env, _fg.generator().ids(env, r, p, may_excludes))); std::copy(i->begin(), i->end(), result->back_inserter()); return result; } virtual std::string as_string() const { return "all versions in some arbitrary order from " + stringify(_fg); } }; class AllVersionsGroupedBySlotSelectioHandler : public SelectionHandler { public: AllVersionsGroupedBySlotSelectioHandler(const FilteredGenerator & g) : SelectionHandler(g) { } virtual std::shared_ptr perform_select(const Environment * const env) const { using namespace std::placeholders; std::shared_ptr result(std::make_shared()); RepositoryContentMayExcludes may_excludes(_fg.filter().may_excludes()); std::shared_ptr r(_fg.filter().repositories(env, _fg.generator().repositories(env, may_excludes))); if (r->empty()) return result; std::shared_ptr c(_fg.filter().categories(env, r, _fg.generator().categories(env, r, may_excludes))); if (c->empty()) return result; std::shared_ptr p(_fg.filter().packages(env, r, _fg.generator().packages(env, r, c, may_excludes))); if (p->empty()) return result; std::shared_ptr id(_fg.filter().ids(env, _fg.generator().ids(env, r, p, may_excludes))); typedef std::map, std::shared_ptr > SlotMap; SlotMap by_slot; for (PackageIDSet::ConstIterator i(id->begin()), i_end(id->end()) ; i != i_end ; ++i) { SlotMap::iterator m(by_slot.find(std::make_pair((*i)->name(), slot_as_string(*i)))); if (m == by_slot.end()) m = by_slot.insert(std::make_pair(std::make_pair((*i)->name(), slot_as_string(*i)), std::make_shared())).first; m->second->push_back(*i); } PackageIDComparator comparator(env); for (SlotMap::iterator i(by_slot.begin()), i_end(by_slot.end()) ; i != i_end ; ++i) i->second->sort(comparator); while (! by_slot.empty()) { SlotMap::iterator m(by_slot.begin()); for (SlotMap::iterator n(by_slot.begin()), n_end(by_slot.end()) ; n != n_end ; ++n) if (! comparator(*m->second->last(), *n->second->last())) m = n; std::copy(m->second->begin(), m->second->end(), result->back_inserter()); by_slot.erase(m); } return result; } virtual std::string as_string() const { return "all versions grouped by slot from " + stringify(_fg); } }; class BestVersionInEachSlotSelectionHandler : public SelectionHandler { public: BestVersionInEachSlotSelectionHandler(const FilteredGenerator & g) : SelectionHandler(g) { } virtual std::shared_ptr perform_select(const Environment * const env) const { using namespace std::placeholders; std::shared_ptr result(std::make_shared()); RepositoryContentMayExcludes may_excludes(_fg.filter().may_excludes()); std::shared_ptr r(_fg.filter().repositories(env, _fg.generator().repositories(env, may_excludes))); if (r->empty()) return result; std::shared_ptr c(_fg.filter().categories(env, r, _fg.generator().categories(env, r, may_excludes))); if (c->empty()) return result; std::shared_ptr p(_fg.filter().packages(env, r, _fg.generator().packages(env, r, c, may_excludes))); if (p->empty()) return result; std::shared_ptr id(_fg.filter().ids(env, _fg.generator().ids(env, r, p, may_excludes))); typedef std::map, std::shared_ptr > SlotMap; SlotMap by_slot; for (PackageIDSet::ConstIterator i(id->begin()), i_end(id->end()) ; i != i_end ; ++i) { SlotMap::iterator m(by_slot.find(std::make_pair((*i)->name(), slot_as_string(*i)))); if (m == by_slot.end()) m = by_slot.insert(std::make_pair(std::make_pair((*i)->name(), slot_as_string(*i)), std::make_shared())).first; m->second->push_back(*i); } PackageIDComparator comparator(env); for (SlotMap::iterator i(by_slot.begin()), i_end(by_slot.end()) ; i != i_end ; ++i) i->second->sort(comparator); while (! by_slot.empty()) { SlotMap::iterator m(by_slot.begin()); for (SlotMap::iterator n(by_slot.begin()), n_end(by_slot.end()) ; n != n_end ; ++n) if (! comparator(*m->second->last(), *n->second->last())) m = n; std::copy(m->second->last(), m->second->end(), result->back_inserter()); by_slot.erase(m); } return result; } virtual std::string as_string() const { return "best version in each slot from " + stringify(_fg); } }; class RequireExactlyOneSelectionHandler : public SelectionHandler { public: RequireExactlyOneSelectionHandler(const FilteredGenerator & g) : SelectionHandler(g) { } virtual std::shared_ptr perform_select(const Environment * const env) const { using namespace std::placeholders; std::shared_ptr result(std::make_shared()); RepositoryContentMayExcludes may_excludes(_fg.filter().may_excludes()); std::shared_ptr r(_fg.filter().repositories(env, _fg.generator().repositories(env, may_excludes))); if (r->empty()) throw DidNotGetExactlyOneError(as_string(), std::make_shared()); std::shared_ptr c(_fg.filter().categories(env, r, _fg.generator().categories(env, r, may_excludes))); if (c->empty()) throw DidNotGetExactlyOneError(as_string(), std::make_shared()); std::shared_ptr p(_fg.filter().packages(env, r, _fg.generator().packages(env, r, c, may_excludes))); if (p->empty()) throw DidNotGetExactlyOneError(as_string(), std::make_shared()); std::shared_ptr i(_fg.filter().ids(env, _fg.generator().ids(env, r, p, may_excludes))); if (i->empty() || next(i->begin()) != i->end()) throw DidNotGetExactlyOneError(as_string(), i); result->push_back(*i->begin()); return result; } virtual std::string as_string() const { return "the single version from " + stringify(_fg); } }; } selection::SomeArbitraryVersion::SomeArbitraryVersion(const FilteredGenerator & f) : Selection(std::make_shared(f)) { } selection::BestVersionOnly::BestVersionOnly(const FilteredGenerator & f) : Selection(std::make_shared(f)) { } selection::AllVersionsSorted::AllVersionsSorted(const FilteredGenerator & f) : Selection(std::make_shared(f)) { } selection::AllVersionsUnsorted::AllVersionsUnsorted(const FilteredGenerator & f) : Selection(std::make_shared(f)) { } selection::AllVersionsGroupedBySlot::AllVersionsGroupedBySlot(const FilteredGenerator & f) : Selection(std::make_shared(f)) { } selection::BestVersionInEachSlot::BestVersionInEachSlot(const FilteredGenerator & f) : Selection(std::make_shared(f)) { } selection::RequireExactlyOne::RequireExactlyOne(const FilteredGenerator & f) : Selection(std::make_shared(f)) { } std::ostream & paludis::operator<< (std::ostream & s, const Selection & g) { s << g.as_string(); return s; } namespace paludis { template class Pimp; }