aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-04-23 21:03:00 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-04-23 21:03:00 +0000
commit6f09bd3174603fcab6695904206609cda734c3fe (patch)
tree863c93e1484bddf3a0c8c69bc24df20363f6e667
parent4bfac78d52e5368bfcc1dcdcd2ee9dec0c7632fa (diff)
downloadpaludis-6f09bd3174603fcab6695904206609cda734c3fe.tar.gz
paludis-6f09bd3174603fcab6695904206609cda734c3fe.tar.xz
Enable use dependencies (library only, no nice user interface to them at present). Enhance priority of use.mask. Add circular detection for per package use masking when use deps are used, to avoid infinite recursion.
-rw-r--r--paludis/default_environment.cc9
-rw-r--r--paludis/dep_atom.cc47
-rw-r--r--paludis/dep_atom.hh46
-rw-r--r--paludis/dep_atom_TEST.cc16
-rw-r--r--paludis/dep_list_TEST.cc192
-rw-r--r--paludis/match_package.cc61
-rw-r--r--paludis/portage_repository.cc24
7 files changed, 386 insertions, 9 deletions
diff --git a/paludis/default_environment.cc b/paludis/default_environment.cc
index 9320f0e..36a266c 100644
--- a/paludis/default_environment.cc
+++ b/paludis/default_environment.cc
@@ -48,6 +48,13 @@ DefaultEnvironment::~DefaultEnvironment()
bool
DefaultEnvironment::query_use(const UseFlagName & f, const PackageDatabaseEntry * e) const
{
+ /* first check package database use masks... */
+ if (e ? package_database()->fetch_repository(e->get<pde_repository>())->query_use_mask(f, e) :
+ package_database()->fetch_repository(
+ package_database()->favourite_repository())->query_use_mask(f, e))
+ return false;
+
+ /* check use: per package user config */
if (e)
{
UseFlagState s(use_unspecified);
@@ -97,6 +104,7 @@ DefaultEnvironment::query_use(const UseFlagName & f, const PackageDatabaseEntry
} while (false);
}
+ /* check use: general user config */
do
{
UseFlagState state(use_unspecified);
@@ -123,6 +131,7 @@ DefaultEnvironment::query_use(const UseFlagName & f, const PackageDatabaseEntry
throw InternalError(PALUDIS_HERE, "bad state " + stringify(state));
} while (false);
+ /* check use: package database config */
switch (e ? package_database()->fetch_repository(e->get<pde_repository>())->query_use(f, e) :
package_database()->fetch_repository(package_database()->favourite_repository())->query_use(f, e))
{
diff --git a/paludis/dep_atom.cc b/paludis/dep_atom.cc
index 790ebcd..920c0f7 100644
--- a/paludis/dep_atom.cc
+++ b/paludis/dep_atom.cc
@@ -84,6 +84,7 @@ PackageDepAtom::PackageDepAtom(const QualifiedPackageName & package) :
_version_spec(0),
_slot(0),
_repository(0),
+ _use_requirements(0),
_tag(0)
{
}
@@ -95,6 +96,7 @@ PackageDepAtom::PackageDepAtom(const std::string & ss) :
_version_spec(0),
_slot(0),
_repository(0),
+ _use_requirements(0),
_tag(0)
{
Context context("When parsing package dep atom '" + ss + "':");
@@ -106,6 +108,33 @@ PackageDepAtom::PackageDepAtom(const std::string & ss) :
if (s.empty())
throw PackageDepAtomError("Got empty dep atom");
+ std::string::size_type use_group_p;
+ while (std::string::npos != ((use_group_p = s.rfind('['))))
+ {
+ if (s.at(s.length() - 1) != ']')
+ throw PackageDepAtomError("Mismatched []");
+
+ std::string flag(s.substr(use_group_p + 1));
+ UseFlagState state(use_enabled);
+ if (flag.length() < 2)
+ throw PackageDepAtomError("Invalid [] contents");
+ flag.erase(flag.length() - 1);
+ if ('-' == flag.at(0))
+ {
+ state = use_disabled;
+ flag.erase(0, 1);
+ if (flag.empty())
+ throw PackageDepAtomError("Invalid [] contents");
+ }
+ UseFlagName name(flag);
+ if (0 == _use_requirements)
+ _use_requirements.assign(new UseRequirements);
+ if (! _use_requirements->insert(name, state))
+ throw PackageDepAtomError("Conflicting [] contents");
+
+ s.erase(use_group_p);
+ }
+
std::string::size_type repo_p;
if (std::string::npos != ((repo_p = s.rfind("::"))))
{
@@ -209,6 +238,15 @@ paludis::operator<< (std::ostream & s, const PackageDepAtom & a)
s << ":" << *a.slot_ptr();
if (a.repository_ptr())
s << "::" << *a.repository_ptr();
+
+ if (a.use_requirements_ptr())
+ {
+ for (UseRequirements::Iterator u(a.use_requirements_ptr()->begin()),
+ u_end(a.use_requirements_ptr()->end()) ; u != u_end ; ++u)
+ s << "[" << (u->second == use_disabled ? "-" + stringify(u->first) :
+ stringify(u->first)) << "]";
+ }
+
return s;
}
@@ -227,3 +265,12 @@ PlainTextDepAtom::PlainTextDepAtom(const std::string & s) :
{
}
+UseFlagState
+UseRequirements::state(const UseFlagName & u) const
+{
+ Iterator i(find(u));
+ if (end() == i)
+ return use_unspecified;
+ return i->second;
+}
+
diff --git a/paludis/dep_atom.hh b/paludis/dep_atom.hh
index 0255eb1..87510d7 100644
--- a/paludis/dep_atom.hh
+++ b/paludis/dep_atom.hh
@@ -30,6 +30,7 @@
#include <paludis/util/visitor.hh>
#include <paludis/version_operator.hh>
#include <paludis/version_spec.hh>
+#include <map>
/** \file
* Declarations for the DepAtom classes.
@@ -240,6 +241,43 @@ namespace paludis
};
/**
+ * A selection of USE flag requirements.
+ *
+ * \ingroup grpdepatoms
+ */
+ class UseRequirements :
+ public InternalCounted<UseRequirements>
+ {
+ private:
+ std::map<UseFlagName, UseFlagState> _reqs;
+
+ public:
+ typedef std::map<UseFlagName, UseFlagState>::const_iterator Iterator;
+
+ Iterator begin() const
+ {
+ return _reqs.begin();
+ }
+
+ Iterator end() const
+ {
+ return _reqs.end();
+ }
+
+ Iterator find(const UseFlagName & u) const
+ {
+ return _reqs.find(u);
+ }
+
+ bool insert(const UseFlagName & u, UseFlagState s)
+ {
+ return _reqs.insert(std::make_pair(u, s)).second;
+ }
+
+ UseFlagState state(const UseFlagName &) const;
+ };
+
+ /**
* A PackageDepAtom represents a package name (for example,
* 'app-editors/vim'), possibly with associated version and SLOT
* restrictions.
@@ -256,6 +294,7 @@ namespace paludis
CountedPtr<VersionSpec, count_policy::ExternalCountTag> _version_spec;
CountedPtr<SlotName, count_policy::ExternalCountTag> _slot;
CountedPtr<RepositoryName, count_policy::ExternalCountTag> _repository;
+ UseRequirements::Pointer _use_requirements;
DepTag::ConstPointer _tag;
public:
@@ -314,6 +353,13 @@ namespace paludis
return _repository;
}
+ /**
+ * Fetch the use requirements (may be a zero pointer).
+ */
+ UseRequirements::ConstPointer use_requirements_ptr() const
+ {
+ return _use_requirements;
+ }
/**
* A non-constant smart pointer to ourself.
diff --git a/paludis/dep_atom_TEST.cc b/paludis/dep_atom_TEST.cc
index 97d5851..109c3d4 100644
--- a/paludis/dep_atom_TEST.cc
+++ b/paludis/dep_atom_TEST.cc
@@ -135,6 +135,22 @@ namespace test_cases
TEST_CHECK_EQUAL(h.version_operator(), vo_greater_equal);
TEST_CHECK_THROWS(PackageDepAtom(""), PackageDepAtomError);
+
+ PackageDepAtom i("foo/bar[one][-two]");
+ TEST_CHECK_STRINGIFY_EQUAL(i.package(), "foo/bar");
+ TEST_CHECK(! i.version_spec_ptr());
+ TEST_CHECK(! i.repository_ptr());
+ TEST_CHECK(! i.slot_ptr());
+ TEST_CHECK(i.use_requirements_ptr());
+ TEST_CHECK(i.use_requirements_ptr()->find(UseFlagName("one")) !=
+ i.use_requirements_ptr()->end());
+ TEST_CHECK(i.use_requirements_ptr()->find(UseFlagName("two")) !=
+ i.use_requirements_ptr()->end());
+ TEST_CHECK(i.use_requirements_ptr()->find(UseFlagName("three")) ==
+ i.use_requirements_ptr()->end());
+ TEST_CHECK(i.use_requirements_ptr()->state(UseFlagName("one")) == use_enabled);
+ TEST_CHECK(i.use_requirements_ptr()->state(UseFlagName("two")) == use_disabled);
+ TEST_CHECK(i.use_requirements_ptr()->state(UseFlagName("moo")) == use_unspecified);
}
} test_package_dep_atom;
}
diff --git a/paludis/dep_list_TEST.cc b/paludis/dep_list_TEST.cc
index 984d50b..e0da065 100644
--- a/paludis/dep_list_TEST.cc
+++ b/paludis/dep_list_TEST.cc
@@ -1123,6 +1123,198 @@ namespace test_cases
} test_dep_list_44;
/**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase45 : DepListTestCase<45>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two[enabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "enabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ expected.push_back("cat/two-1:0::repo");
+ expected.push_back("cat/one-1:0::repo");
+ }
+ } test_dep_list_45;
+
+ /**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase46 : DepListTestCase<46>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two[-disabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "disabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ expected.push_back("cat/two-1:0::repo");
+ expected.push_back("cat/one-1:0::repo");
+ }
+ } test_dep_list_46;
+
+ /**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase47 : DepListTestCase<47>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two[disabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "disabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ }
+
+ void check_lists()
+ {
+ TEST_CHECK(true);
+ DepList d(&env);
+ TEST_CHECK_THROWS(d.add(DepParser::parse(merge_target)), DepListError);
+ TEST_CHECK(d.begin() == d.end());
+ }
+ } test_dep_list_47;
+
+ /**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase48 : DepListTestCase<48>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two[-enabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "enabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ }
+
+ void check_lists()
+ {
+ TEST_CHECK(true);
+ DepList d(&env);
+ TEST_CHECK_THROWS(d.add(DepParser::parse(merge_target)), DepListError);
+ TEST_CHECK(d.begin() == d.end());
+ }
+ } test_dep_list_48;
+
+ /**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase49 : DepListTestCase<49>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two cat/two[enabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "enabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ expected.push_back("cat/two-1:0::repo");
+ expected.push_back("cat/one-1:0::repo");
+ }
+ } test_dep_list_49;
+
+ /**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase50 : DepListTestCase<50>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two cat/two[-disabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "disabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ expected.push_back("cat/two-1:0::repo");
+ expected.push_back("cat/one-1:0::repo");
+ }
+ } test_dep_list_50;
+
+ /**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase51 : DepListTestCase<51>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two cat/two[disabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "disabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ }
+
+ void check_lists()
+ {
+ TEST_CHECK(true);
+ DepList d(&env);
+ TEST_CHECK_THROWS(d.add(DepParser::parse(merge_target)), DepListError);
+ TEST_CHECK(d.begin() == d.end());
+ }
+ } test_dep_list_51;
+
+ /**
+ * \test Test DepList resolution behaviour.
+ *
+ * \ingroup Test
+ */
+ struct DepListTestCase52 : DepListTestCase<52>
+ {
+ void populate_repo()
+ {
+ repo->add_version("cat", "one", "1")->set(vmk_depend, "( cat/two cat/two[-enabled] )");
+ repo->add_version("cat", "two", "1")->set(vmk_iuse, "enabled");
+ }
+
+ void populate_expected()
+ {
+ merge_target="cat/one";
+ }
+
+ void check_lists()
+ {
+ TEST_CHECK(true);
+ DepList d(&env);
+ TEST_CHECK_THROWS(d.add(DepParser::parse(merge_target)), DepListError);
+ TEST_CHECK(d.begin() == d.end());
+ }
+ } test_dep_list_52;
+
+ /**
* \test Test DepList transactional add behaviour.
*
* \ingroup Test
diff --git a/paludis/match_package.cc b/paludis/match_package.cc
index dfa61b3..a18dd87 100644
--- a/paludis/match_package.cc
+++ b/paludis/match_package.cc
@@ -45,11 +45,37 @@ match_package_internals::do_match(
if (*atom->repository_ptr() != entry->get<pde_repository>())
return false;
- if (atom->slot_ptr())
+ if (atom->slot_ptr() || atom->use_requirements_ptr())
{
VersionMetadata::ConstPointer metadata(env->package_database()->fetch_metadata(*entry));
- if (*atom->slot_ptr() != SlotName(metadata->get(vmk_slot)))
- return false;
+
+ if (atom->slot_ptr())
+ if (*atom->slot_ptr() != SlotName(metadata->get(vmk_slot)))
+ return false;
+
+ if (atom->use_requirements_ptr())
+ {
+ for (UseRequirements::Iterator u(atom->use_requirements_ptr()->begin()),
+ u_end(atom->use_requirements_ptr()->end()) ; u != u_end ; ++u)
+ {
+ switch (u->second)
+ {
+ case use_unspecified:
+ continue;
+
+ case use_enabled:
+ if (! env->query_use(u->first, entry))
+ return false;
+ continue;
+
+ case use_disabled:
+ if (env->query_use(u->first, entry))
+ return false;
+ continue;
+ }
+ throw InternalError(PALUDIS_HERE, "bad UseFlagState");
+ }
+ }
}
return true;
@@ -57,7 +83,7 @@ match_package_internals::do_match(
bool
match_package_internals::do_match(
- const Environment * const,
+ const Environment * const env,
const PackageDepAtom * const atom,
const DepListEntry * const entry)
{
@@ -75,6 +101,33 @@ match_package_internals::do_match(
if (atom->slot_ptr() && (atom->slot_ptr()->data() != entry->get<dle_metadata>()->get(vmk_slot)))
return false;
+ if (atom->use_requirements_ptr())
+ {
+ PackageDatabaseEntry e(entry->get<dle_name>(), entry->get<dle_version>(),
+ entry->get<dle_repository>());
+
+ for (UseRequirements::Iterator u(atom->use_requirements_ptr()->begin()),
+ u_end(atom->use_requirements_ptr()->end()) ; u != u_end ; ++u)
+ {
+ switch (u->second)
+ {
+ case use_unspecified:
+ continue;
+
+ case use_enabled:
+ if (! env->query_use(u->first, &e))
+ return false;
+ continue;
+
+ case use_disabled:
+ if (env->query_use(u->first, &e))
+ return false;
+ continue;
+ }
+ throw InternalError(PALUDIS_HERE, "bad UseFlagState");
+ }
+ }
+
return true;
}
diff --git a/paludis/portage_repository.cc b/paludis/portage_repository.cc
index 5d7790a..6b5d29b 100644
--- a/paludis/portage_repository.cc
+++ b/paludis/portage_repository.cc
@@ -30,16 +30,17 @@
#include <paludis/package_database.hh>
#include <paludis/portage_repository.hh>
#include <paludis/syncer.hh>
-#include <paludis/util/iterator.hh>
#include <paludis/util/dir_iterator.hh>
#include <paludis/util/fs_entry.hh>
-#include <paludis/util/system.hh>
#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/iterator.hh>
#include <paludis/util/log.hh>
#include <paludis/util/pstream.hh>
#include <paludis/util/random.hh>
+#include <paludis/util/save.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
#include <paludis/util/tokeniser.hh>
#include <map>
@@ -909,7 +910,7 @@ PortageRepository::do_query_profile_masks(const CategoryNamePart &,
}
UseFlagState
-PortageRepository::do_query_use(const UseFlagName & f, const PackageDatabaseEntry *e) const
+PortageRepository::do_query_use(const UseFlagName & f, const PackageDatabaseEntry * e) const
{
if (! _imp->has_profile)
{
@@ -919,6 +920,7 @@ PortageRepository::do_query_use(const UseFlagName & f, const PackageDatabaseEntr
}
UseMap::iterator p(_imp->use.end());
+
if (query_use_mask(f, e))
return use_disabled;
else if (_imp->use.end() == ((p = _imp->use.find(f))))
@@ -950,8 +952,20 @@ PortageRepository::do_query_use_mask(const UseFlagName & u, const PackageDatabas
for (std::list<std::pair<PackageDepAtom::ConstPointer, UseFlagName> >::iterator i = it->second.begin(),
i_end = it->second.end(); i != i_end; ++i)
{
- if (match_package(_imp->env, i->first, e) && u == i->second)
- return true;
+ static bool recursive(false);
+ if (recursive)
+ {
+ if (i->first->use_requirements_ptr())
+ continue;
+ if (match_package(_imp->env, i->first, e) && u == i->second)
+ return true;
+ }
+ else
+ {
+ Save<bool> save_recursive(&recursive, true);
+ if (match_package(_imp->env, i->first, e) && u == i->second)
+ return true;
+ }
}
return false;