aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-02 15:52:17 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-02 15:52:17 +0100
commitcc02729c347c1bc8d2a3ef8b939fe298588aa30b (patch)
treebae1957c9985a76d96e8b8ac14f7514f2c2414e5
parentbf3114338a8221bd39039acc57b9d233738429cb (diff)
parentd633e73a7db6c4a886d2ceb2fcac7be79d3db107 (diff)
downloadpaludis-cc02729c347c1bc8d2a3ef8b939fe298588aa30b.tar.gz
paludis-cc02729c347c1bc8d2a3ef8b939fe298588aa30b.tar.xz
Merge branch 'serialise'
-rw-r--r--paludis/resolver/Makefile.am2
-rw-r--r--paludis/resolver/arrow.cc21
-rw-r--r--paludis/resolver/arrow.hh6
-rw-r--r--paludis/resolver/constraint.cc80
-rw-r--r--paludis/resolver/constraint.hh11
-rw-r--r--paludis/resolver/decision.cc31
-rw-r--r--paludis/resolver/decision.hh6
-rw-r--r--paludis/resolver/destinations.cc44
-rw-r--r--paludis/resolver/destinations.hh11
-rw-r--r--paludis/resolver/qpn_s.cc24
-rw-r--r--paludis/resolver/qpn_s.hh6
-rw-r--r--paludis/resolver/reason.cc67
-rw-r--r--paludis/resolver/reason.hh14
-rw-r--r--paludis/resolver/resolution-fwd.hh1
-rw-r--r--paludis/resolver/resolution.cc36
-rw-r--r--paludis/resolver/resolution.hh5
-rw-r--r--paludis/resolver/resolutions-fwd.hh3
-rw-r--r--paludis/resolver/resolutions.cc26
-rw-r--r--paludis/resolver/resolutions.hh4
-rw-r--r--paludis/resolver/sanitised_dependencies.cc50
-rw-r--r--paludis/resolver/sanitised_dependencies.hh13
-rw-r--r--paludis/resolver/serialise-fwd.hh34
-rw-r--r--paludis/resolver/serialise-impl.hh229
-rw-r--r--paludis/resolver/serialise.cc340
-rw-r--r--paludis/resolver/serialise.hh158
-rw-r--r--paludis/resolver/use_installed.se2
-rw-r--r--paludis/util/system.cc137
-rw-r--r--paludis/util/system.hh38
-rw-r--r--paludis/util/system_TEST.cc57
-rw-r--r--src/clients/cave/cmd_resolve.cc11
-rw-r--r--src/clients/cave/cmd_resolve_display_resolution.cc4
-rw-r--r--src/clients/cave/cmd_resolve_display_resolution.hh4
32 files changed, 1453 insertions, 22 deletions
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index f820bad..62f2333 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -22,6 +22,7 @@ noinst_HEADERS = \
resolver.hh resolver-fwd.hh \
resolver_functions.hh resolver_functions-fwd.hh \
sanitised_dependencies.hh sanitised_dependencies-fwd.hh \
+ serialise.hh serialise-fwd.hh serialise-impl.hh \
suggest_restart.hh suggest_restart-fwd.hh \
use_installed.hh use_installed-fwd.hh use_installed-se.hh
@@ -36,6 +37,7 @@ libpaludisresolver_a_SOURCES = \
resolutions.cc \
resolver.cc \
sanitised_dependencies.cc \
+ serialise.cc \
suggest_restart.cc \
use_installed.cc
diff --git a/paludis/resolver/arrow.cc b/paludis/resolver/arrow.cc
index 5b745cd..d8f58ab 100644
--- a/paludis/resolver/arrow.cc
+++ b/paludis/resolver/arrow.cc
@@ -18,8 +18,10 @@
*/
#include <paludis/resolver/arrow.hh>
+#include <paludis/resolver/serialise-impl.hh>
#include <paludis/util/sequence-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/make_named_values.hh>
using namespace paludis;
using namespace paludis::resolver;
@@ -34,6 +36,25 @@ paludis::resolver::operator<< (std::ostream & s, const Arrow & a)
return s;
}
+void
+Arrow::serialise(Serialiser & s) const
+{
+ s.object("Arrow")
+ .member(SerialiserFlags<>(), "ignorable_pass", ignorable_pass())
+ .member(SerialiserFlags<>(), "to_qpn_s", to_qpn_s())
+ ;
+}
+
+const std::tr1::shared_ptr<Arrow>
+Arrow::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Arrow");
+ return make_shared_ptr(new Arrow(make_named_values<Arrow>(
+ value_for<n::ignorable_pass>(v.member<bool>("ignorable_pass")),
+ value_for<n::to_qpn_s>(v.member<QPN_S>("to_qpn_s"))
+ )));
+}
+
template class Sequence<std::tr1::shared_ptr<Arrow> >;
template class WrappedForwardIterator<ArrowSequence::ConstIteratorTag, const std::tr1::shared_ptr<Arrow> >;
diff --git a/paludis/resolver/arrow.hh b/paludis/resolver/arrow.hh
index 7798d03..bbdb930 100644
--- a/paludis/resolver/arrow.hh
+++ b/paludis/resolver/arrow.hh
@@ -22,6 +22,7 @@
#include <paludis/resolver/arrow-fwd.hh>
#include <paludis/resolver/qpn_s.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/util/named_value.hh>
namespace paludis
@@ -38,6 +39,11 @@ namespace paludis
{
NamedValue<n::ignorable_pass, int> ignorable_pass;
NamedValue<n::to_qpn_s, QPN_S> to_qpn_s;
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Arrow> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/resolver/constraint.cc b/paludis/resolver/constraint.cc
index cb7bd59..e423427 100644
--- a/paludis/resolver/constraint.cc
+++ b/paludis/resolver/constraint.cc
@@ -19,9 +19,12 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/reason.hh>
+#include <paludis/resolver/serialise-impl.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/sequence-impl.hh>
+#include <paludis/util/make_named_values.hh>
#include <sstream>
#include <list>
@@ -52,7 +55,7 @@ namespace paludis
UseInstalled strictest_use_installed;
bool nothing_is_fine_too;
bool to_destination_slash;
- std::list<std::tr1::shared_ptr<const Constraint> > constraints;
+ Sequence<std::tr1::shared_ptr<const Constraint> > constraints;
Implementation() :
strictest_use_installed(ui_if_possible),
@@ -117,6 +120,81 @@ Constraints::to_destination_slash() const
return _imp->to_destination_slash;
}
+void
+Constraints::serialise(Serialiser & s) const
+{
+ s.object("Constraints")
+ .member(SerialiserFlags<serialise::container>(), "items", _imp->constraints)
+ ;
+}
+
+const std::tr1::shared_ptr<Constraints>
+Constraints::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Constraints");
+ Deserialisator vv(*v.find_remove_member("items"), "c");
+ std::tr1::shared_ptr<Constraints> result(new Constraints);
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ result->add(vv.member<std::tr1::shared_ptr<Constraint> >(stringify(n)));
+ return result;
+}
+
+void
+Constraint::serialise(Serialiser & s) const
+{
+ s.object("Constraint")
+ .member(SerialiserFlags<>(), "nothing_is_fine_too", nothing_is_fine_too())
+ .member(SerialiserFlags<serialise::might_be_null>(), "reason", reason())
+ .member(SerialiserFlags<>(), "spec", spec())
+ .member(SerialiserFlags<>(), "to_destination_slash", to_destination_slash())
+ .member(SerialiserFlags<>(), "use_installed", stringify(use_installed()))
+ ;
+}
+
+namespace
+{
+ struct IDFinder
+ {
+ const std::tr1::shared_ptr<const PackageID> visit(const DependencyReason & r) const
+ {
+ return r.from_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const SetReason &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const PresetReason &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const TargetReason &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+}
+
+const std::tr1::shared_ptr<Constraint>
+Constraint::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Constraint");
+
+ const std::tr1::shared_ptr<Reason> reason(v.member<std::tr1::shared_ptr<Reason> >("reason"));
+ IDFinder id_finder;
+
+ return make_shared_ptr(new Constraint(make_named_values<Constraint>(
+ value_for<n::nothing_is_fine_too>(v.member<bool>("nothing_is_fine_too")),
+ value_for<n::reason>(reason),
+ value_for<n::spec>(PackageOrBlockDepSpec::deserialise(*v.find_remove_member("spec"),
+ reason->accept_returning<std::tr1::shared_ptr<const PackageID> >(id_finder))),
+ value_for<n::to_destination_slash>(v.member<bool>("to_destination_slash")),
+ value_for<n::use_installed>(destringify<UseInstalled>(v.member<std::string>("use_installed")))
+ )));
+}
+
template class PrivateImplementationPattern<Constraints>;
template class WrappedForwardIterator<Constraints::ConstIteratorTag, const std::tr1::shared_ptr<const Constraint> >;
diff --git a/paludis/resolver/constraint.hh b/paludis/resolver/constraint.hh
index 7b6fbdb..2c8c760 100644
--- a/paludis/resolver/constraint.hh
+++ b/paludis/resolver/constraint.hh
@@ -24,6 +24,7 @@
#include <paludis/resolver/reason-fwd.hh>
#include <paludis/resolver/use_installed-fwd.hh>
#include <paludis/resolver/sanitised_dependencies.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/dep_spec.hh>
#include <tr1/memory>
@@ -48,6 +49,11 @@ namespace paludis
NamedValue<n::spec, PackageOrBlockDepSpec> spec;
NamedValue<n::to_destination_slash, bool> to_destination_slash;
NamedValue<n::use_installed, UseInstalled> use_installed;
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Constraint> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
class PALUDIS_VISIBLE Constraints :
@@ -69,6 +75,11 @@ namespace paludis
ConstIterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
bool empty() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Constraints> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
diff --git a/paludis/resolver/decision.cc b/paludis/resolver/decision.cc
index 3d3e675..e00ed96 100644
--- a/paludis/resolver/decision.cc
+++ b/paludis/resolver/decision.cc
@@ -18,6 +18,8 @@
*/
#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/serialise-impl.hh>
+#include <paludis/util/make_named_values.hh>
#include <sstream>
using namespace paludis;
@@ -52,3 +54,32 @@ paludis::resolver::operator<< (std::ostream & s, const Decision & d)
return s;
}
+void
+Decision::serialise(Serialiser & s) const
+{
+ s.object("Decision")
+ .member(SerialiserFlags<serialise::might_be_null>(), "if_package_id", if_package_id())
+ .member(SerialiserFlags<>(), "is_best", is_best())
+ .member(SerialiserFlags<>(), "is_installed", is_installed())
+ .member(SerialiserFlags<>(), "is_nothing", is_nothing())
+ .member(SerialiserFlags<>(), "is_same", is_same())
+ .member(SerialiserFlags<>(), "is_same_version", is_same_version())
+ .member(SerialiserFlags<>(), "is_transient", is_transient())
+ ;
+}
+
+const std::tr1::shared_ptr<Decision>
+Decision::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Decision");
+ return make_shared_ptr(new Decision(make_named_values<Decision>(
+ value_for<n::if_package_id>(v.member<std::tr1::shared_ptr<const PackageID> >("if_package_id")),
+ value_for<n::is_best>(v.member<bool>("is_best")),
+ value_for<n::is_installed>(v.member<bool>("is_installed")),
+ value_for<n::is_nothing>(v.member<bool>("is_nothing")),
+ value_for<n::is_same>(v.member<bool>("is_same")),
+ value_for<n::is_same_version>(v.member<bool>("is_same_version")),
+ value_for<n::is_transient>(v.member<bool>("is_transient"))
+ )));
+}
+
diff --git a/paludis/resolver/decision.hh b/paludis/resolver/decision.hh
index 9bfac0f..a0c6728 100644
--- a/paludis/resolver/decision.hh
+++ b/paludis/resolver/decision.hh
@@ -21,6 +21,7 @@
#define PALUDIS_GUARD_PALUDIS_RESOLVER_DECISION_HH 1
#include <paludis/resolver/decision-fwd.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/package_id.hh>
@@ -48,6 +49,11 @@ namespace paludis
NamedValue<n::is_same, bool> is_same;
NamedValue<n::is_same_version, bool> is_same_version;
NamedValue<n::is_transient, bool> is_transient;
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Decision> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/resolver/destinations.cc b/paludis/resolver/destinations.cc
index 694561c..26c086a 100644
--- a/paludis/resolver/destinations.cc
+++ b/paludis/resolver/destinations.cc
@@ -18,10 +18,12 @@
*/
#include <paludis/resolver/destinations.hh>
+#include <paludis/resolver/serialise-impl.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/util/make_named_values.hh>
#include <paludis/package_id.hh>
#include <ostream>
#include <sstream>
@@ -56,3 +58,45 @@ paludis::resolver::operator<< (std::ostream & s, const Destinations & d)
return s;
}
+void
+Destinations::serialise(Serialiser & s) const
+{
+ s.object("Destinations")
+ .member(SerialiserFlags<serialise::might_be_null>(), "slash", slash())
+ ;
+}
+
+void
+Destination::serialise(Serialiser & s) const
+{
+ s.object("Destination")
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "replacing", replacing())
+ .member(SerialiserFlags<>(), "repository", stringify(repository()))
+ ;
+}
+
+const std::tr1::shared_ptr<Destinations>
+Destinations::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Destinations");
+ return make_shared_ptr(new Destinations(make_named_values<Destinations>(
+ value_for<n::slash>(v.member<std::tr1::shared_ptr<Destination> >("slash"))
+ )));
+}
+
+const std::tr1::shared_ptr<Destination>
+Destination::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Destination");
+
+ std::tr1::shared_ptr<PackageIDSequence> replacing(new PackageIDSequence);
+ Deserialisator vv(*v.find_remove_member("replacing"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ replacing->push_back(vv.member<std::tr1::shared_ptr<const PackageID> >(stringify(n)));
+
+ return make_shared_ptr(new Destination(make_named_values<Destination>(
+ value_for<n::replacing>(replacing),
+ value_for<n::repository>(RepositoryName(v.member<std::string>("repository")))
+ )));
+}
+
diff --git a/paludis/resolver/destinations.hh b/paludis/resolver/destinations.hh
index e3cb66d..8c327dc 100644
--- a/paludis/resolver/destinations.hh
+++ b/paludis/resolver/destinations.hh
@@ -21,6 +21,7 @@
#define PALUDIS_GUARD_PALUDIS_RESOLVER_DESTINATIONS_HH 1
#include <paludis/resolver/destinations-fwd.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/name.hh>
#include <paludis/package_id-fwd.hh>
@@ -41,11 +42,21 @@ namespace paludis
{
NamedValue<n::replacing, std::tr1::shared_ptr<const PackageIDSequence> > replacing;
NamedValue<n::repository, RepositoryName> repository;
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Destination> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
struct Destinations
{
NamedValue<n::slash, std::tr1::shared_ptr<Destination> > slash;
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Destinations> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/resolver/qpn_s.cc b/paludis/resolver/qpn_s.cc
index 47746f3..2f5b2ec 100644
--- a/paludis/resolver/qpn_s.cc
+++ b/paludis/resolver/qpn_s.cc
@@ -18,9 +18,12 @@
*/
#include <paludis/resolver/qpn_s.hh>
+#include <paludis/resolver/serialise-impl.hh>
#include <paludis/util/sequence-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/make_named_values.hh>
#include <paludis/filter.hh>
#include <paludis/dep_spec.hh>
#include <paludis/package_id.hh>
@@ -128,7 +131,7 @@ paludis::resolver::operator<< (std::ostream & s, const QPN_S & q)
if (q.slot_name_or_null())
ss << ":" << *q.slot_name_or_null();
else
- ss << ":(no slot)";
+ ss << " (no slot)";
s << ss.str();
return s;
@@ -154,6 +157,25 @@ QPN_S::operator= (const QPN_S & other)
return *this;
}
+void
+QPN_S::serialise(Serialiser & s) const
+{
+ s.object("QPN_S")
+ .member(SerialiserFlags<>(), "package", stringify(package()))
+ .member(SerialiserFlags<>(), "slot", slot_name_or_null() ? stringify(*slot_name_or_null()) : "")
+ ;
+}
+
+QPN_S
+QPN_S::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "QPN_S");
+ std::string slot_str(v.member<std::string>("slot"));
+ return QPN_S(
+ QualifiedPackageName(v.member<std::string>("package")),
+ ! slot_str.empty() ? make_shared_ptr(new SlotName(slot_str)) : make_null_shared_ptr());
+}
+
template class PrivateImplementationPattern<QPN_S>;
template class WrappedForwardIterator<QPN_S_Sequence::ConstIteratorTag, const QPN_S>;
diff --git a/paludis/resolver/qpn_s.hh b/paludis/resolver/qpn_s.hh
index 2872bbe..4917b62 100644
--- a/paludis/resolver/qpn_s.hh
+++ b/paludis/resolver/qpn_s.hh
@@ -21,6 +21,7 @@
#define PALUDIS_GUARD_PALUDIS_RESOLVER_QPN_S_HH 1
#include <paludis/resolver/qpn_s-fwd.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/util/attributes.hh>
#include <paludis/util/private_implementation_pattern.hh>
@@ -58,6 +59,11 @@ namespace paludis
bool operator< (const QPN_S & other) const PALUDIS_ATTRIBUTE((warn_unused_result));
bool operator== (const QPN_S & other) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void serialise(Serialiser &) const;
+
+ static QPN_S deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
diff --git a/paludis/resolver/reason.cc b/paludis/resolver/reason.cc
index 76b4e6b..382e6e1 100644
--- a/paludis/resolver/reason.cc
+++ b/paludis/resolver/reason.cc
@@ -20,6 +20,7 @@
#include <paludis/resolver/reason.hh>
#include <paludis/resolver/qpn_s.hh>
#include <paludis/resolver/sanitised_dependencies.hh>
+#include <paludis/resolver/serialise-impl.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
@@ -43,6 +44,13 @@ TargetReason::as_string() const
return "Target()";
}
+void
+TargetReason::serialise(Serialiser & s) const
+{
+ s.object("TargetReason")
+ ;
+}
+
namespace paludis
{
template <>
@@ -87,12 +95,28 @@ DependencyReason::as_string() const
return "Dependency(package: " + stringify(*_imp->from_id) + " dep: " + stringify(_imp->dep) + ")";
}
+void
+DependencyReason::serialise(Serialiser & s) const
+{
+ s.object("DependencyReason")
+ .member(SerialiserFlags<serialise::might_be_null>(), "from_id", from_id())
+ .member(SerialiserFlags<>(), "sanitised_dependency", sanitised_dependency())
+ ;
+}
+
std::string
PresetReason::as_string() const
{
return "Preset()";
}
+void
+PresetReason::serialise(Serialiser & s) const
+{
+ s.object("PresetReason")
+ ;
+}
+
namespace paludis
{
template <>
@@ -136,6 +160,49 @@ SetReason::as_string() const
return "Set(set: " + stringify(_imp->set_name) + " because: " + stringify(*_imp->reason_for_set) + ")";
}
+void
+SetReason::serialise(Serialiser & s) const
+{
+ s.object("SetReason")
+ .member(SerialiserFlags<serialise::might_be_null>(), "reason_for_set", reason_for_set())
+ .member(SerialiserFlags<>(), "set_name", stringify(set_name()))
+ ;
+}
+
+const std::tr1::shared_ptr<Reason>
+Reason::deserialise(Deserialisation & d)
+{
+ if (d.class_name() == "TargetReason")
+ {
+ Deserialisator v(d, "TargetReason");
+ return make_shared_ptr(new TargetReason);
+ }
+ else if (d.class_name() == "PresetReason")
+ {
+ Deserialisator v(d, "PresetReason");
+ return make_shared_ptr(new PresetReason);
+ }
+ else if (d.class_name() == "SetReason")
+ {
+ Deserialisator v(d, "SetReason");
+ return make_shared_ptr(new SetReason(
+ SetName(v.member<std::string>("set_name")),
+ v.member<std::tr1::shared_ptr<Reason> >("reason_for_set")
+ ));
+ }
+ else if (d.class_name() == "DependencyReason")
+ {
+ Deserialisator v(d, "DependencyReason");
+ const std::tr1::shared_ptr<const PackageID> from_id(v.member<std::tr1::shared_ptr<const PackageID> >("from_id"));
+ return make_shared_ptr(new DependencyReason(
+ from_id,
+ SanitisedDependency::deserialise(*v.find_remove_member("sanitised_dependency"), from_id))
+ );
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "unknown class '" + stringify(d.class_name()) + "'");
+}
+
template class PrivateImplementationPattern<DependencyReason>;
template class PrivateImplementationPattern<SetReason>;
diff --git a/paludis/resolver/reason.hh b/paludis/resolver/reason.hh
index d6cb177..3b0b2ee 100644
--- a/paludis/resolver/reason.hh
+++ b/paludis/resolver/reason.hh
@@ -23,6 +23,7 @@
#include <paludis/resolver/reason-fwd.hh>
#include <paludis/resolver/qpn_s-fwd.hh>
#include <paludis/resolver/sanitised_dependencies-fwd.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/util/simple_visitor.hh>
#include <paludis/util/type_list.hh>
@@ -41,6 +42,11 @@ namespace paludis
public:
virtual ~Reason() = 0;
virtual std::string as_string() const = 0;
+
+ virtual void serialise(Serialiser &) const = 0;
+
+ static const std::tr1::shared_ptr<Reason> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
class TargetReason :
@@ -49,6 +55,8 @@ namespace paludis
{
public:
virtual std::string as_string() const;
+
+ virtual void serialise(Serialiser &) const;
};
class DependencyReason :
@@ -67,6 +75,8 @@ namespace paludis
const SanitisedDependency & sanitised_dependency() const;
virtual std::string as_string() const;
+
+ virtual void serialise(Serialiser &) const;
};
class PresetReason :
@@ -75,6 +85,8 @@ namespace paludis
{
public:
virtual std::string as_string() const;
+
+ virtual void serialise(Serialiser &) const;
};
class SetReason :
@@ -90,6 +102,8 @@ namespace paludis
const std::tr1::shared_ptr<const Reason> reason_for_set() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual std::string as_string() const;
+
+ virtual void serialise(Serialiser &) const;
};
}
diff --git a/paludis/resolver/resolution-fwd.hh b/paludis/resolver/resolution-fwd.hh
index 0345a2a..2167158 100644
--- a/paludis/resolver/resolution-fwd.hh
+++ b/paludis/resolver/resolution-fwd.hh
@@ -21,6 +21,7 @@
#define PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLUTION_FWD_HH 1
#include <paludis/util/attributes.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <iosfwd>
namespace paludis
diff --git a/paludis/resolver/resolution.cc b/paludis/resolver/resolution.cc
index ef389cd..3e70938 100644
--- a/paludis/resolver/resolution.cc
+++ b/paludis/resolver/resolution.cc
@@ -21,10 +21,14 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/arrow.hh>
#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/serialise-impl.hh>
+#include <paludis/resolver/destinations.hh>
#include <paludis/util/sequence.hh>
#include <paludis/util/join.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_ptr.hh>
#include <sstream>
using namespace paludis;
@@ -45,3 +49,35 @@ paludis::resolver::operator<< (std::ostream & s, const Resolution & r)
return s;
}
+void
+Resolution::serialise(Serialiser & s) const
+{
+ s.object("Resolution")
+ .member(SerialiserFlags<>(), "already_ordered", already_ordered())
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "arrows", arrows())
+ .member(SerialiserFlags<>(), "constraints", *constraints())
+ .member(SerialiserFlags<serialise::might_be_null>(), "decision", decision())
+ .member(SerialiserFlags<serialise::might_be_null>(), "destinations", destinations())
+ ;
+}
+
+const std::tr1::shared_ptr<Resolution>
+Resolution::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Resolution");
+
+ std::tr1::shared_ptr<ArrowSequence> arrows(new ArrowSequence);
+ Deserialisator vv(*v.find_remove_member("arrows"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ arrows->push_back(vv.member<std::tr1::shared_ptr<Arrow> >(stringify(n)));
+
+ return make_shared_ptr(new Resolution(make_named_values<Resolution>(
+ value_for<n::already_ordered>(v.member<bool>("already_ordered")),
+ value_for<n::arrows>(arrows),
+ value_for<n::constraints>(v.member<std::tr1::shared_ptr<Constraints> >("constraints")),
+ value_for<n::decision>(v.member<std::tr1::shared_ptr<Decision> >("decision")),
+ value_for<n::destinations>(v.member<std::tr1::shared_ptr<Destinations> >("destinations")),
+ value_for<n::sanitised_dependencies>(make_null_shared_ptr())
+ )));
+}
+
diff --git a/paludis/resolver/resolution.hh b/paludis/resolver/resolution.hh
index b89304a..d7d9307 100644
--- a/paludis/resolver/resolution.hh
+++ b/paludis/resolver/resolution.hh
@@ -51,6 +51,11 @@ namespace paludis
NamedValue<n::decision, std::tr1::shared_ptr<Decision> > decision;
NamedValue<n::destinations, std::tr1::shared_ptr<Destinations> > destinations;
NamedValue<n::sanitised_dependencies, std::tr1::shared_ptr<SanitisedDependencies> > sanitised_dependencies;
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Resolution> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/resolver/resolutions-fwd.hh b/paludis/resolver/resolutions-fwd.hh
index 4ecdefd..4fb6dfe 100644
--- a/paludis/resolver/resolutions-fwd.hh
+++ b/paludis/resolver/resolutions-fwd.hh
@@ -20,6 +20,9 @@
#ifndef PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLUTIONS_FWD_HH
#define PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLUTIONS_FWD_HH 1
+#include <paludis/util/attributes.hh>
+#include <paludis/resolver/serialise-fwd.hh>
+
namespace paludis
{
namespace resolver
diff --git a/paludis/resolver/resolutions.cc b/paludis/resolver/resolutions.cc
index 37dcca4..afb7f69 100644
--- a/paludis/resolver/resolutions.cc
+++ b/paludis/resolver/resolutions.cc
@@ -18,9 +18,12 @@
*/
#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/serialise-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
-#include <list>
+#include <paludis/util/sequence-impl.hh>
+#include <paludis/util/stringify.hh>
using namespace paludis;
using namespace paludis::resolver;
@@ -30,7 +33,7 @@ namespace paludis
template <>
struct Implementation<Resolutions>
{
- std::list<std::tr1::shared_ptr<const Resolution> > resolutions;
+ Sequence<std::tr1::shared_ptr<const Resolution> > resolutions;
};
}
@@ -61,6 +64,25 @@ Resolutions::end() const
return ConstIterator(_imp->resolutions.end());
}
+void
+Resolutions::serialise(Serialiser & s) const
+{
+ s.object("Resolutions")
+ .member(SerialiserFlags<serialise::container>(), "items", _imp->resolutions)
+ ;
+}
+
+const std::tr1::shared_ptr<Resolutions>
+Resolutions::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Resolutions");
+ Deserialisator vv(*v.find_remove_member("items"), "c");
+ std::tr1::shared_ptr<Resolutions> result(new Resolutions);
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ result->append(vv.member<std::tr1::shared_ptr<Resolution> >(stringify(n)));
+ return result;
+}
+
template class PrivateImplementationPattern<Resolutions>;
template class WrappedForwardIterator<Resolutions::ConstIteratorTag, const std::tr1::shared_ptr<const Resolution> >;
diff --git a/paludis/resolver/resolutions.hh b/paludis/resolver/resolutions.hh
index a2af9f4..1b246f4 100644
--- a/paludis/resolver/resolutions.hh
+++ b/paludis/resolver/resolutions.hh
@@ -46,6 +46,10 @@ namespace paludis
ConstIterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
ConstIterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Resolutions> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
diff --git a/paludis/resolver/sanitised_dependencies.cc b/paludis/resolver/sanitised_dependencies.cc
index 0ccad88..ac4bb48 100644
--- a/paludis/resolver/sanitised_dependencies.cc
+++ b/paludis/resolver/sanitised_dependencies.cc
@@ -20,6 +20,7 @@
#include <paludis/resolver/sanitised_dependencies.hh>
#include <paludis/resolver/resolver.hh>
#include <paludis/resolver/qpn_s.hh>
+#include <paludis/resolver/serialise-impl.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/save.hh>
#include <paludis/util/stringify.hh>
@@ -30,6 +31,7 @@
#include <paludis/slot_requirement.hh>
#include <paludis/metadata_key.hh>
#include <paludis/package_id.hh>
+#include <paludis/user_dep_spec.hh>
#include <set>
#include <list>
@@ -417,5 +419,53 @@ PackageOrBlockDepSpec::PackageOrBlockDepSpec(const PackageDepSpec & s) :
{
}
+void
+PackageOrBlockDepSpec::serialise(Serialiser & s) const
+{
+ s.object("PackageOrBlockDepSpec")
+ .member(SerialiserFlags<>(), "if_block", if_block() ? stringify(*if_block()) : "null")
+ .member(SerialiserFlags<>(), "if_package", if_package() ? stringify(*if_package()) : "null")
+ ;
+}
+
+PackageOrBlockDepSpec
+PackageOrBlockDepSpec::deserialise(Deserialisation & d, const std::tr1::shared_ptr<const PackageID> & for_id)
+{
+ Deserialisator v(d, "PackageOrBlockDepSpec");
+
+ std::string if_block(v.member<std::string>("if_block"));
+ std::string if_package(v.member<std::string>("if_package"));
+
+ if (if_block == "null")
+ return PackageOrBlockDepSpec(parse_user_package_dep_spec(if_package,
+ d.deserialiser().environment(), UserPackageDepSpecOptions() + updso_serialised,
+ filter::All(), for_id));
+ else
+ return PackageOrBlockDepSpec(BlockDepSpec(make_shared_ptr(new PackageDepSpec(
+ parse_user_package_dep_spec(if_block.substr(if_block.find_first_not_of("!")),
+ d.deserialiser().environment(), UserPackageDepSpecOptions() + updso_serialised,
+ filter::All(), for_id))), if_block));
+}
+
+void
+SanitisedDependency::serialise(Serialiser & s) const
+{
+ s.object("SanitisedDependency")
+ .member(SerialiserFlags<>(), "spec", spec())
+ ;
+}
+
+SanitisedDependency
+SanitisedDependency::deserialise(Deserialisation & d, const std::tr1::shared_ptr<const PackageID> & from_id)
+{
+ Deserialisator v(d, "SanitisedDependency");
+
+ return make_named_values<SanitisedDependency>(
+ value_for<n::active_dependency_labels>(make_null_shared_ptr()),
+ value_for<n::spec>(PackageOrBlockDepSpec::deserialise(*v.find_remove_member("spec"),
+ from_id))
+ );
+}
+
template class WrappedForwardIterator<SanitisedDependencies::ConstIteratorTag, const SanitisedDependency>;
diff --git a/paludis/resolver/sanitised_dependencies.hh b/paludis/resolver/sanitised_dependencies.hh
index b2881cd..4678c14 100644
--- a/paludis/resolver/sanitised_dependencies.hh
+++ b/paludis/resolver/sanitised_dependencies.hh
@@ -22,6 +22,7 @@
#include <paludis/resolver/sanitised_dependencies-fwd.hh>
#include <paludis/resolver/resolver-fwd.hh>
+#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/dep_label-fwd.hh>
#include <paludis/dep_spec.hh>
@@ -47,12 +48,24 @@ namespace paludis
PackageOrBlockDepSpec(const BlockDepSpec &);
PackageOrBlockDepSpec(const PackageDepSpec &);
+
+ void serialise(Serialiser &) const;
+
+ static PackageOrBlockDepSpec deserialise(
+ Deserialisation & d,
+ const std::tr1::shared_ptr<const PackageID> & for_id) PALUDIS_ATTRIBUTE((warn_unused_result));
};
struct SanitisedDependency
{
NamedValue<n::active_dependency_labels, std::tr1::shared_ptr<const ActiveDependencyLabels> > active_dependency_labels;
NamedValue<n::spec, PackageOrBlockDepSpec> spec;
+
+ void serialise(Serialiser &) const;
+
+ static SanitisedDependency deserialise(
+ Deserialisation & d,
+ const std::tr1::shared_ptr<const PackageID> & for_id) PALUDIS_ATTRIBUTE((warn_unused_result));
};
class SanitisedDependencies :
diff --git a/paludis/resolver/serialise-fwd.hh b/paludis/resolver/serialise-fwd.hh
new file mode 100644
index 0000000..c84d4ae
--- /dev/null
+++ b/paludis/resolver/serialise-fwd.hh
@@ -0,0 +1,34 @@
+/* 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_SERIALISE_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_SERIALISE_FWD_HH 1
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct Serialiser;
+
+ struct Deserialiser;
+ struct Deserialisation;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/serialise-impl.hh b/paludis/resolver/serialise-impl.hh
new file mode 100644
index 0000000..19d7aea
--- /dev/null
+++ b/paludis/resolver/serialise-impl.hh
@@ -0,0 +1,229 @@
+/* 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_SERIALISE_IMPL_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_SERIALISE_IMPL_HH 1
+
+#include <paludis/resolver/serialise.hh>
+#include <paludis/util/remove_shared_ptr.hh>
+#include <paludis/util/destringify.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <tr1/type_traits>
+#include <ostream>
+#include <istream>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ template <
+ typename Flags_,
+ typename Flag_>
+ struct SerialiserFlagsInclude
+ {
+ static const bool value =
+ std::tr1::is_same<typename Flags_::Flag1, Flag_>::value ||
+ std::tr1::is_same<typename Flags_::Flag2, Flag_>::value ||
+ std::tr1::is_same<typename Flags_::Flag3, Flag_>::value;
+ };
+
+ template <
+ bool is_container_,
+ bool might_be_null_,
+ typename T_>
+ struct SerialiserObjectWriterHandler;
+
+ template <>
+ struct SerialiserObjectWriterHandler<false, false, bool>
+ {
+ static void write(Serialiser & s, const bool t);
+ };
+
+ template <>
+ struct SerialiserObjectWriterHandler<false, false, int>
+ {
+ static void write(Serialiser & s, const int t);
+ };
+
+ template <>
+ struct SerialiserObjectWriterHandler<false, false, std::string>
+ {
+ static void write(Serialiser & s, const std::string & t);
+ };
+
+ template <>
+ struct SerialiserObjectWriterHandler<false, false, const PackageID>
+ {
+ static void write(Serialiser & s, const PackageID & t);
+ };
+
+ template <
+ typename T_>
+ struct SerialiserObjectWriterHandler<false, false, T_>
+ {
+ static void write(Serialiser & s, const T_ & t)
+ {
+ t.serialise(s);
+ }
+ };
+
+ template <
+ bool is_container_,
+ typename T_>
+ struct SerialiserObjectWriterHandler<is_container_, true, T_>
+ {
+ static void write(Serialiser & s, const T_ & t)
+ {
+ if (t)
+ SerialiserObjectWriterHandler<is_container_, false, typename RemoveSharedPtr<T_>::Type>::write(
+ s, *t);
+ else
+ s.raw_stream() << "null;";
+ }
+ };
+
+ template <
+ typename T_>
+ struct SerialiserObjectWriterHandler<true, false, T_>
+ {
+ static void write(Serialiser & s, const T_ & t)
+ {
+ s.raw_stream() << "c(";
+ unsigned n(0);
+ for (typename T_::ConstIterator i(t.begin()), i_end(t.end()) ;
+ i != i_end ; ++i)
+ {
+ typedef typename std::iterator_traits<typename T_::ConstIterator>::value_type ItemValueType;
+ typedef typename std::tr1::remove_reference<ItemValueType>::type ItemType;
+
+ s.raw_stream() << ++n << "=";
+ SerialiserObjectWriterHandler<
+ false,
+ ! std::tr1::is_same<ItemType, typename RemoveSharedPtr<ItemType>::Type>::value,
+ ItemType
+ >::write(s, *i);
+ }
+
+ s.raw_stream() << "count=";
+ SerialiserObjectWriterHandler<false, false, int>::write(s, n);
+
+ s.raw_stream() << ");";
+ }
+ };
+
+ template <
+ typename Flags_,
+ typename T_>
+ SerialiserObjectWriter &
+ SerialiserObjectWriter::member(
+ const Flags_ &,
+ const std::string & item_name,
+ const T_ & t)
+ {
+ _serialiser.raw_stream() << item_name << "=";
+
+ SerialiserObjectWriterHandler<
+ SerialiserFlagsInclude<Flags_, serialise::container>::value,
+ SerialiserFlagsInclude<Flags_, serialise::might_be_null>::value,
+ T_
+ >::write(_serialiser, t);
+
+ return *this;
+ }
+
+ template <typename T_>
+ struct DeserialisatorHandler;
+
+ template <>
+ struct DeserialisatorHandler<bool>
+ {
+ static bool handle(Deserialisation & v)
+ {
+ return destringify<bool>(v.string_value());
+ }
+ };
+
+ template <>
+ struct DeserialisatorHandler<int>
+ {
+ static int handle(Deserialisation & v)
+ {
+ return destringify<int>(v.string_value());
+ }
+ };
+
+ template <>
+ struct DeserialisatorHandler<std::string>
+ {
+ static std::string handle(Deserialisation & v)
+ {
+ return v.string_value();
+ }
+ };
+
+ template <>
+ struct DeserialisatorHandler<std::tr1::shared_ptr<const PackageID> >
+ {
+ static std::tr1::shared_ptr<const PackageID> handle(Deserialisation & v);
+ };
+
+ template <typename T_>
+ struct DeserialisatorHandler<std::tr1::shared_ptr<T_> >
+ {
+ static std::tr1::shared_ptr<T_> handle(Deserialisation & v)
+ {
+ if (v.null())
+ return make_null_shared_ptr();
+ else
+ return T_::deserialise(v);
+ }
+ };
+
+ template <typename T_>
+ struct DeserialisatorHandler
+ {
+ static T_ handle(Deserialisation & v)
+ {
+ return T_::deserialise(v);
+ }
+ };
+
+ template <typename T_>
+ T_
+ Deserialisator::member(const std::string & key_name)
+ {
+ return DeserialisatorHandler<T_>::handle(*find_remove_member(key_name));
+ }
+
+ template <typename T_>
+ std::tr1::shared_ptr<T_> deserialise(
+ const Environment * const env,
+ const std::string & str,
+ const std::string & class_name)
+ {
+ Deserialiser d(env, str);
+ Deserialisation dd(class_name, d);
+ return T_::deserialise(dd);
+ }
+ }
+}
+
+#endif
diff --git a/paludis/resolver/serialise.cc b/paludis/resolver/serialise.cc
new file mode 100644
index 0000000..3a90b96
--- /dev/null
+++ b/paludis/resolver/serialise.cc
@@ -0,0 +1,340 @@
+/* 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/serialise-impl.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/simple_parser.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/member_iterator-impl.hh>
+#include <paludis/package_id.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/environment.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/selection.hh>
+#include <paludis/filter.hh>
+#include <paludis/generator.hh>
+#include <paludis/filtered_generator.hh>
+#include <list>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+SerialiserObjectWriter::SerialiserObjectWriter(Serialiser & s) :
+ _serialiser(s)
+{
+}
+
+SerialiserObjectWriter::~SerialiserObjectWriter()
+{
+ _serialiser.raw_stream() << ");";
+}
+
+Serialiser::Serialiser(std::ostream & s) :
+ _stream(s)
+{
+}
+
+Serialiser::~Serialiser()
+{
+}
+
+std::ostream &
+Serialiser::raw_stream()
+{
+ return _stream;
+}
+
+SerialiserObjectWriter
+Serialiser::object(const std::string & c)
+{
+ raw_stream() << c << "(";
+ return SerialiserObjectWriter(*this);
+}
+
+void
+SerialiserObjectWriterHandler<false, false, bool>::write(Serialiser & s, const bool t)
+{
+ if (t)
+ s.raw_stream() << "\"true\";";
+ else
+ s.raw_stream() << "\"false\";";
+}
+
+void
+SerialiserObjectWriterHandler<false, false, int>::write(Serialiser & s, const int i)
+{
+ s.raw_stream() << "\"" << i << "\";";
+}
+
+void
+SerialiserObjectWriterHandler<false, false, std::string>::write(Serialiser & s, const std::string & t)
+{
+ s.raw_stream() << "\"";
+ s.escape_write(t);
+ s.raw_stream() << "\";";
+}
+
+void
+SerialiserObjectWriterHandler<false, false, const PackageID>::write(Serialiser & s, const PackageID & t)
+{
+ s.raw_stream() << "\"";
+ s.escape_write(stringify(t.uniquely_identifying_spec()));
+ s.raw_stream() << "\";";
+}
+
+void
+Serialiser::escape_write(const std::string & t)
+{
+ for (std::string::const_iterator c(t.begin()), c_end(t.end()) ;
+ c != c_end ; ++c)
+ switch (*c)
+ {
+ case '\\':
+ case '"':
+ case ';':
+ case '(':
+ case ')':
+ raw_stream() << '\\';
+ /* fall through */
+ default:
+ raw_stream() << *c;
+ }
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<Deserialiser>
+ {
+ const Environment * const env;
+ SimpleParser parser;
+
+ Implementation(const Environment * const e, const std::string & s) :
+ env(e),
+ parser(s)
+ {
+ }
+ };
+
+ template <>
+ struct Implementation<Deserialisation>
+ {
+ Deserialiser & deserialiser;
+ const std::string item_name;
+
+ std::string class_name;
+ std::string string_value;
+ bool null;
+ std::list<std::tr1::shared_ptr<Deserialisation> > children;
+
+ Implementation(Deserialiser & d, const std::string & i) :
+ deserialiser(d),
+ item_name(i),
+ null(false)
+ {
+ }
+ };
+
+ template <>
+ struct Implementation<Deserialisator>
+ {
+ const std::string class_name;
+ std::map<std::string, std::tr1::shared_ptr<Deserialisation> > keys;
+
+ Implementation(const std::string & c) :
+ class_name(c)
+ {
+ }
+ };
+}
+
+Deserialiser::Deserialiser(const Environment * const e, const std::string & s) :
+ PrivateImplementationPattern<Deserialiser>(new Implementation<Deserialiser>(e, s))
+{
+}
+
+Deserialiser::~Deserialiser()
+{
+}
+
+SimpleParser &
+Deserialiser::parser()
+{
+ return _imp->parser;
+}
+
+const Environment *
+Deserialiser::environment() const
+{
+ return _imp->env;
+}
+
+Deserialisation::Deserialisation(const std::string & i, Deserialiser & d) :
+ PrivateImplementationPattern<Deserialisation>(new Implementation<Deserialisation>(d, i))
+{
+ if (d.parser().consume(simple_parser::exact("null;")))
+ _imp->null = true;
+ else if (d.parser().consume(simple_parser::exact("\"")))
+ {
+ while (true)
+ {
+ std::string v;
+ if (d.parser().consume(simple_parser::exact("\\")))
+ {
+ if (! d.parser().consume(simple_parser::any_except("") >> v))
+ throw InternalError(PALUDIS_HERE, "can't parse string escape");
+ _imp->string_value.append(v);
+ }
+ else if (d.parser().consume(simple_parser::exact("\";")))
+ break;
+ else if (d.parser().consume((+simple_parser::any_except("\\\"")) >> v))
+ _imp->string_value.append(v);
+ else
+ throw InternalError(PALUDIS_HERE, "can't parse string");
+ }
+ }
+ else if (d.parser().consume(((+simple_parser::any_of(
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "_"
+ )) >> _imp->class_name)
+ & simple_parser::exact("(")))
+ {
+ while (true)
+ {
+ std::string k;
+ if (d.parser().consume(simple_parser::exact(");")))
+ break;
+ else if (d.parser().consume(((+simple_parser::any_of(
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "-_"
+ )) >> k)
+ & simple_parser::exact("=")))
+ {
+ std::tr1::shared_ptr<Deserialisation> c(new Deserialisation(k, d));
+ _imp->children.push_back(c);
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "can't parse keys, remaining text is '"
+ + d.parser().text().substr(d.parser().offset()));
+ }
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "can't parse keys, remaining text is '"
+ + d.parser().text().substr(d.parser().offset()));
+}
+
+Deserialisation::~Deserialisation()
+{
+}
+
+const std::string
+Deserialisation::item_name() const
+{
+ return _imp->item_name;
+}
+
+const std::string
+Deserialisation::class_name() const
+{
+ return _imp->class_name;
+}
+
+bool
+Deserialisation::null() const
+{
+ return _imp->null;
+}
+
+const std::string
+Deserialisation::string_value() const
+{
+ return _imp->string_value;
+}
+
+Deserialisation::ConstIterator
+Deserialisation::begin_children() const
+{
+ return ConstIterator(_imp->children.begin());
+}
+
+Deserialisation::ConstIterator
+Deserialisation::end_children() const
+{
+ return ConstIterator(_imp->children.end());
+}
+
+const Deserialiser &
+Deserialisation::deserialiser() const
+{
+ return _imp->deserialiser;
+}
+
+Deserialisator::Deserialisator(Deserialisation & d, const std::string & c) :
+ PrivateImplementationPattern<Deserialisator>(new Implementation<Deserialisator>(c))
+{
+ if (c != d.class_name())
+ throw InternalError(PALUDIS_HERE, "expected class name '" + stringify(c) + "' but got '"
+ + d.class_name() + "'");
+
+ for (Deserialisation::ConstIterator i(d.begin_children()), i_end(d.end_children()) ;
+ i != i_end ; ++i)
+ _imp->keys.insert(std::make_pair((*i)->item_name(), *i));
+}
+
+Deserialisator::~Deserialisator()
+{
+ if (! std::uncaught_exception())
+ {
+ if (! _imp->keys.empty())
+ throw InternalError(PALUDIS_HERE, "keys not empty when deserialising '" + _imp->class_name + "', keys remaining are { "
+ + join(first_iterator(_imp->keys.begin()), first_iterator(_imp->keys.end()), ", ") + " }");
+ }
+}
+
+const std::tr1::shared_ptr<Deserialisation>
+Deserialisator::find_remove_member(const std::string & s)
+{
+ std::map<std::string, std::tr1::shared_ptr<Deserialisation> >::iterator i(_imp->keys.find(s));
+ if (i == _imp->keys.end())
+ throw InternalError(PALUDIS_HERE, "no key '" + s + "'");
+ std::tr1::shared_ptr<Deserialisation> result(i->second);
+ _imp->keys.erase(i);
+ return result;
+}
+
+std::tr1::shared_ptr<const PackageID>
+DeserialisatorHandler<std::tr1::shared_ptr<const PackageID> >::handle(Deserialisation & v)
+{
+ return *(*v.deserialiser().environment())[
+ selection::RequireExactlyOne(generator::Matches(
+ parse_user_package_dep_spec(v.string_value(), v.deserialiser().environment(),
+ UserPackageDepSpecOptions() + updso_serialised), MatchPackageOptions()))]->begin();
+}
+
+template class PrivateImplementationPattern<Deserialiser>;
+template class PrivateImplementationPattern<Deserialisation>;
+template class PrivateImplementationPattern<Deserialisator>;
+
diff --git a/paludis/resolver/serialise.hh b/paludis/resolver/serialise.hh
new file mode 100644
index 0000000..6262e1b
--- /dev/null
+++ b/paludis/resolver/serialise.hh
@@ -0,0 +1,158 @@
+/* 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_SERIALISE_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_SERIALISE_HH 1
+
+#include <paludis/resolver/serialise-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/simple_parser-fwd.hh>
+#include <paludis/util/wrapped_forward_iterator-fwd.hh>
+#include <paludis/environment-fwd.hh>
+#include <tr1/memory>
+#include <string>
+#include <ostream>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ namespace serialise
+ {
+ struct container;
+ struct might_be_null;
+ }
+
+ template <
+ typename Flag1_ = void,
+ typename Flag2_ = void,
+ typename Flag3_ = void
+ >
+ struct SerialiserFlags
+ {
+ typedef Flag1_ Flag1;
+ typedef Flag2_ Flag2;
+ typedef Flag3_ Flag3;
+ };
+
+ class PALUDIS_VISIBLE SerialiserObjectWriter
+ {
+ private:
+ Serialiser & _serialiser;
+
+ public:
+ SerialiserObjectWriter(Serialiser &);
+ ~SerialiserObjectWriter();
+
+ template <
+ typename Flags_,
+ typename T_>
+ SerialiserObjectWriter & member(
+ const Flags_ &,
+ const std::string & item_name,
+ const T_ &);
+ };
+
+ class PALUDIS_VISIBLE Serialiser
+ {
+ private:
+ std::ostream & _stream;
+
+ public:
+ Serialiser(std::ostream &);
+ ~Serialiser();
+
+ SerialiserObjectWriter object(const std::string & class_name)
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::ostream & raw_stream() PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void escape_write(const std::string &);
+ };
+
+ class PALUDIS_VISIBLE Deserialiser :
+ private PrivateImplementationPattern<Deserialiser>
+ {
+ public:
+ Deserialiser(const Environment * const, const std::string &);
+ ~Deserialiser();
+
+ const Environment * environment() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ SimpleParser & parser() PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE Deserialisation :
+ private PrivateImplementationPattern<Deserialisation>
+ {
+ public:
+ Deserialisation(const std::string &, Deserialiser &);
+ ~Deserialisation();
+
+ const Deserialiser & deserialiser() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::string item_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::string class_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::string string_value() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ bool null() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ struct ConstIteratorTag;
+ typedef WrappedForwardIterator<ConstIteratorTag,
+ const std::tr1::shared_ptr<Deserialisation> > ConstIterator;
+ ConstIterator begin_children() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ ConstIterator end_children() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE Deserialisator :
+ private PrivateImplementationPattern<Deserialisator>
+ {
+ public:
+ Deserialisator(
+ Deserialisation &,
+ const std::string & class_name);
+
+ ~Deserialisator();
+
+ const Deserialisation & deserialisation() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ template <typename T_> T_ member(const std::string & key_name);
+
+ const std::tr1::shared_ptr<Deserialisation> find_remove_member(
+ const std::string &) PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ };
+
+ template <typename T_>
+ std::tr1::shared_ptr<T_> deserialise(
+ const Environment * const,
+ const std::string &,
+ const std::string &) PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<resolver::Deserialiser>;
+ extern template class PrivateImplementationPattern<resolver::Deserialisation>;
+ extern template class PrivateImplementationPattern<resolver::Deserialisator>;
+#endif
+}
+
+#endif
diff --git a/paludis/resolver/use_installed.se b/paludis/resolver/use_installed.se
index ec6e438..1ff9b09 100644
--- a/paludis/resolver/use_installed.se
+++ b/paludis/resolver/use_installed.se
@@ -12,5 +12,7 @@ make_enum_UseInstalled()
key ui_if_same "If it is the same"
key ui_if_same_version "If it is the same version"
key ui_if_possible "If possible"
+
+ want_destringify
}
diff --git a/paludis/util/system.cc b/paludis/util/system.cc
index 4fe74e8..c9340b3 100644
--- a/paludis/util/system.cc
+++ b/paludis/util/system.cc
@@ -165,6 +165,9 @@ namespace paludis
std::tr1::function<std::string (const std::string &)> pipe_command_handler;
std::ostream * captured_stdout_stream;
std::ostream * captured_stderr_stream;
+ std::istream * input_stream;
+ int input_fd;
+ std::string input_fd_env_var;
bool ptys;
Implementation(const std::string & c, bool cl = false,
@@ -176,7 +179,10 @@ namespace paludis
const bool b = false, const bool bb = false,
const std::tr1::function<std::string (const std::string &)> & h = std::tr1::function<std::string (const std::string &)>(),
std::ostream * cs = 0,
- std::ostream * ds = 0) :
+ std::ostream * ds = 0,
+ std::istream * is = 0,
+ int isf = -1,
+ const std::string & isfe = "") :
command(c),
clearenv(cl),
setenv_values(s),
@@ -191,6 +197,9 @@ namespace paludis
pipe_command_handler(h),
captured_stdout_stream(cs),
captured_stderr_stream(ds),
+ input_stream(is),
+ input_fd(isf),
+ input_fd_env_var(isfe),
ptys(false)
{
}
@@ -213,7 +222,8 @@ Command::Command(const Command & other) :
other._imp->uid, other._imp->gid, other._imp->stdout_prefix, other._imp->stderr_prefix,
other._imp->prefix_discard_blank_output,
other._imp->prefix_blank_lines, other._imp->pipe_command_handler, other._imp->captured_stdout_stream,
- other._imp->captured_stderr_stream))
+ other._imp->captured_stderr_stream, other._imp->input_stream, other._imp->input_fd,
+ other._imp->input_fd_env_var))
{
}
@@ -231,7 +241,10 @@ Command::operator= (const Command & other)
other._imp->prefix_discard_blank_output,
other._imp->prefix_blank_lines,
other._imp->pipe_command_handler, other._imp->captured_stdout_stream,
- other._imp->captured_stderr_stream));
+ other._imp->captured_stderr_stream,
+ other._imp->input_stream,
+ other._imp->input_fd,
+ other._imp->input_fd_env_var));
if (other.uid() && other.gid())
with_uid_gid(*other.uid(), *other.gid());
}
@@ -287,6 +300,15 @@ Command::with_captured_stderr_stream(std::ostream * const c)
}
Command &
+Command::with_input_stream(std::istream * const c, int fd, const std::string & e)
+{
+ _imp->input_stream = c;
+ _imp->input_fd = fd;
+ _imp->input_fd_env_var = e;
+ return *this;
+}
+
+Command &
Command::with_ptys()
{
_imp->ptys = true;
@@ -404,7 +426,8 @@ paludis::run_command(const Command & cmd)
Log::get_instance()->message("util.system.execl", ll_debug, lc_no_context) << "execl /bin/sh -c " << command
<< " " << extras;
- std::tr1::shared_ptr<Pipe> internal_command_reader(new Pipe), pipe_command_reader, pipe_command_response;
+ std::tr1::shared_ptr<Pipe> internal_command_reader(new Pipe), pipe_command_reader,
+ pipe_command_response, input_stream;
std::tr1::shared_ptr<Channel> captured_stdout, captured_stderr;
if (cmd.pipe_command_handler())
{
@@ -415,6 +438,8 @@ paludis::run_command(const Command & cmd)
captured_stdout.reset(cmd.ptys() ? static_cast<Channel *>(new Pty) : new Pipe);
if (cmd.captured_stderr_stream())
captured_stderr.reset(cmd.ptys() ? static_cast<Channel *>(new Pty) : new Pipe);
+ if (cmd.input_stream())
+ input_stream.reset(new Pipe);
/* Why do we fork twice, rather than install a SIGCHLD handler that writes to a pipe that
* our pselect watches? Simple: Unix is retarded. APUE 12.8 says "Each thread has its own signal
@@ -469,6 +494,12 @@ paludis::run_command(const Command & cmd)
captured_stderr->clear_read_fd();
}
+ if (cmd.input_stream())
+ {
+ close(input_stream->write_fd());
+ input_stream->clear_write_fd();
+ }
+
close(internal_command_reader->read_fd());
internal_command_reader->clear_read_fd();
close(internal_command_reader->write_fd());
@@ -514,12 +545,12 @@ paludis::run_command(const Command & cmd)
if (cmd.captured_stdout_stream())
{
if (-1 == dup2(captured_stdout->write_fd(), 1))
- throw RunCommandError("dup2 failed: " + stringify(strerror(errno)));
+ throw RunCommandError("captured stdout dup2 failed: " + stringify(strerror(errno)));
}
else if (-1 != stdout_write_fd)
{
if (-1 == dup2(stdout_write_fd, 1))
- throw RunCommandError("dup2 failed: " + stringify(strerror(errno)));
+ throw RunCommandError("stdout dup2 failed: " + stringify(strerror(errno)));
if (-1 != stdout_close_fd)
close(stdout_close_fd);
@@ -528,17 +559,33 @@ paludis::run_command(const Command & cmd)
if (cmd.captured_stderr_stream())
{
if (-1 == dup2(captured_stderr->write_fd(), 2))
- throw RunCommandError("dup2 failed: " + stringify(strerror(errno)));
+ throw RunCommandError("captured stderr dup2 failed: " + stringify(strerror(errno)));
}
else if (-1 != stderr_write_fd)
{
if (-1 == dup2(stderr_write_fd, 2))
- throw RunCommandError("dup2 failed: " + stringify(strerror(errno)));
+ throw RunCommandError("stderr dup2 failed: " + stringify(strerror(errno)));
if (-1 != stderr_close_fd)
close(stderr_close_fd);
}
+ if (cmd.input_stream())
+ {
+ int cmd_input_fd;
+
+ if (-1 == cmd.input_fd())
+ cmd_input_fd = dup(input_stream->read_fd());
+ else
+ cmd_input_fd = dup2(input_stream->read_fd(), cmd.input_fd());
+
+ if (-1 == cmd_input_fd)
+ throw RunCommandError("input dup2 failed: " + stringify(strerror(errno)));
+
+ if (! cmd.input_fd_env_var().empty())
+ setenv(cmd.input_fd_env_var().c_str(), stringify(cmd_input_fd).c_str(), 1);
+ }
+
if (cmd.gid() && *cmd.gid() != getgid())
{
gid_t g(*cmd.gid());
@@ -627,6 +674,14 @@ paludis::run_command(const Command & cmd)
captured_stderr->clear_write_fd();
}
+ if (cmd.input_stream())
+ {
+ close(input_stream->read_fd());
+ input_stream->clear_read_fd();
+ close(input_stream->write_fd());
+ input_stream->clear_write_fd();
+ }
+
close(internal_command_reader->read_fd());
internal_command_reader->clear_read_fd();
@@ -695,14 +750,21 @@ paludis::run_command(const Command & cmd)
captured_stderr->clear_write_fd();
}
+ if (cmd.input_stream())
+ {
+ close(input_stream->read_fd());
+ input_stream->clear_read_fd();
+ }
+
close(internal_command_reader->write_fd());
internal_command_reader->clear_write_fd();
std::string pipe_command_buffer, internal_command_buffer;
while (true)
{
- fd_set read_fds;
+ fd_set read_fds, write_fds;
FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
int max_fd(0);
if (cmd.pipe_command_handler())
@@ -723,6 +785,12 @@ paludis::run_command(const Command & cmd)
max_fd = std::max(max_fd, captured_stderr->read_fd());
}
+ if (cmd.input_stream() && -1 != input_stream->write_fd())
+ {
+ FD_SET(input_stream->write_fd(), &write_fds);
+ max_fd = std::max(max_fd, input_stream->write_fd());
+ }
+
FD_SET(internal_command_reader->read_fd(), &read_fds);
max_fd = std::max(max_fd, internal_command_reader->read_fd());
@@ -730,7 +798,7 @@ paludis::run_command(const Command & cmd)
tv.tv_sec = 5;
tv.tv_nsec = 0;
- int retval(pselect(max_fd + 1, &read_fds, 0, 0, &tv, 0));
+ int retval(pselect(max_fd + 1, &read_fds, &write_fds, 0, &tv, 0));
if (-1 == retval)
throw RunCommandError("select failed: " + stringify(strerror(errno)));
else if (0 == retval)
@@ -779,6 +847,37 @@ paludis::run_command(const Command & cmd)
if (((r = read(internal_command_reader->read_fd(), buf, 1024))) > 0)
internal_command_buffer.append(std::string(buf, r));
}
+
+ if (cmd.input_stream() && (-1 != input_stream->write_fd())
+ && FD_ISSET(input_stream->write_fd(), &write_fds))
+ {
+ bool eof(! cmd.input_stream()->good());
+
+ while (! eof)
+ {
+ char c;
+ if (cmd.input_stream()->get(c).good())
+ {
+ int w(write(input_stream->write_fd(), &c, 1));
+ if (-1 == w)
+ throw RunCommandError("write failed: " + stringify(strerror(errno)));
+ else if (0 == w)
+ {
+ cmd.input_stream()->unget();
+ break;
+ }
+ }
+ else
+ eof = true;
+ }
+
+ if (eof)
+ {
+ if (0 != close(input_stream->write_fd()))
+ throw RunCommandError("close failed: " + stringify(strerror(errno)));
+ input_stream->clear_write_fd();
+ }
+ }
}
if (! pipe_command_buffer.empty())
@@ -973,6 +1072,24 @@ Command::captured_stderr_stream() const
return _imp->captured_stderr_stream;
}
+std::istream *
+Command::input_stream() const
+{
+ return _imp->input_stream;
+}
+
+int
+Command::input_fd() const
+{
+ return _imp->input_fd;
+}
+
+const std::string
+Command::input_fd_env_var() const
+{
+ return _imp->input_fd_env_var;
+}
+
bool
Command::ptys() const
{
diff --git a/paludis/util/system.hh b/paludis/util/system.hh
index bd11f75..20fae26 100644
--- a/paludis/util/system.hh
+++ b/paludis/util/system.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 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
@@ -204,6 +204,21 @@ namespace paludis
Command & with_captured_stderr_stream(std::ostream * const);
/**
+ * Send the contents of a stream in via a particular FD.
+ *
+ * May only be called once.
+ *
+ * \param fd Send the stream to this FD. If -1, pick an unused FD.
+ * \param env_var If not empty, put the FD chosen in this env var.
+ *
+ * \since 0.40
+ */
+ Command & with_input_stream(
+ std::istream * const,
+ int fd,
+ const std::string & env_var);
+
+ /**
* Use ptys instead of pipes to capture stdout and/or stderr.
*
* \since 0.38
@@ -279,6 +294,27 @@ namespace paludis
std::ostream * captured_stderr_stream() const;
/**
+ * The input stream, or null.
+ *
+ * \since 0.40
+ */
+ std::istream * input_stream() const;
+
+ /**
+ * The input FD, if input_stream() not null.
+ *
+ * \since 0.40
+ */
+ int input_fd() const;
+
+ /**
+ * The input FD env var, if input_stream() not null.
+ *
+ * \since 0.40
+ */
+ const std::string input_fd_env_var() const;
+
+ /**
* Uses ptys instead of pipes?
*
* \since 0.38
diff --git a/paludis/util/system_TEST.cc b/paludis/util/system_TEST.cc
index 28ab73c..538b3b6 100644
--- a/paludis/util/system_TEST.cc
+++ b/paludis/util/system_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 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
@@ -279,7 +279,6 @@ namespace test_cases
}
} test_captured_fail;
-
struct CapturedPipeCommandTest : TestCase
{
CapturedPipeCommandTest() : TestCase("captured pipe command") { }
@@ -297,5 +296,59 @@ namespace test_cases
TEST_CHECK(! std::getline(s, line));
}
} test_captured_pipe_command;
+
+ struct StdinCommandTest : TestCase
+ {
+ StdinCommandTest() : TestCase("stdin") { }
+
+ void run()
+ {
+ std::stringstream is, os;
+ for (int n(0) ; n < 300 ; ++n)
+ is << "I chased a bug around a tree\n";
+
+ TEST_CHECK_EQUAL(run_command(Command("cat")
+ .with_input_stream(&is, 0, "")
+ .with_captured_stdout_stream(&os)
+ ),
+ 0);
+
+ std::string line;
+ for (int n(0) ; n < 300 ; ++n)
+ {
+ std::getline(os, line);
+ TEST_CHECK_EQUAL(line, "I chased a bug around a tree");
+ }
+
+ TEST_CHECK(! std::getline(os, line));
+ }
+ } test_stdin;
+
+ struct InputCommandTest : TestCase
+ {
+ InputCommandTest() : TestCase("input") { }
+
+ void run()
+ {
+ std::stringstream is, os;
+ for (int n(0) ; n < 300 ; ++n)
+ is << "The cat crept into the crypt\n";
+
+ TEST_CHECK_EQUAL(run_command(Command("cat <&$THE_FD")
+ .with_input_stream(&is, -1, "THE_FD")
+ .with_captured_stdout_stream(&os)
+ ),
+ 0);
+
+ std::string line;
+ for (int n(0) ; n < 300 ; ++n)
+ {
+ std::getline(os, line);
+ TEST_CHECK_EQUAL(line, "The cat crept into the crypt");
+ }
+
+ TEST_CHECK(! std::getline(os, line));
+ }
+ } test_input;
}
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index 6ac09b0..c9c6fa2 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -41,6 +41,8 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/sanitised_dependencies.hh>
#include <paludis/resolver/destinations.hh>
+#include <paludis/resolver/serialise-impl.hh>
+#include <paludis/resolver/resolutions.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/notifier_callback.hh>
#include <paludis/generator.hh>
@@ -616,7 +618,14 @@ ResolveCommand::run(
}
}
- display_resolution(env, resolver, cmdline);
+ std::stringstream ser;
+ Serialiser s(ser);
+ resolver->resolutions()->serialise(s);
+
+ std::tr1::shared_ptr<Resolutions> copied_resolutions(deserialise<Resolutions>(
+ env.get(), ser.str(), "Resolutions"));
+
+ display_resolution(env, copied_resolutions, cmdline);
display_explanations(env, resolver, cmdline);
}
catch (...)
diff --git a/src/clients/cave/cmd_resolve_display_resolution.cc b/src/clients/cave/cmd_resolve_display_resolution.cc
index f5ea9a6..6a6e95b 100644
--- a/src/clients/cave/cmd_resolve_display_resolution.cc
+++ b/src/clients/cave/cmd_resolve_display_resolution.cc
@@ -76,14 +76,14 @@ namespace
void
paludis::cave::display_resolution(
const std::tr1::shared_ptr<Environment> &,
- const std::tr1::shared_ptr<Resolver> & resolver,
+ const std::tr1::shared_ptr<Resolutions> & resolutions,
const ResolveCommandLine &)
{
Context context("When displaying chosen resolution:");
std::cout << "These are the actions I will take, in order:" << std::endl << std::endl;
- for (Resolutions::ConstIterator c(resolver->resolutions()->begin()), c_end(resolver->resolutions()->end()) ;
+ for (Resolutions::ConstIterator c(resolutions->begin()), c_end(resolutions->end()) ;
c != c_end ; ++c)
{
const std::tr1::shared_ptr<const PackageID> id((*c)->decision()->if_package_id());
diff --git a/src/clients/cave/cmd_resolve_display_resolution.hh b/src/clients/cave/cmd_resolve_display_resolution.hh
index ded734e..472d7a0 100644
--- a/src/clients/cave/cmd_resolve_display_resolution.hh
+++ b/src/clients/cave/cmd_resolve_display_resolution.hh
@@ -21,7 +21,7 @@
#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_RESOLVE_DISPLAY_RESOLUTION_HH 1
#include <paludis/environment-fwd.hh>
-#include <paludis/resolver/resolver-fwd.hh>
+#include <paludis/resolver/resolutions-fwd.hh>
#include "cmd_resolve_cmdline.hh"
namespace paludis
@@ -30,7 +30,7 @@ namespace paludis
{
void display_resolution(
const std::tr1::shared_ptr<Environment> &,
- const std::tr1::shared_ptr<resolver::Resolver> & resolver,
+ const std::tr1::shared_ptr<resolver::Resolutions> &,
const ResolveCommandLine &);
}
}