aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-06-18 15:50:19 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-06-18 15:50:19 +0100
commit797685710b6f60cb299b72036cfc3bcd8a13eafb (patch)
treea2e7214ea3d906daa19d32a3f64814e07ae01caf
parentd2281be210f759c8d07ffa2704b2ed158fe6d71d (diff)
downloadpaludis-797685710b6f60cb299b72036cfc3bcd8a13eafb.tar.gz
paludis-797685710b6f60cb299b72036cfc3bcd8a13eafb.tar.xz
Handle self-deps properly
Fixes: ticket:865
-rw-r--r--paludis/resolver/orderer.cc49
-rw-r--r--paludis/resolver/orderer.hh5
-rw-r--r--paludis/resolver/resolver_TEST_blockers.cc99
-rwxr-xr-xpaludis/resolver/resolver_TEST_blockers_setup.sh46
-rw-r--r--paludis/resolver/resolver_TEST_cycles.cc77
-rwxr-xr-xpaludis/resolver/resolver_TEST_cycles_setup.sh23
6 files changed, 296 insertions, 3 deletions
diff --git a/paludis/resolver/orderer.cc b/paludis/resolver/orderer.cc
index 7b4f20b..54e8976 100644
--- a/paludis/resolver/orderer.cc
+++ b/paludis/resolver/orderer.cc
@@ -395,7 +395,7 @@ Orderer::resolve()
{
/* there's only one real package in the component, so there's no
* need to try anything clever */
- _schedule(*changes_in_scc.begin(),
+ _check_self_deps_and_schedule(*changes_in_scc.begin(),
_imp->change_or_remove_resolvents.find(*changes_in_scc.begin())->second,
make_shared_copy(make_named_values<OrdererNotes>(
n::cycle_breaking() = ""
@@ -450,7 +450,7 @@ Orderer::_order_sub_ssccs(
if (sub_scc->nodes()->size() == 1)
{
/* yay. it's all on its own. */
- _schedule(*sub_scc->nodes()->begin(),
+ _check_self_deps_and_schedule(*sub_scc->nodes()->begin(),
_imp->change_or_remove_resolvents.find(*sub_scc->nodes()->begin())->second,
make_shared_copy(make_named_values<OrdererNotes>(
n::cycle_breaking() = (can_recurse ?
@@ -465,7 +465,7 @@ Orderer::_order_sub_ssccs(
* dependency cycles which we can order however we like! */
for (Set<Resolvent>::ConstIterator r(sub_scc->nodes()->begin()), r_end(sub_scc->nodes()->end()) ;
r != r_end ; ++r)
- _schedule(*r,
+ _check_self_deps_and_schedule(*r,
_imp->change_or_remove_resolvents.find(*r)->second,
make_shared_copy(make_named_values<OrdererNotes>(
n::cycle_breaking() = "In run dependency cycle with: " + join(
@@ -558,6 +558,49 @@ namespace
}
void
+Orderer::_check_self_deps_and_schedule(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const ChangeOrRemoveDecision> & d,
+ const std::tr1::shared_ptr<OrdererNotes> & n)
+{
+ /* do we dep directly upon ourself? */
+ bool direct_self_dep(false), self_dep_is_met(true), self_dep_is_not_build(true);
+ for (NAG::EdgesFromConstIterator e(_imp->resolved->nag()->begin_edges_from(resolvent)),
+ e_end(_imp->resolved->nag()->end_edges_from(resolvent)) ;
+ e != e_end ; ++e)
+ {
+ if (e->first == resolvent)
+ {
+ direct_self_dep = true;
+ self_dep_is_met = self_dep_is_met && e->second.build_all_met() && e->second.run_all_met();
+ self_dep_is_not_build = self_dep_is_not_build && ! e->second.build();
+ }
+ }
+
+ if (direct_self_dep)
+ {
+ if (! n->cycle_breaking().empty())
+ n->cycle_breaking().append("; ");
+
+ if (self_dep_is_met)
+ n->cycle_breaking().append("Self dependent (already met)");
+ else if (self_dep_is_not_build)
+ n->cycle_breaking().append("Self dependent (runtime only)");
+ else
+ n->cycle_breaking().append("Self dependent (unsolvable)");
+ }
+
+ if (direct_self_dep && ! self_dep_is_met && ! self_dep_is_not_build)
+ {
+ _imp->resolved->taken_unorderable_decisions()->push_back(
+ _imp->change_or_remove_resolvents.find(resolvent)->second,
+ n);
+ }
+ else
+ _schedule(resolvent, d, n);
+}
+
+void
Orderer::_schedule(
const Resolvent & resolvent,
const std::tr1::shared_ptr<const ChangeOrRemoveDecision> & d,
diff --git a/paludis/resolver/orderer.hh b/paludis/resolver/orderer.hh
index 8edc785..e524244 100644
--- a/paludis/resolver/orderer.hh
+++ b/paludis/resolver/orderer.hh
@@ -38,6 +38,11 @@ namespace paludis
private PrivateImplementationPattern<Orderer>
{
private:
+ void _check_self_deps_and_schedule(
+ const Resolvent &,
+ const std::tr1::shared_ptr<const ChangeOrRemoveDecision> &,
+ const std::tr1::shared_ptr<OrdererNotes> &);
+
void _schedule(
const Resolvent &,
const std::tr1::shared_ptr<const ChangeOrRemoveDecision> &,
diff --git a/paludis/resolver/resolver_TEST_blockers.cc b/paludis/resolver/resolver_TEST_blockers.cc
index b64e1fe..f8c3b67 100644
--- a/paludis/resolver/resolver_TEST_blockers.cc
+++ b/paludis/resolver/resolver_TEST_blockers.cc
@@ -313,5 +313,104 @@ namespace test_cases
);
}
} test_hard_block_and_dep_cycle;
+
+ struct SelfBlock : ResolverBlockersTestCase
+ {
+ const int installed_version;
+ const int dep_version;
+ const bool strong;
+ const std::string cat;
+
+ SelfBlock(int i, int d, bool s) :
+ ResolverBlockersTestCase("self block " + stringify(i) + " " + stringify(d) + " " + stringify(s), "0"),
+ installed_version(i),
+ dep_version(d),
+ strong(s),
+ cat(std::string("self-block-") +
+ (-1 == installed_version ? "x" : stringify(installed_version)) + "-" +
+ (-1 == dep_version ? "x" : stringify(dep_version)) + "-" +
+ (strong ? "s" : "w"))
+ {
+ if (installed_version != -1)
+ install(cat, "dep", stringify(installed_version));
+
+ allowed_to_remove_names->insert(QualifiedPackageName(cat + "/dep"));
+ }
+
+ void run()
+ {
+ std::tr1::shared_ptr<const Resolved> resolved(get_resolved(cat + "/target"));
+ std::tr1::shared_ptr<DecisionChecks> checks, u_checks, o_checks;
+
+ if (dep_version != 0)
+ {
+ checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/target"))
+ .finished());
+ u_checks = make_shared_copy(DecisionChecks()
+ .unable(QualifiedPackageName(cat + "/dep"))
+ .finished());
+ o_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ }
+ else if (installed_version == -1)
+ {
+ checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/dep"))
+ .change(QualifiedPackageName(cat + "/target"))
+ .finished());
+ u_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ o_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ }
+ else if (installed_version == 1 || ((! strong) && installed_version == 0))
+ {
+ checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/dep"))
+ .change(QualifiedPackageName(cat + "/target"))
+ .finished());
+ u_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ o_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ }
+ else if (strong && installed_version == 0 && dep_version == 0)
+ {
+ checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/target"))
+ .finished());
+ u_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ o_checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/dep"))
+ .finished());
+ }
+
+ TEST_CHECK(checks);
+ TEST_CHECK(u_checks);
+ TEST_CHECK(o_checks);
+
+ check_resolved(resolved,
+ n::taken_change_or_remove_decisions() = checks,
+ n::taken_unable_to_make_decisions() = u_checks,
+ n::taken_unconfirmed_decisions() = make_shared_copy(DecisionChecks()
+ .finished()),
+ n::taken_unorderable_decisions() = o_checks,
+ n::untaken_change_or_remove_decisions() = make_shared_copy(DecisionChecks()
+ .finished()),
+ n::untaken_unable_to_make_decisions() = make_shared_copy(DecisionChecks()
+ .finished())
+ );
+ }
+ } test_self_block_x_x_w(-1, -1, false), test_self_block_x_x_s(-1, -1, true),
+ test_self_block_0_x_w( 0, -1, false), test_self_block_0_x_s( 0, -1, true),
+ test_self_block_1_x_w( 1, -1, false), test_self_block_1_x_s( 1, -1, true),
+ test_self_block_x_0_w(-1, 0, false), test_self_block_x_0_s(-1, 0, true),
+ test_self_block_0_0_w( 0, 0, false), test_self_block_0_0_s( 0, 0, true),
+ test_self_block_1_0_w( 1, 0, false), test_self_block_1_0_s( 1, 0, true),
+ test_self_block_x_1_w(-1, 1, false), test_self_block_x_1_s(-1, 1, true),
+ test_self_block_0_1_w( 0, 1, false), test_self_block_0_1_s( 0, 1, true),
+ test_self_block_1_1_w( 1, 1, false), test_self_block_1_1_s( 1, 1, true);
}
diff --git a/paludis/resolver/resolver_TEST_blockers_setup.sh b/paludis/resolver/resolver_TEST_blockers_setup.sh
index 1381960..47cd67c 100755
--- a/paludis/resolver/resolver_TEST_blockers_setup.sh
+++ b/paludis/resolver/resolver_TEST_blockers_setup.sh
@@ -156,5 +156,51 @@ DEPEND="
"
END
+# self-block
+for i in "x" "0" "1" ; do
+ for d in "x" "0" "1" ; do
+ for b in "w" "s" ; do
+ cat=self-block-${i}-${d}-${b}
+
+ dep=${cat}/dep
+
+ if [[ "${d}" != "x" ]] ; then
+ dep="=${dep}-${d}"
+ fi
+
+ if [[ "${b}" == "w" ]] ; then
+ dep="!${dep}"
+ else
+ dep="!!${dep}"
+ fi
+
+ echo $cat >> metadata/categories.conf
+
+ mkdir -p 'packages/'$cat'/target'
+ cat <<END > packages/$cat/target/target-1.ebuild
+EAPI="2"
+DESCRIPTION="target"
+KEYWORDS="test"
+SLOT="0"
+DEPEND="
+ ${cat}/dep
+ "
+END
+
+ mkdir -p 'packages/'$cat'/dep'
+ cat <<END > packages/$cat/dep/dep-1.ebuild
+EAPI="2"
+DESCRIPTION="target"
+KEYWORDS="test"
+SLOT="0"
+DEPEND="
+ ${dep}
+ "
+END
+
+ done
+ done
+done
+
cd ..
diff --git a/paludis/resolver/resolver_TEST_cycles.cc b/paludis/resolver/resolver_TEST_cycles.cc
index eeb7383..3383abb 100644
--- a/paludis/resolver/resolver_TEST_cycles.cc
+++ b/paludis/resolver/resolver_TEST_cycles.cc
@@ -271,5 +271,82 @@ namespace test_cases
);
}
} test_triangle_none(false, false), test_triangle_b(true, false), test_triangle_c(false, true);
+
+ struct TestSelf : ResolverCyclesTestCase
+ {
+ const int installed_version;
+ const bool runtime;
+ const std::string cat;
+
+ TestSelf (const int i, const bool r) :
+ ResolverCyclesTestCase("self " + stringify(i) + " " + stringify(r)),
+ installed_version(i),
+ runtime(r),
+ cat(runtime ? "self-run" : "self-build")
+ {
+ if (-1 != installed_version)
+ install(cat, "dep", stringify(installed_version));
+ }
+
+ virtual ResolverFunctions get_resolver_functions(InitialConstraints & initial_constraints)
+ {
+ ResolverFunctions result(ResolverCyclesTestCase::get_resolver_functions(initial_constraints));
+ result.get_use_existing_fn() = std::tr1::bind(&use_existing_if_same, std::tr1::placeholders::_1,
+ std::tr1::placeholders::_2, std::tr1::placeholders::_3);
+ return result;
+ }
+
+ void run()
+ {
+ std::tr1::shared_ptr<const Resolved> resolved(get_resolved(cat + "/target"));
+ std::tr1::shared_ptr<DecisionChecks> checks, u_checks;
+
+ if (runtime || installed_version == 1)
+ {
+ if (installed_version == 1)
+ {
+ checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/target"))
+ .finished());
+ u_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ }
+ else
+ {
+ checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/dep"))
+ .change(QualifiedPackageName(cat + "/target"))
+ .finished());
+ u_checks = make_shared_copy(DecisionChecks()
+ .finished());
+ }
+ }
+ else
+ {
+ checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/target"))
+ .finished());
+ u_checks = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName(cat + "/dep"))
+ .finished());
+ }
+
+ check_resolved(resolved,
+ n::taken_change_or_remove_decisions() = checks,
+ n::taken_unable_to_make_decisions() = make_shared_copy(DecisionChecks()
+ .finished()),
+ n::taken_unconfirmed_decisions() = make_shared_copy(DecisionChecks()
+ .finished()),
+ n::taken_unorderable_decisions() = u_checks,
+ n::untaken_change_or_remove_decisions() = make_shared_copy(DecisionChecks()
+ .finished()),
+ n::untaken_unable_to_make_decisions() = make_shared_copy(DecisionChecks()
+ .finished())
+ );
+ }
+ }
+ test_self_x_b(-1, false), test_self_x_r(-1, true),
+ test_self_0_b( 0, false), test_self_0_r( 0, true),
+ test_self_1_b( 1, false), test_self_1_r( 1, true);
}
diff --git a/paludis/resolver/resolver_TEST_cycles_setup.sh b/paludis/resolver/resolver_TEST_cycles_setup.sh
index a3ca2b3..dec11a5 100755
--- a/paludis/resolver/resolver_TEST_cycles_setup.sh
+++ b/paludis/resolver/resolver_TEST_cycles_setup.sh
@@ -165,5 +165,28 @@ SLOT="0"
DEPENDENCIES="run: triangle/dep-b"
END
+# self
+for r in "build" "run" ; do
+ cat=self-${r}
+ echo $cat >> metadata/categories.conf
+
+ mkdir -p 'packages/'$cat'/target'
+ cat <<END > packages/$cat/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="${cat}/dep"
+END
+
+ mkdir -p 'packages/'$cat'/dep'
+ cat <<END > packages/$cat/dep/dep-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="${r}: ${cat}/dep[=1]"
+END
+
+ done
+
cd ..