diff options
author | 2010-01-02 22:24:38 +0000 | |
---|---|---|
committer | 2010-01-02 22:24:38 +0000 | |
commit | 09fd9de589f9b5edbaa23cc242d28ebc2ae62531 (patch) | |
tree | 1551c3a76961847c37a11a7d4c8654efaba7553e /paludis | |
parent | d47ccc4a0abc3f87339fdb7d24bcb4b854fdc647 (diff) | |
download | paludis-09fd9de589f9b5edbaa23cc242d28ebc2ae62531.tar.gz paludis-09fd9de589f9b5edbaa23cc242d28ebc2ae62531.tar.xz |
Cleaner output managers
Diffstat (limited to 'paludis')
40 files changed, 1023 insertions, 783 deletions
diff --git a/paludis/messages_to_stdout_output_handler-fwd.hh b/paludis/buffer_output_manager-fwd.hh index 9e2ec56a1..270f97a47 100644 --- a/paludis/messages_to_stdout_output_handler-fwd.hh +++ b/paludis/buffer_output_manager-fwd.hh @@ -17,12 +17,14 @@ * Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PALUDIS_GUARD_PALUDIS_MESSAGES_TO_STDOUT_OUTPUT_HANDLER_FWD_HH -#define PALUDIS_GUARD_PALUDIS_MESSAGES_TO_STDOUT_OUTPUT_HANDLER_FWD_HH 1 +#ifndef PALUDIS_GUARD_PALUDIS_BUFFER_OUTPUT_MANAGER_FWD_HH +#define PALUDIS_GUARD_PALUDIS_BUFFER_OUTPUT_MANAGER_FWD_HH 1 + +#include <paludis/output_manager-fwd.hh> namespace paludis { - struct MessagesToStdoutOutputManager; + class BufferOutputManager; } #endif diff --git a/paludis/buffer_output_manager.cc b/paludis/buffer_output_manager.cc new file mode 100644 index 000000000..27808c325 --- /dev/null +++ b/paludis/buffer_output_manager.cc @@ -0,0 +1,118 @@ +/* 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/buffer_output_manager.hh> +#include <paludis/util/buffer_output_stream.hh> +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <paludis/util/wrapped_forward_iterator.hh> +#include <paludis/util/make_shared_ptr.hh> +#include <paludis/util/set.hh> +#include <paludis/util/exception.hh> + +using namespace paludis; + +namespace paludis +{ + template <> + struct Implementation<BufferOutputManager> + { + const std::tr1::shared_ptr<OutputManager> child; + BufferOutputStream stdout_stream; + BufferOutputStream stderr_stream; + + Implementation( + const std::tr1::shared_ptr<OutputManager> & c) : + child(c) + { + } + }; +} + +BufferOutputManager::BufferOutputManager( + const std::tr1::shared_ptr<OutputManager> & c) : + PrivateImplementationPattern<BufferOutputManager>(new Implementation<BufferOutputManager>(c)) +{ +} + +BufferOutputManager::~BufferOutputManager() +{ + flush(); +} + +std::ostream & +BufferOutputManager::stdout_stream() +{ + return _imp->stdout_stream; +} + +std::ostream & +BufferOutputManager::stderr_stream() +{ + return _imp->stderr_stream; +} + +void +BufferOutputManager::succeeded() +{ + _imp->child->succeeded(); +} + +void +BufferOutputManager::message(const MessageType, const std::string &) +{ +} + +void +BufferOutputManager::flush() +{ + _imp->stdout_stream.unbuffer(_imp->child->stdout_stream()); + _imp->stderr_stream.unbuffer(_imp->child->stderr_stream()); + _imp->child->flush(); +} + +void +BufferOutputManager::nothing_more_to_come() +{ + _imp->child->nothing_more_to_come(); +} + +const std::tr1::shared_ptr<const Set<std::string> > +BufferOutputManager::factory_managers() +{ + std::tr1::shared_ptr<Set<std::string> > result(new Set<std::string>); + result->insert("buffer"); + return result; +} + +const std::tr1::shared_ptr<OutputManager> +BufferOutputManager::factory_create( + const OutputManagerFactory::KeyFunction & key_func, + const OutputManagerFactory::CreateChildFunction & create_child, + const OutputManagerFactory::ReplaceVarsFunc &) +{ + std::string child_str(key_func("child")); + if (child_str.empty()) + throw ConfigurationError("No child specified for BufferOutputManager"); + const std::tr1::shared_ptr<OutputManager> child(create_child(child_str)); + + return make_shared_ptr(new BufferOutputManager(child)); +} + +template class PrivateImplementationPattern<BufferOutputManager>; + diff --git a/paludis/messages_to_stdout_output_handler.hh b/paludis/buffer_output_manager.hh index 5591931e6..4f079dc39 100644 --- a/paludis/messages_to_stdout_output_handler.hh +++ b/paludis/buffer_output_manager.hh @@ -17,40 +17,34 @@ * Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PALUDIS_GUARD_PALUDIS_MESSAGES_TO_STDOUT_OUTPUT_HANDLER_HH -#define PALUDIS_GUARD_PALUDIS_MESSAGES_TO_STDOUT_OUTPUT_HANDLER_HH 1 +#ifndef PALUDIS_GUARD_PALUDIS_BUFFER_OUTPUT_MANAGER_HH +#define PALUDIS_GUARD_PALUDIS_BUFFER_OUTPUT_MANAGER_HH 1 -#include <paludis/messages_to_stdout_output_handler-fwd.hh> +#include <paludis/tee_output_manager-fwd.hh> #include <paludis/output_manager.hh> #include <paludis/output_manager_factory.hh> -#include <paludis/util/set-fwd.hh> #include <paludis/util/private_implementation_pattern.hh> -#include <paludis/util/fs_entry-fwd.hh> #include <tr1/memory> #include <tr1/functional> namespace paludis { - class PALUDIS_VISIBLE MessagesToStdoutOutputManager : - private PrivateImplementationPattern<MessagesToStdoutOutputManager>, + class PALUDIS_VISIBLE BufferOutputManager : + private PrivateImplementationPattern<BufferOutputManager>, public OutputManager { public: - MessagesToStdoutOutputManager( - const std::tr1::shared_ptr<OutputManager> &, - const OutputManagerFactory::ReplaceVarsFunc &, - const std::string & f_debug, - const std::string & f_info, - const std::string & f_warn, - const std::string & f_error, - const std::string & f_log); - - ~MessagesToStdoutOutputManager(); + BufferOutputManager( + const std::tr1::shared_ptr<OutputManager> & + ); + ~BufferOutputManager(); virtual std::ostream & stdout_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual std::ostream & stderr_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual void succeeded(); + virtual void flush(); + virtual void nothing_more_to_come(); virtual void message(const MessageType, const std::string &); static const std::tr1::shared_ptr<const Set<std::string> > factory_managers() @@ -64,8 +58,9 @@ namespace paludis }; #ifdef PALUDIS_HAVE_EXTERN_TEMPLATE - extern template class PrivateImplementationPattern<MessagesToStdoutOutputManager>; + extern template class PrivateImplementationPattern<BufferOutputManager>; #endif } + #endif diff --git a/paludis/environments/paludis/Makefile.am b/paludis/environments/paludis/Makefile.am index e0e46e7ed..c32a93990 100644 --- a/paludis/environments/paludis/Makefile.am +++ b/paludis/environments/paludis/Makefile.am @@ -1,6 +1,6 @@ include $(top_srcdir)/misc/common-makefile.am -SUBDIRS = output_managers . +SUBDIRS = . AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@ DEFS= \ -DSYSCONFDIR=\"$(sysconfdir)\" \ @@ -18,7 +18,6 @@ libpaludispaludisenvironment_la_SOURCES = \ use_conf.cc use_conf.hh \ mirrors_conf.cc mirrors_conf.hh \ output_conf.cc output_conf.hh \ - output_managers.cc output_managers.hh \ world.cc world.hh \ paludis_config.cc paludis_config.hh \ paludis_environment.cc paludis_environment.hh \ diff --git a/paludis/environments/paludis/default_output.conf b/paludis/environments/paludis/default_output.conf index 863880e18..906175ceb 100644 --- a/paludis/environments/paludis/default_output.conf +++ b/paludis/environments/paludis/default_output.conf @@ -1,19 +1,193 @@ -# By default, output to stdout, keep logs of messages and keep output logs on -# failure: +# vim: set tw=80 ft=conf et sw=4 sts=4 : -type = * : logged +# This is the default output configuration. In general, we show output to stdout +# where possible, we keep logs of messages, and we keep logs of output only if a +# failure occurs. +# +# We use a few user-settable variables: +# +# always_keep_output_logs may be set to 'true' to always keep output logs, even +# if a build succeeds. +# +# quiet may be set to 'true' to show only messages, rather than all output, when +# carrying out an action. -# But if we're being run in the background, display only messages to stdout, and -# keep logs of messages and keep output logs on failure: +# First, we define some basic rules. If we're running exclusively, use the +# 'exclusive' manager: +[rule default_exclusive] +type = * +output_exclusivity = exclusive +manager = exclusive -type = * output_exclusivity = background : quiet +# If we're running with others, use the 'interleaved' manager: +[rule default_interleaved] +type = * +output_exclusivity = with_others +manager = interleaved -# We don't want to log pretend actions though. They're often run as a normal -# user, and keeping logs isn't useful. +# And if we're running in the background, use the 'background' manager: +[rule default_background] +type = * +output_exclusivity = background +manager = background -type = package action = pretend : standard +# We want special handling for pretends. Logging them is generally a bad idea, +# since it often prevents running as a normal user, and it's a waste of space, +# so we go straight to 'standard'. This generally shouldn't be overridden. +[rule default_pretend] +type = package +action = pretend +output_exclusivity = exclusive +manager = standard -# We only want to show pretend-time fetch verification if it failed. +# For pretend-fetches, we don't want to display any output at all, except if +# something fails, so we go to 'standard_on_failure'. Again, this generally +# shouldn't be overridden: +[rule default_pretend_fetch] +type = package +action = fetch +ignore_unfetched = true +output_exclusivity = exclusive +manager = standard_on_failure -type = package action = fetch ignore_unfetched = true : standard_on_failure +# Next, our output managers. The simplest goes straight to stdout / stderr: +[manager standard] +handler = standard + +# For when we want to send output to stdout / stderr, but only if things failed: +[manager standard_on_failure] +handler = forward_on_failure +child = standard + +# For when we're running with other processes, we send output to stdout / +# stderr, but only when we're told to do so, to avoid mixing up outputs from +# different processes in a huge confusing mess: +[manager standard_interleaved] +handler = buffer +child = standard + +# The 'log_output' manager forwards to 'log_output_keep_always', unless the user +# has set 'always_keep_output_logs' to 'true', in which case it goes to +# 'log_output_keep_failures'. +[manager log_output] +handler = conditional_alias +condition_variable = always_keep_output_logs +if_true = log_output_keep_always +if_false = log_output_keep_failures +if_unset = log_output_keep_failures + +# Our output log goes to a file, which gets discarded if we succeed or if it's +# empty. The summary_output options are used to display a message showing the +# location of the log when our output manager is closed: +[manager log_output_keep_failures] +handler = file +filename = ${root}/var/log/paludis/%{time}-%{action}-%{full_name}.out +keep_on_empty = false +keep_on_success = false +summary_output_manager = format_messages_standard +summary_output_message = Output log: ${filename} + +# A variant on log_output_keep_failures, that always keeps logs. Selected if +# 'always_keep_output_logs' is 'true'. +[manager log_output_keep_always] +handler = file +filename = ${root}/var/log/paludis/%{time}-%{action}-%{full_name}.out +keep_on_empty = false +keep_on_success = true +summary_output_manager = format_messages_standard +summary_output_message = Output log: ${filename} + +# For messages from background and quiet processes, we format them, and then +# send them to standard output when we're told to do so: +[manager format_messages_interleaved] +handler = format_messages +format_debug = +format_info = "%{green}***%{normal} %{message}%{newline}" +format_warn = "%{yellow}***%{normal} %{message}%{newline}" +format_error = "%{red}***%{normal} %{message}%{newline}" +format_log = "%{blue}***%{normal} %{message}%{newline}" +child = standard_interleaved + +# For messages from quiet exclusive processes, we format them, and send them to +# standard output immediately: +[manager format_messages_standard] +handler = format_messages +format_debug = +format_info = "%{green}***%{normal} %{message}%{newline}" +format_warn = "%{yellow}***%{normal} %{message}%{newline}" +format_error = "%{red}***%{normal} %{message}%{newline}" +format_log = "%{blue}***%{normal} %{message}%{newline}" +child = standard + +# For messages going to logs, we format without colour: +[manager format_log_messages_always] +handler = format_messages +format_debug = +format_info = I %{message}%{newline} +format_warn = W %{message}%{newline} +format_error = E %{message}%{newline} +format_log = L %{message}%{newline} +child = log_messages_always + +# Our messages log goes to a file, which gets discarded only if it is empty: +[manager log_messages_always] +handler = file +filename = ${root}/var/log/paludis/${time}-%{action}-%{full_name}.messages +keep_on_empty = false +keep_on_success = true +summary_output_manager = format_messages_standard +summary_output_message = Messages log: ${filename} + +# Our handler for 'exclusive' forwards to either 'exclusive_default', or, if +# 'quiet' is set to 'true', 'exclusive_quiet'. +[manager exclusive] +handler = conditional_alias +condition_variable = quiet +if_true = exclusive_quiet +if_false = exclusive_default +if_unset = exclusive_default + +# When we're running exclusively, send output to standard, keep an output log +# which, at user option, is deleted upon success, and keep a messages log: +[manager exclusive_default] +handler = tee +children = standard log_output +messages = format_log_messages_always + +# Alternatively, only send messages to standard rather than full output: +[manager exclusive_quiet] +handler = tee +children = log_output +messages = format_log_messages_always format_messages + +# Our handler for 'interleaved' forwards to either 'interleaved_default' or, if +# 'quiet' is set to 'true', 'interleaved_quiet': +[manager interleaved] +handler = conditional_alias +condition_variable = quiet +if_true = interleaved_quiet +if_false = interleaved_default +if_unset = interleaved_default + +# When we're running with other processes, send output to standard only when +# told to, keep an output which, at user option, is deleted upon success, and +# keep a messages log: +[manager interleaved_default] +handler = tee +children = standard_interleaved log_output +messages = format_log_messages_always + +# Alternatively, only send messages to standard rather than full output: +[manager interleaved_quiet] +handler = tee +children = log_output +messages = format_log_messages_always format_messages_interleaved + +# When we're running in the background, keep an output log which, at user +# option, is deleted upon success, always keep a messages log, and send messages +# to standard only when told to: +[manager background] +handler = tee +children = log_output +messages = format_log_messages_always format_messages_interleaved diff --git a/paludis/environments/paludis/output_conf.cc b/paludis/environments/paludis/output_conf.cc index 826ed4a19..29cce1d23 100644 --- a/paludis/environments/paludis/output_conf.cc +++ b/paludis/environments/paludis/output_conf.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 2010 Ciaran McCreesh * * This file is part of the Paludis package manager. Paludis is free software; * you can redistribute it and/or modify it under the terms of the GNU General @@ -34,13 +34,19 @@ #include <paludis/util/make_shared_copy.hh> #include <paludis/util/tribool.hh> #include <paludis/util/simple_visitor_cast.hh> +#include <paludis/util/map.hh> +#include <paludis/util/simple_parser.hh> #include <paludis/user_dep_spec.hh> #include <paludis/create_output_manager_info.hh> #include <paludis/package_id.hh> #include <paludis/match_package.hh> #include <paludis/action.hh> +#include <paludis/output_manager_factory.hh> +#include <paludis/metadata_key.hh> #include <list> #include <vector> +#include <map> +#include <algorithm> using namespace paludis; using namespace paludis::paludis_environment; @@ -73,6 +79,17 @@ namespace }; typedef std::list<Rule> RuleList; + typedef std::map<std::string, std::tr1::shared_ptr<Map<std::string, std::string> > > Managers; + + std::string from_keys( + const std::tr1::shared_ptr<const Map<std::string, std::string> > & m, + const std::string & k) + { + if (m->end() == m->find(k)) + return ""; + else + return m->find(k)->second; + } } namespace paludis @@ -82,6 +99,8 @@ namespace paludis { const PaludisEnvironment * const env; RuleList rules; + Managers managers; + std::map<std::string, std::string> misc_vars; Implementation(const PaludisEnvironment * const e) : env(e) @@ -116,6 +135,8 @@ namespace rule.action_requirement() = v; else if (k == "ignore_unfetched") rule.ignore_unfetched_requirement() = destringify<Tribool>(v); + else if (k == "manager") + rule.manager() = v; else throw PaludisConfigError("Unknown rule '" + k + "'"); } @@ -192,6 +213,100 @@ namespace MatchRuleVisitor v(e, rule); return i.accept_returning<bool>(v); } + + std::string escape(const std::string & s) + { + std::string result(s); + std::replace(result.begin(), result.end(), ' ', '_'); + std::replace(result.begin(), result.end(), '/', '_'); + return result; + } + + struct CreateVarsFromInfo + { + std::tr1::shared_ptr<Map<std::string, std::string> > m; + + CreateVarsFromInfo(std::tr1::shared_ptr<Map<std::string, std::string> > & mm) : + m(mm) + { + /* convenience, for everyone */ + m->insert("newline", "\n"); + m->insert("red", "\033[1;31m"); + m->insert("yellow", "\033[1;33m"); + m->insert("green", "\033[1;32m"); + m->insert("blue", "\033[1;34m"); + m->insert("normal", "\033[0;0m"); + m->insert("time", stringify(time(0))); + m->insert("pid", stringify(getpid())); + } + + void visit(const CreateOutputManagerForRepositorySyncInfo & i) + { + m->insert("type", "repository"); + m->insert("action", "sync"); + m->insert("name", stringify(i.repository().name())); + m->insert("full_name", stringify(i.repository().name())); + } + + void visit(const CreateOutputManagerForPackageIDActionInfo & i) + { + m->insert("type", "package"); + m->insert("action", action_to_string(i.action())); + m->insert("name", stringify(i.package_id()->name())); + m->insert("id", escape(stringify(*i.package_id()))); + m->insert("full_name", escape(stringify(*i.package_id()))); + if (i.package_id()->slot_key()) + m->insert("slot", stringify(i.package_id()->slot_key()->value())); + m->insert("version", stringify(i.package_id()->version())); + m->insert("repository", stringify(i.package_id()->repository()->name())); + m->insert("category", stringify(i.package_id()->name().category())); + m->insert("package", stringify(i.package_id()->name().package())); + } + }; + + const std::tr1::shared_ptr<Map<std::string, std::string> > + vars_from_create_output_manager_info(const CreateOutputManagerInfo & i) + { + std::tr1::shared_ptr<Map<std::string, std::string> > result(new Map<std::string, std::string>); + CreateVarsFromInfo v(result); + i.accept(v); + return result; + } + + const std::string replace_percent_vars( + const std::string & s, + const std::tr1::shared_ptr<const Map<std::string, std::string> > & vars, + const std::tr1::shared_ptr<const Map<std::string, std::string> > & override_vars, + const std::tr1::shared_ptr<const Map<std::string, std::string> > & file_vars) + { + std::string result, token; + SimpleParser parser(s); + while (! parser.eof()) + { + if (parser.consume((+simple_parser::any_except("%")) >> token)) + result.append(token); + else if (parser.consume(simple_parser::exact("%%"))) + result.append("%"); + else if (parser.consume(simple_parser::exact("%{") & + ((+simple_parser::any_except("} \t\r\n%")) >> token) & + simple_parser::exact("}"))) + { + Map<std::string, std::string>::ConstIterator v(override_vars->find(token)); + if (v == override_vars->end()) + v = vars->find(token); + if (v == vars->end()) + v = file_vars->find(token); + if (v == file_vars->end()) + throw PaludisConfigError("No variable named '" + token + "' in var string '" + s + "'"); + + result.append(v->second); + } + else + throw PaludisConfigError("Invalid var string '" + s + "'"); + } + + return result; + } } void @@ -199,28 +314,55 @@ OutputConf::add(const FSEntry & filename) { Context context("When adding source '" + stringify(filename) + "' as an output file:"); - std::tr1::shared_ptr<LineConfigFile> f(make_bashable_conf(filename, LineConfigFileOptions())); + std::tr1::shared_ptr<KeyValueConfigFile> f(make_bashable_kv_conf(filename, + make_shared_ptr(new Map<std::string, std::string>), + KeyValueConfigFileOptions() + kvcfo_allow_sections)); if (! f) return; - for (LineConfigFile::ConstIterator line(f->begin()), line_end(f->end()) ; - line != line_end ; ++line) - { - std::vector<std::string> tokens; - tokenise_whitespace_quoted(*line, std::back_inserter(tokens)); + Managers local_managers, local_rules; - if (tokens.empty()) + for (KeyValueConfigFile::ConstIterator k(f->begin()), k_end(f->end()) ; + k != k_end ; ++k) + { + std::string remainder(k->first); + std::string::size_type p(remainder.find('/')); + if (std::string::npos == p) + { + _imp->misc_vars[k->first] = k->second; continue; + } - if ("source" == tokens.at(0)) - { - if (tokens.size() != 2) - throw PaludisConfigError("Invalid source line '" + *line + "'"); + std::string section_kind(remainder.substr(0, p)); + remainder.erase(0, p + 1); - add(FSEntry(tokens.at(1))); - continue; + p = remainder.find('/'); + if (std::string::npos == p) + throw PaludisConfigError("Section '" + section_kind + "' has no name"); + std::string section_name(remainder.substr(0, p)); + remainder.erase(0, p + 1); + + if (section_kind == "rule") + { + local_rules.insert( + std::make_pair(section_name, + make_shared_ptr(new Map<std::string, std::string>))).first->second->insert( + remainder, k->second); } + else if (section_kind == "manager") + { + local_managers.insert( + std::make_pair(section_name, + make_shared_ptr(new Map<std::string, std::string>))).first->second->insert( + remainder, k->second); + } + else + throw PaludisConfigError("Section kind '" + section_kind + "' unknown"); + } + for (Managers::const_iterator r(local_rules.begin()), r_end(local_rules.end()) ; + r != r_end ; ++r) + { Rule rule(make_named_values<Rule>( value_for<n::action_requirement>("*"), value_for<n::ignore_unfetched_requirement>(indeterminate), @@ -230,45 +372,16 @@ OutputConf::add(const FSEntry & filename) value_for<n::output_exclusivity_requirement>(static_cast<OutputExclusivity>(-1)), value_for<n::type_requirement>("*") )); + for (Map<std::string, std::string>::ConstIterator m(r->second->begin()), m_end(r->second->end()) ; + m != m_end ; ++m) + set_rule(_imp->env, rule, m->first, m->second); - std::vector<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()); - - for ( ; t != t_end ; ++t) - { - if (*t == ":") - break; - - std::string::size_type p(t->find("=")); - if (std::string::npos != p) - set_rule(_imp->env, rule, t->substr(0, p), t->substr(p + 1)); - else - { - std::string r(*t); - if (++t == t_end) - throw PaludisConfigError("Expected '=' but found end of line for line '" + *line + "'"); - - if (*t != "=") - throw PaludisConfigError("Expected '=' but found '" + *t + "' for line '" + *line + "'"); - - if (++t == t_end) - throw PaludisConfigError("Expected value but found end of for line '" + *line + "'"); - - set_rule(_imp->env, rule, r, *t); - } - } - - if (t == t_end) - throw PaludisConfigError("Found no ':' for line '" + *line + "'"); - - if (++t == t_end) - throw PaludisConfigError("Found no manager after ':' for line '" + *line + "'"); - - rule.manager() = *t; _imp->rules.push_back(rule); - - if (++t != t_end) - throw PaludisConfigError("Trailing text after manager on line '" + *line + "'"); } + + for (Managers::const_iterator m(local_managers.begin()), m_end(local_managers.end()) ; + m != m_end ; ++m) + _imp->managers[m->first] = m->second; } const std::tr1::shared_ptr<OutputManager> @@ -279,10 +392,69 @@ OutputConf::create_output_manager(const CreateOutputManagerInfo & i) const for (RuleList::const_reverse_iterator r(_imp->rules.rbegin()), r_end(_imp->rules.rend()) ; r != r_end ; ++r) if (match_rule(_imp->env, *r, i)) - return _imp->env->create_named_output_manager(r->manager(), i); + return create_named_output_manager(r->manager(), i); throw PaludisConfigError("No matching output manager rule specified"); } +const std::tr1::shared_ptr<OutputManager> +OutputConf::create_named_output_manager(const std::string & s, const CreateOutputManagerInfo & n) const +{ + Context context("When creating output manager named '" + s + "':"); + + Managers::const_iterator i(_imp->managers.find(s)); + if (i == _imp->managers.end()) + throw PaludisConfigError("No output manager named '" + s + "' exists"); + + std::tr1::shared_ptr<Map<std::string, std::string> > vars(vars_from_create_output_manager_info(n)); + + std::string handler; + if (i->second->end() != i->second->find("handler")) + handler = i->second->find("handler")->second; + + if (handler == "conditional_alias") + { + /* easier to handle this specially here */ + std::string condition_variable; + if (i->second->end() != i->second->find("condition_variable")) + condition_variable = i->second->find("condition_variable")->second; + + if (condition_variable.empty()) + throw PaludisConfigError("No condition_variable specified for manager '" + s + "'"); + + std::string value; + if (_imp->misc_vars.end() != _imp->misc_vars.find(condition_variable)) + value = _imp->misc_vars.find(condition_variable)->second; + + std::string alias_var; + if (value.empty()) + alias_var = "if_unset"; + else if (value == "true") + alias_var = "if_true"; + else if (value == "false") + alias_var = "if_false"; + else + throw PaludisConfigError("For manager '" + s + "', condition_variable '" + condition_variable + + "' should be either 'true', 'false' or unset, but is instead '" + alias_var + "'"); + + std::string alias; + if (i->second->end() != i->second->find(alias_var)) + alias = i->second->find(alias_var)->second; + + if (alias.empty()) + throw PaludisConfigError("For manager '" + s + "', no alias is defined"); + + return create_named_output_manager(alias, n); + } + else + return OutputManagerFactory::get_instance()->create( + std::tr1::bind(&from_keys, i->second, std::tr1::placeholders::_1), + std::tr1::bind(&OutputConf::create_named_output_manager, this, + std::tr1::placeholders::_1, std::tr1::cref(n)), + std::tr1::bind(replace_percent_vars, std::tr1::placeholders::_1, vars, std::tr1::placeholders::_2, + i->second) + ); +} + template class PrivateImplementationPattern<paludis_environment::OutputConf>; diff --git a/paludis/environments/paludis/output_conf.hh b/paludis/environments/paludis/output_conf.hh index 903b03cea..1edbb3b65 100644 --- a/paludis/environments/paludis/output_conf.hh +++ b/paludis/environments/paludis/output_conf.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 2010 Ciaran McCreesh * * This file is part of the Paludis package manager. Paludis is free software; * you can redistribute it and/or modify it under the terms of the GNU General @@ -53,6 +53,9 @@ namespace paludis const std::tr1::shared_ptr<OutputManager> create_output_manager( const CreateOutputManagerInfo &) const; + + const std::tr1::shared_ptr<OutputManager> create_named_output_manager( + const std::string & s, const CreateOutputManagerInfo & n) const; }; } diff --git a/paludis/environments/paludis/output_managers.cc b/paludis/environments/paludis/output_managers.cc deleted file mode 100644 index 24ed0270a..000000000 --- a/paludis/environments/paludis/output_managers.cc +++ /dev/null @@ -1,198 +0,0 @@ -/* 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/environments/paludis/output_managers.hh> -#include <paludis/environments/paludis/bashable_conf.hh> -#include <paludis/environments/paludis/paludis_config.hh> -#include <paludis/environments/paludis/paludis_environment.hh> -#include <paludis/environments/paludis/action_to_string.hh> -#include <paludis/util/private_implementation_pattern-impl.hh> -#include <paludis/util/config_file.hh> -#include <paludis/util/wrapped_forward_iterator.hh> -#include <paludis/util/map.hh> -#include <paludis/util/strip.hh> -#include <paludis/util/simple_parser.hh> -#include <paludis/output_manager_factory.hh> -#include <paludis/create_output_manager_info.hh> -#include <paludis/package_id.hh> -#include <paludis/metadata_key.hh> -#include <algorithm> -#include <tr1/unordered_map> -#include <sys/types.h> -#include <unistd.h> -#include <time.h> - -using namespace paludis; -using namespace paludis::paludis_environment; - -namespace -{ - typedef std::tr1::unordered_map<std::string, std::tr1::shared_ptr<const KeyValueConfigFile> > Store; - - std::string from_kv(const std::tr1::shared_ptr<const KeyValueConfigFile> & m, - const std::string & k) - { - return m->get(k); - } -} - -namespace paludis -{ - template<> - struct Implementation<OutputManagers> - { - Store store; - }; -} - -OutputManagers::OutputManagers(const PaludisEnvironment * const) : - PrivateImplementationPattern<OutputManagers>(new Implementation<OutputManagers>) -{ -} - -OutputManagers::~OutputManagers() -{ -} - -void -OutputManagers::add(const FSEntry & filename, const std::tr1::shared_ptr<const Map<std::string, std::string> > & predefined_variables) -{ - Context context("When adding source '" + stringify(filename) + "' as an output manager file:"); - - std::tr1::shared_ptr<KeyValueConfigFile> f(make_bashable_kv_conf(filename, predefined_variables, KeyValueConfigFileOptions())); - if (! f) - return; - - std::string manager(filename.basename()); - manager = strip_trailing_string(manager, ".conf"); - manager = strip_trailing_string(manager, ".bash"); - - _imp->store[manager] = f; -} - -const std::tr1::shared_ptr<OutputManager> -OutputManagers::create_named_output_manager(const std::string & s, const CreateOutputManagerInfo & n) const -{ - Context context("When creating output manager named '" + s + "':"); - - Store::const_iterator i(_imp->store.find(s)); - if (i == _imp->store.end()) - throw PaludisConfigError("No output manager named '" + s + "' exists"); - - std::tr1::shared_ptr<Map<std::string, std::string> > vars(vars_from_create_output_manager_info(n)); - return OutputManagerFactory::get_instance()->create( - std::tr1::bind(&from_kv, i->second, std::tr1::placeholders::_1), - std::tr1::bind(&OutputManagers::create_named_output_manager, this, std::tr1::placeholders::_1, std::tr1::cref(n)), - std::tr1::bind(replace_percent_vars, std::tr1::placeholders::_1, vars, std::tr1::placeholders::_2) - ); -} - -namespace -{ - std::string escape(const std::string & s) - { - std::string result(s); - std::replace(result.begin(), result.end(), ' ', '_'); - std::replace(result.begin(), result.end(), '/', '_'); - return result; - } - - struct CreateVarsFromInfo - { - std::tr1::shared_ptr<Map<std::string, std::string> > m; - - CreateVarsFromInfo(std::tr1::shared_ptr<Map<std::string, std::string> > & mm) : - m(mm) - { - } - - void visit(const CreateOutputManagerForRepositorySyncInfo & i) - { - m->insert("type", "repository"); - m->insert("action", "sync"); - m->insert("name", stringify(i.repository().name())); - m->insert("full_name", stringify(i.repository().name())); - m->insert("pid", stringify(getpid())); - m->insert("time", stringify(time(0))); - } - - void visit(const CreateOutputManagerForPackageIDActionInfo & i) - { - m->insert("type", "package"); - m->insert("action", action_to_string(i.action())); - m->insert("name", stringify(i.package_id()->name())); - m->insert("id", escape(stringify(*i.package_id()))); - m->insert("full_name", escape(stringify(*i.package_id()))); - if (i.package_id()->slot_key()) - m->insert("slot", stringify(i.package_id()->slot_key()->value())); - m->insert("version", stringify(i.package_id()->version())); - m->insert("repository", stringify(i.package_id()->repository()->name())); - m->insert("category", stringify(i.package_id()->name().category())); - m->insert("package", stringify(i.package_id()->name().package())); - m->insert("pid", stringify(getpid())); - m->insert("time", stringify(time(0))); - } - }; -} - -const std::tr1::shared_ptr<Map<std::string, std::string> > -OutputManagers::vars_from_create_output_manager_info( - const CreateOutputManagerInfo & i) const -{ - std::tr1::shared_ptr<Map<std::string, std::string> > result(new Map<std::string, std::string>); - CreateVarsFromInfo v(result); - i.accept(v); - return result; -} - -const std::string -paludis::paludis_environment::replace_percent_vars( - const std::string & s, - const std::tr1::shared_ptr<const Map<std::string, std::string> > & vars, - const std::tr1::shared_ptr<const Map<std::string, std::string> > & override_vars) -{ - std::string result, token; - SimpleParser parser(s); - while (! parser.eof()) - { - if (parser.consume((+simple_parser::any_except("%")) >> token)) - result.append(token); - else if (parser.consume(simple_parser::exact("%%"))) - result.append("%"); - else if (parser.consume(simple_parser::exact("%{") & - ((+simple_parser::any_except("} \t\r\n%")) >> token) & - simple_parser::exact("}"))) - { - Map<std::string, std::string>::ConstIterator v(override_vars->find(token)); - if (v == override_vars->end()) - v = vars->find(token); - if (v == vars->end()) - throw PaludisConfigError("No variable named '" + token + "' in var string '" + s + "'"); - - result.append(v->second); - } - else - throw PaludisConfigError("Invalid var string '" + s + "'"); - } - - return result; -} - -template class PrivateImplementationPattern<paludis_environment::OutputManagers>; - diff --git a/paludis/environments/paludis/output_managers.hh b/paludis/environments/paludis/output_managers.hh deleted file mode 100644 index 2c514804a..000000000 --- a/paludis/environments/paludis/output_managers.hh +++ /dev/null @@ -1,76 +0,0 @@ -/* 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_ENVIRONMENTS_PALUDIS_OUTPUT_MANAGERS_HH -#define PALUDIS_GUARD_PALUDIS_ENVIRONMENTS_PALUDIS_OUTPUT_MANAGERS_HH 1 - -#include <paludis/util/attributes.hh> -#include <paludis/util/private_implementation_pattern.hh> -#include <paludis/util/instantiation_policy.hh> -#include <paludis/util/fs_entry-fwd.hh> -#include <paludis/util/map-fwd.hh> -#include <paludis/output_manager-fwd.hh> -#include <paludis/create_output_manager_info-fwd.hh> -#include <tr1/memory> -#include <string> - -namespace paludis -{ - class PaludisEnvironment; - - namespace paludis_environment - { - const std::string replace_percent_vars( - const std::string &, - const std::tr1::shared_ptr<const Map<std::string, std::string> > & vars, - const std::tr1::shared_ptr<const Map<std::string, std::string> > & override_vars); - - class OutputManagers : - private PrivateImplementationPattern<OutputManagers>, - private InstantiationPolicy<OutputManagers, instantiation_method::NonCopyableTag> - { - public: - ///\name Basic operations - ///\{ - - OutputManagers(const PaludisEnvironment * const); - ~OutputManagers(); - - ///\} - - /** - * Add another file. - */ - void add(const FSEntry &, const std::tr1::shared_ptr<const Map<std::string, std::string> > &); - - const std::tr1::shared_ptr<OutputManager> create_named_output_manager( - const std::string &, - const CreateOutputManagerInfo &) const; - - const std::tr1::shared_ptr<Map<std::string, std::string> > vars_from_create_output_manager_info( - const CreateOutputManagerInfo &) const; - }; - } - -#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE - extern template class PrivateImplementationPattern<paludis_environment::OutputManagers>; -#endif -} - -#endif diff --git a/paludis/environments/paludis/output_managers/Makefile.am b/paludis/environments/paludis/output_managers/Makefile.am deleted file mode 100644 index fa920bde9..000000000 --- a/paludis/environments/paludis/output_managers/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -SUBDIRS = . -CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT *.epicfail .keep -BUILT_SOURCES = -MAINTAINERCLEANFILES = Makefile.in -AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@ -DEFS= \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DLIBDIR=\"$(libdir)\" - -AUTOMAKE_OPTIONS = parallel-tests - -shareenvpaludisdir = $(datarootdir)/paludis/environments/paludis/output_managers - -dist_shareenvpaludis_DATA = \ - logged.conf \ - quiet.conf \ - standard.conf \ - standard_on_failure.conf \ - keep_messages.part.conf \ - keep_stdout_as_messages.part.conf \ - logged_only.part.conf \ - show_messages.part.conf - -logdir = @HACKED_LOG_DIR@ - -log_DATA = .keep - -.keep : - touch $@ - -built-sources : $(BUILT_SOURCES) - for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done - diff --git a/paludis/environments/paludis/output_managers/keep_messages.part.conf b/paludis/environments/paludis/output_managers/keep_messages.part.conf deleted file mode 100644 index 5cc0f7b4e..000000000 --- a/paludis/environments/paludis/output_managers/keep_messages.part.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Keep message logs, ignore stdout / stderr. Not directly usable. - -handler = messages_to_stdout -child = keep_stdout_as_messages.part -format_debug = -format_info = --- %{message} -format_warn = *** %{message} -format_error = !!! %{message} -format_log = +++ %{message} - diff --git a/paludis/environments/paludis/output_managers/keep_stdout_as_messages.part.conf b/paludis/environments/paludis/output_managers/keep_stdout_as_messages.part.conf deleted file mode 100644 index 112293fe5..000000000 --- a/paludis/environments/paludis/output_managers/keep_stdout_as_messages.part.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Keep message logs. For use by keep_messages.part; do not use directly. - -handler = file -stdout = ${root}/var/log/paludis/%{time}-%{action}-%{full_name}.messages -stderr = ${stdout} -keep_on_success = true -keep_on_empty = false -summary_output_manager = standard -summary_output_stdout_message = Messages log: ${stdout} - diff --git a/paludis/environments/paludis/output_managers/logged.conf b/paludis/environments/paludis/output_managers/logged.conf deleted file mode 100644 index 1e40328dd..000000000 --- a/paludis/environments/paludis/output_managers/logged.conf +++ /dev/null @@ -1,6 +0,0 @@ -# Output to stdout / stderr, keep logs of messages and keep output logs on -# failure. - -handler = tee -children = standard logged_only.part keep_messages.part - diff --git a/paludis/environments/paludis/output_managers/logged_only.part.conf b/paludis/environments/paludis/output_managers/logged_only.part.conf deleted file mode 100644 index 8b0d2b6a4..000000000 --- a/paludis/environments/paludis/output_managers/logged_only.part.conf +++ /dev/null @@ -1,11 +0,0 @@ -# Keep logs of output only, and discard on success. Used by logged and quiet; -# not directly usable. -# -handler = file -stdout = ${root}/var/log/paludis/%{time}-%{action}-%{full_name}.out -stderr = ${stdout} -keep_on_success = false -keep_on_empty = true -summary_output_manager = standard -summary_output_stdout_message = Output log: ${stdout} - diff --git a/paludis/environments/paludis/output_managers/quiet.conf b/paludis/environments/paludis/output_managers/quiet.conf deleted file mode 100644 index 980db2979..000000000 --- a/paludis/environments/paludis/output_managers/quiet.conf +++ /dev/null @@ -1,6 +0,0 @@ -# Messages only to stdout / stderr, keep logs of messages and keep output logs -# on failure. - -handler = tee -children = logged_only.part show_messages.part keep_messages.part - diff --git a/paludis/environments/paludis/output_managers/show_messages.part.conf b/paludis/environments/paludis/output_managers/show_messages.part.conf deleted file mode 100644 index 39cfa2c51..000000000 --- a/paludis/environments/paludis/output_managers/show_messages.part.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Show messages only. Not usable on its own. - -handler = messages_to_stdout -child = standard - diff --git a/paludis/environments/paludis/output_managers/standard.conf b/paludis/environments/paludis/output_managers/standard.conf deleted file mode 100644 index 7b910c7db..000000000 --- a/paludis/environments/paludis/output_managers/standard.conf +++ /dev/null @@ -1,4 +0,0 @@ -# This output manager sends stdout output to stdout and stderr output to -# stderr. There is no special handling for messages. - -handler = standard diff --git a/paludis/environments/paludis/output_managers/standard_on_failure.conf b/paludis/environments/paludis/output_managers/standard_on_failure.conf deleted file mode 100644 index f6dd6e04b..000000000 --- a/paludis/environments/paludis/output_managers/standard_on_failure.conf +++ /dev/null @@ -1,6 +0,0 @@ -# This handler saves up output (in memory, so don't use it for big processes) -# and displays it to standard only if an error occurs. - -handler = forward_on_failure -child = standard - diff --git a/paludis/environments/paludis/paludis_config.cc b/paludis/environments/paludis/paludis_config.cc index c325dee97..26cf38145 100644 --- a/paludis/environments/paludis/paludis_config.cc +++ b/paludis/environments/paludis/paludis_config.cc @@ -25,7 +25,6 @@ #include <paludis/environments/paludis/licenses_conf.hh> #include <paludis/environments/paludis/package_mask_conf.hh> #include <paludis/environments/paludis/output_conf.hh> -#include <paludis/environments/paludis/output_managers.hh> #include <paludis/environments/paludis/world.hh> #include <paludis/environments/paludis/extra_distribution_data.hh> @@ -183,7 +182,6 @@ namespace paludis std::tr1::shared_ptr<PackageMaskConf> package_unmask_conf; std::tr1::shared_ptr<MirrorsConf> mirrors_conf; std::tr1::shared_ptr<OutputConf> output_conf; - std::tr1::shared_ptr<OutputManagers> output_managers; mutable std::tr1::shared_ptr<World> world; mutable Mutex reduced_mutex; @@ -215,7 +213,6 @@ namespace paludis package_unmask_conf(new PackageMaskConf(e)), mirrors_conf(new MirrorsConf(e)), output_conf(new OutputConf(e)), - output_managers(new OutputManagers(e)), has_environment_conf(false), accept_all_breaks_portage(false), reduced_username(getenv_with_default("PALUDIS_REDUCED_USERNAME", "paludisbuild")), @@ -706,46 +703,6 @@ PaludisConfig::PaludisConfig(PaludisEnvironment * const e, const std::string & s throw PaludisConfigError("No output confs found"); } - /* output managers */ - { - std::list<FSEntry> dirs, files; - dirs.push_back(getenv_with_default("PALUDIS_OUTPUT_MANAGERS_DIR", - SHAREDIR "/paludis/environments/paludis/output_managers/")); - dirs.push_back(local_config_dir / dist->output_managers_directory()); - - for (std::list<FSEntry>::const_iterator dir(dirs.begin()), dir_end(dirs.end()) ; - dir != dir_end ; ++dir) - { - if (! dir->exists()) - continue; - - std::remove_copy_if(DirIterator(*dir), DirIterator(), std::back_inserter(files), - std::tr1::bind(std::logical_not<bool>(), std::tr1::bind(&is_file_with_extension, _1, ".conf", IsFileWithOptions()))); - std::remove_copy_if(DirIterator(*dir), DirIterator(), std::back_inserter(files), - std::tr1::bind(std::logical_not<bool>(), std::tr1::bind(&is_file_with_extension, _1, ".bash", IsFileWithOptions()))); - } - - bool any(false); - for (std::list<FSEntry>::const_iterator file(files.begin()), file_end(files.end()) ; - file != file_end ; ++file) - { - Context local_context("When reading output manager file '" + stringify(*file) + "':"); - - if (! file->exists()) - continue; - - std::tr1::shared_ptr<Map<std::string, std::string> > predefined_variables( - new Map<std::string, std::string>); - predefined_variables->insert("root", _imp->root); - predefined_variables->insert("ROOT", _imp->root); - _imp->output_managers->add(*file, predefined_variables); - any = true; - } - - if (! any) - throw PaludisConfigError("No output managers found"); - } - /* use */ { std::list<FSEntry> files; @@ -1033,12 +990,6 @@ PaludisConfig::package_unmask_conf() const return _imp->package_unmask_conf; } -std::tr1::shared_ptr<const OutputManagers> -PaludisConfig::output_managers() const -{ - return _imp->output_managers; -} - std::tr1::shared_ptr<const MirrorsConf> PaludisConfig::mirrors_conf() const { diff --git a/paludis/environments/paludis/paludis_config.hh b/paludis/environments/paludis/paludis_config.hh index f3b1d94cf..73d932229 100644 --- a/paludis/environments/paludis/paludis_config.hh +++ b/paludis/environments/paludis/paludis_config.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh + * Copyright (c) 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh * * This file is part of the Paludis package manager. Paludis is free software; * you can redistribute it and/or modify it under the terms of the GNU General @@ -51,7 +51,6 @@ namespace paludis struct PackageMaskConf; struct MirrorsConf; struct OutputConf; - struct OutputManagers; struct World; /** @@ -122,7 +121,6 @@ namespace paludis std::tr1::shared_ptr<const MirrorsConf> mirrors_conf() const; std::tr1::shared_ptr<const World> world() const; std::tr1::shared_ptr<const OutputConf> output_conf() const; - std::tr1::shared_ptr<const OutputManagers> output_managers() const; ///\} diff --git a/paludis/environments/paludis/paludis_environment.cc b/paludis/environments/paludis/paludis_environment.cc index 25c4fede5..8dd5babba 100644 --- a/paludis/environments/paludis/paludis_environment.cc +++ b/paludis/environments/paludis/paludis_environment.cc @@ -25,7 +25,6 @@ #include <paludis/environments/paludis/licenses_conf.hh> #include <paludis/environments/paludis/mirrors_conf.hh> #include <paludis/environments/paludis/output_conf.hh> -#include <paludis/environments/paludis/output_managers.hh> #include <paludis/environments/paludis/world.hh> #include <paludis/util/config_file.hh> @@ -489,12 +488,6 @@ PaludisEnvironment::create_output_manager(const CreateOutputManagerInfo & i) con return _imp->config->output_conf()->create_output_manager(i); } -const std::tr1::shared_ptr<OutputManager> -PaludisEnvironment::create_named_output_manager(const std::string & s, const CreateOutputManagerInfo & i) const -{ - return _imp->config->output_managers()->create_named_output_manager(s, i); -} - namespace { std::tr1::shared_ptr<const SetSpecTree> make_world_set(const std::tr1::shared_ptr<const World> & world) diff --git a/paludis/environments/paludis/paludis_environment.hh b/paludis/environments/paludis/paludis_environment.hh index 605dc4c45..5be027520 100644 --- a/paludis/environments/paludis/paludis_environment.hh +++ b/paludis/environments/paludis/paludis_environment.hh @@ -166,10 +166,6 @@ namespace paludis virtual const std::tr1::shared_ptr<OutputManager> create_output_manager( const CreateOutputManagerInfo &) const; - - const std::tr1::shared_ptr<OutputManager> create_named_output_manager( - const std::string &, - const CreateOutputManagerInfo &) const; }; } #endif diff --git a/paludis/environments/paludis/tests_output.conf b/paludis/environments/paludis/tests_output.conf index 8f4e2800b..13161cd1e 100644 --- a/paludis/environments/paludis/tests_output.conf +++ b/paludis/environments/paludis/tests_output.conf @@ -1 +1,11 @@ -type = * : standard +# vim: set tw=80 ft=conf et sw=4 sts=4 : + +# When running tests, just send everything to standard output. + +[rule all] +type = * +manager = standard + +[manager standard] +handler = standard + diff --git a/paludis/file_output_manager.cc b/paludis/file_output_manager.cc index ff797a51f..aa9eff807 100644 --- a/paludis/file_output_manager.cc +++ b/paludis/file_output_manager.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 2010 Ciaran McCreesh * * This file is part of the Paludis package manager. Paludis is free software; * you can redistribute it and/or modify it under the terms of the GNU General @@ -35,49 +35,39 @@ namespace paludis template <> struct Implementation<FileOutputManager> { - FSEntry stdout_file; - FSEntry stderr_file; + FSEntry filename; std::tr1::shared_ptr<SafeOFStream> stdout_stream; std::tr1::shared_ptr<SafeOFStream> stderr_stream; const bool keep_on_success, keep_on_empty; const std::tr1::shared_ptr<OutputManager> summary_output_manager; - const std::string summary_output_stdout_message; - const std::string summary_output_stderr_message; + const std::string summary_output_message; - bool succeeded, unlinked_stdout, unlinked_stderr; + bool succeeded, unlinked; Implementation( const FSEntry & o, - const FSEntry & e, const bool k, const bool l, const std::tr1::shared_ptr<OutputManager> & m, - const std::string & s, - const std::string & t + const std::string & s ) : - stdout_file(o), - stderr_file(e), - stdout_stream(new SafeOFStream(o)), + filename(o), + stdout_stream(new SafeOFStream(filename)), + stderr_stream(new SafeOFStream(filename)), keep_on_success(k), keep_on_empty(l), summary_output_manager(m), - summary_output_stdout_message(s), - summary_output_stderr_message(t), + summary_output_message(s), succeeded(false), - unlinked_stdout(false), - unlinked_stderr(false) + unlinked(false) { - if (o == e) - stderr_stream = stdout_stream; - else - stderr_stream.reset(new SafeOFStream(e)); } }; } -FileOutputManager::FileOutputManager(const FSEntry & o, const FSEntry & e, const bool k, const bool l, - const std::tr1::shared_ptr<OutputManager> & m, const std::string & s, const std::string & t) : - PrivateImplementationPattern<FileOutputManager>(new Implementation<FileOutputManager>(o, e, k, l, m, s, t)) +FileOutputManager::FileOutputManager(const FSEntry & o, const bool k, const bool l, + const std::tr1::shared_ptr<OutputManager> & m, const std::string & s) : + PrivateImplementationPattern<FileOutputManager>(new Implementation<FileOutputManager>(o, k, l, m, s)) { } @@ -88,39 +78,19 @@ FileOutputManager::~FileOutputManager() *_imp->stdout_stream << std::flush; *_imp->stderr_stream << std::flush; - FSEntry stdout_file_now(stringify(_imp->stdout_file)), stderr_file_now(stringify(_imp->stderr_file)); - if (stdout_file_now.exists() && 0 == stdout_file_now.file_size()) + FSEntry filename_now(stringify(_imp->filename)); + if (filename_now.exists() && 0 == filename_now.file_size()) { - _imp->stdout_file.unlink(); - _imp->unlinked_stdout = true; - } - - if (stdout_file_now != stderr_file_now) - { - if (stderr_file_now.exists() && 0 == stderr_file_now.file_size()) - { - _imp->stderr_file.unlink(); - _imp->unlinked_stderr = true; - } + filename_now.unlink(); + _imp->unlinked = true; } } if (_imp->summary_output_manager) { - if ((! _imp->unlinked_stdout) && (! _imp->summary_output_stdout_message.empty())) - { - _imp->summary_output_manager->stdout_stream() - << _imp->summary_output_stdout_message - << std::endl; - } - - if (_imp->stdout_file != _imp->stderr_file) - { - if ((! _imp->unlinked_stderr) && (! _imp->summary_output_stderr_message.empty())) - _imp->summary_output_manager->stdout_stream() - << _imp->summary_output_stderr_message - << std::endl; - } + if ((! _imp->unlinked) && (! _imp->summary_output_message.empty())) + _imp->summary_output_manager->message(_imp->succeeded ? mt_info : mt_error, + _imp->summary_output_message); } } @@ -137,21 +107,29 @@ FileOutputManager::stderr_stream() } void +FileOutputManager::message(const MessageType, const std::string &) +{ +} + +void FileOutputManager::succeeded() { _imp->succeeded = true; if (! _imp->keep_on_success) { - _imp->stdout_file.unlink(); - _imp->stderr_file.unlink(); - _imp->unlinked_stdout = true; - _imp->unlinked_stderr = true; + _imp->filename.unlink(); + _imp->unlinked = true; } } void -FileOutputManager::message(const MessageType, const std::string &) +FileOutputManager::flush() +{ +} + +void +FileOutputManager::nothing_more_to_come() { } @@ -169,19 +147,15 @@ FileOutputManager::factory_create( const OutputManagerFactory::CreateChildFunction & create_child_function, const OutputManagerFactory::ReplaceVarsFunc & replace_vars_func) { - std::string stdout_s(key_func("stdout")), stderr_s(key_func("stderr")), - keep_on_success_s(key_func("keep_on_success")), keep_on_empty_s(key_func("keep_on_empty")), + std::string filename_s(key_func("filename")), + keep_on_success_s(key_func("keep_on_success")), + keep_on_empty_s(key_func("keep_on_empty")), summary_output_manager_s(key_func("summary_output_manager")), - summary_output_stdout_message_s(key_func("summary_output_stdout_message")), - summary_output_stderr_message_s(key_func("summary_output_stderr_message")); - - if (stdout_s.empty()) - throw ConfigurationError("Key 'stdout' not specified when creating a file output manager"); - stdout_s = replace_vars_func(stdout_s, make_shared_ptr(new Map<std::string, std::string>)); + summary_output_message_s(key_func("summary_output_message")); - if (stderr_s.empty()) - throw ConfigurationError("Key 'stderr' not specified when creating a file output manager"); - stderr_s = replace_vars_func(stderr_s, make_shared_ptr(new Map<std::string, std::string>)); + if (filename_s.empty()) + throw ConfigurationError("Key 'filename' not specified when creating a file output manager"); + filename_s = replace_vars_func(filename_s, make_shared_ptr(new Map<std::string, std::string>)); if (keep_on_success_s.empty()) keep_on_success_s = "true"; @@ -193,13 +167,11 @@ FileOutputManager::factory_create( if (! summary_output_manager_s.empty()) summary_output_manager = create_child_function(summary_output_manager_s); - summary_output_stdout_message_s = replace_vars_func(summary_output_stdout_message_s, make_shared_ptr(new Map<std::string, std::string>)); - summary_output_stderr_message_s = replace_vars_func(summary_output_stderr_message_s, make_shared_ptr(new Map<std::string, std::string>)); + summary_output_message_s = replace_vars_func(summary_output_message_s, make_shared_ptr(new Map<std::string, std::string>)); - return make_shared_ptr(new FileOutputManager(FSEntry(stdout_s), FSEntry(stderr_s), + return make_shared_ptr(new FileOutputManager(FSEntry(filename_s), destringify<bool>(keep_on_success_s), destringify<bool>(keep_on_empty_s), - summary_output_manager, summary_output_stdout_message_s, - summary_output_stderr_message_s)); + summary_output_manager, summary_output_message_s)); } template class PrivateImplementationPattern<FileOutputManager>; diff --git a/paludis/file_output_manager.hh b/paludis/file_output_manager.hh index 5009abe31..31e206cfa 100644 --- a/paludis/file_output_manager.hh +++ b/paludis/file_output_manager.hh @@ -36,16 +36,19 @@ namespace paludis public OutputManager { public: - FileOutputManager(const FSEntry &, const FSEntry &, const bool keep_on_success, - const bool keep_on_empty, const std::tr1::shared_ptr<OutputManager> & summary_output_manager, - const std::string & summary_output_stdout_message, - const std::string & summary_output_stderr_message); + FileOutputManager(const FSEntry &, + const bool keep_on_success, + const bool keep_on_empty, + const std::tr1::shared_ptr<OutputManager> & summary_output_manager, + const std::string & summary_output_message); ~FileOutputManager(); virtual std::ostream & stdout_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual std::ostream & stderr_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual void succeeded(); + virtual void flush(); + virtual void nothing_more_to_come(); virtual void message(const MessageType, const std::string &); static const std::tr1::shared_ptr<const Set<std::string> > factory_managers() diff --git a/paludis/files.m4 b/paludis/files.m4 index b9f1470fe..4c346e9ff 100644 --- a/paludis/files.m4 +++ b/paludis/files.m4 @@ -11,6 +11,7 @@ dnl on this file at present... add(`about', `hh', `test') add(`action', `hh', `cc', `fwd', `se') add(`action_names', `hh', `cc', `fwd') +add(`buffer_output_manager', `hh', `cc', `fwd') add(`choice', `hh', `cc', `fwd') add(`common_sets', `hh', `cc', `fwd') add(`contents', `hh', `cc', `fwd') @@ -37,6 +38,7 @@ add(`filter', `hh', `cc', `fwd', `test') add(`filter_handler', `hh', `cc', `fwd') add(`filtered_generator', `hh', `cc', `fwd', `test') add(`find_unused_packages_task', `hh', `cc') +add(`format_messages_output_manager', `hh', `fwd', `cc') add(`formatter', `hh', `fwd', `cc') add(`forward_on_failure_output_manager', `hh', `fwd', `cc') add(`fuzzy_finder', `hh', `cc', `test') @@ -51,7 +53,6 @@ add(`mask', `hh', `cc', `fwd', `se') add(`match_package', `hh', `cc', `se', `fwd') add(`merger', `hh', `cc', `fwd', `se', `test', `testscript') add(`merger_entry_type', `hh', `cc', `se') -add(`messages_to_stdout_output_handler', `hh', `cc', `fwd') add(`metadata_key', `hh', `cc', `se', `fwd') add(`metadata_key_holder', `hh', `cc', `fwd') add(`name', `hh', `cc', `fwd', `test') diff --git a/paludis/format_messages_output_manager-fwd.hh b/paludis/format_messages_output_manager-fwd.hh new file mode 100644 index 000000000..e2509d73d --- /dev/null +++ b/paludis/format_messages_output_manager-fwd.hh @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2010 Ciaran McCreesh + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_FORMAT_MESSAGES_OUTPUT_MANAGER_FWD_HH +#define PALUDIS_GUARD_PALUDIS_FORMAT_MESSAGES_OUTPUT_MANAGER_FWD_HH 1 + +namespace paludis +{ + struct FormatMessagesOutputManager; +} + +#endif diff --git a/paludis/format_messages_output_manager.cc b/paludis/format_messages_output_manager.cc new file mode 100644 index 000000000..0053e0d97 --- /dev/null +++ b/paludis/format_messages_output_manager.cc @@ -0,0 +1,192 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2010 Ciaran McCreesh + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <paludis/format_messages_output_manager.hh> +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <paludis/util/discard_output_stream.hh> +#include <paludis/util/set.hh> +#include <paludis/util/map.hh> +#include <paludis/util/wrapped_forward_iterator.hh> +#include <paludis/util/make_shared_ptr.hh> +#include <paludis/util/destringify.hh> +#include <paludis/util/stringify.hh> + +using namespace paludis; + +namespace paludis +{ + template <> + struct Implementation<FormatMessagesOutputManager> + { + DiscardOutputStream stream; + const std::tr1::shared_ptr<OutputManager> child; + const std::string format_debug; + const std::string format_info; + const std::string format_warn; + const std::string format_error; + const std::string format_log; + + const FormatMessagesOutputManagerFormatFunction format_func; + + Implementation( + const std::tr1::shared_ptr<OutputManager> & c, + const std::string & d, + const std::string & i, + const std::string & w, + const std::string & e, + const std::string & l, + const FormatMessagesOutputManagerFormatFunction & f + ) : + child(c), + format_debug(d), + format_info(i), + format_warn(w), + format_error(e), + format_log(l), + format_func(f) + { + } + }; +} + +FormatMessagesOutputManager::FormatMessagesOutputManager( + const std::tr1::shared_ptr<OutputManager> & child, + const std::string & format_debug, + const std::string & format_info, + const std::string & format_warn, + const std::string & format_error, + const std::string & format_log, + const FormatMessagesOutputManagerFormatFunction & f) : + PrivateImplementationPattern<FormatMessagesOutputManager>(new Implementation<FormatMessagesOutputManager>( + child, format_debug, format_info, format_warn, format_error, format_log, f)) +{ +} + +FormatMessagesOutputManager::~FormatMessagesOutputManager() +{ +} + +std::ostream & +FormatMessagesOutputManager::stdout_stream() +{ + return _imp->stream; +} + +std::ostream & +FormatMessagesOutputManager::stderr_stream() +{ + return _imp->stream; +} + +void +FormatMessagesOutputManager::message(const MessageType t, const std::string & s) +{ + std::string f; + switch (t) + { + case mt_info: + f = _imp->format_info; + break; + case mt_debug: + f = _imp->format_debug; + break; + case mt_warn: + f = _imp->format_warn; + break; + case mt_error: + f = _imp->format_error; + break; + case mt_log: + f = _imp->format_log; + break; + + default: + break; + } + + if (f.empty()) + return; + + f = _imp->format_func(f, s); + _imp->child->stdout_stream() << f << std::flush; +} + +void +FormatMessagesOutputManager::succeeded() +{ + _imp->child->succeeded(); +} + +void +FormatMessagesOutputManager::flush() +{ + _imp->child->flush(); +} + +void +FormatMessagesOutputManager::nothing_more_to_come() +{ + _imp->child->nothing_more_to_come(); +} + +const std::tr1::shared_ptr<const Set<std::string> > +FormatMessagesOutputManager::factory_managers() +{ + std::tr1::shared_ptr<Set<std::string> > result(new Set<std::string>); + result->insert("format_messages"); + return result; +} + +namespace +{ + std::string format_message( + const OutputManagerFactory::ReplaceVarsFunc r, + const std::string & f, + const std::string & s) + { + std::tr1::shared_ptr<Map<std::string, std::string> > m(new Map<std::string, std::string>); + m->insert("message", s); + return r(f, m); + } +} + +const std::tr1::shared_ptr<OutputManager> +FormatMessagesOutputManager::factory_create( + const OutputManagerFactory::KeyFunction & key_func, + const OutputManagerFactory::CreateChildFunction & create_child_function, + const OutputManagerFactory::ReplaceVarsFunc & replace_vars_func) +{ + std::string child_s(key_func("child")), + format_debug_s(key_func("format_debug")), + format_info_s(key_func("format_info")), + format_warn_s(key_func("format_warn")), + format_error_s(key_func("format_error")), + format_log_s(key_func("format_log")); + + std::tr1::shared_ptr<OutputManager> child(create_child_function(child_s)); + + FormatMessagesOutputManagerFormatFunction format_func(std::tr1::bind( + &format_message, replace_vars_func, std::tr1::placeholders::_1, std::tr1::placeholders::_2)); + + return make_shared_ptr(new FormatMessagesOutputManager( + child, format_debug_s, format_info_s, format_warn_s, format_error_s, format_log_s, format_func)); +} + +template class PrivateImplementationPattern<FormatMessagesOutputManager>; + diff --git a/paludis/format_messages_output_manager.hh b/paludis/format_messages_output_manager.hh new file mode 100644 index 000000000..6aafba8b5 --- /dev/null +++ b/paludis/format_messages_output_manager.hh @@ -0,0 +1,76 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2010 Ciaran McCreesh + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_FORMAT_MESSAGES_OUTPUT_MANAGER_HH +#define PALUDIS_GUARD_PALUDIS_FORMAT_MESSAGES_OUTPUT_MANAGER_HH 1 + +#include <paludis/format_messages_output_manager-fwd.hh> +#include <paludis/output_manager.hh> +#include <paludis/output_manager_factory.hh> +#include <paludis/util/set-fwd.hh> +#include <paludis/util/private_implementation_pattern.hh> +#include <tr1/memory> +#include <tr1/functional> + +namespace paludis +{ + typedef std::tr1::function<std::string ( + const std::string &, + const std::string &)> FormatMessagesOutputManagerFormatFunction; + + class PALUDIS_VISIBLE FormatMessagesOutputManager : + private PrivateImplementationPattern<FormatMessagesOutputManager>, + public OutputManager + { + public: + FormatMessagesOutputManager( + const std::tr1::shared_ptr<OutputManager> & child, + const std::string & format_debug, + const std::string & format_info, + const std::string & format_warn, + const std::string & format_error, + const std::string & format_log, + const FormatMessagesOutputManagerFormatFunction &); + + ~FormatMessagesOutputManager(); + + virtual std::ostream & stdout_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual std::ostream & stderr_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); + + virtual void succeeded(); + virtual void flush(); + virtual void nothing_more_to_come(); + virtual void message(const MessageType, const std::string &); + + static const std::tr1::shared_ptr<const Set<std::string> > factory_managers() + PALUDIS_ATTRIBUTE((warn_unused_result)); + + static const std::tr1::shared_ptr<OutputManager> factory_create( + const OutputManagerFactory::KeyFunction &, + const OutputManagerFactory::CreateChildFunction &, + const OutputManagerFactory::ReplaceVarsFunc &) + PALUDIS_ATTRIBUTE((warn_unused_result)); + }; + +#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE + extern template class PrivateImplementationPattern<FormatMessagesOutputManager>; +#endif +} + +#endif diff --git a/paludis/forward_on_failure_output_manager.cc b/paludis/forward_on_failure_output_manager.cc index 21135441d..fe16c76a1 100644 --- a/paludis/forward_on_failure_output_manager.cc +++ b/paludis/forward_on_failure_output_manager.cc @@ -90,6 +90,16 @@ ForwardOnFailureOutputManager::message(const MessageType, const std::string &) { } +void +ForwardOnFailureOutputManager::flush() +{ +} + +void +ForwardOnFailureOutputManager::nothing_more_to_come() +{ +} + const std::tr1::shared_ptr<const Set<std::string> > ForwardOnFailureOutputManager::factory_managers() { diff --git a/paludis/forward_on_failure_output_manager.hh b/paludis/forward_on_failure_output_manager.hh index a5e06110a..1ac69b22c 100644 --- a/paludis/forward_on_failure_output_manager.hh +++ b/paludis/forward_on_failure_output_manager.hh @@ -42,7 +42,9 @@ namespace paludis virtual std::ostream & stderr_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual void succeeded(); + virtual void flush(); virtual void message(const MessageType, const std::string &); + virtual void nothing_more_to_come(); static const std::tr1::shared_ptr<const Set<std::string> > factory_managers() PALUDIS_ATTRIBUTE((warn_unused_result)); diff --git a/paludis/messages_to_stdout_output_handler.cc b/paludis/messages_to_stdout_output_handler.cc deleted file mode 100644 index 0492fe469..000000000 --- a/paludis/messages_to_stdout_output_handler.cc +++ /dev/null @@ -1,171 +0,0 @@ -/* 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/messages_to_stdout_output_handler.hh> -#include <paludis/util/private_implementation_pattern-impl.hh> -#include <paludis/util/discard_output_stream.hh> -#include <paludis/util/sequence-impl.hh> -#include <paludis/util/set.hh> -#include <paludis/util/wrapped_forward_iterator.hh> -#include <paludis/util/make_shared_ptr.hh> -#include <paludis/util/exception.hh> -#include <paludis/util/map.hh> -#include <paludis/util/stringify.hh> - -using namespace paludis; - -namespace paludis -{ - template <> - struct Implementation<MessagesToStdoutOutputManager> - { - DiscardOutputStream output_stream; - const std::tr1::shared_ptr<OutputManager> child; - const OutputManagerFactory::ReplaceVarsFunc replace_vars_func; - const std::string f_debug; - const std::string f_info; - const std::string f_warn; - const std::string f_error; - const std::string f_log; - - Implementation( - const std::tr1::shared_ptr<OutputManager> & c, - const OutputManagerFactory::ReplaceVarsFunc & r, - const std::string & f_d, - const std::string & f_i, - const std::string & f_w, - const std::string & f_e, - const std::string & f_l) : - child(c), - replace_vars_func(r), - f_debug(f_d), - f_info(f_i), - f_warn(f_w), - f_error(f_e), - f_log(f_l) - { - } - }; -} - -MessagesToStdoutOutputManager::MessagesToStdoutOutputManager( - const std::tr1::shared_ptr<OutputManager> & s, - const OutputManagerFactory::ReplaceVarsFunc & replace_vars_func, - const std::string & f_debug, - const std::string & f_info, - const std::string & f_warn, - const std::string & f_error, - const std::string & f_log) : - PrivateImplementationPattern<MessagesToStdoutOutputManager>(new Implementation<MessagesToStdoutOutputManager>(s, replace_vars_func, - f_debug, f_info, f_warn, f_error, f_log)) -{ -} - -MessagesToStdoutOutputManager::~MessagesToStdoutOutputManager() -{ -} - -std::ostream & -MessagesToStdoutOutputManager::stdout_stream() -{ - return _imp->output_stream; -} - -std::ostream & -MessagesToStdoutOutputManager::stderr_stream() -{ - return _imp->output_stream; -} - -void -MessagesToStdoutOutputManager::succeeded() -{ - _imp->child->succeeded(); -} - -void -MessagesToStdoutOutputManager::message(const MessageType t, const std::string & s) -{ - std::string msg; - std::tr1::shared_ptr<Map<std::string, std::string> > x(new Map<std::string, std::string>); - x->insert("message", s); - - do - { - switch (t) - { - case mt_debug: - msg = _imp->replace_vars_func(_imp->f_debug, x); - continue; - - case mt_info: - msg = _imp->replace_vars_func(_imp->f_info, x); - continue; - - case mt_warn: - msg = _imp->replace_vars_func(_imp->f_warn, x); - continue; - - case mt_error: - msg = _imp->replace_vars_func(_imp->f_error, x); - continue; - - case mt_log: - msg = _imp->replace_vars_func(_imp->f_log, x); - continue; - - case last_mt: - break; - } - - throw InternalError(PALUDIS_HERE, "bad MessageType"); - } - while (false); - - if (! msg.empty()) - _imp->child->stdout_stream() << msg << std::endl; -} - -const std::tr1::shared_ptr<const Set<std::string> > -MessagesToStdoutOutputManager::factory_managers() -{ - std::tr1::shared_ptr<Set<std::string> > result(new Set<std::string>); - result->insert("messages_to_stdout"); - return result; -} - -const std::tr1::shared_ptr<OutputManager> -MessagesToStdoutOutputManager::factory_create( - const OutputManagerFactory::KeyFunction & key_func, - const OutputManagerFactory::CreateChildFunction & create_child, - const OutputManagerFactory::ReplaceVarsFunc & replace_vars_func) -{ - std::string child(key_func("child")); - if (child.empty()) - throw ConfigurationError("No child specified for MessagesToStdoutOutputManager"); - - std::string f_d(key_func("format_debug")), f_i(key_func("format_info")), f_w(key_func("format_warn")), - f_e(key_func("format_error")), f_l(key_func("format_log")); - - return make_shared_ptr(new MessagesToStdoutOutputManager(create_child(child), replace_vars_func, - f_d, f_i, f_w, f_e, f_l)); -} - -template class PrivateImplementationPattern<MessagesToStdoutOutputManager>; - diff --git a/paludis/output_manager.hh b/paludis/output_manager.hh index 8c0dfa964..1edee95af 100644 --- a/paludis/output_manager.hh +++ b/paludis/output_manager.hh @@ -46,6 +46,15 @@ namespace paludis virtual void message(const MessageType, const std::string &) = 0; /** + * Clients may call this method every few seconds when running + * multiple processes. + * + * This is used to display ongoing buffered messages without mixing + * output from multiple processes. + */ + virtual void flush() = 0; + + /** * Called if an action succeeds. This can be used to, for example, * unlink the files behind a to-disk logged output manager. * @@ -60,6 +69,18 @@ namespace paludis * carries out the action in question. */ virtual void succeeded() = 0; + + /** + * May be called to indicate that no further output or messages + * will occur, allowing for files to be closed off etc. + * + * Summary messages are shown when the output manager is + * destructed, not when this method is called. + * + * If this method and succeeded are both to be called, succeeded + * must be called first. + */ + virtual void nothing_more_to_come() = 0; }; } diff --git a/paludis/output_manager_factory.cc b/paludis/output_manager_factory.cc index 0013e1e62..c262ac2d2 100644 --- a/paludis/output_manager_factory.cc +++ b/paludis/output_manager_factory.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 2010 Ciaran McCreesh * * This file is part of the Paludis package manager. Paludis is free software; * you can redistribute it and/or modify it under the terms of the GNU General @@ -34,9 +34,9 @@ #include <tr1/unordered_map> #include <list> +#include <paludis/buffer_output_manager.hh> #include <paludis/file_output_manager.hh> -#include <paludis/forward_on_failure_output_manager.hh> -#include <paludis/messages_to_stdout_output_handler.hh> +#include <paludis/format_messages_output_manager.hh> #include <paludis/standard_output_manager.hh> #include <paludis/tee_output_manager.hh> @@ -67,7 +67,7 @@ namespace Keys::const_iterator i(keys.find(key)); if (i == keys.end()) throw ConfigurationError("Format '" + key + "' not supported when creating an output manager (known formats are { " - + join(first_iterator(keys.begin()), first_iterator(keys.end()), ", ") + "})"); + + join(first_iterator(keys.begin()), first_iterator(keys.end()), ", ") + " })"); return i->second; } @@ -93,9 +93,9 @@ OutputManagerFactory::OutputManagerFactory() : PrivateImplementationPattern<OutputManagerFactory>(new Implementation<OutputManagerFactory>) { /* we might want to make this plugin loadable at some point */ + add_manager(BufferOutputManager::factory_managers(), BufferOutputManager::factory_create); add_manager(FileOutputManager::factory_managers(), FileOutputManager::factory_create); - add_manager(ForwardOnFailureOutputManager::factory_managers(), ForwardOnFailureOutputManager::factory_create); - add_manager(MessagesToStdoutOutputManager::factory_managers(), MessagesToStdoutOutputManager::factory_create); + add_manager(FormatMessagesOutputManager::factory_managers(), FormatMessagesOutputManager::factory_create); add_manager(StandardOutputManager::factory_managers(), StandardOutputManager::factory_create); add_manager(TeeOutputManager::factory_managers(), TeeOutputManager::factory_create); } diff --git a/paludis/standard_output_manager.cc b/paludis/standard_output_manager.cc index 881ffddcd..ef4fd2407 100644 --- a/paludis/standard_output_manager.cc +++ b/paludis/standard_output_manager.cc @@ -50,6 +50,16 @@ StandardOutputManager::succeeded() } void +StandardOutputManager::flush() +{ +} + +void +StandardOutputManager::nothing_more_to_come() +{ +} + +void StandardOutputManager::message(const MessageType, const std::string &) { } diff --git a/paludis/standard_output_manager.hh b/paludis/standard_output_manager.hh index 5d2cf4639..f70cb7727 100644 --- a/paludis/standard_output_manager.hh +++ b/paludis/standard_output_manager.hh @@ -40,7 +40,9 @@ namespace paludis virtual std::ostream & stderr_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual void succeeded(); + virtual void flush(); virtual void message(const MessageType, const std::string &); + virtual void nothing_more_to_come(); static const std::tr1::shared_ptr<const Set<std::string> > factory_managers() PALUDIS_ATTRIBUTE((warn_unused_result)); diff --git a/paludis/tee_output_manager.cc b/paludis/tee_output_manager.cc index 167c11c9d..302190075 100644 --- a/paludis/tee_output_manager.cc +++ b/paludis/tee_output_manager.cc @@ -35,22 +35,27 @@ namespace paludis struct Implementation<TeeOutputManager> { const std::tr1::shared_ptr<const Sequence<std::tr1::shared_ptr<OutputManager> > > streams; + const std::tr1::shared_ptr<const Sequence<std::tr1::shared_ptr<OutputManager> > > messages_streams; + TeeOutputStream stdout_stream; TeeOutputStream stderr_stream; Implementation( - const std::tr1::shared_ptr<const Sequence<std::tr1::shared_ptr<OutputManager> > > & s) : - streams(s) + const std::tr1::shared_ptr<const Sequence<std::tr1::shared_ptr<OutputManager> > > & s, + const std::tr1::shared_ptr<const Sequence<std::tr1::shared_ptr<OutputManager> > > & ss) : + streams(s), + messages_streams(ss) { } }; } TeeOutputManager::TeeOutputManager( - const std::tr1::shared_ptr<const OutputManagerSequence> & s) : - PrivateImplementationPattern<TeeOutputManager>(new Implementation<TeeOutputManager>(s)) + const std::tr1::shared_ptr<const OutputManagerSequence> & s, + const std::tr1::shared_ptr<const OutputManagerSequence> & ss) : + PrivateImplementationPattern<TeeOutputManager>(new Implementation<TeeOutputManager>(s, ss)) { - for (OutputManagerSequence::ConstIterator i(s->begin()), i_end(s->end()) ; + for (OutputManagerSequence::ConstIterator i(_imp->streams->begin()), i_end(_imp->streams->end()) ; i != i_end ; ++i) { _imp->stdout_stream.add_stream(&(*i)->stdout_stream()); @@ -75,19 +80,47 @@ TeeOutputManager::stderr_stream() } void +TeeOutputManager::message(const MessageType t, const std::string & m) +{ + for (OutputManagerSequence::ConstIterator i(_imp->messages_streams->begin()), i_end(_imp->messages_streams->end()) ; + i != i_end ; ++i) + (*i)->message(t, m); +} + +void TeeOutputManager::succeeded() { for (OutputManagerSequence::ConstIterator i(_imp->streams->begin()), i_end(_imp->streams->end()) ; i != i_end ; ++i) (*i)->succeeded(); + + for (OutputManagerSequence::ConstIterator i(_imp->messages_streams->begin()), i_end(_imp->messages_streams->end()) ; + i != i_end ; ++i) + (*i)->succeeded(); } void -TeeOutputManager::message(const MessageType t, const std::string & s) +TeeOutputManager::flush() { for (OutputManagerSequence::ConstIterator i(_imp->streams->begin()), i_end(_imp->streams->end()) ; i != i_end ; ++i) - (*i)->message(t, s); + (*i)->flush(); + + for (OutputManagerSequence::ConstIterator i(_imp->messages_streams->begin()), i_end(_imp->messages_streams->end()) ; + i != i_end ; ++i) + (*i)->flush(); +} + +void +TeeOutputManager::nothing_more_to_come() +{ + for (OutputManagerSequence::ConstIterator i(_imp->streams->begin()), i_end(_imp->streams->end()) ; + i != i_end ; ++i) + (*i)->nothing_more_to_come(); + + for (OutputManagerSequence::ConstIterator i(_imp->messages_streams->begin()), i_end(_imp->messages_streams->end()) ; + i != i_end ; ++i) + (*i)->nothing_more_to_come(); } const std::tr1::shared_ptr<const Set<std::string> > @@ -105,17 +138,25 @@ TeeOutputManager::factory_create( const OutputManagerFactory::ReplaceVarsFunc &) { std::tr1::shared_ptr<OutputManagerSequence> children(new OutputManagerSequence); + std::tr1::shared_ptr<OutputManagerSequence> messages_children(new OutputManagerSequence); std::vector<std::string> children_keys; tokenise_whitespace(key_func("children"), std::back_inserter(children_keys)); if (children_keys.empty()) throw ConfigurationError("No children specified for TeeOutputManager"); + std::vector<std::string> messages_children_keys; + tokenise_whitespace(key_func("messages_children"), std::back_inserter(messages_children_keys)); + for (std::vector<std::string>::const_iterator c(children_keys.begin()), c_end(children_keys.end()) ; c != c_end ; ++c) children->push_back(create_child(*c)); - return make_shared_ptr(new TeeOutputManager(children)); + for (std::vector<std::string>::const_iterator c(messages_children_keys.begin()), c_end(messages_children_keys.end()) ; + c != c_end ; ++c) + messages_children->push_back(create_child(*c)); + + return make_shared_ptr(new TeeOutputManager(children, messages_children)); } template class PrivateImplementationPattern<TeeOutputManager>; diff --git a/paludis/tee_output_manager.hh b/paludis/tee_output_manager.hh index 2a47bfbd4..7bc59f176 100644 --- a/paludis/tee_output_manager.hh +++ b/paludis/tee_output_manager.hh @@ -36,13 +36,17 @@ namespace paludis public OutputManager { public: - TeeOutputManager(const std::tr1::shared_ptr<const OutputManagerSequence> &); + TeeOutputManager( + const std::tr1::shared_ptr<const OutputManagerSequence> &, + const std::tr1::shared_ptr<const OutputManagerSequence> &); ~TeeOutputManager(); virtual std::ostream & stdout_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual std::ostream & stderr_stream() PALUDIS_ATTRIBUTE((warn_unused_result)); virtual void succeeded(); + virtual void flush(); + virtual void nothing_more_to_come(); virtual void message(const MessageType, const std::string &); static const std::tr1::shared_ptr<const Set<std::string> > factory_managers() diff --git a/paludis/util/executor.cc b/paludis/util/executor.cc index 90fec4ee9..78036738d 100644 --- a/paludis/util/executor.cc +++ b/paludis/util/executor.cc @@ -106,7 +106,7 @@ Executor::add(const std::tr1::shared_ptr<Executive> & x) void Executor::execute() { - typedef std::map<std::string, std::tr1::shared_ptr<Thread> > Running; + typedef std::map<std::string, std::pair<std::tr1::shared_ptr<Thread>, std::tr1::shared_ptr<Executive> > > Running; Running running; Lock lock(_imp->mutex); @@ -125,8 +125,8 @@ Executor::execute() ++_imp->active; --_imp->pending; q->second->pre_execute_exclusive(); - running.insert(std::make_pair(q->first, make_shared_ptr(new Thread( - std::tr1::bind(&Executor::_one, this, q->second))))); + running.insert(std::make_pair(q->first, std::make_pair(make_shared_ptr(new Thread( + std::tr1::bind(&Executor::_one, this, q->second))), q->second))); _imp->queues.erase(q++); any = true; } @@ -134,7 +134,11 @@ Executor::execute() if ((! any) && running.empty()) break; - _imp->condition.wait(_imp->mutex); + _imp->condition.timed_wait(_imp->mutex, 1); + + for (Running::iterator r(running.begin()), r_end(running.end()) ; + r != r_end ; ++r) + r->second.second->flush_threaded(); for (ReadyForPost::iterator p(_imp->ready_for_post.begin()), p_end(_imp->ready_for_post.end()) ; p != p_end ; ++p) diff --git a/paludis/util/executor.hh b/paludis/util/executor.hh index e468de2b4..7c82d1257 100644 --- a/paludis/util/executor.hh +++ b/paludis/util/executor.hh @@ -38,6 +38,7 @@ namespace paludis virtual void pre_execute_exclusive() = 0; virtual void execute_threaded() = 0; + virtual void flush_threaded() = 0; virtual void post_execute_exclusive() = 0; }; |