# # # add_file "automate_stdio_helpers.hh" # content [03f4e756e3292af111da1994d11e4b9c33d1a520] # # patch "Makefile.am" # from [c22791893a2e339375c609fe99533f01904f1234] # to [fd7dc077e1a7bbca7c09ee694c9d90f1cb9e6a0f] # # patch "automate.cc" # from [d96be09abbc83bfaf658641ec3c02485e06403f2] # to [d1bd5147b257f8621658e43ae74438b050cc3753] # # patch "cmd.cc" # from [8daafa921ab88dc3d17980c4e404c162bea020c1] # to [a27ed4ca98dfa30a83e591ef493c801a54fd93d2] # # patch "cmd.hh" # from [a51a739713b8b2dbbf2dd6ffb9aa71bd201bdbb9] # to [7af603b7cdc6ae26cc06d89671c8cd9bf9d04b75] # # patch "cmd_automate.cc" # from [aa4a56a485bdd740054af3ddc6a7a6ee3ab6674a] # to [ed92af7bbe757d262e38549cd4bf84ad875eb747] # # patch "commands.hh" # from [2172ef5bb183521c3ed7f297517e2a2c94776687] # to [23533dfe704f8fae0492404a0188363fea27d9c1] # # patch "network/automate_session.cc" # from [d5da42fac971b0eac4d4bdf5ba0ece498e57576a] # to [d953e802c3d9a9f9b4fde075a616cdbfbed0f041] # ============================================================ --- automate_stdio_helpers.hh 03f4e756e3292af111da1994d11e4b9c33d1a520 +++ automate_stdio_helpers.hh 03f4e756e3292af111da1994d11e4b9c33d1a520 @@ -0,0 +1,50 @@ +// Copyright (C) 2005 and later by various people +// see monotone commit logs for details and authors +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#ifndef __AUTOMATE_STDIO_HELPERS__ +#define __AUTOMATE_STDIO_HELPERS__ + +#include +#include + +#include + +#include "commands.hh" + +// these are in a class instead of stand-alone just because there's a +// friend declaration in cmd.hh, which shouldn't have to know about boost::function +class automate_stdio_helpers +{ +public: + static void + automate_stdio_shared_setup(app_state & app, + std::vector const & cmdline, + std::vector > + const & params, + commands::command_id & id, + /* reference-to-pointer here is intentional */ + commands::automate const * & acmd); + static std::pair + automate_stdio_shared_body(app_state & app, + std::vector const & cmdline, + std::vector > + const & params, + std::ostream & os, + boost::function init_fn, + boost::function pre_exec_fn); +}; +#endif +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- Makefile.am c22791893a2e339375c609fe99533f01904f1234 +++ Makefile.am fd7dc077e1a7bbca7c09ee694c9d90f1cb9e6a0f @@ -41,6 +41,7 @@ MOST_SOURCES = \ automate_ostream.hh \ automate_ostream_demuxed.hh \ automate_reader.hh automate_reader.cc \ + automate_stdio_helpers.hh \ botan_pipe_cache.hh \ cache_logger.hh cache_logger.cc \ commands.cc commands.hh $(CMD_SOURCES) \ ============================================================ --- automate.cc d96be09abbc83bfaf658641ec3c02485e06403f2 +++ automate.cc d1bd5147b257f8621658e43ae74438b050cc3753 @@ -21,6 +21,7 @@ #include #include "app_state.hh" +#include "automate_stdio_helpers.hh" #include "project.hh" #include "basic_io.hh" #include "cert.hh" @@ -2337,6 +2338,125 @@ CMD_AUTOMATE(lua, "LUA_FUNCTION [ARG1 [A output << out; } +CMD_FWD_DECL(automate); + +void automate_stdio_helpers:: +automate_stdio_shared_setup(app_state & app, + vector const & cmdline, + vector > const & params, + commands::command_id & id, + commands::automate const * & acmd) +{ + using commands::command_id; + using commands::command; + using commands::automate; + + args_vector args; + for (vector::const_iterator i = cmdline.begin(); + i != cmdline.end(); ++i) + { + args.push_back(arg_type(*i, origin::user)); + id.push_back(utf8(*i, origin::user)); + } + + set< command_id > matches = + CMD_REF(automate)->complete_command(id); + + if (matches.empty()) + { + E(false, origin::network, + F("no completions for this command")); + } + else if (matches.size() > 1) + { + E(false, origin::network, + F("multiple completions possible for this command")); + } + + id = *matches.begin(); + + command const * cmd = CMD_REF(automate)->find_command(id); + I(cmd != NULL); + + acmd = dynamic_cast< automate const * >(cmd); + I(acmd != NULL); + + E(acmd->can_run_from_stdio(), origin::network, + F("sorry, that can't be run remotely or over stdio")); + + + commands::command_id my_id_for_hook = id; + my_id_for_hook.insert(my_id_for_hook.begin(), utf8("automate", origin::internal)); + // group name + my_id_for_hook.insert(my_id_for_hook.begin(), utf8("automation", origin::internal)); + commands::reapply_options(app, + app.reset_info.cmd, + commands::command_id() /* doesn't matter */, + cmd, my_id_for_hook, 2, + args, + ¶ms); + + // disable user prompts, f.e. for password decryption + app.opts.non_interactive = true; + + + // set a fixed ticker type regardless what the user wants to + // see, because anything else would screw the stdio-encoded output + ui.set_tick_write_stdio(); +} + +std::pair automate_stdio_helpers:: +automate_stdio_shared_body(app_state & app, + std::vector const & cmdline, + std::vector > + const & params, + std::ostream & os, + boost::function init_fn, + boost::function pre_exec_fn) +{ + using commands::command_id; + using commands::command; + using commands::automate; + + options original_opts = app.opts; + automate const * acmd = 0; + command_id id; + try + { + if (init_fn) + init_fn(); + automate_stdio_shared_setup(app, cmdline, params, id, acmd); + } + catch (option::option_error & e) + { + return make_pair(1, e.what()); + } + catch (recoverable_failure & f) + { + return make_pair(1, f.what()); + } + if (pre_exec_fn) + pre_exec_fn(id); + try + { + // as soon as a command requires a workspace, this is set to true + workspace::used = false; + + acmd->exec_from_automate(app, id, app.opts.args, os); + + // usually, if a command succeeds, any of its workspace-relevant + // options are saved back to _MTN/options, this shouldn't be + // any different here + workspace::maybe_set_options(app.opts, app.lua); + } + catch (recoverable_failure & f) + { + return make_pair(2, f.what()); + } + app.opts = original_opts; + return make_pair(0, string()); +} + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- cmd.cc 8daafa921ab88dc3d17980c4e404c162bea020c1 +++ cmd.cc a27ed4ca98dfa30a83e591ef493c801a54fd93d2 @@ -86,7 +86,6 @@ CMD_GROUP(user, "user", "", CMD_REF(__ro ""); -CMD_FWD_DECL(automate); template<> void dump(size_t const & in, std::string & out) { @@ -172,114 +171,6 @@ namespace commands { } } - void automate_stdio_shared_setup(app_state & app, - vector const & cmdline, - vector > const & params, - command_id & id, - automate const * & acmd) - { - args_vector args; - for (vector::const_iterator i = cmdline.begin(); - i != cmdline.end(); ++i) - { - args.push_back(arg_type(*i, origin::user)); - id.push_back(utf8(*i, origin::user)); - } - - set< command_id > matches = - CMD_REF(automate)->complete_command(id); - - if (matches.empty()) - { - E(false, origin::network, - F("no completions for this command")); - } - else if (matches.size() > 1) - { - E(false, origin::network, - F("multiple completions possible for this command")); - } - - id = *matches.begin(); - - command const * cmd = CMD_REF(automate)->find_command(id); - I(cmd != NULL); - - acmd = dynamic_cast< automate const * >(cmd); - I(acmd != NULL); - - E(acmd->can_run_from_stdio(), origin::network, - F("sorry, that can't be run remotely or over stdio")); - - - commands::command_id my_id_for_hook = id; - my_id_for_hook.insert(my_id_for_hook.begin(), utf8("automate", origin::internal)); - // group name - my_id_for_hook.insert(my_id_for_hook.begin(), utf8("automation", origin::internal)); - commands::reapply_options(app, - app.reset_info.cmd, - commands::command_id() /* doesn't matter */, - cmd, my_id_for_hook, 2, - args, - ¶ms); - - // disable user prompts, f.e. for password decryption - app.opts.non_interactive = true; - - - // set a fixed ticker type regardless what the user wants to - // see, because anything else would screw the stdio-encoded output - ui.set_tick_write_stdio(); - } - - std::pair - automate_stdio_shared_body(app_state & app, - std::vector const & cmdline, - std::vector > - const & params, - std::ostream & os, - boost::function init_fn, - boost::function pre_exec_fn) - { - options original_opts = app.opts; - automate const * acmd = 0; - command_id id; - try - { - if (init_fn) - init_fn(); - commands::automate_stdio_shared_setup(app, cmdline, params, id, acmd); - } - catch (option::option_error & e) - { - return make_pair(1, e.what()); - } - catch (recoverable_failure & f) - { - return make_pair(1, f.what()); - } - if (pre_exec_fn) - pre_exec_fn(id); - try - { - // as soon as a command requires a workspace, this is set to true - workspace::used = false; - - acmd->exec_from_automate(app, id, app.opts.args, os); - - // usually, if a command succeeds, any of its workspace-relevant - // options are saved back to _MTN/options, this shouldn't be - // any different here - workspace::maybe_set_options(app.opts, app.lua); - } - catch (recoverable_failure & f) - { - return make_pair(2, f.what()); - } - app.opts = original_opts; - return make_pair(0, string()); - } - // monotone.cc calls this function after option processing. void process(app_state & app, command_id const & ident, args_vector const & args) ============================================================ --- cmd.hh a51a739713b8b2dbbf2dd6ffb9aa71bd201bdbb9 +++ cmd.hh 7af603b7cdc6ae26cc06d89671c8cd9bf9d04b75 @@ -19,7 +19,7 @@ class app_state; class app_state; -class automate_session; +class automate_stdio_helpers; namespace commands { @@ -113,14 +113,7 @@ namespace commands command_id const & execid, args_vector const & args, std::ostream & output) const = 0; - friend std::pair - automate_stdio_shared_body(app_state & app, - std::vector const & cmdline, - std::vector > - const & params, - std::ostream & os, - boost::function init_fn, - boost::function pre_exec_fn); + friend class ::automate_stdio_helpers; public: automate(std::string const & name, ============================================================ --- cmd_automate.cc aa4a56a485bdd740054af3ddc6a7a6ee3ab6674a +++ cmd_automate.cc ed92af7bbe757d262e38549cd4bf84ad875eb747 @@ -18,6 +18,7 @@ #include "app_state.hh" #include "automate_ostream.hh" #include "automate_reader.hh" +#include "automate_stdio_helpers.hh" #include "ui.hh" #include "lua.hh" #include "lua_hooks.hh" @@ -250,10 +251,10 @@ CMD_AUTOMATE_NO_STDIO(stdio, "", { try { - pair err - = commands::automate_stdio_shared_body(app, cmdline, params, os, - local_stdio_pre_fn(ar, cmdline, params), - boost::function()); + pair err = automate_stdio_helpers:: + automate_stdio_shared_body(app, cmdline, params, os, + local_stdio_pre_fn(ar, cmdline, params), + boost::function()); if (err.first != 0) os.write_out_of_band('e', err.second); os.end_cmd(err.first); ============================================================ --- commands.hh 2172ef5bb183521c3ed7f297517e2a2c94776687 +++ commands.hh 23533dfe704f8fae0492404a0188363fea27d9c1 @@ -10,8 +10,6 @@ #ifndef __COMMANDS_HH__ #define __COMMANDS_HH__ -#include - #include "vector.hh" #include "options.hh" class app_state; @@ -41,23 +39,6 @@ namespace commands { args_vector const & subcmd_cmdline = args_vector(), std::vector > const * const separate_params = 0); - // really no good place to put this - // used by 'automate stdio' and automate_session::do_work - void automate_stdio_shared_setup(app_state & app, - std::vector const & cmdline, - std::vector > - const & params, - command_id & id, - /* reference-to-pointer here is intentional */ - automate const * & acmd); - std::pair - automate_stdio_shared_body(app_state & app, - std::vector const & cmdline, - std::vector > - const & params, - std::ostream & os, - boost::function init_fn, - boost::function pre_exec_fn); void process(app_state & app, command_id const & ident, args_vector const & args); options::options_type command_options(command_id const & ident); ============================================================ --- network/automate_session.cc d5da42fac971b0eac4d4bdf5ba0ece498e57576a +++ network/automate_session.cc d953e802c3d9a9f9b4fde075a616cdbfbed0f041 @@ -12,6 +12,7 @@ #include "app_state.hh" #include "automate_reader.hh" +#include "automate_stdio_helpers.hh" #include "simplestring_xform.hh" #include "ui.hh" #include "vocab_cast.hh" @@ -178,10 +179,10 @@ bool automate_session::do_work(transacti ostringstream oss; - pair err - = commands::automate_stdio_shared_body(app, cmdline, params, oss, - remote_stdio_pre_fn(app, remote_identity, cmdline, params), - remote_stdio_log_fn(get_peer())); + pair err = automate_stdio_helpers:: + automate_stdio_shared_body(app, cmdline, params, oss, + remote_stdio_pre_fn(app, remote_identity, cmdline, params), + remote_stdio_log_fn(get_peer())); if (err.first != 0) write_automate_packet_cmd('e', err.second); if (!oss.str().empty())