aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-08-02 00:56:15 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-08-02 00:56:15 +0100
commit057bb9835c0533f2cc75c321b3f6645b7b1cf3b3 (patch)
tree3c4e888510683b5bfd6778c98de9a6fffe4d9f68
parenteefa945bb28ca2ec409161a0520a1f92787ada84 (diff)
downloadpaludis-057bb9835c0533f2cc75c321b3f6645b7b1cf3b3.tar.gz
paludis-057bb9835c0533f2cc75c321b3f6645b7b1cf3b3.tar.xz
destinations
-rw-r--r--paludis/resolver/Makefile.am4
-rw-r--r--paludis/resolver/constraint.hh2
-rw-r--r--paludis/resolver/destinations-fwd.hh38
-rw-r--r--paludis/resolver/destinations.cc58
-rw-r--r--paludis/resolver/destinations.hh53
-rw-r--r--paludis/resolver/resolution.cc4
-rw-r--r--paludis/resolver/resolution.hh3
-rw-r--r--paludis/resolver/resolver.cc141
-rw-r--r--paludis/resolver/resolver.hh19
-rw-r--r--src/clients/cave/cmd_resolve.cc2
10 files changed, 320 insertions, 4 deletions
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index 5946cd1..3042b46 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -17,7 +17,8 @@ noinst_HEADERS = \
arrow.hh arrow-fwd.hh \
constraint.hh constraint-fwd.hh \
decision.hh decision-fwd.hh \
- desire_strength.hh desire_strength-fwd.hh desire_strength-se.hh
+ desire_strength.hh desire_strength-fwd.hh desire_strength-se.hh \
+ destinations.hh destinations-fwd.hh \
qpn_s.hh qpn_s-fwd.hh \
reason.hh reason-fwd.hh \
resolution.hh resolution-fwd.hh \
@@ -30,6 +31,7 @@ libpaludisresolver_a_SOURCES = \
constraint.cc \
decision.cc \
desire_strength.cc \
+ destinations.cc \
qpn_s.cc \
reason.cc \
resolution.cc \
diff --git a/paludis/resolver/constraint.hh b/paludis/resolver/constraint.hh
index 8fe4729..5bafe7e 100644
--- a/paludis/resolver/constraint.hh
+++ b/paludis/resolver/constraint.hh
@@ -35,6 +35,7 @@ namespace paludis
struct desire_strength;
struct reason;
struct spec;
+ struct to_destination_slash;
struct use_installed;
}
@@ -45,6 +46,7 @@ namespace paludis
NamedValue<n::desire_strength, DesireStrength> desire_strength;
NamedValue<n::reason, std::tr1::shared_ptr<const Reason> > reason;
NamedValue<n::spec, PackageDepSpec> spec;
+ NamedValue<n::to_destination_slash, bool> to_destination_slash;
NamedValue<n::use_installed, UseInstalled> use_installed;
};
diff --git a/paludis/resolver/destinations-fwd.hh b/paludis/resolver/destinations-fwd.hh
new file mode 100644
index 0000000..9424462
--- /dev/null
+++ b/paludis/resolver/destinations-fwd.hh
@@ -0,0 +1,38 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 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_DESTINATIONS_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_DESTINATIONS_FWD_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <iosfwd>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct Destination;
+ struct Destinations;
+
+ std::ostream & operator<< (std::ostream &, const Destination &) PALUDIS_VISIBLE;
+ std::ostream & operator<< (std::ostream &, const Destinations &) PALUDIS_VISIBLE;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/destinations.cc b/paludis/resolver/destinations.cc
new file mode 100644
index 0000000..694561c
--- /dev/null
+++ b/paludis/resolver/destinations.cc
@@ -0,0 +1,58 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 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/destinations.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/join.hh>
+#include <paludis/package_id.hh>
+#include <ostream>
+#include <sstream>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+std::ostream &
+paludis::resolver::operator<< (std::ostream & s, const Destination & d)
+{
+ std::stringstream ss;
+ ss << "Destination(" << d.repository();
+ if (! d.replacing()->empty())
+ ss << " replacing " << join(indirect_iterator(d.replacing()->begin()),
+ indirect_iterator(d.replacing()->end()), ", ");
+ ss << ")";
+
+ s << ss.str();
+ return s;
+}
+
+std::ostream &
+paludis::resolver::operator<< (std::ostream & s, const Destinations & d)
+{
+ std::stringstream ss;
+ ss << "Destinations(";
+ if (d.slash())
+ ss << "slash: " << *d.slash();
+ ss << ")";
+
+ s << ss.str();
+ return s;
+}
+
diff --git a/paludis/resolver/destinations.hh b/paludis/resolver/destinations.hh
new file mode 100644
index 0000000..e3cb66d
--- /dev/null
+++ b/paludis/resolver/destinations.hh
@@ -0,0 +1,53 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 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_DESTINATIONS_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_DESTINATIONS_HH 1
+
+#include <paludis/resolver/destinations-fwd.hh>
+#include <paludis/util/named_value.hh>
+#include <paludis/name.hh>
+#include <paludis/package_id-fwd.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace n
+ {
+ struct replacing;
+ struct repository;
+ struct slash;
+ }
+
+ namespace resolver
+ {
+ struct Destination
+ {
+ NamedValue<n::replacing, std::tr1::shared_ptr<const PackageIDSequence> > replacing;
+ NamedValue<n::repository, RepositoryName> repository;
+ };
+
+ struct Destinations
+ {
+ NamedValue<n::slash, std::tr1::shared_ptr<Destination> > slash;
+ };
+ }
+}
+
+#endif
diff --git a/paludis/resolver/resolution.cc b/paludis/resolver/resolution.cc
index 9c67877..ef389cd 100644
--- a/paludis/resolver/resolution.cc
+++ b/paludis/resolver/resolution.cc
@@ -38,7 +38,9 @@ paludis::resolver::operator<< (std::ostream & s, const Resolution & r)
<< "constraints: " << join(indirect_iterator(r.constraints()->begin()), indirect_iterator(r.constraints()->end()), ", ")
<< "; decision: " << (r.decision() ? stringify(*r.decision()) : "none")
<< "; arrows: " << join(indirect_iterator(r.arrows()->begin()), indirect_iterator(r.arrows()->end()), ", ")
- << "; already_ordered: " << stringify(r.already_ordered()) << ")";
+ << "; already_ordered: " << stringify(r.already_ordered()) << ")"
+ << "; destinations: " << (r.destinations() ? stringify(*r.destinations()) : "unknown")
+ << ")";
s << ss.str();
return s;
}
diff --git a/paludis/resolver/resolution.hh b/paludis/resolver/resolution.hh
index 18d8fb4..864bc0d 100644
--- a/paludis/resolver/resolution.hh
+++ b/paludis/resolver/resolution.hh
@@ -24,6 +24,7 @@
#include <paludis/resolver/arrow-fwd.hh>
#include <paludis/resolver/constraint-fwd.hh>
#include <paludis/resolver/decision-fwd.hh>
+#include <paludis/resolver/destinations-fwd.hh>
#include <paludis/util/named_value.hh>
#include <tr1/memory>
@@ -35,6 +36,7 @@ namespace paludis
struct arrows;
struct constraints;
struct decision;
+ struct destinations;
}
namespace resolver
@@ -45,6 +47,7 @@ namespace paludis
NamedValue<n::arrows, std::tr1::shared_ptr<ArrowSequence> > arrows;
NamedValue<n::constraints, std::tr1::shared_ptr<Constraints> > constraints;
NamedValue<n::decision, std::tr1::shared_ptr<Decision> > decision;
+ NamedValue<n::destinations, std::tr1::shared_ptr<Destinations> > destinations;
};
}
}
diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc
index 61bdbd7..3412c38 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -25,6 +25,7 @@
#include <paludis/resolver/sanitised_dependencies.hh>
#include <paludis/resolver/arrow.hh>
#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/destinations.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/log.hh>
@@ -44,10 +45,13 @@
#include <paludis/action.hh>
#include <paludis/version_spec.hh>
#include <paludis/version_requirements.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repository.hh>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
+#include <set>
using namespace paludis;
using namespace paludis::resolver;
@@ -88,6 +92,7 @@ Resolver::resolve()
Context context("When finding an appropriate resolution:");
_resolve_dependencies();
+ _resolve_destinations();
_resolve_arrows();
_resolve_order();
}
@@ -119,6 +124,130 @@ Resolver::_resolve_dependencies()
}
void
+Resolver::_resolve_destinations()
+{
+ Context context("When resolving destinations:");
+
+ for (ResolutionsByQPN_SMap::iterator i(_imp->resolutions_by_qpn_s.begin()), i_end(_imp->resolutions_by_qpn_s.end()) ;
+ i != i_end ; ++i)
+ {
+ if (i->second->destinations())
+ continue;
+
+ i->second->destinations() = _make_destinations_for(i->first, i->second);
+ }
+}
+
+const std::tr1::shared_ptr<Destinations>
+Resolver::_make_destinations_for(const QPN_S & qpn_s,
+ const std::tr1::shared_ptr<const Resolution> & resolution) const
+{
+ Context context("When finding destinations for '" + stringify(qpn_s) + "':");
+
+ if (resolution->decision()->is_installed())
+ return make_shared_ptr(new Destinations(make_named_values<Destinations>(
+ value_for<n::slash>(make_null_shared_ptr())
+ )));
+
+ bool requires_slash(false);
+
+ for (Constraints::ConstIterator c(resolution->constraints()->begin()),
+ c_end(resolution->constraints()->end()) ;
+ c != c_end ; ++c)
+ requires_slash = requires_slash || (*c)->to_destination_slash();
+
+ return make_shared_ptr(new Destinations(
+ make_named_values<Destinations>(
+ value_for<n::slash>(requires_slash ?
+ _make_slash_destination_for(qpn_s, resolution) :
+ make_null_shared_ptr())
+ )));
+}
+
+const std::tr1::shared_ptr<Destination>
+Resolver::_make_slash_destination_for(const QPN_S & qpn_s,
+ const std::tr1::shared_ptr<const Resolution> & resolution) const
+{
+ Context context("When finding / destination for '" + stringify(qpn_s) + "':");
+
+ if (! resolution->decision())
+ throw InternalError(PALUDIS_HERE, "not decided. shouldn't happen.");
+
+ std::tr1::shared_ptr<const Repository> repo;
+ for (PackageDatabase::RepositoryConstIterator r(_imp->env->package_database()->begin_repositories()),
+ r_end(_imp->env->package_database()->end_repositories()) ;
+ r != r_end ; ++r)
+ {
+ if ((*r)->destination_interface() && (*r)->destination_interface()->is_suitable_destination_for(
+ *resolution->decision()->package_id()))
+ {
+ if (repo)
+ throw InternalError(PALUDIS_HERE, "multiple valid destinations.");
+ else
+ repo = *r;
+ }
+ }
+
+ if (! repo)
+ throw InternalError(PALUDIS_HERE, "no valid destination for " + stringify(*resolution));
+
+ return make_shared_ptr(new Destination(make_named_values<Destination>(
+ value_for<n::replacing>(_find_replacing(resolution->decision()->package_id(), repo)),
+ value_for<n::repository>(repo->name())
+ )));
+}
+
+const std::tr1::shared_ptr<const PackageIDSequence>
+Resolver::_find_replacing(
+ const std::tr1::shared_ptr<const PackageID> & id,
+ const std::tr1::shared_ptr<const Repository> & repo) const
+{
+ Context context("When working out what is replaced by '" + stringify(*id) +
+ "' when it is installed to '" + stringify(repo->name()) + "':");
+
+ std::set<RepositoryName, RepositoryNameComparator> repos;
+
+ if (repo->installed_root_key())
+ {
+ for (PackageDatabase::RepositoryConstIterator r(_imp->env->package_database()->begin_repositories()),
+ r_end(_imp->env->package_database()->end_repositories()) ;
+ r != r_end ; ++r)
+ if ((*r)->installed_root_key() &&
+ (*r)->installed_root_key()->value() == repo->installed_root_key()->value())
+ repos.insert((*r)->name());
+ }
+ else
+ repos.insert(repo->name());
+
+ std::tr1::shared_ptr<PackageIDSequence> result(new PackageIDSequence);
+ for (std::set<RepositoryName, RepositoryNameComparator>::const_iterator r(repos.begin()),
+ r_end(repos.end()) ;
+ r != r_end ; ++r)
+ {
+ std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::AllVersionsUnsorted(
+ generator::Package(id->name()) & generator::InRepository(*r))]);
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->version() == id->version() || _same_slot(*i, id))
+ result->push_back(*i);
+ }
+ }
+
+ return result;
+}
+
+bool
+Resolver::_same_slot(const std::tr1::shared_ptr<const PackageID> & a,
+ const std::tr1::shared_ptr<const PackageID> & b) const
+{
+ if (a->slot_key())
+ return b->slot_key() && a->slot_key()->value() == b->slot_key()->value();
+ else
+ return ! b->slot_key();
+}
+
+void
Resolver::add_target(const PackageDepSpec & spec, const UseInstalled use_installed)
{
Context context("When adding target '" + stringify(spec) + "':");
@@ -235,7 +364,8 @@ Resolver::_create_resolution_for_qpn_s(const QPN_S & qpn_s) const
value_for<n::already_ordered>(false),
value_for<n::arrows>(make_shared_ptr(new ArrowSequence)),
value_for<n::constraints>(_initial_constraints_for(qpn_s)),
- value_for<n::decision>(make_null_shared_ptr())
+ value_for<n::decision>(make_null_shared_ptr()),
+ value_for<n::destinations>(make_null_shared_ptr())
)));
}
@@ -280,6 +410,7 @@ Resolver::_make_constraint_from_target(const PackageDepSpec & spec, const UseIns
value_for<n::desire_strength>(ds_target),
value_for<n::reason>(make_shared_ptr(new TargetReason)),
value_for<n::spec>(spec),
+ value_for<n::to_destination_slash>(true),
value_for<n::use_installed>(use_installed)
)));
}
@@ -291,6 +422,7 @@ Resolver::_make_constraint_from_dependency(const QPN_S & qpn_s, const SanitisedD
value_for<n::desire_strength>(_desire_strength_from_sanitised_dependency(qpn_s, dep)),
value_for<n::reason>(make_shared_ptr(new DependencyReason(qpn_s, dep))),
value_for<n::spec>(dep.spec()),
+ value_for<n::to_destination_slash>(_dependency_to_destination_slash(qpn_s, dep)),
value_for<n::use_installed>(ui_if_same)
)));
}
@@ -788,6 +920,7 @@ Resolver::_make_constraint_for_preloading(
value_for<n::desire_strength>(ds_none),
value_for<n::reason>(make_shared_ptr(new TargetReason)),
value_for<n::spec>(d->package_id()->uniquely_identifying_spec()),
+ value_for<n::to_destination_slash>(false),
value_for<n::use_installed>(ui_if_possible)
)));
}
@@ -850,6 +983,12 @@ Resolver::_desire_strength_from_sanitised_dependency(const QPN_S &, const Saniti
return result;
}
+bool
+Resolver::_dependency_to_destination_slash(const QPN_S &, const SanitisedDependency &) const
+{
+ return true;
+}
+
Resolver::ConstIterator
Resolver::begin() const
{
diff --git a/paludis/resolver/resolver.hh b/paludis/resolver/resolver.hh
index 610f624..039c536 100644
--- a/paludis/resolver/resolver.hh
+++ b/paludis/resolver/resolver.hh
@@ -29,6 +29,7 @@
#include <paludis/resolver/reason-fwd.hh>
#include <paludis/resolver/use_installed-fwd.hh>
#include <paludis/resolver/desire_strength-fwd.hh>
+#include <paludis/resolver/destinations-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/util/wrapped_forward_iterator-fwd.hh>
#include <paludis/package_id-fwd.hh>
@@ -36,6 +37,7 @@
#include <paludis/name.hh>
#include <paludis/filter-fwd.hh>
#include <paludis/environment-fwd.hh>
+#include <paludis/repository-fwd.hh>
#include <tr1/memory>
namespace paludis
@@ -79,7 +81,18 @@ namespace paludis
const std::tr1::shared_ptr<const Constraint> &,
const std::tr1::shared_ptr<const Decision> &) const;
+ const std::tr1::shared_ptr<Destinations> _make_destinations_for(const QPN_S &,
+ const std::tr1::shared_ptr<const Resolution> &) const;
+
+ const std::tr1::shared_ptr<Destination> _make_slash_destination_for(const QPN_S &,
+ const std::tr1::shared_ptr<const Resolution> &) const;
+
+ const std::tr1::shared_ptr<const PackageIDSequence> _find_replacing(
+ const std::tr1::shared_ptr<const PackageID> &,
+ const std::tr1::shared_ptr<const Repository> &) const;
+
void _resolve_dependencies();
+ void _resolve_destinations();
void _resolve_arrows();
void _resolve_order();
@@ -129,6 +142,12 @@ namespace paludis
DesireStrength _desire_strength_from_sanitised_dependency(
const QPN_S &, const SanitisedDependency &) const;
+ bool _dependency_to_destination_slash(
+ const QPN_S &, const SanitisedDependency &) const;
+
+ bool _same_slot(const std::tr1::shared_ptr<const PackageID> & a,
+ const std::tr1::shared_ptr<const PackageID> & b) const;
+
public:
Resolver(const Environment * const);
~Resolver();
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index 907ef60..73e8283 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -458,7 +458,7 @@ namespace
{
const std::tr1::shared_ptr<const PackageID> id((*c)->decision()->package_id());
std::cout << "* " << id->canonical_form(idcf_no_version) << " " << id->canonical_form(idcf_version)
- << " replacing { }" << std::endl;
+ << " to " << *(*c)->destinations() << std::endl;
}
std::cout << std::endl;