aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-02-23 22:51:02 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-02-23 22:51:02 +0000
commitc0220371b5b821fb2a01aaa983046d0a330fe0b9 (patch)
tree7f516959a80c84a72d2b35f7ee2f98d80b73c1d7
parent4993721605cc141b0d4eaeacdfc139bc95cbde74 (diff)
downloadpaludis-c0220371b5b821fb2a01aaa983046d0a330fe0b9.tar.gz
paludis-c0220371b5b821fb2a01aaa983046d0a330fe0b9.tar.xz
[.key=value] user specs
-rw-r--r--doc/configuration/specs.html.part2
-rw-r--r--paludis/user_dep_spec-fwd.hh4
-rw-r--r--paludis/user_dep_spec.cc198
-rw-r--r--paludis/user_dep_spec.hh31
-rw-r--r--paludis/user_dep_spec_TEST.cc5
5 files changed, 237 insertions, 3 deletions
diff --git a/doc/configuration/specs.html.part b/doc/configuration/specs.html.part
index 96debd5..f8ad6fa 100644
--- a/doc/configuration/specs.html.part
+++ b/doc/configuration/specs.html.part
@@ -32,6 +32,8 @@ the following order:</p>
<li><code>[=1.23]</code>: Match a particular version. Any operator described below
can be used. May be extended to ranged dependencies, using either <code>[=1.23|=1.24|=1.25]</code> for an or
dependency or <code>[&gt;=1.2&amp;&lt;2]</code> for an and dependency.</li>
+ <li><code>[.key=value]</code>: Match only if the specified metadata key has a particular exact value. Only works for
+ simple values, not compound keys.</li>
</ul>
<p>Repository requirements are in the form <code>to</code>, <code>from-&gt;</code> or <code>::from-&gt;to</code>. The
diff --git a/paludis/user_dep_spec-fwd.hh b/paludis/user_dep_spec-fwd.hh
index af7a7ef..116d434 100644
--- a/paludis/user_dep_spec-fwd.hh
+++ b/paludis/user_dep_spec-fwd.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009 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
@@ -63,6 +63,8 @@ namespace paludis
};
struct UserSlotExactRequirement;
+
+ struct UserKeyRequirement;
}
#endif
diff --git a/paludis/user_dep_spec.cc b/paludis/user_dep_spec.cc
index 5cdafe9..5a0319a 100644
--- a/paludis/user_dep_spec.cc
+++ b/paludis/user_dep_spec.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009 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
@@ -26,10 +26,15 @@
#include <paludis/version_requirements.hh>
#include <paludis/package_database.hh>
#include <paludis/filter.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/options.hh>
#include <paludis/util/log.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/sequence.hh>
using namespace paludis;
@@ -171,6 +176,13 @@ namespace
}
break;
+ case '.':
+ {
+ std::tr1::shared_ptr<const AdditionalPackageDepSpecRequirement> req(new UserKeyRequirement(flag.substr(1)));
+ result.additional_requirement(req);
+ }
+ break;
+
default:
{
std::tr1::shared_ptr<const AdditionalPackageDepSpecRequirement> req(parse_elike_use_requirement(flag,
@@ -313,3 +325,187 @@ GotASetNotAPackageDepSpec::GotASetNotAPackageDepSpec(const std::string & s) thro
{
}
+namespace paludis
+{
+ template <>
+ struct Implementation<UserKeyRequirement>
+ {
+ std::string key;
+ std::string value;
+
+ Implementation(const std::string & s)
+ {
+ std::string::size_type p(s.find('='));
+ if (std::string::npos == p)
+ throw PackageDepSpecError("Expected an = inside '[." + s + "]'");
+
+ key = s.substr(0, p);
+ value = s.substr(p + 1);
+ }
+ };
+}
+
+UserKeyRequirement::UserKeyRequirement(const std::string & s) :
+ PrivateImplementationPattern<UserKeyRequirement>(new Implementation<UserKeyRequirement>(s))
+{
+}
+
+UserKeyRequirement::~UserKeyRequirement()
+{
+}
+
+namespace
+{
+ struct KeyComparator
+ {
+ const std::string pattern;
+
+ KeyComparator(const std::string & p) :
+ pattern(p)
+ {
+ }
+
+ bool visit(const MetadataSectionKey &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataTimeKey & k) const
+ {
+ return pattern == stringify(k.value());
+ }
+
+ bool visit(const MetadataValueKey<std::string> & k) const
+ {
+ return pattern == stringify(k.value());
+ }
+
+ bool visit(const MetadataValueKey<SlotName> & k) const
+ {
+ return pattern == stringify(k.value());
+ }
+
+ bool visit(const MetadataValueKey<FSEntry> & k) const
+ {
+ return pattern == stringify(k.value());
+ }
+
+ bool visit(const MetadataValueKey<bool> & k) const
+ {
+ return pattern == stringify(k.value());
+ }
+
+ bool visit(const MetadataValueKey<long> & k) const
+ {
+ return pattern == stringify(k.value());
+ }
+
+ bool visit(const MetadataValueKey<std::tr1::shared_ptr<const Choices> > &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataValueKey<std::tr1::shared_ptr<const RepositoryMaskInfo> > &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataValueKey<std::tr1::shared_ptr<const Contents> > &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > & k) const
+ {
+ return pattern == stringify(*k.value());
+ }
+
+ bool visit(const MetadataSpecTreeKey<DependencySpecTree> &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataSpecTreeKey<SetSpecTree> &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataSpecTreeKey<PlainTextSpecTree> &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataSpecTreeKey<ProvideSpecTree> &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataSpecTreeKey<SimpleURISpecTree> &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataSpecTreeKey<FetchableURISpecTree> &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataSpecTreeKey<LicenseSpecTree> &) const
+ {
+ return false;
+ }
+
+ bool visit(const MetadataCollectionKey<FSEntrySequence> & s) const
+ {
+ return pattern == join(s.value()->begin(), s.value()->end(), " ");
+ }
+
+ bool visit(const MetadataCollectionKey<PackageIDSequence> & s) const
+ {
+ return pattern == join(indirect_iterator(s.value()->begin()), indirect_iterator(s.value()->end()), " ");
+ }
+
+ bool visit(const MetadataCollectionKey<Sequence<std::string> > & s) const
+ {
+ return pattern == join(s.value()->begin(), s.value()->end(), " ");
+ }
+
+ bool visit(const MetadataCollectionKey<Set<std::string> > & s) const
+ {
+ return pattern == join(s.value()->begin(), s.value()->end(), " ");
+ }
+
+ bool visit(const MetadataCollectionKey<KeywordNameSet> & s) const
+ {
+ return pattern == join(s.value()->begin(), s.value()->end(), " ");
+ }
+ };
+}
+
+bool
+UserKeyRequirement::requirement_met(const Environment * const, const PackageID & id) const
+{
+ Context context("When working out whether '" + stringify(id) + "' matches " + as_raw_string() + ":");
+
+ PackageID::MetadataConstIterator m(id.find_metadata(_imp->key));
+ if (m == id.end_metadata())
+ return false;
+
+ KeyComparator c(_imp->value);
+ return (*m)->accept_returning<bool>(c);
+}
+
+const std::string
+UserKeyRequirement::as_human_string() const
+{
+ return "Key '" + _imp->key + "' has simple string value '" + _imp->value + "'";
+}
+
+const std::string
+UserKeyRequirement::as_raw_string() const
+{
+ return "[." + _imp->key + "=" + _imp->value + "]";
+}
+
+template class PrivateImplementationPattern<UserKeyRequirement>;
+
diff --git a/paludis/user_dep_spec.hh b/paludis/user_dep_spec.hh
index 6af3b85..4433a5f 100644
--- a/paludis/user_dep_spec.hh
+++ b/paludis/user_dep_spec.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009 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
@@ -24,6 +24,7 @@
#include <paludis/dep_spec.hh>
#include <paludis/slot_requirement.hh>
#include <paludis/filter.hh>
+#include <paludis/util/private_implementation_pattern.hh>
namespace paludis
{
@@ -56,6 +57,34 @@ namespace paludis
virtual const SlotName slot() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::string as_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
+
+ /**
+ * A key requirement for a user PackageDepSpec.
+ *
+ * \since 0.36
+ * \ingroup g_dep_spec
+ */
+ class PALUDIS_VISIBLE UserKeyRequirement :
+ public AdditionalPackageDepSpecRequirement,
+ private PrivateImplementationPattern<UserKeyRequirement>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ UserKeyRequirement(const std::string &);
+ ~UserKeyRequirement();
+
+ ///\}
+
+ virtual bool requirement_met(const Environment * const, const PackageID &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::string as_human_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::string as_raw_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<UserKeyRequirement>;
+#endif
}
#endif
diff --git a/paludis/user_dep_spec_TEST.cc b/paludis/user_dep_spec_TEST.cc
index 56269f1..0bb2bdc 100644
--- a/paludis/user_dep_spec_TEST.cc
+++ b/paludis/user_dep_spec_TEST.cc
@@ -218,6 +218,11 @@ namespace test_cases
PackageDepSpec o(parse_user_package_dep_spec("=foo/bar---1.2.3", &env, UserPackageDepSpecOptions()));
check_spec(o, "foo/bar--", "", "", "=1.2.3", "", "", "", "", "");
+
+ TEST_CHECK_THROWS(parse_user_package_dep_spec("=foo/bar[.foo]", &env, UserPackageDepSpecOptions()), PackageDepSpecError);
+
+ PackageDepSpec p(parse_user_package_dep_spec("foo/bar[.key=value]", &env, UserPackageDepSpecOptions()));
+ check_spec(p, "foo/bar", "", "", "", "", "", "", "", "[.key=value]");
}
} test_user_package_dep_spec;