aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-01-26 19:50:46 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-01-26 19:50:46 +0000
commit8b2c25001c61cfca1239cdc4c3c61e11a6e0eb97 (patch)
tree10805cd68a23a76dee4d8e2656ed23cd94d5dae9
parent371b8e8426b88be82f043bfa047a80814b901295 (diff)
downloadpaludis-8b2c25001c61cfca1239cdc4c3c61e11a6e0eb97.tar.gz
paludis-8b2c25001c61cfca1239cdc4c3c61e11a6e0eb97.tar.xz
Handle blocks on virtuals correctly. Fixes: ticket:53.
-rw-r--r--paludis/dep_list/dep_list.cc178
-rw-r--r--paludis/dep_list/dep_list.hh19
-rw-r--r--paludis/dep_list/dep_list_TEST.hh5
-rw-r--r--paludis/dep_list/dep_list_TEST_blockers.cc28
-rw-r--r--ruby/dep_list.cc2
5 files changed, 164 insertions, 68 deletions
diff --git a/paludis/dep_list/dep_list.cc b/paludis/dep_list/dep_list.cc
index bee6159..7f13288 100644
--- a/paludis/dep_list/dep_list.cc
+++ b/paludis/dep_list/dep_list.cc
@@ -290,12 +290,10 @@ struct DepList::QueryVisitor :
{
bool result;
const DepList * const d;
- bool ignore_current_pde;
- QueryVisitor(const DepList * const dd, const bool i) :
+ QueryVisitor(const DepList * const dd) :
result(true),
- d(dd),
- ignore_current_pde(i)
+ d(dd)
{
}
@@ -332,7 +330,6 @@ DepList::QueryVisitor::visit(const PackageDepAtom * const a)
VersionMetadata::ConstPointer vm(d->_imp->env->package_database()->fetch_repository(m->repository)->
version_metadata(m->name, m->version));
SlotName slot(vm->slot);
- const VirtualMetadata * const vif(vm->get_virtual_interface());
std::pair<MergeListIndex::const_iterator, MergeListIndex::const_iterator> p(
d->_imp->merge_list_index.equal_range(a->package()));
@@ -344,15 +341,6 @@ DepList::QueryVisitor::visit(const PackageDepAtom * const a)
{
if (p.first->second->metadata->slot != slot)
p.first = next(p.first);
- else if (ignore_current_pde &&
- p.first->second == d->_imp->current_merge_list_entry)
- p.first = next(p.first);
- else if (ignore_current_pde &&
- d->_imp->current_merge_list_entry != d->_imp->merge_list.end() &&
- p.first->second->associated_entry == &*d->_imp->current_merge_list_entry &&
- (a->version_requirements_ptr() || a->slot_ptr() ||
- (vif && vif->virtual_for.name != p.first->second->associated_entry->package.name)))
- p.first = next(p.first);
else
{
replaced = true;
@@ -371,19 +359,11 @@ DepList::QueryVisitor::visit(const PackageDepAtom * const a)
std::pair<MergeListIndex::const_iterator, MergeListIndex::const_iterator> p(
d->_imp->merge_list_index.equal_range(a->package()));
- while (p.second != ((p.first = std::find_if(p.first, p.second,
- MatchDepListEntryAgainstPackageDepAtom(d->_imp->env, a)))))
+ if (p.second != std::find_if(p.first, p.second,
+ MatchDepListEntryAgainstPackageDepAtom(d->_imp->env, a)))
{
- if (ignore_current_pde && p.first->second == d->_imp->current_merge_list_entry)
- p.first = next(p.first);
- else if (ignore_current_pde && d->_imp->current_merge_list_entry != d->_imp->merge_list.end()
- && p.first->second->associated_entry == &*d->_imp->current_merge_list_entry)
- p.first = next(p.first);
- else
- {
- result = true;
- return;
- }
+ result = true;
+ return;
}
}
@@ -785,7 +765,7 @@ DepList::AddVisitor::visit(const AnyDepAtom * const a)
for (std::list<DepAtom::ConstPointer>::const_iterator c(viable_children.begin()),
c_end(viable_children.end()) ; c != c_end ; ++c)
{
- if (d->already_installed(*c))
+ if (d->already_installed(**c))
{
d->add(*c);
return;
@@ -837,53 +817,119 @@ DepList::AddVisitor::visit(const AnyDepAtom * const a)
}
}
+#include <iostream>
+
void
DepList::AddVisitor::visit(const BlockDepAtom * const a)
{
- /* special case: the provider of virtual/blah can DEPEND upon !virtual/blah. */
- /* special case: foo/bar can DEPEND upon !foo/bar. */
+ Context context("When checking BlockDepAtom '!" + stringify(*a->blocked_atom()) + "':");
- if (d->_imp->current_merge_list_entry != d->_imp->merge_list.end())
- if (d->_imp->current_merge_list_entry->kind == dlk_already_installed)
- return;
+ PackageDepAtom just_package(a->blocked_atom()->package());
+ PackageDatabaseEntryCollection::ConstPointer already_installed(d->_imp->env->package_database()->query(
+ just_package, is_installed_only, qo_whatever));
- if (! d->already_installed(a->blocked_atom(), true))
- return;
+ std::list<MergeList::const_iterator> will_be_installed;
+ MatchDepListEntryAgainstPackageDepAtom m(d->_imp->env, &just_package);
+ for (std::pair<MergeListIndex::const_iterator, MergeListIndex::const_iterator> p(
+ d->_imp->merge_list_index.equal_range(a->blocked_atom()->package())) ;
+ p.first != p.second ; ++p.first)
+ {
+ if (d->_imp->current_merge_list_entry != d->_imp->merge_list.end())
+ {
+ if (d->_imp->current_merge_list_entry == p.first->second)
+ continue;
- Context context("When checking BlockDepAtom '!" + stringify(*a->blocked_atom()) + "':");
+ if (d->_imp->current_merge_list_entry->associated_entry == &*p.first->second)
+ continue;
+ }
+
+ if (m(*p.first))
+ will_be_installed.push_back(p.first->second);
+ }
+
+ if (already_installed->empty() && will_be_installed.empty())
+ return;
- switch (d->_imp->opts->blocks)
+ for (PackageDatabaseEntryCollection::Iterator aa(already_installed->begin()),
+ aa_end(already_installed->end()) ; aa != aa_end ; ++aa)
{
- case dl_blocks_error:
- throw BlockError(stringify(*a->blocked_atom()));
+ if (! match_package(d->_imp->env, *a->blocked_atom(), *aa))
+ continue;
- case dl_blocks_accumulate:
- if (d->_imp->throw_on_blocker)
- throw BlockError(stringify(*a->blocked_atom()));
- else
+ VersionMetadata::ConstPointer metadata(d->_imp->env->package_database()->fetch_repository(
+ aa->repository)->version_metadata(aa->name, aa->version));
+ bool replaced(false);
+ for (std::list<MergeList::const_iterator>::const_iterator r(will_be_installed.begin()),
+ r_end(will_be_installed.end()) ; r != r_end && ! replaced ; ++r)
+ if ((*r)->metadata->slot == metadata->slot)
{
- PackageDatabaseEntryCollection::ConstPointer m(d->_imp->env->package_database()->query(
- *a->blocked_atom(), is_installed_only, qo_order_by_version));
- if (m->empty())
+ /* if it's a virtual, it only replaces if it's the same package. */
+ if ((*r)->metadata->get_virtual_interface())
{
- /* this happens if we match an already on the list package, so always
- * throw */
- throw BlockError(stringify(*a->blocked_atom()));
+ if ((*r)->metadata->get_virtual_interface()->virtual_for.name == aa->name)
+ replaced = true;
}
else
- for (PackageDatabaseEntryCollection::Iterator p(m->begin()), p_end(m->end()) ;
- p != p_end ; ++p)
- d->add_error_package(*p, dlk_block);
+ replaced = true;
}
- break;
- case dl_blocks_discard:
- Log::get_instance()->message(ll_warning, lc_context, "Discarding block '!"
- + stringify(*a->blocked_atom()) + "'");
- break;
+ if (replaced)
+ continue;
- case last_dl_blocks:
- ;
+ /* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking
+ * ourself */
+ if (! (a->blocked_atom()->version_requirements_ptr() || a->blocked_atom()->slot_ptr()
+ || a->blocked_atom()->use_requirements_ptr() || a->blocked_atom()->repository_ptr())
+ && d->_imp->current_pde())
+ {
+ if (aa->name == d->_imp->current_pde()->name)
+ continue;
+
+ if (metadata->get_virtual_interface() &&
+ metadata->get_virtual_interface()->virtual_for.name == d->_imp->current_pde()->name)
+ continue;
+ }
+
+ switch (d->_imp->throw_on_blocker ? dl_blocks_error : d->_imp->opts->blocks)
+ {
+ case dl_blocks_error:
+ throw BlockError(stringify(*a->blocked_atom()));
+
+ case dl_blocks_discard:
+ Log::get_instance()->message(ll_warning, lc_context, "Discarding block '!"
+ + stringify(*a->blocked_atom()) + "'");
+ break;
+
+ case dl_blocks_accumulate:
+ d->add_error_package(*aa, dlk_block);
+ break;
+
+ case last_dl_blocks:
+ break;
+ }
+ }
+
+ for (std::list<MergeList::const_iterator>::const_iterator r(will_be_installed.begin()),
+ r_end(will_be_installed.end()) ; r != r_end ; ++r)
+ {
+ if (! match_package(d->_imp->env, *a->blocked_atom(), (*r)->package))
+ continue;
+
+ /* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking
+ * ourself */
+ if (! (a->blocked_atom()->version_requirements_ptr() || a->blocked_atom()->slot_ptr()
+ || a->blocked_atom()->use_requirements_ptr() || a->blocked_atom()->repository_ptr())
+ && d->_imp->current_pde())
+ {
+ if ((*r)->package.name == d->_imp->current_pde()->name)
+ continue;
+
+ if ((*r)->metadata->get_virtual_interface() &&
+ (*r)->metadata->get_virtual_interface()->virtual_for.name == d->_imp->current_pde()->name)
+ continue;
+ }
+
+ throw BlockError(stringify(*a->blocked_atom()));
}
}
@@ -1413,16 +1459,22 @@ DepList::prefer_installed_over_uninstalled(const PackageDatabaseEntry & installe
}
bool
-DepList::already_installed(DepAtom::ConstPointer atom, const bool ignore_current_pde) const
+DepList::already_installed(DepAtom::ConstPointer atom, const bool) const
{
- return already_installed(atom.raw_pointer(), ignore_current_pde);
+ return already_installed(*atom.raw_pointer());
}
bool
-DepList::already_installed(const DepAtom * const atom, const bool ignore_current_pde) const
+DepList::already_installed(const DepAtom * const atom, const bool) const
{
- QueryVisitor visitor(this, ignore_current_pde);
- atom->accept(&visitor);
+ return already_installed(*atom);
+}
+
+bool
+DepList::already_installed(const DepAtom & atom) const
+{
+ QueryVisitor visitor(this);
+ atom.accept(&visitor);
return visitor.result;
}
diff --git a/paludis/dep_list/dep_list.hh b/paludis/dep_list/dep_list.hh
index 7a29c86..59f03c7 100644
--- a/paludis/dep_list/dep_list.hh
+++ b/paludis/dep_list/dep_list.hh
@@ -99,14 +99,25 @@ namespace paludis
void clear();
/**
- * Is an atom structure already installed?
+ * Return whether an atom structure already installed.
+ *
+ * \deprecated Use the one arg form.
*/
- bool already_installed(DepAtom::ConstPointer, const bool ignore_current_pde = false) const;
+ bool already_installed(DepAtom::ConstPointer, const bool dummy) const
+ PALUDIS_ATTRIBUTE((deprecated));
/**
- * Is an atom structure already installed (overloaded for raw pointer)?
+ * Return whether an atom structure already installed (overloaded for raw pointer).
+ *
+ * \deprecated Use the one arg form.
*/
- bool already_installed(const DepAtom * const, const bool ignore_current_pde = false) const;
+ bool already_installed(const DepAtom * const, const bool dummy) const
+ PALUDIS_ATTRIBUTE((deprecated));
+
+ /**
+ * Return whether an atom structure already installed.
+ */
+ bool already_installed(const DepAtom &) const;
/**
* Whether we have any errors.
diff --git a/paludis/dep_list/dep_list_TEST.hh b/paludis/dep_list/dep_list_TEST.hh
index 07ef067..dd10f65 100644
--- a/paludis/dep_list/dep_list_TEST.hh
+++ b/paludis/dep_list/dep_list_TEST.hh
@@ -119,12 +119,17 @@ namespace test_cases
*/
virtual void populate_expected() = 0;
+ virtual void set_options(DepListOptions &)
+ {
+ }
+
/**
* Check expected is what we got.
*/
virtual void check_lists()
{
DepList d(&env, DepListOptions());
+ set_options(*d.options());
d.add(PortageDepParser::parse(merge_target));
TEST_CHECK(true);
diff --git a/paludis/dep_list/dep_list_TEST_blockers.cc b/paludis/dep_list/dep_list_TEST_blockers.cc
index a315452..fba8534 100644
--- a/paludis/dep_list/dep_list_TEST_blockers.cc
+++ b/paludis/dep_list/dep_list_TEST_blockers.cc
@@ -225,6 +225,34 @@ namespace test_cases
}
} test_dep_list_no_block_on_no_upgrade_via_provided;
+ struct DepListTestCaseNoBlockOnNoReinstallViaProvided : DepListTestCaseBase
+ {
+ DepListTestCaseNoBlockOnNoReinstallViaProvided() : DepListTestCaseBase("no block on no reinstall via provided") { }
+
+ void populate_repo()
+ {
+ VersionMetadata::Pointer one_m(repo->add_version("cat", "one", "1"));
+ one_m->get_ebuild_interface()->provide_string = "virtual/one";
+ one_m->deps.build_depend_string = "!virtual/one";
+ one_m->deps.run_depend_string = "!virtual/one";
+ VersionMetadata::Pointer i_one_m(installed_repo->add_version("cat", "one", "1"));
+ i_one_m->get_ebuild_interface()->provide_string = "virtual/one";
+ i_one_m->deps.run_depend_string = "!virtual/one";
+ }
+
+ void populate_expected()
+ {
+ merge_target = "virtual/one";
+ expected.push_back("cat/one-1:0::repo");
+ expected.push_back("virtual/one-1:0::virtuals");
+ }
+
+ virtual void set_options(DepListOptions & p)
+ {
+ p.reinstall = dl_reinstall_always;
+ }
+ } test_dep_list_no_block_on_no_reinstall_via_provided;
+
struct DepListTestCaseNoBlockOnReplacedProvide : DepListTestCaseBase
{
DepListTestCaseNoBlockOnReplacedProvide() : DepListTestCaseBase("no block on replaced provide") { }
diff --git a/ruby/dep_list.cc b/ruby/dep_list.cc
index 0463dd6..aa0e150 100644
--- a/ruby/dep_list.cc
+++ b/ruby/dep_list.cc
@@ -885,7 +885,7 @@ namespace
{
DepList * p;
Data_Get_Struct(self, DepList, p);
- return p->already_installed(value_to_dep_atom(da)) ? Qtrue : Qfalse;
+ return p->already_installed(*value_to_dep_atom(da)) ? Qtrue : Qfalse;
}
/*