aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-12-11 23:51:23 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-12-11 23:51:23 +0000
commit4c757c6778371e139f302112c401cd9b1f11276c (patch)
treeca886c163b69325d0ca731f7a313043eb50486a7
parent17713e3263bd523cd60208e221f0cebdbad0f3af (diff)
downloadpaludis-4c757c6778371e139f302112c401cd9b1f11276c.tar.gz
paludis-4c757c6778371e139f302112c401cd9b1f11276c.tar.xz
Rewrite resolve ui code to make better use of jobs
-rw-r--r--src/clients/cave/cmd_display_resolution.cc1083
-rw-r--r--src/clients/cave/cmd_resolve_cmdline.cc4
-rw-r--r--src/clients/cave/cmd_resolve_cmdline.hh1
3 files changed, 567 insertions, 521 deletions
diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index 43be03f..0d2b9ac 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -37,6 +37,7 @@
#include <paludis/util/make_named_values.hh>
#include <paludis/util/make_shared_copy.hh>
#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/simple_visitor_cast.hh>
#include <paludis/resolver/resolutions.hh>
#include <paludis/resolver/reason.hh>
#include <paludis/resolver/sanitised_dependencies.hh>
@@ -163,523 +164,634 @@ namespace
}
};
- struct NotBestVisitor
+ struct IDForDecisionOrNullVisitor
{
- bool visit(const ExistingNoChangeDecision &) const
+ const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & d) const
{
- return false;
+ return d.existing_id();
}
- bool visit(const NothingNoChangeDecision &) const
+ const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & d) const
{
- return false;
+ return d.origin_id();
}
- bool visit(const UnableToMakeDecision &) const
+ const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
{
- return false;
+ return make_null_shared_ptr();
}
- bool visit(const ChangesToMakeDecision & d) const
+ const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
{
- return ! d.best();
+ return make_null_shared_ptr();
}
};
- void display_reasons(
- const std::tr1::shared_ptr<const Resolution> & resolution,
- const bool verbose)
+ const std::tr1::shared_ptr<const PackageID> id_for_decision_or_null(const Decision & d)
{
- std::set<std::string> reason_names, special_reason_names;
- for (Constraints::ConstIterator r(resolution->constraints()->begin()),
- r_end(resolution->constraints()->end()) ;
- r != r_end ; ++r)
+ return d.accept_returning<std::tr1::shared_ptr<const PackageID> >(IDForDecisionOrNullVisitor());
+ }
+
+ bool decision_matches_spec(
+ const std::tr1::shared_ptr<Environment> & env,
+ const Resolvent & resolvent,
+ const Decision & decision,
+ const PackageDepSpec & spec)
+ {
+ const std::tr1::shared_ptr<const PackageID> maybe_id(id_for_decision_or_null(decision));
+ if (maybe_id)
+ return match_package(*env, spec, *maybe_id, MatchPackageOptions());
+ else
{
- ReasonNameGetter g(verbose);
- std::pair<std::string, bool> s((*r)->reason()->accept_returning<std::pair<std::string, bool> >(g));
- if (! s.first.empty())
- {
- if (s.second)
- special_reason_names.insert(s.first);
- else
- reason_names.insert(s.first);
- }
+ /* could also match slot here too */
+ return match_qpns(*env, spec, resolvent.package());
}
+ }
- if ((! special_reason_names.empty()) || (! reason_names.empty()))
- {
- if (verbose)
- {
- cout << " Because of" << endl;
- if (! special_reason_names.empty())
- cout << " * " << c::bold_yellow() << join(special_reason_names.begin(),
- special_reason_names.end(), c::normal() + "\n * " + c::bold_yellow())
- << c::normal() << endl;
-
- if (! reason_names.empty())
- cout << " * " << join(reason_names.begin(), reason_names.end(), "\n * ")
- << endl;
- }
- else
- {
- cout << " Because of ";
+ void display_one_constraint(const Constraint & c)
+ {
+ cout << c.spec();
- if (! special_reason_names.empty())
- cout << c::bold_yellow() << join(special_reason_names.begin(), special_reason_names.end(), ", ")
- << c::normal();
+ switch (c.use_existing())
+ {
+ case ue_if_same:
+ cout << ", use existing if same";
+ break;
+ case ue_never:
+ cout << ", never using existing";
+ break;
+ case ue_only_if_transient:
+ cout << ", using existing only if transient";
+ break;
+ case ue_if_same_version:
+ cout << ", use existing if same version";
+ break;
+ case ue_if_possible:
+ cout << ", use existing if possible";
+ break;
- if (! reason_names.empty())
- {
- if (! special_reason_names.empty())
- cout << ", ";
+ case last_ue:
+ break;
+ }
- if (reason_names.size() > 4)
- cout << join(reason_names.begin(), next(reason_names.begin(), 3), ", ")
- << ", " << (reason_names.size() - 3) << " more";
- else
- cout << join(reason_names.begin(), reason_names.end(), ", ");
- }
+ switch (c.destination_type())
+ {
+ case dt_install_to_slash:
+ cout << ", installing to /";
+ break;
- cout << endl;
- }
+ case dt_create_binary:
+ cout << ", creating a binary";
+ break;
- if (resolution->decision()->accept_returning<bool>(NotBestVisitor()))
- cout << c::bold_red() << " Which prevented selection of the best candidate" << c::normal() << endl;
+ case last_dt:
+ break;
}
}
- std::string mask_stringifier(const Mask & mask)
+ void display_explanation_constraints(const Constraints & constraints)
{
- return stringify(mask.key());
+ cout << " The following constraints were in action:" << endl;
+ for (Constraints::ConstIterator c(constraints.begin()), c_end(constraints.end()) ;
+ c != c_end ; ++c)
+ {
+ cout << " * ";
+ display_one_constraint(**c);
+ cout << endl;
+ cout << " Because of ";
+ ReasonNameGetter g(true);
+ cout << (*c)->reason()->accept_returning<std::pair<std::string, bool> >(g).first;
+ cout << endl;
+ }
}
- struct DisplayOneErrorVisitor
+ struct DisplayExplanationDecisionVisitor
{
- void visit(const UnableToMakeDecision & d) const
+ void visit(const ExistingNoChangeDecision & d) const
{
- if (d.unsuitable_candidates()->empty())
- cout << " No potential candidates were found" << endl;
- else
- {
- cout << " Potential candidates were:" << endl;
- for (UnsuitableCandidates::ConstIterator u(d.unsuitable_candidates()->begin()), u_end(d.unsuitable_candidates()->end()) ;
- u != u_end ; ++u)
- {
- cout << " " << *u->package_id() << ": ";
-
- if (u->package_id()->masked())
- cout << c::bold_red() << "masked" << c::normal() << " (" << join(indirect_iterator(u->package_id()->begin_masks()),
- indirect_iterator(u->package_id()->end_masks()), "", mask_stringifier) << ")";
-
- if (! u->unmet_constraints()->empty())
- {
- if (u->package_id()->masked())
- cout << ", ";
- cout << c::bold_red() << "unmatching" << c::normal() << " (" << (*u->unmet_constraints()->begin())->spec();
- int dx(std::distance(u->unmet_constraints()->begin(), u->unmet_constraints()->end()));
- if (dx > 1)
- cout << ", " << dx << " more";
- cout << ")";
- }
-
- cout << endl;
- }
- }
+ cout << " The decision made was:" << endl;
+ cout << " Use existing ID " << *d.existing_id() << endl;
}
- void visit(const ExistingNoChangeDecision &) const
+ void visit(const NothingNoChangeDecision &) const
{
+ cout << " The decision made was:" << endl;
+ cout << " Do not do anything" << endl;
}
- void visit(const ChangesToMakeDecision &) const
+ void visit(const ChangesToMakeDecision & d) const
{
+ cout << " The decision made was:" << endl;
+ cout << " Use origin ID " << *d.origin_id() << endl;
+ cout << " Install to repository " << d.destination()->repository() << endl;
+ for (PackageIDSequence::ConstIterator i(d.destination()->replacing()->begin()), i_end(d.destination()->replacing()->end()) ;
+ i != i_end ; ++i)
+ cout << " Replacing " << **i << endl;
}
- void visit(const NothingNoChangeDecision &) const
+ void visit(const UnableToMakeDecision &) const
{
+ cout << " No decision could be made" << endl;
}
};
- void display_one_error(
- const std::tr1::shared_ptr<Environment> &,
- const DisplayResolutionCommandLine &,
- const std::tr1::shared_ptr<const Resolution> & resolution,
- const bool verbose)
+ void display_explanation_decision(const Decision & decision)
{
- if (resolution->resolvent().slot().name_or_null())
- cout << "? " << c::bold_red() << resolution->resolvent() << c::normal();
- else if (! resolution->resolvent().slot().null_means_unknown())
- cout << "? " << c::bold_red() << resolution->resolvent() << c::normal();
- else
- cout << "? " << c::bold_red() << resolution->resolvent().package()
- << " -> " << resolution->resolvent().destination_type() << c::normal();
- cout << " (no decision could be reached)" << endl;
+ decision.accept(DisplayExplanationDecisionVisitor());
+ }
+
+ void display_explanations(
+ const std::tr1::shared_ptr<Environment> & env,
+ const ResolverLists & lists,
+ const DisplayResolutionCommandLine & cmdline)
+ {
+ Context context("When displaying explanations:");
+
+ if (cmdline.display_options.a_explain.begin_args() == cmdline.display_options.a_explain.end_args())
+ return;
- display_reasons(resolution, verbose);
+ cout << "Explaining requested decisions:" << endl << endl;
- resolution->decision()->accept(DisplayOneErrorVisitor());
+ for (args::StringSetArg::ConstIterator i(cmdline.display_options.a_explain.begin_args()),
+ i_end(cmdline.display_options.a_explain.end_args()) ;
+ i != i_end ; ++i)
+ {
+ bool any(false);
+ PackageDepSpec spec(parse_user_package_dep_spec(*i, env.get(), UserPackageDepSpecOptions() + updso_allow_wildcards));
+ for (Resolutions::ConstIterator r(lists.all_resolutions()->begin()), r_end(lists.all_resolutions()->end()) ;
+ r != r_end ; ++r)
+ {
+ if (! decision_matches_spec(env, (*r)->resolvent(), *(*r)->decision(), spec))
+ continue;
+
+ any = true;
+
+ cout << "For " << (*r)->resolvent() << ":" << endl;
+
+ display_explanation_constraints(*(*r)->constraints());
+ display_explanation_decision(*(*r)->decision());
+ }
+
+ if (! any)
+ throw args::DoHelp("There is nothing matching '" + *i + "' in the resolution set.");
+ }
}
- struct ChosenIDVisitor
+ void display_one_description(
+ const std::tr1::shared_ptr<Environment> &,
+ const DisplayResolutionCommandLine & cmdline,
+ const std::tr1::shared_ptr<const PackageID> & id,
+ const bool is_new)
{
- const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
- {
- return decision.origin_id();
+ if (id->short_description_key())
+ {
+ bool show(false);
+ if (cmdline.display_options.a_show_descriptions.argument() == "none")
+ show = false;
+ else if (cmdline.display_options.a_show_descriptions.argument() == "new")
+ show = is_new;
+ else if (cmdline.display_options.a_show_descriptions.argument() == "all")
+ show = true;
+ else
+ throw args::DoHelp("Don't understand argument '"
+ + cmdline.display_options.a_show_descriptions.argument() + "' to '--"
+ + cmdline.display_options.a_show_descriptions.long_name() + "'");
+
+ if (show)
+ cout << " \"" << id->short_description_key()->value() << "\"" << endl;
}
+ }
- const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ void display_choices(
+ const std::tr1::shared_ptr<Environment> &,
+ const DisplayResolutionCommandLine &,
+ const std::tr1::shared_ptr<const PackageID> & id,
+ const std::tr1::shared_ptr<const PackageID> & old_id
+ )
+ {
+ if (! id->choices_key())
+ return;
+
+ ColourFormatter formatter(0);
+
+ std::tr1::shared_ptr<const Choices> old_choices;
+ if (old_id && old_id->choices_key())
+ old_choices = old_id->choices_key()->value();
+
+ bool non_blank_prefix(false);
+ std::string s;
+ for (Choices::ConstIterator k(id->choices_key()->value()->begin()),
+ k_end(id->choices_key()->value()->end()) ;
+ k != k_end ; ++k)
{
- return decision.existing_id();
+ if ((*k)->hidden())
+ continue;
+
+ bool shown_prefix(false);
+ for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
+ i != i_end ; ++i)
+ {
+ if (! (*i)->explicitly_listed())
+ continue;
+
+ if (! shown_prefix)
+ {
+ if (non_blank_prefix || ! (*k)->show_with_no_prefix())
+ {
+ shown_prefix = true;
+ if (! s.empty())
+ s.append(" ");
+ s.append((*k)->raw_name() + ":");
+ }
+ }
+
+ if (! s.empty())
+ s.append(" ");
+
+ std::string t;
+ if ((*i)->enabled())
+ {
+ if ((*i)->locked())
+ t = formatter.format(**i, format::Forced());
+ else
+ t = formatter.format(**i, format::Enabled());
+ }
+ else
+ {
+ if ((*i)->locked())
+ t = formatter.format(**i, format::Masked());
+ else
+ t = formatter.format(**i, format::Disabled());
+ }
+
+ bool changed(false), added(false);
+ if ((*k)->consider_added_or_changed())
+ {
+ if (old_choices)
+ {
+ std::tr1::shared_ptr<const ChoiceValue> old_choice(
+ old_choices->find_by_name_with_prefix((*i)->name_with_prefix()));
+ if (! old_choice)
+ added = true;
+ else if (old_choice->enabled() != (*i)->enabled())
+ changed = true;
+ }
+ else
+ added = true;
+ }
+
+ if (changed)
+ {
+ t = formatter.decorate(**i, t, format::Changed());
+ }
+ else if (added)
+ {
+ if (old_id)
+ t = formatter.decorate(**i, t, format::Added());
+ }
+
+ s.append(t);
+ }
}
- const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ if (s.empty())
+ return;
+
+ cout << " " << s << endl;
+ }
+
+ void display_reasons(
+ const std::tr1::shared_ptr<const Resolution> & resolution
+ )
+ {
+ std::set<std::string> reasons, special_reasons;
+ for (Constraints::ConstIterator c(resolution->constraints()->begin()),
+ c_end(resolution->constraints()->end()) ;
+ c != c_end ; ++c)
{
- return make_null_shared_ptr();
+ ReasonNameGetter g(false);
+ std::pair<std::string, bool> r((*c)->reason()->accept_returning<std::pair<std::string, bool> >(g));
+ if (r.first.empty())
+ continue;
+
+ if (r.second)
+ special_reasons.insert(r.first);
+ else
+ reasons.insert(r.first);
}
- const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ for (std::set<std::string>::const_iterator r(special_reasons.begin()), r_end(special_reasons.end()) ;
+ r != r_end ; ++r)
+ reasons.erase(*r);
+
+ if (reasons.empty() && special_reasons.empty())
+ return;
+
+ cout << " Reasons: ";
+
+ int n_shown(0);
+ for (std::set<std::string>::const_iterator r(special_reasons.begin()), r_end(special_reasons.end()) ;
+ r != r_end ; ++r)
{
- return make_null_shared_ptr();
+ if (++n_shown != 1)
+ cout << ", ";
+ cout << c::bold_yellow() << *r << c::normal();
}
- };
- struct DestinationVisitor
- {
- const std::tr1::shared_ptr<const Destination> visit(const ChangesToMakeDecision & decision) const
+ int n_remaining(reasons.size());
+ for (std::set<std::string>::const_iterator r(reasons.begin()), r_end(reasons.end()) ;
+ r != r_end ; ++r)
{
- return decision.destination();
+ if (n_shown >= 3 && n_remaining > 1)
+ {
+ cout << ", " << n_remaining << " more";
+ break;
+ }
+
+ --n_remaining;
+ if (++n_shown != 1)
+ cout << ", ";
+ cout << c::yellow() << *r << c::normal();
}
- const std::tr1::shared_ptr<const Destination> visit(const ExistingNoChangeDecision &) const
+ cout << endl;
+ }
+
+ void display_one_installish(
+ const std::tr1::shared_ptr<Environment> & env,
+ const DisplayResolutionCommandLine & cmdline,
+ 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);
+
+ if (decision.destination()->replacing()->empty())
{
- return make_null_shared_ptr();
+ 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();
}
-
- const std::tr1::shared_ptr<const Destination> visit(const NothingNoChangeDecision &) const
+ else
{
- return make_null_shared_ptr();
+ 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())
+ 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;
+ }
}
- const std::tr1::shared_ptr<const Destination> visit(const UnableToMakeDecision &) const
+ /* pick the worst, in case we're replacing multiple things */
+ is_upgrade = is_upgrade && (! is_reinstall) && (! is_downgrade);
+ is_reinstall = is_reinstall && (! is_downgrade);
+
+ if (is_new && ! other_slots)
+ cout << "n " << c::bold_blue();
+ else if (is_new && other_slots)
+ cout << "s " << c::bold_blue();
+ else if (is_upgrade)
+ cout << "u " << c::blue();
+ else if (is_reinstall)
+ cout << "r " << c::yellow();
+ else if (is_downgrade)
+ cout << "d " << c::bold_yellow();
+ else
+ throw InternalError(PALUDIS_HERE, "not new, upgrade, reinstall or downgrade. huh?");
+
+ cout << decision.origin_id()->canonical_form(idcf_no_version);
+ cout << c::normal() << " " << decision.origin_id()->canonical_form(idcf_version) <<
+ " to " << decision.destination()->repository();
+
+ if (! decision.destination()->replacing()->empty())
{
- return make_null_shared_ptr();
+ cout << " replacing ";
+ bool first(true);
+ for (PackageIDSequence::ConstIterator i(decision.destination()->replacing()->begin()),
+ i_end(decision.destination()->replacing()->end()) ;
+ i != i_end ; ++i)
+ {
+ if (! first)
+ cout << ", ";
+ first = false;
+
+ if ((*i)->name() == decision.origin_id()->name())
+ cout << (*i)->canonical_form(idcf_version);
+ else
+ cout << (*i)->canonical_form(idcf_full);
+ }
}
- };
+ cout << endl;
+
+ std::tr1::shared_ptr<const PackageID> old_id;
+ if (! decision.destination()->replacing()->empty())
+ old_id = *decision.destination()->replacing()->begin();
- struct GetResolutionIfInstall
+ display_one_description(env, cmdline, decision.origin_id(), ! old_id);
+ display_choices(env, cmdline, decision.origin_id(), old_id);
+ display_reasons(resolution);
+ }
+
+ void display_one_install(
+ const std::tr1::shared_ptr<Environment> & env,
+ const DisplayResolutionCommandLine & cmdline,
+ const SimpleInstallJob & job)
{
- const std::tr1::shared_ptr<const Resolution> visit(
- const SimpleInstallJob & j) const
+ display_one_installish(env, cmdline, *job.decision(), job.resolution());
+ }
+
+ void display_special_job_decision(
+ const std::tr1::shared_ptr<Environment> &,
+ const DisplayResolutionCommandLine &,
+ const std::string & job_name,
+ const std::tr1::shared_ptr<const PackageID> & id)
+ {
+ cout << "- " << job_name << " " << *id << endl;
+ }
+
+ void display_unable_to_make_decision(
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const UnableToMakeDecision & d)
+ {
+ cout << "! " << c::bold_red() << resolution->resolvent() << c::normal() << endl;
+ display_reasons(resolution);
+
+ if (d.unsuitable_candidates()->empty())
+ return;
+
+ cout << " Unsuitable candidates:" << endl;
+ for (UnsuitableCandidates::ConstIterator u(d.unsuitable_candidates()->begin()),
+ u_end(d.unsuitable_candidates()->end()) ;
+ u != u_end ; ++u)
{
- return j.resolution();
+ cout << " * " << *u->package_id() << endl;
+ for (PackageID::MasksConstIterator m(u->package_id()->begin_masks()),
+ m_end(u->package_id()->end_masks()) ;
+ m != m_end ; ++m)
+ cout << " Masked by " << (*m)->description() << endl;
+
+ for (Constraints::ConstIterator c(u->unmet_constraints()->begin()),
+ c_end(u->unmet_constraints()->end()) ;
+ c != c_end ; ++c)
+ {
+ cout << " Did not meet ";
+ display_one_constraint(**c);
+ ReasonNameGetter g(false);
+ cout << " from " << (*c)->reason()->accept_returning<std::pair<std::string, bool> >(g).first;
+ cout << endl;
+ }
}
+ }
- const std::tr1::shared_ptr<const Resolution> visit(
- const UntakenInstallJob & j) const
+ struct DisplayOneUntakenVisitor
+ {
+ const std::tr1::shared_ptr<Environment> env;
+ const DisplayResolutionCommandLine & cmdline;
+ const std::tr1::shared_ptr<const Resolution> resolution;
+
+ DisplayOneUntakenVisitor(const std::tr1::shared_ptr<Environment> & e,
+ const DisplayResolutionCommandLine & c,
+ const std::tr1::shared_ptr<const Resolution> & r) :
+ env(e),
+ cmdline(c),
+ resolution(r)
{
- return j.resolution();
}
- const std::tr1::shared_ptr<const Resolution> visit(
- const UsableJob &) const
+ bool visit(const NothingNoChangeDecision &) const
{
- return make_null_shared_ptr();
+ return false;
}
- const std::tr1::shared_ptr<const Resolution> visit(
- const PretendJob &) const
+ bool visit(const ExistingNoChangeDecision &) const
{
- return make_null_shared_ptr();
+ return false;
}
- const std::tr1::shared_ptr<const Resolution> visit(
- const FetchJob &) const
+ bool visit(const ChangesToMakeDecision & d) const
{
- return make_null_shared_ptr();
+ display_one_installish(env, cmdline, d, resolution);
+ return true;
}
- const std::tr1::shared_ptr<const Resolution> visit(
- const SyncPointJob &) const
+ bool visit(const UnableToMakeDecision & d) const
{
- return make_null_shared_ptr();
+ display_unable_to_make_decision(resolution, d);
+ return true;
}
};
- void display_resolution_list(
+ bool display_one_untaken(
const std::tr1::shared_ptr<Environment> & env,
- const std::tr1::shared_ptr<const Jobs> & jobs,
- const std::tr1::shared_ptr<const JobIDSequence> & list,
- const DisplayResolutionCommandLine & cmdline)
+ const DisplayResolutionCommandLine & cmdline,
+ const UntakenInstallJob & job)
{
- for (JobIDSequence::ConstIterator c(list->begin()), c_end(list->end()) ;
- c != c_end ; ++c)
- {
- const std::tr1::shared_ptr<const Resolution> resolution(jobs->fetch(*c)->accept_returning<
- std::tr1::shared_ptr<const Resolution> >(GetResolutionIfInstall()));
- if (! resolution)
- continue;
-
- const std::tr1::shared_ptr<const PackageID> id(resolution->decision()->accept_returning<
- std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
- if (! id)
- {
- display_one_error(env, cmdline, resolution, false);
- continue;
- }
-
- bool is_new(false), is_upgrade(false), is_downgrade(false), is_reinstall(false),
- other_slots(false);
- std::tr1::shared_ptr<const PackageID> old_id;
-
- const std::tr1::shared_ptr<const Destination> destination(resolution->decision()->accept_returning<
- std::tr1::shared_ptr<const Destination> >(DestinationVisitor()));
- if (! destination)
- throw InternalError(PALUDIS_HERE, "huh? ! destination");
-
- if (destination->replacing()->empty())
- {
- is_new = true;
- const std::tr1::shared_ptr<const PackageIDSequence> others((*env)[selection::SomeArbitraryVersion(
- generator::Package(id->name()) &
- generator::InRepository(destination->repository())
- )]);
- other_slots = ! others->empty();
- }
- else
- for (PackageIDSequence::ConstIterator x(destination->replacing()->begin()),
- x_end(destination->replacing()->end()) ;
- x != x_end ; ++x)
- {
- old_id = *x;
- if ((*x)->version() == id->version())
- is_reinstall = true;
- else if ((*x)->version() < id->version())
- is_upgrade = true;
- else if ((*x)->version() > id->version())
- is_downgrade = true;
- }
-
- /* pick the worst of what it is */
- is_upgrade = is_upgrade && (! is_reinstall) && (! is_downgrade);
- is_reinstall = is_reinstall && (! is_downgrade);
-
- std::string destination_string(c::red() + "/" + c::normal());
- switch (resolution->resolvent().destination_type())
- {
- case dt_install_to_slash:
- destination_string = "/";
- break;
-
- case dt_create_binary:
- destination_string = "b";
- break;
-
- case last_dt:
- break;
- }
-
- if (! resolution->decision()->taken())
- {
- cout << "-" << destination_string << " " << c::blue() << id->canonical_form(idcf_no_version);
- }
- else if (is_new)
- {
- if (other_slots)
- cout << "s" << destination_string << " " << c::bold_blue() << id->canonical_form(idcf_no_version);
- else
- cout << "n" << destination_string << " " << c::bold_blue() << id->canonical_form(idcf_no_version);
- }
- else if (is_upgrade)
- cout << "u" << destination_string << " " << c::blue() << id->canonical_form(idcf_no_version);
- else if (is_reinstall)
- cout << "r" << destination_string << " " << c::yellow() << id->canonical_form(idcf_no_version);
- else if (is_downgrade)
- cout << "d" << destination_string << " " << c::bold_yellow() << id->canonical_form(idcf_no_version);
- else
- throw InternalError(PALUDIS_HERE, "why did that happen?");
+ return job.resolution()->decision()->accept_returning<bool>(DisplayOneUntakenVisitor(
+ env, cmdline, job.resolution()));
+ }
- cout << c::normal() << " " << id->canonical_form(idcf_version);
+ struct DisplayOneJobVisitor
+ {
+ const std::tr1::shared_ptr<Environment> env;
+ const DisplayResolutionCommandLine & cmdline;
- cout << " to ::" << destination->repository();
- if (! destination->replacing()->empty())
- {
- cout << " replacing";
- bool first(true);
- for (PackageIDSequence::ConstIterator x(destination->replacing()->begin()),
- x_end(destination->replacing()->end()) ;
- x != x_end ; ++x)
- {
- bool different(false);
- std::string old_from;
- if ((*x)->from_repositories_key())
- {
- for (Set<std::string>::ConstIterator k((*x)->from_repositories_key()->value()->begin()),
- k_end((*x)->from_repositories_key()->value()->end()) ;
- k != k_end ; ++k)
- {
- if (stringify(id->repository()->name()) != *k)
- {
- if (id->from_repositories_key() && (id->from_repositories_key()->value()->end() !=
- id->from_repositories_key()->value()->find(*k)))
- {
- }
- else
- different = true;
- }
-
- if (old_from.empty())
- old_from = " from ::";
- else
- old_from.append(", ::");
-
- old_from.append(*k);
- }
- }
+ DisplayOneJobVisitor(
+ const std::tr1::shared_ptr<Environment> & e,
+ const DisplayResolutionCommandLine & c) :
+ env(e),
+ cmdline(c)
+ {
+ }
- if (! first)
- cout << ", ";
- else
- cout << " ";
- first = false;
+ bool visit(const PretendJob & job) const
+ {
+ if (! cmdline.display_options.a_show_all_jobs.specified())
+ return false;
- cout << (*x)->canonical_form(idcf_version);
- if (different)
- cout << old_from;
- }
- }
+ display_special_job_decision(env, cmdline, "Pretend", job.decision()->origin_id());
- cout << endl;
+ return true;
+ }
- if (id->choices_key())
- {
- ColourFormatter formatter(0);
+ bool visit(const FetchJob & job) const
+ {
+ if (! cmdline.display_options.a_show_all_jobs.specified())
+ return false;
- std::tr1::shared_ptr<const Choices> old_choices;
- if (old_id && old_id->choices_key())
- old_choices = old_id->choices_key()->value();
+ display_special_job_decision(env, cmdline, "Fetch", job.decision()->origin_id());
- bool non_blank_prefix(false);
- std::string s;
- for (Choices::ConstIterator k(id->choices_key()->value()->begin()),
- k_end(id->choices_key()->value()->end()) ;
- k != k_end ; ++k)
- {
- if ((*k)->hidden())
- continue;
+ return true;
+ }
- bool shown_prefix(false);
- for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
- i != i_end ; ++i)
- {
- if (! (*i)->explicitly_listed())
- continue;
-
- if (! shown_prefix)
- {
- if (non_blank_prefix || ! (*k)->show_with_no_prefix())
- {
- shown_prefix = true;
- if (! s.empty())
- s.append(" ");
- s.append((*k)->raw_name() + ":");
- }
- }
+ bool visit(const UsableJob & job) const
+ {
+ if (! cmdline.display_options.a_show_all_jobs.specified())
+ return false;
- if (! s.empty())
- s.append(" ");
+ cout << "- Can now use " << job.resolution()->resolvent() << endl;
- std::string t;
- if ((*i)->enabled())
- {
- if ((*i)->locked())
- t = formatter.format(**i, format::Forced());
- else
- t = formatter.format(**i, format::Enabled());
- }
- else
- {
- if ((*i)->locked())
- t = formatter.format(**i, format::Masked());
- else
- t = formatter.format(**i, format::Disabled());
- }
-
- bool changed(false), added(false);
- if ((*k)->consider_added_or_changed())
- {
- if (old_choices)
- {
- std::tr1::shared_ptr<const ChoiceValue> old_choice(
- old_choices->find_by_name_with_prefix((*i)->name_with_prefix()));
- if (! old_choice)
- added = true;
- else if (old_choice->enabled() != (*i)->enabled())
- changed = true;
- }
- else
- added = true;
- }
-
- if (changed)
- {
- t = formatter.decorate(**i, t, format::Changed());
- }
- else if (added)
- {
- if (old_id)
- t = formatter.decorate(**i, t, format::Added());
- }
-
- s.append(t);
- }
- }
+ return true;
+ }
- if (s.empty())
- break;
+ bool visit(const SimpleInstallJob & job) const
+ {
+ display_one_install(env, cmdline, job);
+ return true;
+ }
- cout << " " << s << endl;
- }
+ bool visit(const SyncPointJob & job) const
+ {
+ if (! cmdline.display_options.a_show_all_jobs.specified())
+ return false;
- if (id->short_description_key())
- {
- bool show(false);
- if (cmdline.display_options.a_show_descriptions.argument() == "none")
- show = false;
- else if (cmdline.display_options.a_show_descriptions.argument() == "new")
- show = is_new;
- else if (cmdline.display_options.a_show_descriptions.argument() == "all")
- show = true;
- else
- throw args::DoHelp("Don't understand argument '"
- + cmdline.display_options.a_show_descriptions.argument() + "' to '--"
- + cmdline.display_options.a_show_descriptions.long_name() + "'");
+ cout << "- Sync point " << job.sync_point() << endl;
- if (show)
- cout << " \"" << id->short_description_key()->value() << "\"" << endl;
- }
+ return true;
+ }
- display_reasons(resolution, false);
+ bool visit(const UntakenInstallJob & job) const
+ {
+ return display_one_untaken(env, cmdline, job);
}
+ };
- cout << endl;
+ bool display_one_job(
+ const std::tr1::shared_ptr<Environment> & env,
+ const DisplayResolutionCommandLine & cmdline,
+ const std::tr1::shared_ptr<const Job> & job)
+ {
+ return job->accept_returning<bool>(DisplayOneJobVisitor(env, cmdline));
}
- void display_resolution(
+ void display_jobs(
const std::tr1::shared_ptr<Environment> & env,
const ResolverLists & lists,
const DisplayResolutionCommandLine & cmdline)
{
- Context context("When displaying chosen resolution:");
+ Context context("When displaying jobs:");
+
+ cout << "These are the actions I will take, in order:" << endl << endl;
- if (lists.ordered_job_ids()->empty())
+ bool shown_any(false);
+ for (JobIDSequence::ConstIterator i(lists.ordered_job_ids()->begin()),
+ i_end(lists.ordered_job_ids()->end()) ;
+ i != i_end ; ++i)
{
- if (lists.error_resolutions()->empty())
- cout << "There are no actions to carry out" << endl << endl;
- return;
+ const std::tr1::shared_ptr<const Job> job(lists.jobs()->fetch(*i));
+ shown_any |= display_one_job(env, cmdline, job);
}
- cout << "These are the actions I will take, in order:" << endl << endl;
- display_resolution_list(env, lists.jobs(), lists.ordered_job_ids(), cmdline);
+ if (! shown_any)
+ cout << "(nothing to do)" << endl;
+
+ cout << endl;
}
void display_untaken(
@@ -687,151 +799,82 @@ namespace
const ResolverLists & lists,
const DisplayResolutionCommandLine & cmdline)
{
- Context context("When displaying untaken resolutions:");
+ Context context("When displaying untaken jobs:");
if (lists.untaken_job_ids()->empty())
return;
- cout << "I didn't take the following suggestions:" << endl << endl;
- display_resolution_list(env, lists.jobs(), lists.untaken_job_ids(), cmdline);
- }
-
- void display_errors(
- const std::tr1::shared_ptr<Environment> & env,
- const ResolverLists & lists,
- const DisplayResolutionCommandLine & cmdline)
- {
- Context context("When displaying errors for chosen resolution:");
-
- if (lists.error_resolutions()->empty())
- return;
-
- cout << "I encountered the following errors:" << endl << endl;
+ cout << "I did not take the following:" << endl << endl;
- for (Resolutions::ConstIterator c(lists.error_resolutions()->begin()),
- c_end(lists.error_resolutions()->end()) ;
- c != c_end ; ++c)
- display_one_error(env, cmdline, *c, true);
+ for (JobIDSequence::ConstIterator i(lists.untaken_job_ids()->begin()),
+ i_end(lists.untaken_job_ids()->end()) ;
+ i != i_end ; ++i)
+ {
+ const std::tr1::shared_ptr<const Job> job(lists.jobs()->fetch(*i));
+ if (! display_one_job(env, cmdline, job))
+ throw InternalError(PALUDIS_HERE, "who put something icky on the untaken list?");
+ }
cout << endl;
}
- void display_explanations(
- const std::tr1::shared_ptr<Environment> & env,
- const ResolverLists & lists,
- const DisplayResolutionCommandLine & cmdline)
+ struct DisplayOneDecisionVisitor
{
- Context context("When displaying explanations:");
-
- if (cmdline.display_options.a_explain.begin_args() == cmdline.display_options.a_explain.end_args())
- return;
+ const std::tr1::shared_ptr<const Resolution> resolution;
- std::cout << "Explaining requested decisions:" << std::endl << std::endl;
-
- for (args::StringSetArg::ConstIterator i(cmdline.display_options.a_explain.begin_args()),
- i_end(cmdline.display_options.a_explain.end_args()) ;
- i != i_end ; ++i)
+ DisplayOneDecisionVisitor(const std::tr1::shared_ptr<const Resolution> & r) :
+ resolution(r)
{
- bool any(false);
- PackageDepSpec spec(parse_user_package_dep_spec(*i, env.get(), UserPackageDepSpecOptions() + updso_allow_wildcards));
- for (Resolutions::ConstIterator r(lists.all_resolutions()->begin()), r_end(lists.all_resolutions()->end()) ;
- r != r_end ; ++r)
- {
- const std::tr1::shared_ptr<const PackageID> id((*r)->decision()->accept_returning<
- std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
- const std::tr1::shared_ptr<const Destination> destination((*r)->decision()->accept_returning<
- std::tr1::shared_ptr<const Destination> >(DestinationVisitor()));
+ }
- if (! id)
- {
- /* decided nothing, so we can only work for cat/pkg, where
- * either can be wildcards (we could work for :slot too,
- * but we're lazy) */
- Resolvent resolvent((*r)->resolvent());
- if (! match_qpns(*env, spec, resolvent.package()))
- continue;
- }
- else
- {
- if (! match_package(*env, spec, *id, MatchPackageOptions()))
- continue;
- }
+ void visit(const NothingNoChangeDecision &) const PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "nothing no change?");
+ }
- any = true;
+ void visit(const ExistingNoChangeDecision &) const PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "existing no change?");
+ }
- std::cout << "For " << (*r)->resolvent() << ":" << std::endl;
- std::cout << " The following constraints were in action:" << std::endl;
- for (Constraints::ConstIterator c((*r)->constraints()->begin()),
- c_end((*r)->constraints()->end()) ;
- c != c_end ; ++c)
- {
- std::cout << " * " << (*c)->spec();
+ void visit(const ChangesToMakeDecision &) const PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "changes to make?");
+ }
- switch ((*c)->use_existing())
- {
- case ue_if_same:
- std::cout << ", use existing if same";
- break;
- case ue_never:
- std::cout << ", never using existing";
- break;
- case ue_only_if_transient:
- std::cout << ", using existing only if transient";
- break;
- case ue_if_same_version:
- std::cout << ", use existing if same version";
- break;
- case ue_if_possible:
- std::cout << ", use existing if possible";
- break;
-
- case last_ue:
- break;
- }
+ void visit(const UnableToMakeDecision & d) const
+ {
+ display_unable_to_make_decision(resolution, d);
+ }
+ };
- switch ((*c)->destination_type())
- {
- case dt_install_to_slash:
- std::cout << ", installing to /";
- break;
+ void display_one_decision(
+ const std::tr1::shared_ptr<Environment> &,
+ const DisplayResolutionCommandLine &,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const Decision & decision)
+ {
+ decision.accept(DisplayOneDecisionVisitor(resolution));
+ }
- case dt_create_binary:
- std::cout << ", creating a binary";
- break;
+ void display_errors(
+ const std::tr1::shared_ptr<Environment> & env,
+ const ResolverLists & lists,
+ const DisplayResolutionCommandLine & cmdline)
+ {
+ Context context("When displaying errors:");
- case last_dt:
- break;
- }
+ if (lists.error_resolutions()->empty())
+ return;
- std::cout << std::endl;
- std::cout << " Because of ";
- ReasonNameGetter v(true);
- std::cout << (*c)->reason()->accept_returning<std::pair<std::string, bool> >(v).first;
- std::cout << std::endl;
- }
+ cout << "I encountered the following errors:" << endl << endl;
- if (id)
- {
- std::cout << " The decision made was:" << std::endl;
- std::cout << " Use " << *id << std::endl;
- if (destination)
- {
- std::cout << " Install to repository " << destination->repository() << std::endl;
- if (! destination->replacing()->empty())
- for (PackageIDSequence::ConstIterator x(destination->replacing()->begin()),
- x_end(destination->replacing()->end()) ;
- x != x_end ; ++x)
- std::cout << " Replacing " << **x << std::endl;
- }
- std::cout << std::endl;
- }
- else
- std::cout << " No decision could be made" << std::endl << std::endl;
- }
+ for (Resolutions::ConstIterator r(lists.error_resolutions()->begin()),
+ r_end(lists.error_resolutions()->end()) ;
+ r != r_end ; ++r)
+ display_one_decision(env, cmdline, *r, *(*r)->decision());
- if (! any)
- throw args::DoHelp("There is nothing matching '" + *i + "' in the resolution set.");
- }
+ cout << endl;
}
}
@@ -866,7 +909,7 @@ DisplayResolutionCommand::run(
Deserialisation deserialisation("ResolverLists", deserialiser);
ResolverLists lists(ResolverLists::deserialise(deserialisation));
- display_resolution(env, lists, cmdline);
+ display_jobs(env, lists, cmdline);
display_untaken(env, lists, cmdline);
display_errors(env, lists, cmdline);
display_explanations(env, lists, cmdline);
diff --git a/src/clients/cave/cmd_resolve_cmdline.cc b/src/clients/cave/cmd_resolve_cmdline.cc
index 2aa1d09..6d0975b 100644
--- a/src/clients/cave/cmd_resolve_cmdline.cc
+++ b/src/clients/cave/cmd_resolve_cmdline.cc
@@ -204,7 +204,9 @@ ResolveCommandLineDisplayOptions::ResolveCommandLineDisplayOptions(args::ArgsHan
"that it made"),
a_explain(&g_explanations, "explain", '\0', "Explain why the resolver made a particular decision. The "
"argument is a package dependency specification, so --explain dev-libs/boost or --explain qt:3"
- " or even --explain '*/*' (although --dump is a better way of getting highly noisy debug output).")
+ " or even --explain '*/*' (although --dump is a better way of getting highly noisy debug output)."),
+ a_show_all_jobs(&g_explanations, "show-all-jobs", '\0', "Show all jobs that will be executed, rather than "
+ "just installs.", true)
{
}
diff --git a/src/clients/cave/cmd_resolve_cmdline.hh b/src/clients/cave/cmd_resolve_cmdline.hh
index a01b7db..9661228 100644
--- a/src/clients/cave/cmd_resolve_cmdline.hh
+++ b/src/clients/cave/cmd_resolve_cmdline.hh
@@ -130,6 +130,7 @@ namespace paludis
args::ArgsGroup g_explanations;
args::StringSetArg a_explain;
+ args::SwitchArg a_show_all_jobs;
};
struct ResolveCommandLineProgramOptions :