aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-02-19 17:00:50 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-02-19 17:00:50 +0000
commitf40a4273d3a6001148eea6d053923e8af753038a (patch)
tree69e5735b0a3bac03ac6ffbf82a3c0c41d58763ae
parent7e1c6abfa30aab20915696e4a9f44b23d5d97c28 (diff)
downloadpaludis-f40a4273d3a6001148eea6d053923e8af753038a.tar.gz
paludis-f40a4273d3a6001148eea6d053923e8af753038a.tar.xz
Move up/downgrade detection to Decider
-rw-r--r--paludis/resolver/Makefile.am11
-rw-r--r--paludis/resolver/change_type-fwd.hh36
-rw-r--r--paludis/resolver/change_type.cc30
-rw-r--r--paludis/resolver/change_type.hh33
-rw-r--r--paludis/resolver/change_type.se17
-rw-r--r--paludis/resolver/decider.cc62
-rw-r--r--paludis/resolver/decider.hh6
-rw-r--r--paludis/resolver/decision.cc20
-rw-r--r--paludis/resolver/decision.hh6
-rw-r--r--src/clients/cave/cmd_display_resolution.cc65
10 files changed, 239 insertions, 47 deletions
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index f479e56..5eeb9cf 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -2,6 +2,7 @@ include $(top_srcdir)/misc/common-makefile.am
DISTCLEANFILES = \
any_child_score-se.hh any_child_score-se.cc \
+ change_type-se.hh change_type-se.cc \
destination_types-se.hh destination_types-se.cc \
failure_kinds-se.hh failure_kinds-se.cc \
sync_point-se.hh sync_point-se.cc \
@@ -9,6 +10,7 @@ DISTCLEANFILES = \
AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
EXTRA_DIST = \
any_child_score-se.hh any_child_score-se.cc any_child_score.se \
+ change_type-se.hh change_type-se.cc change_type.se \
destination_types-se.hh destination_types-se.cc destination_types.se \
failure_kinds-se.hh failure_kinds-se.cc failure_kinds.se \
sync_point-se.hh sync_point-se.cc sync_point.se \
@@ -16,6 +18,7 @@ EXTRA_DIST = \
$(check_SCRIPTS)
BUILT_SOURCES = \
any_child_score-se.hh any_child_score-se.cc \
+ change_type-se.hh change_type-se.cc \
destination_types-se.hh destination_types-se.cc \
failure_kinds-se.hh failure_kinds-se.cc \
sync_point-se.hh sync_point-se.cc \
@@ -24,6 +27,7 @@ BUILT_SOURCES = \
noinst_HEADERS = \
any_child_score.hh any_child_score-fwd.hh any_child_score-se.hh \
arrow.hh arrow-fwd.hh \
+ change_type.hh change_type-fwd.hh change_type-se.hh \
constraint.hh constraint-fwd.hh \
job.hh job-fwd.hh \
job_id.hh job_id-fwd.hh \
@@ -52,6 +56,7 @@ noinst_HEADERS = \
libpaludisresolver_a_SOURCES = \
any_child_score.cc \
arrow.cc \
+ change_type.cc \
constraint.cc \
decider.cc \
decision.cc \
@@ -230,3 +235,9 @@ any_child_score-se.hh : any_child_score.se $(top_srcdir)/misc/make_se.bash
any_child_score-se.cc : any_child_score.se $(top_srcdir)/misc/make_se.bash
if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/any_child_score.se > $@ ; then rm -f $@ ; exit 1 ; fi
+change_type-se.hh : change_type.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/change_type.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+change_type-se.cc : change_type.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/change_type.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
diff --git a/paludis/resolver/change_type-fwd.hh b/paludis/resolver/change_type-fwd.hh
new file mode 100644
index 0000000..935dec4
--- /dev/null
+++ b/paludis/resolver/change_type-fwd.hh
@@ -0,0 +1,36 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 Ciaran McCreesh
+ *
+ * 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_RESOLVER_CHANGE_TYPE_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_CHANGE_TYPE_FWD_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <iosfwd>
+
+namespace paludis
+{
+ namespace resolver
+ {
+
+#include <paludis/resolver/change_type-se.hh>
+
+ }
+}
+
+#endif
diff --git a/paludis/resolver/change_type.cc b/paludis/resolver/change_type.cc
new file mode 100644
index 0000000..4c18804
--- /dev/null
+++ b/paludis/resolver/change_type.cc
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 Ciaran McCreesh
+ *
+ * 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 <paludis/resolver/change_type.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/exception.hh>
+#include <istream>
+#include <ostream>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+#include <paludis/resolver/change_type-se.cc>
+
diff --git a/paludis/resolver/change_type.hh b/paludis/resolver/change_type.hh
new file mode 100644
index 0000000..53be739
--- /dev/null
+++ b/paludis/resolver/change_type.hh
@@ -0,0 +1,33 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 Ciaran McCreesh
+ *
+ * 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_RESOLVER_CHANGE_TYPE_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_CHANGE_TYPE_HH 1
+
+#include <paludis/resolver/change_type-fwd.hh>
+
+namespace paludis
+{
+ namespace resolver
+ {
+
+ }
+}
+
+#endif
diff --git a/paludis/resolver/change_type.se b/paludis/resolver/change_type.se
new file mode 100644
index 0000000..3648b24
--- /dev/null
+++ b/paludis/resolver/change_type.se
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_ChangeType()
+{
+ prefix ct
+ namespace paludis::resolver
+
+ key ct_downgrade "It's a downgrade"
+ key ct_reinstall "It's a reinstall"
+ key ct_upgrade "It's an upgrade"
+ key ct_slot_new "It's a new slot, but other slots are installed"
+ key ct_new "It's new"
+
+ want_destringify
+}
+
diff --git a/paludis/resolver/decider.cc b/paludis/resolver/decider.cc
index fc22335..f42cd94 100644
--- a/paludis/resolver/decider.cc
+++ b/paludis/resolver/decider.cc
@@ -152,11 +152,15 @@ namespace
{
typedef std::tr1::function<const std::tr1::shared_ptr<const Destination> (
const ChangesToMakeDecision &)> MakeDestinationFunc;
+ typedef std::tr1::function<ChangeType (
+ const ChangesToMakeDecision &)> MakeChangeTypeForFunc;
MakeDestinationFunc make_destination_for;
+ MakeChangeTypeForFunc make_change_type_for;
- DoDestinationIfNecessaryVisitor(const MakeDestinationFunc & f) :
- make_destination_for(f)
+ DoDestinationIfNecessaryVisitor(const MakeDestinationFunc & f, const MakeChangeTypeForFunc & c) :
+ make_destination_for(f),
+ make_change_type_for(c)
{
}
@@ -179,7 +183,10 @@ namespace
void visit(ChangesToMakeDecision & decision)
{
if (! decision.destination())
+ {
decision.set_destination(make_destination_for(decision));
+ decision.set_change_type(make_change_type_for(decision));
+ }
}
};
}
@@ -189,8 +196,10 @@ Decider::_do_destination_if_necessary(
const Resolvent & resolvent,
const std::tr1::shared_ptr<Resolution> & resolution)
{
- DoDestinationIfNecessaryVisitor v(std::tr1::bind(&Decider::_make_destination_for,
- this, resolvent, resolution, std::tr1::placeholders::_1));
+ DoDestinationIfNecessaryVisitor v(
+ std::tr1::bind(&Decider::_make_destination_for, this, resolvent, resolution, std::tr1::placeholders::_1),
+ std::tr1::bind(&Decider::_make_change_type_for, this, resolvent, resolution, std::tr1::placeholders::_1)
+ );
resolution->decision()->accept(v);
}
@@ -212,6 +221,44 @@ Decider::_make_destination_for(
)));
}
+const ChangeType
+Decider::_make_change_type_for(
+ const Resolvent &,
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision & decision) const
+{
+ if (decision.destination()->replacing()->empty())
+ {
+ const std::tr1::shared_ptr<const PackageIDSequence> others((*_imp->env)[selection::SomeArbitraryVersion(
+ generator::Package(decision.origin_id()->name()) &
+ generator::InRepository(decision.destination()->repository())
+ )]);
+ if (others->empty())
+ return ct_new;
+ else
+ return ct_slot_new;
+ }
+ else
+ {
+ /* we pick the worst, so replacing 1 and 3 with 2 requires permission to
+ * downgrade */
+ ChangeType result(last_ct);
+ for (PackageIDSequence::ConstIterator i(decision.destination()->replacing()->begin()),
+ i_end(decision.destination()->replacing()->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->version() == decision.origin_id()->version())
+ result = std::min(result, ct_reinstall);
+ else if ((*i)->version() < decision.origin_id()->version())
+ result = std::min(result, ct_upgrade);
+ else if ((*i)->version() > decision.origin_id()->version())
+ result = std::min(result, ct_downgrade);
+ }
+
+ return result;
+ }
+}
+
const std::tr1::shared_ptr<const Repository>
Decider::_find_repository_for(const Resolvent & resolvent,
const std::tr1::shared_ptr<const Resolution> & resolution,
@@ -1088,10 +1135,12 @@ Decider::_try_to_find_decision_for(
}
else if (installable_id && ! existing_id)
{
- /* there's nothing suitable existing. */
+ /* there's nothing suitable existing. we fix the last_ct when we do
+ * destinations. */
return make_shared_ptr(new ChangesToMakeDecision(
installable_id,
best,
+ last_ct,
! resolution->constraints()->all_untaken(),
make_null_shared_ptr()
));
@@ -1209,6 +1258,7 @@ Decider::_try_to_find_decision_for(
const std::tr1::shared_ptr<Decision> changes_to_make(new ChangesToMakeDecision(
installable_id,
best,
+ last_ct,
! resolution->constraints()->all_untaken(),
make_null_shared_ptr()
));
@@ -1220,6 +1270,7 @@ Decider::_try_to_find_decision_for(
return make_shared_ptr(new ChangesToMakeDecision(
installable_id,
best,
+ last_ct,
! resolution->constraints()->all_untaken(),
make_null_shared_ptr()
));
@@ -1396,6 +1447,7 @@ Decider::_get_unmatching_constraints(
decision.reset(new ChangesToMakeDecision(
id,
false,
+ last_ct,
! (*c)->untaken(),
make_null_shared_ptr()
));
diff --git a/paludis/resolver/decider.hh b/paludis/resolver/decider.hh
index 1466b84..872b293 100644
--- a/paludis/resolver/decider.hh
+++ b/paludis/resolver/decider.hh
@@ -35,6 +35,7 @@
#include <paludis/resolver/resolver_functions-fwd.hh>
#include <paludis/resolver/resolver-fwd.hh>
#include <paludis/resolver/any_child_score-fwd.hh>
+#include <paludis/resolver/change_type-fwd.hh>
#include <paludis/util/attributes.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/dep_spec-fwd.hh>
@@ -129,6 +130,11 @@ namespace paludis
const std::tr1::shared_ptr<const Resolution> & resolution,
const ChangesToMakeDecision &) const;
+ const ChangeType _make_change_type_for(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const ChangesToMakeDecision &) const;
+
FilteredGenerator _make_destination_filtered_generator(const Generator &, const Resolvent & resolvent) const;
void _decide(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution);
diff --git a/paludis/resolver/decision.cc b/paludis/resolver/decision.cc
index 0188ce2..f2b001d 100644
--- a/paludis/resolver/decision.cc
+++ b/paludis/resolver/decision.cc
@@ -83,6 +83,7 @@ ChangesToMakeDecision::deserialise(Deserialisation & d)
return make_shared_ptr(new ChangesToMakeDecision(
v.member<std::tr1::shared_ptr<const PackageID> >("origin_id"),
v.member<bool>("best"),
+ destringify<ChangeType>(v.member<std::string>("change_type")),
v.member<bool>("taken"),
v.member<std::tr1::shared_ptr<const Destination> >("destination")
));
@@ -248,16 +249,19 @@ namespace paludis
{
const std::tr1::shared_ptr<const PackageID> origin_id;
const bool best;
+ ChangeType change_type;
const bool taken;
std::tr1::shared_ptr<const Destination> destination;
Implementation(
const std::tr1::shared_ptr<const PackageID> & o,
const bool b,
+ const ChangeType c,
const bool t,
const std::tr1::shared_ptr<const Destination> & d) :
origin_id(o),
best(b),
+ change_type(c),
taken(t),
destination(d)
{
@@ -268,9 +272,10 @@ namespace paludis
ChangesToMakeDecision::ChangesToMakeDecision(
const std::tr1::shared_ptr<const PackageID> & o,
const bool b,
+ const ChangeType c,
const bool t,
const std::tr1::shared_ptr<const Destination> & d) :
- PrivateImplementationPattern<ChangesToMakeDecision>(new Implementation<ChangesToMakeDecision>(o, b, t, d))
+ PrivateImplementationPattern<ChangesToMakeDecision>(new Implementation<ChangesToMakeDecision>(o, b, c, t, d))
{
}
@@ -300,6 +305,18 @@ ChangesToMakeDecision::origin_id() const
return _imp->origin_id;
}
+ChangeType
+ChangesToMakeDecision::change_type() const
+{
+ return _imp->change_type;
+}
+
+void
+ChangesToMakeDecision::set_change_type(const ChangeType t)
+{
+ _imp->change_type = t;
+}
+
bool
ChangesToMakeDecision::best() const
{
@@ -318,6 +335,7 @@ ChangesToMakeDecision::serialise(Serialiser & s) const
s.object("ChangesToMakeDecision")
.member(SerialiserFlags<serialise::might_be_null>(), "origin_id", origin_id())
.member(SerialiserFlags<>(), "best", best())
+ .member(SerialiserFlags<>(), "change_type", stringify(change_type()))
.member(SerialiserFlags<serialise::might_be_null>(), "destination", destination())
.member(SerialiserFlags<>(), "taken", taken())
;
diff --git a/paludis/resolver/decision.hh b/paludis/resolver/decision.hh
index cf6e4c2..8b5f9a1 100644
--- a/paludis/resolver/decision.hh
+++ b/paludis/resolver/decision.hh
@@ -23,6 +23,7 @@
#include <paludis/resolver/decision-fwd.hh>
#include <paludis/resolver/destination-fwd.hh>
#include <paludis/resolver/unsuitable_candidates-fwd.hh>
+#include <paludis/resolver/change_type-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/util/simple_visitor.hh>
#include <paludis/util/type_list.hh>
@@ -100,6 +101,7 @@ namespace paludis
ChangesToMakeDecision(
const std::tr1::shared_ptr<const PackageID> &,
const bool best,
+ const ChangeType,
const bool taken,
const std::tr1::shared_ptr<const Destination> &
);
@@ -116,6 +118,10 @@ namespace paludis
virtual bool best() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual ChangeType change_type() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void set_change_type(ChangeType);
+
virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void serialise(Serialiser &) const;
diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index e25c83a..d7cece1 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -547,52 +547,35 @@ namespace
const ChangesToMakeDecision & decision,
const std::tr1::shared_ptr<const Resolution> & resolution)
{
- bool is_new(false), is_upgrade(false), is_downgrade(false), is_reinstall(false), other_slots(false);
+ std::string x(" ");
+ if (! decision.best())
+ x[0] = '-';
- if (decision.destination()->replacing()->empty())
- {
- is_new = true;
- const std::tr1::shared_ptr<const PackageIDSequence> others((*env)[selection::SomeArbitraryVersion(
- generator::Package(decision.origin_id()->name()) &
- generator::InRepository(decision.destination()->repository())
- )]);
- other_slots = ! others->empty();
- }
- else
+ do
{
- for (PackageIDSequence::ConstIterator i(decision.destination()->replacing()->begin()),
- i_end(decision.destination()->replacing()->end()) ;
- i != i_end ; ++i)
+ switch (decision.change_type())
{
- if ((*i)->version() == decision.origin_id()->version())
- is_reinstall = true;
- else if ((*i)->version() < decision.origin_id()->version())
- is_upgrade = true;
- else if ((*i)->version() > decision.origin_id()->version())
- is_downgrade = true;
+ case ct_new:
+ cout << "n" << x << c::bold_blue();
+ continue;
+ case ct_slot_new:
+ cout << "s" << x << c::bold_blue();
+ continue;
+ case ct_upgrade:
+ cout << "u" << x << c::blue();
+ continue;
+ case ct_reinstall:
+ cout << "r" << x << c::yellow();
+ continue;
+ case ct_downgrade:
+ cout << "d" << x << c::bold_yellow();
+ continue;
+ case last_ct:
+ break;
}
+ throw InternalError(PALUDIS_HERE, "bad change_type. huh?");
}
-
- /* pick the worst, in case we're replacing multiple things */
- is_upgrade = is_upgrade && (! is_reinstall) && (! is_downgrade);
- is_reinstall = is_reinstall && (! is_downgrade);
-
- std::string x(" ");
- if (! decision.best())
- x[0] = '-';
-
- if (is_new && ! other_slots)
- cout << "n" << x << c::bold_blue();
- else if (is_new && other_slots)
- cout << "s" << x << c::bold_blue();
- else if (is_upgrade)
- cout << "u" << x << c::blue();
- else if (is_reinstall)
- cout << "r" << x << c::yellow();
- else if (is_downgrade)
- cout << "d" << x << c::bold_yellow();
- else
- throw InternalError(PALUDIS_HERE, "not new, upgrade, reinstall or downgrade. huh?");
+ while (false);
cout << decision.origin_id()->canonical_form(idcf_no_version);