/* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* * Copyright (c) 2008, 2009, 2010, 2012 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 #include using namespace paludis; using namespace paludis::erepository; namespace { void cannot_add(const std::shared_ptr &) PALUDIS_ATTRIBUTE((noreturn)); void cannot_add(const std::shared_ptr &) { throw InternalError(PALUDIS_HERE, "Got weird tree"); } struct SlotRewriter { const Environment * const env; const EAPI & eapi; const std::shared_ptr id; const std::shared_ptr spec; std::shared_ptr visit(const SlotExactPartialRequirement &) const { return make_null_shared_ptr(); } std::shared_ptr visit(const SlotExactFullRequirement &) const { return make_null_shared_ptr(); } std::shared_ptr visit(const SlotAnyUnlockedRequirement &) const { return make_null_shared_ptr(); } std::shared_ptr visit(const SlotAnyPartialLockedRequirement &) const { std::shared_ptr matches((*env)[selection::AllVersionsSorted( generator::Matches(*spec, id, { }) | filter::InstalledAtRoot(env->system_root_key()->parse_value()))]); if (matches->empty()) return make_null_shared_ptr(); if ((*matches->last())->slot_key()) { auto ss((*matches->last())->slot_key()->parse_value()); if (ss.match_values().first == ss.match_values().second) return std::make_shared(ss.match_values().first, spec->slot_requirement_ptr()); else return std::make_shared(ss.match_values(), spec->slot_requirement_ptr()); } else return make_null_shared_ptr(); } std::shared_ptr visit(const SlotAnyAtAllLockedRequirement &) const { std::shared_ptr matches((*env)[selection::AllVersionsSorted( generator::Matches(*spec, id, { }) | filter::InstalledAtRoot(env->system_root_key()->parse_value()))]); if (matches->empty()) return make_null_shared_ptr(); if ((*matches->last())->slot_key()) { auto ss((*matches->last())->slot_key()->parse_value()); if (eapi.supported()->ebuild_options()->has_subslots()) return std::make_shared(ss.match_values(), spec->slot_requirement_ptr()); else return std::make_shared(ss.match_values().first, spec->slot_requirement_ptr()); } else return make_null_shared_ptr(); } }; struct Fixer { std::list > stack; std::shared_ptr result; const Environment * const env; const EAPI & eapi; const std::shared_ptr id; Fixer(const Environment * const e, const EAPI & a, const std::shared_ptr & i) : result(std::make_shared(std::make_shared())), env(e), eapi(a), id(i) { stack.push_front(result->top()); } void visit(const DependencySpecTree::NodeType::Type & node) { std::shared_ptr spec(std::static_pointer_cast(node.spec()->clone())); stack.push_front((*stack.begin())->append(spec)); std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this)); stack.pop_front(); } void visit(const DependencySpecTree::NodeType::Type & node) { std::shared_ptr spec(std::static_pointer_cast(node.spec()->clone())); stack.push_front((*stack.begin())->append(spec)); std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this)); stack.pop_front(); } void visit(const DependencySpecTree::NodeType::Type & node) { std::shared_ptr spec(std::static_pointer_cast(node.spec()->clone())); stack.push_front((*stack.begin())->append(spec)); std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this)); stack.pop_front(); } void visit(const DependencySpecTree::NodeType::Type & node) { std::shared_ptr c; do { if (! node.spec()->slot_requirement_ptr()) break; auto rewritten(node.spec()->slot_requirement_ptr()->accept_returning >(SlotRewriter{env, eapi, id, node.spec()})); if (! rewritten) break; PackageDepSpec new_s(PartiallyMadePackageDepSpec(*node.spec()).slot_requirement(rewritten)); new_s.set_annotations(node.spec()->maybe_annotations()); c = std::make_shared(new_s); } while (false); if (! c) c = node.spec(); (*stack.begin())->append(c); } void visit(const DependencySpecTree::NodeType::Type & node) { (*stack.begin())->append(node.spec()); } void visit(const DependencySpecTree::NodeType::Type & node) { (*stack.begin())->append(node.spec()); } void visit(const DependencySpecTree::NodeType::Type & node) { (*stack.begin())->append(node.spec()); } }; } const std::shared_ptr paludis::erepository::fix_locked_dependencies( const Environment * const env, const EAPI & e, const std::shared_ptr & id, const std::shared_ptr & b) { Fixer f(env, e, id); b->top()->accept(f); return f.result; }