Exheredludis/paludis/match_package.cc
Saleem Abdulrasool 6b0e48f888 paludis: c++11-ify repository iteration
Add a `repositories` in `Environment` which provides an iterator range
for the repositories, allowing C++11 style range based iteration.
2017-01-16 13:56:45 -08:00

263 lines
8.6 KiB
C++

/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 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 <paludis/match_package.hh>
#include <paludis/dep_spec.hh>
#include <paludis/dep_spec_annotations.hh>
#include <paludis/dep_spec_flattener.hh>
#include <paludis/environment.hh>
#include <paludis/version_requirements.hh>
#include <paludis/package_id.hh>
#include <paludis/slot_requirement.hh>
#include <paludis/metadata_key.hh>
#include <paludis/action.hh>
#include <paludis/repository.hh>
#include <paludis/additional_package_dep_spec_requirement.hh>
#include <paludis/slot.hh>
#include <paludis/util/set.hh>
#include <paludis/util/options.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/sequence.hh>
#include <paludis/util/indirect_iterator-impl.hh>
#include <paludis/util/stringify.hh>
#include <functional>
#include <algorithm>
#include <istream>
#include <ostream>
using namespace paludis;
#include <paludis/match_package-se.cc>
namespace
{
struct SlotRequirementChecker
{
const std::shared_ptr<const PackageID> id;
bool result;
SlotRequirementChecker(const std::shared_ptr<const PackageID> & i) :
id(i),
result(true)
{
}
void visit(const SlotExactPartialRequirement & s)
{
result = id->slot_key() && id->slot_key()->parse_value().match_values().first == s.slot();
}
void visit(const SlotExactFullRequirement & s)
{
result = id->slot_key() && id->slot_key()->parse_value().match_values() == s.slots();
}
void visit(const SlotAnyPartialLockedRequirement & s)
{
result = id->slot_key() && id->slot_key()->parse_value().match_values().first == s.slot();
}
void visit(const SlotAnyAtAllLockedRequirement &)
{
result = true;
}
void visit(const SlotAnyUnlockedRequirement &)
{
result = true;
}
void visit(const SlotUnknownRewrittenRequirement &) PALUDIS_ATTRIBUTE((noreturn))
{
throw InternalError(PALUDIS_HERE, "Should not be matching against SlotUnknownRewrittenRequirement");
}
};
}
bool
paludis::match_package_with_maybe_changes(
const Environment & env,
const PackageDepSpec & spec,
const ChangedChoices * const maybe_changes_to_owner,
const std::shared_ptr<const PackageID> & id,
const std::shared_ptr<const PackageID> & from_id,
const ChangedChoices * const maybe_changes_to_target,
const MatchPackageOptions & options)
{
if (spec.package_ptr() && *spec.package_ptr() != id->name())
return false;
if (spec.package_name_part_ptr() && *spec.package_name_part_ptr() != id->name().package())
return false;
if (spec.category_name_part_ptr() && *spec.category_name_part_ptr() != id->name().category())
return false;
if (spec.version_requirements_ptr())
switch (spec.version_requirements_mode())
{
case vr_and:
for (VersionRequirements::ConstIterator r(spec.version_requirements_ptr()->begin()),
r_end(spec.version_requirements_ptr()->end()) ; r != r_end ; ++r)
if (! r->version_operator().as_version_spec_comparator()(id->version(), r->version_spec()))
return false;
break;
case vr_or:
{
bool matched(false);
for (VersionRequirements::ConstIterator r(spec.version_requirements_ptr()->begin()),
r_end(spec.version_requirements_ptr()->end()) ; r != r_end ; ++r)
if (r->version_operator().as_version_spec_comparator()(id->version(), r->version_spec()))
{
matched = true;
break;
}
if (! matched)
return false;
}
break;
case last_vr:
;
}
if (spec.in_repository_ptr())
if (*spec.in_repository_ptr() != id->repository_name())
return false;
if (spec.from_repository_ptr())
{
if (! id->from_repositories_key())
return false;
auto v(id->from_repositories_key()->parse_value());
if (v->end() == v->find(stringify(*spec.from_repository_ptr())))
return false;
}
if (spec.installed_at_path_ptr())
{
auto repo(env.fetch_repository(id->repository_name()));
if (! repo->installed_root_key())
return false;
if (repo->installed_root_key()->parse_value() != *spec.installed_at_path_ptr())
return false;
}
if (spec.installable_to_repository_ptr())
{
if (! id->supports_action(SupportsActionTest<InstallAction>()))
return false;
if (! spec.installable_to_repository_ptr()->include_masked())
if (id->masked())
return false;
const std::shared_ptr<const Repository> dest(env.fetch_repository(
spec.installable_to_repository_ptr()->repository()));
if (! dest->destination_interface())
return false;
if (! dest->destination_interface()->is_suitable_destination_for(id))
return false;
}
if (spec.installable_to_path_ptr())
{
if (! id->supports_action(SupportsActionTest<InstallAction>()))
return false;
if (! spec.installable_to_path_ptr()->include_masked())
if (id->masked())
return false;
bool ok(false);
for (const auto & repository : env.repositories())
{
if (! repository->destination_interface())
continue;
if (! repository->installed_root_key())
continue;
if (repository->installed_root_key()->parse_value() != spec.installable_to_path_ptr()->path())
continue;
if (! repository->destination_interface()->is_suitable_destination_for(id))
continue;
ok = true;
break;
}
if (! ok)
return false;
}
if (spec.slot_requirement_ptr())
{
SlotRequirementChecker v(id);
spec.slot_requirement_ptr()->accept(v);
if (! v.result)
return false;
}
if (! options[mpo_ignore_additional_requirements])
{
if (spec.additional_requirements_ptr())
{
for (AdditionalPackageDepSpecRequirements::ConstIterator u(spec.additional_requirements_ptr()->begin()),
u_end(spec.additional_requirements_ptr()->end()) ; u != u_end ; ++u)
if (! (*u)->requirement_met(&env, maybe_changes_to_owner, id, from_id, maybe_changes_to_target).first)
return false;
}
}
if (from_id && *id == *from_id && spec.maybe_annotations() && spec.maybe_annotations()->end() != spec.maybe_annotations()->find(dsar_no_self_match))
return false;
return true;
}
bool
paludis::match_package(
const Environment & env,
const PackageDepSpec & spec,
const std::shared_ptr<const PackageID> & id,
const std::shared_ptr<const PackageID> & from_id,
const MatchPackageOptions & options)
{
return match_package_with_maybe_changes(env, spec, nullptr, id, from_id, nullptr, options);
}
bool
paludis::match_package_in_set(
const Environment & env,
const SetSpecTree & target,
const std::shared_ptr<const PackageID> & id,
const MatchPackageOptions & options)
{
using namespace std::placeholders;
DepSpecFlattener<SetSpecTree, PackageDepSpec> f(&env, id);
target.top()->accept(f);
return indirect_iterator(f.end()) != std::find_if(
indirect_iterator(f.begin()), indirect_iterator(f.end()),
std::bind(&match_package, std::cref(env), _1, std::cref(id), nullptr, std::cref(options)));
}