aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-02-09 16:39:38 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-02-09 16:39:38 +0000
commit0645c90066c9d4bd448b2ba8449bc40f55f53c80 (patch)
tree21961ee1a062506e0e98a3c87f3394dbd36d9b7c
parent8d1878ec91739acc79a45ea8bcd99ef6b10da1e9 (diff)
downloadpaludis-0645c90066c9d4bd448b2ba8449bc40f55f53c80.tar.gz
paludis-0645c90066c9d4bd448b2ba8449bc40f55f53c80.tar.xz
New improved query() method
-rw-r--r--paludis/dep_atom.cc9
-rw-r--r--paludis/files.m41
-rw-r--r--paludis/package_database.cc102
-rw-r--r--paludis/package_database.hh11
-rw-r--r--paludis/package_database_TEST.cc24
-rw-r--r--paludis/qa/deps_exist_check.cc8
-rw-r--r--paludis/qa/deps_visible_check.cc3
-rw-r--r--paludis/query.cc348
-rw-r--r--paludis/query.hh141
-rw-r--r--paludis/repositories/portage/portage_repository_news.cc4
10 files changed, 616 insertions, 35 deletions
diff --git a/paludis/dep_atom.cc b/paludis/dep_atom.cc
index dd3941f..ad9e5b6 100644
--- a/paludis/dep_atom.cc
+++ b/paludis/dep_atom.cc
@@ -137,15 +137,18 @@ PackageDepAtom::PackageDepAtom(const PackageDepAtom & other) :
StringDepAtom(stringify(other)),
Visitable<PackageDepAtom, DepAtomVisitorTypes>(other),
_package(other._package),
- _version_requirements(new VersionRequirements::Concrete),
_version_requirements_mode(other._version_requirements_mode),
_slot(other._slot),
_repository(other._repository),
_use_requirements(other._use_requirements),
_tag(other._tag)
{
- std::copy(other._version_requirements->begin(), other._version_requirements->end(),
- _version_requirements->inserter());
+ if (other._version_requirements)
+ {
+ _version_requirements.reset(new VersionRequirements::Concrete);
+ std::copy(other._version_requirements->begin(), other._version_requirements->end(),
+ _version_requirements->inserter());
+ }
}
PackageDepAtom::PackageDepAtom(const std::string & ss) :
diff --git a/paludis/files.m4 b/paludis/files.m4
index 9182c5f..1efd14b 100644
--- a/paludis/files.m4
+++ b/paludis/files.m4
@@ -27,6 +27,7 @@ add(`package_database_entry', `hh', `cc', `sr')
add(`paludis', `hh', `cc')
add(`portage_dep_lexer', `hh', `cc', `test')
add(`portage_dep_parser', `hh', `cc', `test')
+add(`query', `hh', `cc')
add(`repository', `hh', `cc', `sr')
add(`repository_name_cache', `hh', `cc', `test', `testscript')
add(`syncer', `hh', `cc', `sr')
diff --git a/paludis/package_database.cc b/paludis/package_database.cc
index a4706e3..a55d2f0 100644
--- a/paludis/package_database.cc
+++ b/paludis/package_database.cc
@@ -24,6 +24,7 @@
#include <paludis/util/stringify.hh>
#include <paludis/util/collection_concrete.hh>
#include <paludis/util/compare.hh>
+#include <paludis/query.hh>
#include <list>
#include <map>
@@ -211,30 +212,91 @@ std::tr1::shared_ptr<PackageDatabaseEntryCollection>
PackageDatabase::query(const PackageDepAtom & a, const InstallState installed_state,
const QueryOrder query_order) const
{
+ switch (installed_state)
+ {
+ case is_installed_only:
+ return query(query::Matches(a) & query::RepositoryHasInstalledInterface(), query_order);
+
+ case is_installable_only:
+ return query(query::Matches(a) & query::RepositoryHasInstallableInterface(), query_order);
+
+ case is_any:
+ return query(query::Matches(a), query_order);
+
+ case last_is:
+ ;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad InstallState");
+}
+
+std::tr1::shared_ptr<PackageDatabaseEntryCollection>
+PackageDatabase::query(const Query & q, const QueryOrder query_order) const
+{
std::tr1::shared_ptr<PackageDatabaseEntryCollection::Concrete> result(new PackageDatabaseEntryCollection::Concrete);
- IndirectIterator<std::list<std::tr1::shared_ptr<Repository> >::const_iterator, const Repository>
- r(_imp->repositories.begin()),
- r_end(_imp->repositories.end());
- for ( ; r != r_end ; ++r)
+ std::tr1::shared_ptr<RepositoryNameCollection> repos(q.repositories(*_imp->environment));
+ if (! repos)
{
- if ((installed_state == is_installed_only) && ! r->installed_interface)
- continue;
-
- if ((installed_state == is_installable_only) && ! r->installable_interface)
- continue;
+ repos.reset(new RepositoryNameCollection::Concrete);
+ for (RepositoryIterator r(_imp->repositories.begin()), r_end(_imp->repositories.end()) ;
+ r != r_end ; ++r)
+ repos->push_back((*r)->name());
+ }
+ if (repos->empty())
+ return result;
- std::tr1::shared_ptr<const VersionSpecCollection> versions(r->version_specs(a.package()));
- VersionSpecCollection::Iterator v(versions->begin()), v_end(versions->end());
- for ( ; v != v_end ; ++v)
+ std::tr1::shared_ptr<CategoryNamePartCollection> cats(q.categories(*_imp->environment, repos));
+ if (! cats)
+ {
+ cats.reset(new CategoryNamePartCollection::Concrete);
+ for (RepositoryNameCollection::Iterator r(repos->begin()), r_end(repos->end()) ;
+ r != r_end ; ++r)
{
- PackageDatabaseEntry e(a.package(), *v, r->name());
- if (! match_package(*_imp->environment, a, e))
- continue;
-
- result->push_back(e);
+ std::tr1::shared_ptr<const CategoryNamePartCollection> local_cats(fetch_repository(*r)->category_names());
+ std::copy(local_cats->begin(), local_cats->end(), cats->inserter());
}
}
+ if (cats->empty())
+ return result;
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> pkgs(q.packages(*_imp->environment, repos, cats));
+ if (! pkgs)
+ {
+ pkgs.reset(new QualifiedPackageNameCollection::Concrete);
+ for (RepositoryNameCollection::Iterator r(repos->begin()), r_end(repos->end()) ;
+ r != r_end ; ++r)
+ for (CategoryNamePartCollection::Iterator c(cats->begin()), c_end(cats->end()) ;
+ c != c_end ; ++c)
+ {
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> local_pkgs(fetch_repository(*r)->package_names(*c));
+ std::copy(local_pkgs->begin(), local_pkgs->end(), pkgs->inserter());
+ }
+ }
+ if (pkgs->empty())
+ return result;
+
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection> pdes(q.versions(*_imp->environment, repos, pkgs));
+ if (! pdes)
+ {
+ for (RepositoryNameCollection::Iterator r(repos->begin()), r_end(repos->end()) ;
+ r != r_end ; ++r)
+ for (QualifiedPackageNameCollection::Iterator p(pkgs->begin()), p_end(pkgs->end()) ;
+ p != p_end ; ++p)
+ {
+ std::tr1::shared_ptr<const VersionSpecCollection> local_vers(fetch_repository(*r)->version_specs(*p));
+ for (VersionSpecCollection::Iterator v(local_vers->begin()), v_end(local_vers->end()) ;
+ v != v_end ; ++v)
+ result->push_back(PackageDatabaseEntry(*p, *v, *r));
+ }
+ }
+ else
+ {
+ if (pdes->empty())
+ return result;
+
+ std::copy(pdes->begin(), pdes->end(), result->inserter());
+ }
do
{
@@ -261,8 +323,10 @@ PackageDatabase::query(const PackageDepAtom & a, const InstallState installed_st
while (false);
return result;
+
}
+
std::tr1::shared_ptr<const Repository>
PackageDatabase::fetch_repository(const RepositoryName & n) const
{
@@ -400,6 +464,9 @@ PackageDatabase::_group_package_database_entry_collection(PackageDatabaseEntryCo
for (std::list<PackageDatabaseEntry>::reverse_iterator rr(next(r)) ;
rr != p.list.rend() ; ++rr)
{
+ if (r->name != rr->name)
+ break;
+
SlotName rr_slot(fetch_repository(rr->repository)->version_metadata(rr->name, rr->version)->slot);
if (rr_slot != r_slot)
continue;
@@ -480,3 +547,4 @@ paludis::operator<< (std::ostream & o, const QueryOrder & s)
return o;
}
+
diff --git a/paludis/package_database.hh b/paludis/package_database.hh
index a42a1dd..267f230 100644
--- a/paludis/package_database.hh
+++ b/paludis/package_database.hh
@@ -47,6 +47,7 @@
namespace paludis
{
class PackageDepAtom;
+ class Query;
class Environment;
/**
@@ -285,11 +286,11 @@ namespace paludis
/**
* Query the repository.
*
- * \deprecated Use the three argument form.
+ * \deprecated use the Query form
*/
std::tr1::shared_ptr<PackageDatabaseEntryCollection> query(
const PackageDepAtom & a,
- const InstallState) const PALUDIS_ATTRIBUTE((deprecated));
+ const InstallState) const;
/**
* Query the repository.
@@ -300,6 +301,12 @@ namespace paludis
const QueryOrder) const;
/**
+ * Query the repository.
+ */
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection> query(
+ const Query &, const QueryOrder) const;
+
+ /**
* Return true if the first repository is more important than the second.
*/
bool more_important_than(const RepositoryName &, const RepositoryName &) const;
diff --git a/paludis/package_database_TEST.cc b/paludis/package_database_TEST.cc
index 50792f4..2a87daf 100644
--- a/paludis/package_database_TEST.cc
+++ b/paludis/package_database_TEST.cc
@@ -114,35 +114,43 @@ namespace test_cases
TEST_CHECK(true);
PackageDepAtom d1("r1c1/r1c1p1");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q1(p.query(d1, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q1(p.query(
+ query::Matches(d1), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q1->begin(), q1->end()), 1);
PackageDepAtom d2("r1c1/r1c1p2");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q2(p.query(d2, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q2(p.query(
+ query::Matches(d2), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q2->begin(), q2->end()), 2);
PackageDepAtom d3(">=r1c1/r1c1p2-1");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q3(p.query(d3, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q3(p.query(
+ query::Matches(d3), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q3->begin(), q3->end()), 2);
PackageDepAtom d4(">=r1c1/r1c1p2-2");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q4(p.query(d4, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q4(p.query(
+ query::Matches(d4), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q4->begin(), q4->end()), 1);
PackageDepAtom d5(">=r1c1/r1c1p2-3");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q5(p.query(d5, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q5(p.query(
+ query::Matches(d5), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q5->begin(), q5->end()), 0);
PackageDepAtom d6("<r1c1/r1c1p2-3");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q6(p.query(d6, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q6(p.query(
+ query::Matches(d6), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q6->begin(), q6->end()), 2);
PackageDepAtom d7("rac1/rac1pa");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q7(p.query(d7, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q7(p.query(
+ query::Matches(d7), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q7->begin(), q7->end()), 4);
PackageDepAtom d8("foo/bar");
- const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q8(p.query(d8, is_any, qo_order_by_version));
+ const std::tr1::shared_ptr<PackageDatabaseEntryCollection> q8(p.query(
+ query::Matches(d8), qo_order_by_version));
TEST_CHECK_EQUAL(std::distance(q8->begin(), q8->end()), 0);
}
} package_database_query_test;
diff --git a/paludis/qa/deps_exist_check.cc b/paludis/qa/deps_exist_check.cc
index dbec561..eb0eb90 100644
--- a/paludis/qa/deps_exist_check.cc
+++ b/paludis/qa/deps_exist_check.cc
@@ -23,6 +23,7 @@
#include <paludis/portage_dep_parser.hh>
#include <paludis/qa/deps_exist_check.hh>
#include <paludis/util/save.hh>
+#include <paludis/query.hh>
#include <paludis/qa/qa_environment.hh>
#include <paludis/repositories/portage/portage_repository.hh>
@@ -54,7 +55,7 @@ namespace
void visit(const PackageDepAtom * const p)
{
- if (env->package_database()->query(PackageDepAtom(p->package()), is_any, qo_whatever)->empty())
+ if (env->package_database()->query(query::Package(p->package()), qo_whatever)->empty())
{
if (in_any)
result << Message(qal_maybe, "No match for " + role + " entry '"
@@ -74,9 +75,10 @@ namespace
void visit(const BlockDepAtom * const b)
{
- if (env->package_database()->query(*b->blocked_atom(), is_any, qo_whatever)->empty())
+ if (env->package_database()->query(query::Package(b->blocked_atom()->package()),
+ qo_whatever)->empty())
result << Message(qal_maybe, "No match for " + role + " block '!"
- + stringify(*b->blocked_atom()) + "'");
+ + stringify(b->blocked_atom()->package()) + "'");
}
void visit(const PlainTextDepAtom * const)
diff --git a/paludis/qa/deps_visible_check.cc b/paludis/qa/deps_visible_check.cc
index 89dcd8a..c8aceaf 100644
--- a/paludis/qa/deps_visible_check.cc
+++ b/paludis/qa/deps_visible_check.cc
@@ -26,6 +26,7 @@
#include <paludis/dep_atom.hh>
#include <paludis/dep_atom_pretty_printer.hh>
#include <paludis/util/save.hh>
+#include <paludis/query.hh>
#include <list>
@@ -102,7 +103,7 @@ namespace
bool found(false);
std::string candidates;
std::tr1::shared_ptr<PackageDatabaseEntryCollection> matches(env->package_database()->query(
- *p, is_any, qo_order_by_version));
+ query::Matches(*p), qo_order_by_version));
for (PackageDatabaseEntryCollection::ReverseIterator m(matches->rbegin()),
m_end(matches->rend()) ; m != m_end ; ++m)
{
diff --git a/paludis/query.cc b/paludis/query.cc
new file mode 100644
index 0000000..16701b8
--- /dev/null
+++ b/paludis/query.cc
@@ -0,0 +1,348 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "query.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/package_database.hh>
+#include <paludis/environment.hh>
+#include <paludis/match_package.hh>
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+
+QueryDelegate::QueryDelegate()
+{
+}
+
+QueryDelegate::~QueryDelegate()
+{
+}
+
+std::tr1::shared_ptr<RepositoryNameCollection>
+QueryDelegate::repositories(const Environment &) const
+{
+ return std::tr1::shared_ptr<RepositoryNameCollection>();
+}
+
+std::tr1::shared_ptr<CategoryNamePartCollection>
+QueryDelegate::categories(const Environment &, std::tr1::shared_ptr<const RepositoryNameCollection>) const
+{
+ return std::tr1::shared_ptr<CategoryNamePartCollection>();
+}
+
+std::tr1::shared_ptr<QualifiedPackageNameCollection>
+QueryDelegate::packages(const Environment &, std::tr1::shared_ptr<const RepositoryNameCollection>,
+ std::tr1::shared_ptr<const CategoryNamePartCollection>) const
+{
+ return std::tr1::shared_ptr<QualifiedPackageNameCollection>();
+}
+
+std::tr1::shared_ptr<PackageDatabaseEntryCollection>
+QueryDelegate::versions(const Environment &, std::tr1::shared_ptr<const RepositoryNameCollection>,
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection>) const
+{
+ return std::tr1::shared_ptr<PackageDatabaseEntryCollection>();
+}
+
+Query::Query(std::tr1::shared_ptr<const QueryDelegate> d) :
+ _d(d)
+{
+}
+
+Query::~Query()
+{
+}
+
+namespace
+{
+ struct MatchesDelegate :
+ QueryDelegate
+ {
+ const PackageDepAtom atom;
+
+ MatchesDelegate(const PackageDepAtom & a) :
+ atom(a)
+ {
+ }
+
+ std::tr1::shared_ptr<RepositoryNameCollection>
+ repositories(const Environment & e) const
+ {
+ if (atom.repository_ptr())
+ {
+ std::tr1::shared_ptr<RepositoryNameCollection> result(new RepositoryNameCollection::Concrete);
+
+ for (PackageDatabase::RepositoryIterator i(e.package_database()->begin_repositories()),
+ i_end(e.package_database()->end_repositories()) ; i != i_end ; ++i)
+ if ((*i)->name() == *atom.repository_ptr())
+ {
+ result->push_back((*i)->name());
+ break;
+ }
+
+ return result;
+ }
+
+ return QueryDelegate::repositories(e);
+ }
+
+ std::tr1::shared_ptr<CategoryNamePartCollection>
+ categories(const Environment &,
+ std::tr1::shared_ptr<const RepositoryNameCollection>) const
+ {
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+ result->insert(atom.package().category);
+ return result;
+ }
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection>
+ packages(const Environment &,
+ std::tr1::shared_ptr<const RepositoryNameCollection>,
+ std::tr1::shared_ptr<const CategoryNamePartCollection>) const
+ {
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+ result->insert(atom.package());
+ return result;
+ }
+
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection>
+ versions(const Environment & e,
+ std::tr1::shared_ptr<const RepositoryNameCollection> repos,
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> pkgs) const
+ {
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection> result(new PackageDatabaseEntryCollection::Concrete);
+ for (RepositoryNameCollection::Iterator r(repos->begin()), r_end(repos->end()) ;
+ r != r_end ; ++r)
+ {
+ std::tr1::shared_ptr<const Repository> repo(e.package_database()->fetch_repository(*r));
+
+ for (QualifiedPackageNameCollection::Iterator p(pkgs->begin()), p_end(pkgs->end()) ;
+ p != p_end ; ++p)
+ {
+ std::tr1::shared_ptr<const VersionSpecCollection> vers(repo->version_specs(*p));
+ for (VersionSpecCollection::Iterator v(vers->begin()), v_end(vers->end()) ;
+ v != v_end ; ++v)
+ {
+ PackageDatabaseEntry dbe(*p, *v, *r);
+ if (match_package(e, atom, dbe))
+ result->push_back(dbe);
+ }
+ }
+ }
+
+ return result;
+ }
+ };
+}
+
+query::Matches::Matches(const PackageDepAtom & a) :
+ Query(std::tr1::shared_ptr<QueryDelegate>(new MatchesDelegate(a)))
+{
+}
+
+query::Package::Package(const QualifiedPackageName & a) :
+ Query(std::tr1::shared_ptr<QueryDelegate>(new MatchesDelegate(PackageDepAtom(a))))
+{
+}
+
+namespace
+{
+ struct NotMaskedDelegate :
+ QueryDelegate
+ {
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection>
+ versions(const Environment & e,
+ std::tr1::shared_ptr<const RepositoryNameCollection> repos,
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> pkgs) const
+ {
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection> result(new PackageDatabaseEntryCollection::Concrete);
+ for (RepositoryNameCollection::Iterator r(repos->begin()), r_end(repos->end()) ;
+ r != r_end ; ++r)
+ {
+ std::tr1::shared_ptr<const Repository> repo(e.package_database()->fetch_repository(*r));
+
+ for (QualifiedPackageNameCollection::Iterator p(pkgs->begin()), p_end(pkgs->end()) ;
+ p != p_end ; ++p)
+ {
+ std::tr1::shared_ptr<const VersionSpecCollection> vers(repo->version_specs(*p));
+ for (VersionSpecCollection::Iterator v(vers->begin()), v_end(vers->end()) ;
+ v != v_end ; ++v)
+ {
+ PackageDatabaseEntry dbe(*p, *v, *r);
+ if (! e.mask_reasons(dbe).any())
+ result->push_back(dbe);
+ }
+ }
+ }
+
+ return result;
+ }
+ };
+}
+
+query::NotMasked::NotMasked() :
+ Query(std::tr1::shared_ptr<QueryDelegate>(new NotMaskedDelegate))
+{
+}
+
+namespace
+{
+ template <typename I_, I_ * (RepositoryCapabilities::* i_)>
+ struct RepositoryHasDelegate :
+ QueryDelegate
+ {
+ std::tr1::shared_ptr<RepositoryNameCollection>
+ repositories(const Environment & e) const
+ {
+ std::tr1::shared_ptr<RepositoryNameCollection> result(new RepositoryNameCollection::Concrete);
+
+ for (PackageDatabase::RepositoryIterator i(e.package_database()->begin_repositories()),
+ i_end(e.package_database()->end_repositories()) ; i != i_end ; ++i)
+ if ((**i).*i_)
+ result->push_back((*i)->name());
+
+ return result;
+ }
+ };
+}
+
+query::RepositoryHasInstalledInterface::RepositoryHasInstalledInterface() :
+ Query(std::tr1::shared_ptr<QueryDelegate>(
+ new RepositoryHasDelegate<RepositoryInstalledInterface, &RepositoryCapabilities::installed_interface>))
+{
+}
+
+query::RepositoryHasInstallableInterface::RepositoryHasInstallableInterface() :
+ Query(std::tr1::shared_ptr<QueryDelegate>(
+ new RepositoryHasDelegate<RepositoryInstallableInterface, &RepositoryCapabilities::installable_interface>))
+{
+}
+
+query::RepositoryHasUninstallableInterface::RepositoryHasUninstallableInterface() :
+ Query(std::tr1::shared_ptr<QueryDelegate>(
+ new RepositoryHasDelegate<RepositoryUninstallableInterface, &RepositoryCapabilities::uninstallable_interface>))
+{
+}
+
+namespace
+{
+ struct RepositoryNameComparator
+ {
+ bool operator() (const RepositoryName & l, const RepositoryName & r) const
+ {
+ return stringify(l) < stringify(r);
+ }
+ };
+
+ struct AndQueryDelegate :
+ QueryDelegate
+ {
+ std::tr1::shared_ptr<const QueryDelegate> q1, q2;
+
+ AndQueryDelegate(std::tr1::shared_ptr<const QueryDelegate> qq1,
+ std::tr1::shared_ptr<const QueryDelegate> qq2) :
+ q1(qq1),
+ q2(qq2)
+ {
+ }
+
+ std::tr1::shared_ptr<RepositoryNameCollection>
+ repositories(const Environment & e) const
+ {
+ std::tr1::shared_ptr<RepositoryNameCollection> r1(q1->repositories(e)), r2(q2->repositories(e));
+
+ if (r1 && r2)
+ {
+ std::set<RepositoryName, RepositoryNameComparator> s1(r1->begin(), r1->end()), s2(r2->begin(), r2->end());
+ std::tr1::shared_ptr<RepositoryNameCollection> result(new RepositoryNameCollection::Concrete);
+ std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), result->inserter(),
+ RepositoryNameComparator());
+ return result;
+ }
+ else if (r1)
+ return r1;
+ else
+ return r2;
+ }
+
+ std::tr1::shared_ptr<CategoryNamePartCollection>
+ categories(const Environment & e, std::tr1::shared_ptr<const RepositoryNameCollection> r) const
+ {
+ std::tr1::shared_ptr<CategoryNamePartCollection> r1(q1->categories(e, r)), r2(q2->categories(e, r));
+
+ if (r1 && r2)
+ {
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+ std::set_intersection(r1->begin(), r1->end(), r2->begin(), r2->end(), result->inserter());
+ return result;
+ }
+ else if (r1)
+ return r1;
+ else
+ return r2;
+ }
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection>
+ packages(const Environment & e, std::tr1::shared_ptr<const RepositoryNameCollection> r,
+ std::tr1::shared_ptr<const CategoryNamePartCollection> c) const
+ {
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> r1(q1->packages(e, r, c)), r2(q2->packages(e, r, c));
+
+ if (r1 && r2)
+ {
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+ std::set_intersection(r1->begin(), r1->end(), r2->begin(), r2->end(), result->inserter());
+ return result;
+ }
+ else if (r1)
+ return r1;
+ else
+ return r2;
+ }
+
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection>
+ versions(const Environment & e, std::tr1::shared_ptr<const RepositoryNameCollection> r,
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> q) const
+ {
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection> r1(q1->versions(e, r, q)), r2(q2->versions(e, r, q));
+
+ if (r1 && r2)
+ {
+ std::set<PackageDatabaseEntry, ArbitrarilyOrderedPackageDatabaseEntryCollectionComparator>
+ s1(r1->begin(), r1->end()), s2(r2->begin(), r2->end());
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection> result(new PackageDatabaseEntryCollection::Concrete);
+ std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), result->inserter(),
+ ArbitrarilyOrderedPackageDatabaseEntryCollectionComparator());
+ return result;
+ }
+ else if (r1)
+ return r1;
+ else
+ return r2;
+ }
+ };
+}
+
+Query
+paludis::operator& (const Query & q1, const Query & q2)
+{
+ return Query(std::tr1::shared_ptr<QueryDelegate>(new AndQueryDelegate(q1._d, q2._d)));
+}
+
diff --git a/paludis/query.hh b/paludis/query.hh
new file mode 100644
index 0000000..6a12cb5
--- /dev/null
+++ b/paludis/query.hh
@@ -0,0 +1,141 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_QUERY_HH
+#define PALUDIS_GUARD_PALUDIS_QUERY_HH 1
+
+#include <paludis/util/collection.hh>
+#include <paludis/name.hh>
+#include <paludis/package_database_entry.hh>
+
+namespace paludis
+{
+ class Environment;
+ class PackageDepAtom;
+
+ class QueryDelegate
+ {
+ protected:
+ QueryDelegate();
+
+ public:
+ virtual ~QueryDelegate();
+
+ virtual std::tr1::shared_ptr<RepositoryNameCollection> repositories(const Environment &) const;
+
+ virtual std::tr1::shared_ptr<CategoryNamePartCollection> categories(const Environment &,
+ std::tr1::shared_ptr<const RepositoryNameCollection>) const;
+
+ virtual std::tr1::shared_ptr<QualifiedPackageNameCollection> packages(const Environment &,
+ std::tr1::shared_ptr<const RepositoryNameCollection>,
+ std::tr1::shared_ptr<const CategoryNamePartCollection>) const;
+
+ virtual std::tr1::shared_ptr<PackageDatabaseEntryCollection> versions(const Environment &,
+ std::tr1::shared_ptr<const RepositoryNameCollection>,
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection>) const;
+ };
+
+ class Query
+ {
+ friend Query operator& (const Query &, const Query &);
+
+ private:
+ std::tr1::shared_ptr<const QueryDelegate> _d;
+
+ protected:
+ Query(std::tr1::shared_ptr<const QueryDelegate>);
+
+ public:
+ ~Query();
+
+ std::tr1::shared_ptr<RepositoryNameCollection> repositories(const Environment & e) const
+ {
+ return _d->repositories(e);
+ }
+
+ std::tr1::shared_ptr<CategoryNamePartCollection> categories(const Environment & e,
+ std::tr1::shared_ptr<const RepositoryNameCollection> r) const
+ {
+ return _d->categories(e, r);
+ }
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> packages(const Environment & e,
+ std::tr1::shared_ptr<const RepositoryNameCollection> r,
+ std::tr1::shared_ptr<const CategoryNamePartCollection> c) const
+ {
+ return _d->packages(e, r, c);
+ }
+
+ std::tr1::shared_ptr<PackageDatabaseEntryCollection> versions(const Environment & e,
+ std::tr1::shared_ptr<const RepositoryNameCollection> r,
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> q) const
+ {
+ return _d->versions(e, r, q);
+ }
+ };
+
+ namespace query
+ {
+ class Matches :
+ public Query
+ {
+ public:
+ Matches(const PackageDepAtom &);
+ };
+
+ class Package :
+ public Query
+ {
+ public:
+ Package(const QualifiedPackageName &);
+ };
+
+ class NotMasked :
+ public Query
+ {
+ public:
+ NotMasked();
+ };
+
+ class RepositoryHasInstalledInterface :
+ public Query
+ {
+ public:
+ RepositoryHasInstalledInterface();
+ };
+
+ class RepositoryHasInstallableInterface :
+ public Query
+ {
+ public:
+ RepositoryHasInstallableInterface();
+ };
+
+ class RepositoryHasUninstallableInterface :
+ public Query
+ {
+ public:
+ RepositoryHasUninstallableInterface();
+ };
+ }
+
+ Query operator& (const Query &, const Query &);
+}
+
+#endif
diff --git a/paludis/repositories/portage/portage_repository_news.cc b/paludis/repositories/portage/portage_repository_news.cc
index d36f5b3..3ac2f9b 100644
--- a/paludis/repositories/portage/portage_repository_news.cc
+++ b/paludis/repositories/portage/portage_repository_news.cc
@@ -26,6 +26,7 @@
#include <paludis/util/fs_entry.hh>
#include <paludis/util/log.hh>
#include <paludis/util/strip.hh>
+#include <paludis/query.hh>
#include <set>
#include <ostream>
@@ -117,7 +118,8 @@ PortageRepositoryNews::update_news() const
bool local_show(false);
for (NewsFile::DisplayIfInstalledIterator i(news.begin_display_if_installed()),
i_end(news.end_display_if_installed()) ; i != i_end ; ++i)
- if (! _imp->environment->package_database()->query(PackageDepAtom(*i), is_installed_only,
+ if (! _imp->environment->package_database()->query(
+ query::Package(*i) & query::RepositoryHasInstalledInterface(),
qo_whatever)->empty())
local_show = true;
show &= local_show;