aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2007-11-20 20:25:29 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2007-11-20 20:25:29 +0000
commit6ae1d90a0cebdc74a3368af481b3d429a8d9c8f4 (patch)
tree37abf026812fe9a883edae4ea731ec36ebade956
parentfada389df0902a4e0e975909b3d4b4e23429f4c9 (diff)
downloadpaludis-6ae1d90a0cebdc74a3368af481b3d429a8d9c8f4.tar.gz
paludis-6ae1d90a0cebdc74a3368af481b3d429a8d9c8f4.tar.xz
Make fetch_unique_qualified_package_name take a query to limit the potential results, and use it to pick out installable or installed packages when appropriate.
-rw-r--r--paludis/install_task.cc2
-rw-r--r--paludis/package_database.cc56
-rw-r--r--paludis/package_database.hh9
-rw-r--r--paludis/package_database_TEST.cc48
-rw-r--r--paludis/query.cc13
-rw-r--r--paludis/uninstall_task.cc4
-rw-r--r--python/package_database.cc10
-rwxr-xr-xpython/package_database_TEST.py2
-rw-r--r--ruby/package_database.cc21
-rw-r--r--ruby/package_database_TEST.rb19
-rw-r--r--src/clients/paludis/do_config.cc2
11 files changed, 134 insertions, 52 deletions
diff --git a/paludis/install_task.cc b/paludis/install_task.cc
index 8379acd..624a785 100644
--- a/paludis/install_task.cc
+++ b/paludis/install_task.cc
@@ -195,7 +195,7 @@ InstallTask::add_target(const std::string & target)
try
{
QualifiedPackageName q(_imp->env->package_database()->fetch_unique_qualified_package_name(
- PackageNamePart(target)));
+ PackageNamePart(target), query::MaybeSupportsAction<InstallAction>()));
modified_target = stringify(q);
tr1::shared_ptr<PackageDepSpec> spec(
new PackageDepSpec(tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(q))));
diff --git a/paludis/package_database.cc b/paludis/package_database.cc
index 9f8ac74..40f0350 100644
--- a/paludis/package_database.cc
+++ b/paludis/package_database.cc
@@ -190,6 +190,17 @@ PackageDatabase::add_repository(int i, const tr1::shared_ptr<Repository> r)
namespace
{
+ struct CategoryRepositoryNamePairComparator
+ {
+ bool operator() (const std::pair<CategoryNamePart, RepositoryName> & a,
+ const std::pair<CategoryNamePart, RepositoryName> & b) const
+ {
+ if (a.first != b.first)
+ return a.first < b.first;
+ return RepositoryNameComparator()(a.second, b.second);
+ }
+ };
+
struct IsInstalled
{
const FSEntry _root;
@@ -215,42 +226,53 @@ namespace
typedef QualifiedPackageName argument_type;
typedef bool result_type;
- typedef Map<const QualifiedPackageName, const tr1::shared_ptr<const CategoryNamePartSet> > QPNCMap;
- const tr1::shared_ptr<QPNCMap> _map;
+ typedef Map<const QualifiedPackageName, bool> QPNIMap;
+ const tr1::shared_ptr<QPNIMap> _map;
- IsImportant(const tr1::shared_ptr<QPNCMap> & m) :
+ IsImportant(const tr1::shared_ptr<QPNIMap> & m) :
_map(m)
{
}
bool operator() (const QualifiedPackageName & qpn) const
{
- return (_map->find(qpn)->second->end() == _map->find(qpn)->second->find(qpn.category));
+ return _map->find(qpn)->second;
}
};
}
QualifiedPackageName
PackageDatabase::fetch_unique_qualified_package_name(
- const PackageNamePart & p) const
+ const PackageNamePart & p, const Query & q) const
{
Context context("When disambiguating package name '" + stringify(p) + "':");
- // Map matching QualifiedPackageNames with unimportant_category_names sets from their repository.
- typedef Map<const QualifiedPackageName, const tr1::shared_ptr<const CategoryNamePartSet> > QPNCMap;
- tr1::shared_ptr<QPNCMap> result(new QPNCMap);
-
- for (IndirectIterator<RepositoryConstIterator> r(begin_repositories()), r_end(end_repositories()) ;
- r != r_end ; ++r)
+ const Query & real_q(q & query::Matches(PackageDepSpec(
+ tr1::shared_ptr<QualifiedPackageName>(),
+ tr1::shared_ptr<CategoryNamePart>(),
+ tr1::shared_ptr<PackageNamePart>(new PackageNamePart(p)))));
+
+ // Map matching QualifiedPackageNames with a flag specifying that
+ // at least one repository containing the package things the
+ // category is important
+ typedef Map<const QualifiedPackageName, bool> QPNIMap;
+ tr1::shared_ptr<QPNIMap> result(new QPNIMap);
+ std::set<std::pair<CategoryNamePart, RepositoryName>, CategoryRepositoryNamePairComparator> checked;
+
+ tr1::shared_ptr<const PackageIDSequence> pkgs(query(real_q, qo_whatever));
+ for (IndirectIterator<PackageIDSequence::ConstIterator> it(pkgs->begin()),
+ it_end(pkgs->end()); it_end != it; ++it)
{
- Context local_context("When looking in repository '" + stringify(r->name()) + "':");
+ Context local_context("When checking category '" + stringify(it->name().category) + "' in repository '" + stringify(it->repository()->name()) + "':");
- tr1::shared_ptr<const CategoryNamePartSet> cats(r->category_names_containing_package(p));
- tr1::shared_ptr<const CategoryNamePartSet> unimportant_cats(r->unimportant_category_names());
+ if (! checked.insert(std::make_pair(it->name().category, it->repository()->name())).second)
+ continue;
- for (CategoryNamePartSet::ConstIterator c(cats->begin()), c_end(cats->end()) ;
- c != c_end ; ++c)
- result->insert(*c + p, unimportant_cats);
+ tr1::shared_ptr<const CategoryNamePartSet> unimportant_cats(it->repository()->unimportant_category_names());
+ bool is_important(unimportant_cats->end() == unimportant_cats->find(it->name().category));
+ if (is_important)
+ result->erase(it->name());
+ result->insert(it->name(), is_important);
}
if (result->empty())
diff --git a/paludis/package_database.hh b/paludis/package_database.hh
index b04d4fc..c90a5a1 100644
--- a/paludis/package_database.hh
+++ b/paludis/package_database.hh
@@ -24,7 +24,7 @@
#include <paludis/dep_spec.hh>
#include <paludis/name.hh>
#include <paludis/repository.hh>
-#include <paludis/query-fwd.hh>
+#include <paludis/query.hh>
#include <paludis/util/exception.hh>
#include <paludis/util/instantiation_policy.hh>
#include <paludis/util/join.hh>
@@ -289,13 +289,14 @@ namespace paludis
PALUDIS_ATTRIBUTE((warn_unused_result));
/**
- * Disambiguate a package name.
+ * Disambiguate a package name. If a query is specified,
+ * limit the potential results to packages that match.
*
* \throw AmbiguousPackageNameError if there is no unambiguous
- * disabmiguation.
+ * disambiguation.
*/
QualifiedPackageName fetch_unique_qualified_package_name(
- const PackageNamePart &) const
+ const PackageNamePart &, const Query & = query::All()) const
PALUDIS_ATTRIBUTE((warn_unused_result));
/**
diff --git a/paludis/package_database_TEST.cc b/paludis/package_database_TEST.cc
index b038099..0997844 100644
--- a/paludis/package_database_TEST.cc
+++ b/paludis/package_database_TEST.cc
@@ -278,37 +278,39 @@ namespace test_cases
PackageDatabase & p(*e.package_database());
tr1::shared_ptr<FakeRepository> r1(new FakeRepository(&e, RepositoryName("repo1")));
- r1->add_package(CategoryNamePart("cat-one") + PackageNamePart("pkg-one"));
- r1->add_package(CategoryNamePart("cat-one") + PackageNamePart("pkg-two"));
- r1->add_package(CategoryNamePart("cat-two") + PackageNamePart("pkg-two"));
- r1->add_package(CategoryNamePart("cat-two") + PackageNamePart("pkg-three"));
+ r1->add_version(CategoryNamePart("cat-one") + PackageNamePart("pkg-one"), VersionSpec("0"));
+ r1->add_version(CategoryNamePart("cat-one") + PackageNamePart("pkg-two"), VersionSpec("0"));
+ r1->add_version(CategoryNamePart("cat-two") + PackageNamePart("pkg-two"), VersionSpec("0"));
+ r1->add_version(CategoryNamePart("cat-two") + PackageNamePart("pkg-three"), VersionSpec("0"));
p.add_repository(10, r1);
TEST_CHECK(true);
tr1::shared_ptr<FakeRepository> r2(new FakeRepository(&e, RepositoryName("repo2")));
- r2->add_package(CategoryNamePart("cat-three") + PackageNamePart("pkg-three"));
- r2->add_package(CategoryNamePart("cat-three") + PackageNamePart("pkg-four"));
+ r2->add_version(CategoryNamePart("cat-three") + PackageNamePart("pkg-three"), VersionSpec("0"));
+ r2->add_version(CategoryNamePart("cat-three") + PackageNamePart("pkg-four"), VersionSpec("0"));
p.add_repository(10, r2);
TEST_CHECK(true);
tr1::shared_ptr<FakeRepository> r3(new CoolFakeRepository(&e, RepositoryName("repo3")));
- r3->add_package(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-important"));
- r3->add_package(CategoryNamePart("good-cat1") + PackageNamePart("pkg-important"));
+ r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-important"), VersionSpec("0"));
+ r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-important"), VersionSpec("0"));
- r3->add_package(CategoryNamePart("good-cat1") + PackageNamePart("pkg-installed"));
- r3->add_package(CategoryNamePart("good-cat2") + PackageNamePart("pkg-installed"));
+ r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-installed"), VersionSpec("0"));
+ r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-installed"), VersionSpec("0"));
- r3->add_package(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail1"));
- r3->add_package(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail1"));
+ r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail1"), VersionSpec("0"));
+ r3->add_version(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail1"), VersionSpec("0"));
- r3->add_package(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail2"));
- r3->add_package(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail2"));
+ r3->add_version(CategoryNamePart("bad-cat1") + PackageNamePart("pkg-fail2"), VersionSpec("0"));
+ r3->add_version(CategoryNamePart("bad-cat2") + PackageNamePart("pkg-fail2"), VersionSpec("0"));
- r3->add_package(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail3"));
- r3->add_package(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail3"));
+ r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail3"), VersionSpec("0"));
+ r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail3"), VersionSpec("0"));
- r3->add_package(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail4"));
- r3->add_package(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail4"));
+ r3->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail4"), VersionSpec("0"));
+ r3->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail4"), VersionSpec("0"));
+
+ r3->add_version(CategoryNamePart("avail-cat") + PackageNamePart("pkg-foo"), VersionSpec("0"));
p.add_repository(10, r3);
TEST_CHECK(true);
@@ -316,6 +318,7 @@ namespace test_cases
r4->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-installed"), VersionSpec("0"));
r4->add_version(CategoryNamePart("good-cat1") + PackageNamePart("pkg-fail4"), VersionSpec("0"));
r4->add_version(CategoryNamePart("good-cat2") + PackageNamePart("pkg-fail4"), VersionSpec("0"));
+ r4->add_version(CategoryNamePart("inst-cat") + PackageNamePart("pkg-foo"), VersionSpec("0"));
p.add_repository(10, r4);
TEST_CHECK_STRINGIFY_EQUAL(p.fetch_unique_qualified_package_name(PackageNamePart("pkg-one")),
@@ -346,6 +349,15 @@ namespace test_cases
TEST_CHECK_THROWS(p.fetch_unique_qualified_package_name(PackageNamePart("pkg-five")),
NoSuchPackageError);
+ TEST_CHECK_THROWS(p.fetch_unique_qualified_package_name(PackageNamePart("pkg-one"),
+ query::SupportsAction<InstalledAction>()),
+ NoSuchPackageError);
+ TEST_CHECK_STRINGIFY_EQUAL(p.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo")),
+ "inst-cat/pkg-foo");
+ TEST_CHECK_STRINGIFY_EQUAL(p.fetch_unique_qualified_package_name(PackageNamePart("pkg-foo"),
+ query::SupportsAction<InstallAction>()),
+ "avail-cat/pkg-foo");
+
}
} package_database_disambiguate_test;
}
diff --git a/paludis/query.cc b/paludis/query.cc
index 25d9b06..547d439 100644
--- a/paludis/query.cc
+++ b/paludis/query.cc
@@ -128,6 +128,19 @@ namespace
result->insert(*spec.category_name_part_ptr());
return result;
}
+ else if (spec.package_name_part_ptr())
+ {
+ tr1::shared_ptr<CategoryNamePartSet> result(new CategoryNamePartSet);
+ for (RepositoryNameSequence::ConstIterator it(r->begin()),
+ it_end(r->end()); it_end != it; ++it)
+ {
+ tr1::shared_ptr<const CategoryNamePartSet> cats(
+ e.package_database()->fetch_repository(*it)
+ ->category_names_containing_package(*spec.package_name_part_ptr()));
+ std::copy(cats->begin(), cats->end(), result->inserter());
+ }
+ return result;
+ }
else
return QueryDelegate::categories(e, r);
}
diff --git a/paludis/uninstall_task.cc b/paludis/uninstall_task.cc
index e819905..8e7037a 100644
--- a/paludis/uninstall_task.cc
+++ b/paludis/uninstall_task.cc
@@ -190,7 +190,7 @@ UninstallTask::add_target(const std::string & target)
tr1::shared_ptr<PackageDepSpec> pds(new PackageDepSpec(
tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(
_imp->env->package_database()->fetch_unique_qualified_package_name(
- PackageNamePart(target))))));
+ PackageNamePart(target), query::MaybeSupportsAction<UninstallAction>())))));
pds->set_tag(tr1::shared_ptr<const DepTag>(new TargetDepTag));
_imp->targets.push_back(pds);
}
@@ -204,7 +204,7 @@ UninstallTask::add_target(const std::string & target)
tr1::shared_ptr<PackageDepSpec> pds(new PackageDepSpec(
tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(
_imp->env->package_database()->fetch_unique_qualified_package_name(
- PackageNamePart(target))))));
+ PackageNamePart(target), query::MaybeSupportsAction<UninstallAction>())))));
pds->set_tag(tr1::shared_ptr<const DepTag>(new TargetDepTag));
_imp->targets.push_back(pds);
}
diff --git a/python/package_database.cc b/python/package_database.cc
index e0cedcd..08cb59a 100644
--- a/python/package_database.cc
+++ b/python/package_database.cc
@@ -31,6 +31,9 @@ using namespace paludis;
using namespace paludis::python;
namespace bp = boost::python;
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(
+ fetch_unique_qualified_package_name_overloads, fetch_unique_qualified_package_name, 1, 2)
+
void expose_package_database()
{
/**
@@ -91,8 +94,11 @@ void expose_package_database()
)
.def("fetch_unique_qualified_package_name", &PackageDatabase::fetch_unique_qualified_package_name,
- "fetch_unique_qualified_package_name(PackageNamePart) -> QualifiedPackageName\n"
- "Disambiguate a package name."
+ fetch_unique_qualified_package_name_overloads(
+ "fetch_unique_qualified_package_name(PackageNamePart[, Query]) -> QualifiedPackageName\n"
+ "Disambiguate a package name. If a query is specified, "
+ "limit the potential results to packages that match."
+ )
)
.def("more_important_than", &PackageDatabase::more_important_than,
diff --git a/python/package_database_TEST.py b/python/package_database_TEST.py
index a6300ae..1fba70a 100755
--- a/python/package_database_TEST.py
+++ b/python/package_database_TEST.py
@@ -42,11 +42,13 @@ class TestCase_PackageDatabase(unittest.TestCase):
def test_03_fech_unique_qpn(self):
self.get_db()
self.assertEqual(str(QualifiedPackageName("foo/bar")), str(self.db.fetch_unique_qualified_package_name("bar")))
+ self.assertEqual(str(QualifiedPackageName("foo/bar")), str(self.db.fetch_unique_qualified_package_name("bar", Query.SupportsInstallAction())))
def test_04_exceptions(self):
self.get_db()
self.assertRaises(AmbiguousPackageNameError, self.db.fetch_unique_qualified_package_name, "baz")
self.assertRaises(NoSuchPackageError, self.db.fetch_unique_qualified_package_name, "foobarbaz")
+ self.assertRaises(NoSuchPackageError, self.db.fetch_unique_qualified_package_name, "bar", Query.SupportsUninstallAction())
def test_5_query(self):
self.get_db()
diff --git a/ruby/package_database.cc b/ruby/package_database.cc
index 7301ffc..4313b83 100644
--- a/ruby/package_database.cc
+++ b/ruby/package_database.cc
@@ -58,18 +58,25 @@ namespace
/*
* call-seq:
* fetch_unique_qualified_package_name(package_name) -> QualifiedPackageName
+ * fetch_unique_qualified_package_name(package_name, query) -> QualifiedPackageName
*
- * Disambiguate a package name
+ * Disambiguate a package name. If a query is specified, limit
+ * the potential results to packages that match.
*/
VALUE
- package_database_fetch_unique_qualified_package_name(VALUE self, VALUE pkg)
+ package_database_fetch_unique_qualified_package_name(int argc, VALUE *argv, VALUE self)
{
try
{
- tr1::shared_ptr<PackageDatabase> * self_ptr;
- Data_Get_Struct(self, tr1::shared_ptr<PackageDatabase>, self_ptr);
- return rb_str_new2(stringify((*self_ptr)->fetch_unique_qualified_package_name(
- PackageNamePart(StringValuePtr(pkg)))).c_str());
+ if (1 == argc || 2 == argc)
+ {
+ tr1::shared_ptr<PackageDatabase> * self_ptr;
+ Data_Get_Struct(self, tr1::shared_ptr<PackageDatabase>, self_ptr);
+ return rb_str_new2(stringify((*self_ptr)->fetch_unique_qualified_package_name(
+ PackageNamePart(StringValuePtr(argv[0])), 2 == argc ? value_to_query(argv[1]) : query::All())).c_str());
+ }
+ else
+ rb_raise(rb_eArgError, "fetch_unique_qualified_package_name expects one or two arguments, but got %d",argc);
}
catch (const std::exception & e)
{
@@ -208,7 +215,7 @@ namespace
rb_funcall(c_package_database, rb_intern("private_class_method"), 1, rb_str_new2("new"));
rb_define_method(c_package_database, "favourite_repository", RUBY_FUNC_CAST(&package_database_favourite_repository), 0);
rb_define_method(c_package_database, "fetch_unique_qualified_package_name",
- RUBY_FUNC_CAST(&package_database_fetch_unique_qualified_package_name), 1);
+ RUBY_FUNC_CAST(&package_database_fetch_unique_qualified_package_name), -1);
rb_define_method(c_package_database, "query",
RUBY_FUNC_CAST(&package_database_query), -1);
rb_define_method(c_package_database, "repositories",
diff --git a/ruby/package_database_TEST.rb b/ruby/package_database_TEST.rb
index 3273235..b332a60 100644
--- a/ruby/package_database_TEST.rb
+++ b/ruby/package_database_TEST.rb
@@ -56,6 +56,7 @@ module Paludis
def test_package_database_fetch_unique_qualified_package_name
assert_equal "foo/bar", db.fetch_unique_qualified_package_name("bar")
+ assert_equal "foo/bar", db.fetch_unique_qualified_package_name("bar", Query::SupportsInstallAction.new)
end
def test_error
@@ -65,6 +66,24 @@ module Paludis
assert_raise NoSuchPackageError do
db.fetch_unique_qualified_package_name('foobarbaz')
end
+ assert_raise NoSuchPackageError do
+ db.fetch_unique_qualified_package_name('bar', Query::SupportsInstalledAction.new)
+ end
+ end
+
+ def test_bad
+ assert_raise ArgumentError do
+ db.fetch_unique_qualified_package_name
+ end
+ assert_raise ArgumentError do
+ db.fetch_unique_qualified_package_name(1, 2, 3)
+ end
+ assert_raise TypeError do
+ db.fetch_unique_qualified_package_name([])
+ end
+ assert_raise TypeError do
+ db.fetch_unique_qualified_package_name('bar', db)
+ end
end
end
diff --git a/src/clients/paludis/do_config.cc b/src/clients/paludis/do_config.cc
index 1c9b093..caa92a1 100644
--- a/src/clients/paludis/do_config.cc
+++ b/src/clients/paludis/do_config.cc
@@ -75,7 +75,7 @@ namespace
tr1::shared_ptr<PackageDepSpec> spec(std::string::npos == target.find('/') ?
new PackageDepSpec(tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(
env->package_database()->fetch_unique_qualified_package_name(
- PackageNamePart(target))))) :
+ PackageNamePart(target), query::InstalledAtRoot(env->root()))))) :
new PackageDepSpec(target, pds_pm_permissive));
tr1::shared_ptr<const PackageIDSequence>