aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-01-26 14:51:16 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-01-26 14:51:16 +0000
commit47b84d5397f12dee8beb36959e7140f4cdbf6085 (patch)
tree1e9692a3580baeb26a006e5f3cd324f4f0073e8e
parent5392e5995fd3cdc6b24ef081b7662cfc4f1eb4d7 (diff)
parentd0a6e12af44da6f8425571bf97b5e5fac16b8df4 (diff)
downloadpaludis-47b84d5397f12dee8beb36959e7140f4cdbf6085.tar.gz
paludis-47b84d5397f12dee8beb36959e7140f4cdbf6085.tar.xz
Merge branch 'display-job-summary'
-rw-r--r--paludis/file_output_manager.cc11
-rw-r--r--paludis/forward_at_finish_output_manager.cc9
-rw-r--r--paludis/resolver/job_state.cc22
-rw-r--r--paludis/resolver/job_state.hh2
-rw-r--r--src/clients/cave/cmd_execute_resolution.cc150
5 files changed, 181 insertions, 13 deletions
diff --git a/paludis/file_output_manager.cc b/paludis/file_output_manager.cc
index e0b9423..75ff585 100644
--- a/paludis/file_output_manager.cc
+++ b/paludis/file_output_manager.cc
@@ -42,7 +42,7 @@ namespace paludis
const std::tr1::shared_ptr<OutputManager> summary_output_manager;
const std::string summary_output_message;
- bool succeeded, unlinked;
+ bool succeeded, unlinked, nothing_more_to_come;
Implementation(
const FSEntry & o,
@@ -59,7 +59,8 @@ namespace paludis
summary_output_manager(m),
summary_output_message(s),
succeeded(false),
- unlinked(false)
+ unlinked(false),
+ nothing_more_to_come(false)
{
}
};
@@ -120,12 +121,16 @@ FileOutputManager::flush()
bool
FileOutputManager::want_to_flush() const
{
- return false;
+ return _imp->nothing_more_to_come &&
+ (! _imp->unlinked) &&
+ (! _imp->summary_output_message.empty());
}
void
FileOutputManager::nothing_more_to_come()
{
+ _imp->nothing_more_to_come = true;
+
if (! _imp->stdout_stream)
return;
diff --git a/paludis/forward_at_finish_output_manager.cc b/paludis/forward_at_finish_output_manager.cc
index 8c2a38b..964aff4 100644
--- a/paludis/forward_at_finish_output_manager.cc
+++ b/paludis/forward_at_finish_output_manager.cc
@@ -39,6 +39,7 @@ namespace paludis
const bool if_success, if_failure;
const std::tr1::shared_ptr<OutputManager> child;
bool success;
+ bool nothing_more_to_come;
Implementation(
const bool s,
@@ -48,7 +49,8 @@ namespace paludis
if_success(s),
if_failure(f),
child(m),
- success(false)
+ success(false),
+ nothing_more_to_come(false)
{
}
};
@@ -107,6 +109,9 @@ ForwardAtFinishOutputManager::flush()
bool
ForwardAtFinishOutputManager::want_to_flush() const
{
+ if (_imp->nothing_more_to_come && ((! _imp->stdout_stream.str().empty()) || (! _imp->stderr_stream.str().empty())))
+ return true;
+
return false;
}
@@ -118,6 +123,8 @@ ForwardAtFinishOutputManager::nothing_more_to_come()
_imp->stdout_stream.clear();
_imp->stderr_stream.clear();
}
+
+ _imp->nothing_more_to_come = true;
}
const std::tr1::shared_ptr<const Set<std::string> >
diff --git a/paludis/resolver/job_state.cc b/paludis/resolver/job_state.cc
index 60afc2c..c3e63f1 100644
--- a/paludis/resolver/job_state.cc
+++ b/paludis/resolver/job_state.cc
@@ -19,7 +19,11 @@
#include <paludis/resolver/job_state.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/output_manager.hh>
#include <list>
+#include <algorithm>
+#include <tr1/functional>
using namespace paludis;
using namespace paludis::resolver;
@@ -125,6 +129,15 @@ JobSucceededState::add_output_manager(const std::tr1::shared_ptr<OutputManager>
_imp->output_managers.push_back(o);
}
+bool
+JobSucceededState::any_output_manager_wants_to_flush() const
+{
+ return indirect_iterator(_imp->output_managers.end()) != std::find_if(
+ indirect_iterator(_imp->output_managers.begin()),
+ indirect_iterator(_imp->output_managers.end()),
+ std::tr1::bind(&OutputManager::want_to_flush, std::tr1::placeholders::_1));
+}
+
JobFailedState::JobFailedState(const std::tr1::shared_ptr<const Job> & j) :
PrivateImplementationPattern<JobFailedState>(new Implementation<JobFailedState>(j))
{
@@ -146,6 +159,15 @@ JobFailedState::add_output_manager(const std::tr1::shared_ptr<OutputManager> & o
_imp->output_managers.push_back(o);
}
+bool
+JobFailedState::any_output_manager_wants_to_flush() const
+{
+ return indirect_iterator(_imp->output_managers.end()) != std::find_if(
+ indirect_iterator(_imp->output_managers.begin()),
+ indirect_iterator(_imp->output_managers.end()),
+ std::tr1::bind(&OutputManager::want_to_flush, std::tr1::placeholders::_1));
+}
+
const std::string
JobFailedState::state_name() const
{
diff --git a/paludis/resolver/job_state.hh b/paludis/resolver/job_state.hh
index 1479e76..c3c946d 100644
--- a/paludis/resolver/job_state.hh
+++ b/paludis/resolver/job_state.hh
@@ -72,6 +72,7 @@ namespace paludis
virtual const std::string state_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
void add_output_manager(const std::tr1::shared_ptr<OutputManager> &);
+ bool any_output_manager_wants_to_flush() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
class PALUDIS_VISIBLE JobFailedState :
@@ -87,6 +88,7 @@ namespace paludis
virtual const std::string state_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
void add_output_manager(const std::tr1::shared_ptr<OutputManager> &);
+ bool any_output_manager_wants_to_flush() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
class PALUDIS_VISIBLE JobSkippedState :
diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc
index 8365a7f..ae97b08 100644
--- a/src/clients/cave/cmd_execute_resolution.cc
+++ b/src/clients/cave/cmd_execute_resolution.cc
@@ -381,6 +381,7 @@ namespace
typedef std::tr1::unordered_map<JobID, std::tr1::shared_ptr<JobState>, Hash<JobID> > JobStateMap;
typedef std::list<std::tr1::shared_ptr<JobPendingState> > PendingJobsList;
+ typedef std::list<std::tr1::shared_ptr<JobState> > Summary;
struct DoOneTakenVisitor
{
@@ -733,7 +734,8 @@ namespace
int execute_taken(
const std::tr1::shared_ptr<Environment> & env,
const ResolverLists & lists,
- const ExecuteResolutionCommandLine & cmdline)
+ const ExecuteResolutionCommandLine & cmdline,
+ Summary & summary)
{
int retcode(0);
@@ -810,13 +812,13 @@ namespace
{
DoOneTakenVisitor v(env, cmdline, counts, s->second, job_state_map);
if (! s->second->job()->accept_returning<bool>(v))
- {
retcode |= 1;
-
- if (cmdline.execution_options.a_continue_on_failure.argument() == "never")
- break;
- }
}
+
+ summary.push_back(s->second);
+
+ if ((0 != retcode) && (cmdline.execution_options.a_continue_on_failure.argument() == "never"))
+ break;
}
if (0 != env->perform_hook(Hook("install_all_post")
@@ -909,7 +911,8 @@ namespace
int execute_resolution_main(
const std::tr1::shared_ptr<Environment> & env,
const ResolverLists & lists,
- const ExecuteResolutionCommandLine & cmdline)
+ const ExecuteResolutionCommandLine & cmdline,
+ Summary & summary)
{
int retcode(0);
@@ -917,7 +920,7 @@ namespace
if (0 != retcode || cmdline.a_pretend.specified())
return retcode;
- retcode |= execute_taken(env, lists, cmdline);
+ retcode |= execute_taken(env, lists, cmdline, summary);
if (0 != retcode)
return retcode;
@@ -926,6 +929,129 @@ namespace
return retcode;
}
+ struct SummaryJobNameDisplayer
+ {
+ const ResolverLists & lists;
+ const std::string colour;
+ const std::string state;
+ const bool want_to_flush;
+ const bool this_failed;
+ const bool something_failed;
+ bool & done_summary;
+
+ SummaryJobNameDisplayer(
+ const ResolverLists & l,
+ const std::string & c,
+ const std::string & s,
+ const bool w,
+ const bool t,
+ const bool f,
+ bool & d
+ ) :
+ lists(l),
+ colour(c),
+ state(s),
+ want_to_flush(w),
+ this_failed(t),
+ something_failed(f),
+ done_summary(d)
+ {
+ }
+
+ void summary() const
+ {
+ if (! done_summary)
+ cout << endl << c::bold_blue() << "Summary:" << c::normal() << endl << endl;
+ done_summary = true;
+ }
+
+ void visit(const SimpleInstallJob & job) const
+ {
+ if (want_to_flush || something_failed)
+ {
+ summary();
+ cout << colour << state << c::normal() << *job.decision()->origin_id()
+ << " to " << job.decision()->destination()->repository() << endl;
+ }
+ }
+
+ void visit(const FetchJob & job) const
+ {
+ if (want_to_flush || this_failed)
+ {
+ summary();
+ cout << colour << state << c::normal() << "fetch " << *job.decision()->origin_id() << endl;
+ }
+ }
+
+ void visit(const ErrorJob &) const PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "ErrorJob?");
+ }
+
+ void visit(const UsableJob &) const
+ {
+ }
+
+ void visit(const UsableGroupJob &) const
+ {
+ }
+ };
+
+ struct SummaryStateDisplayer
+ {
+ const ResolverLists & lists;
+ const bool something_failed;
+ bool & done_summary;
+
+ SummaryStateDisplayer(const ResolverLists & l, const bool s, bool & d) :
+ lists(l),
+ something_failed(s),
+ done_summary(d)
+ {
+ }
+
+ void visit(const JobPendingState & state) const
+ {
+ state.job()->accept(SummaryJobNameDisplayer(lists, c::bold_normal(), "pending: ",
+ false, false, something_failed, done_summary));
+ }
+
+ void visit(const JobSucceededState & state) const
+ {
+ state.job()->accept(SummaryJobNameDisplayer(lists, c::bold_green(), "succeeded: ",
+ state.any_output_manager_wants_to_flush(), false, something_failed, done_summary));
+ }
+
+ void visit(const JobSkippedState & state) const
+ {
+ state.job()->accept(SummaryJobNameDisplayer(lists, c::bold_yellow(), "skipped: ",
+ false, false, something_failed, done_summary));
+ }
+
+ void visit(const JobFailedState & state) const
+ {
+ state.job()->accept(SummaryJobNameDisplayer(lists, c::bold_red(), "failed: ",
+ state.any_output_manager_wants_to_flush(), true, something_failed, done_summary));
+ }
+ };
+
+ void display_summary(
+ const ResolverLists & lists,
+ Summary & summary,
+ const bool something_failed)
+ {
+ bool done_summary(false);
+ for (Summary::iterator s(summary.begin()), s_end(summary.end()) ;
+ s != s_end ; )
+ {
+ const std::tr1::shared_ptr<JobState> state(*s);
+ summary.erase(s++);
+
+ state->accept(SummaryStateDisplayer(lists, something_failed, done_summary));
+ }
+ }
+
int execute_resolution(
const std::tr1::shared_ptr<Environment> & env,
const ResolverLists & lists,
@@ -939,12 +1065,16 @@ namespace
).max_exit_status())
throw ActionAbortedError("Aborted by hook");
+ Summary summary;
+
try
{
- retcode = execute_resolution_main(env, lists, cmdline);
+ retcode = execute_resolution_main(env, lists, cmdline, summary);
}
catch (...)
{
+ display_summary(lists, summary, 0 != retcode);
+
if (0 != env->perform_hook(Hook("install_task_execute_post")
("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
("PRETEND", stringify(cmdline.a_pretend.specified()))
@@ -954,6 +1084,8 @@ namespace
throw;
}
+ display_summary(lists, summary, 0 != retcode);
+
if (0 != env->perform_hook(Hook("install_task_execute_post")
("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
("PRETEND", stringify(cmdline.a_pretend.specified()))