# # # patch "cmd.hh" # from [383cb296f13b9a2f5d2daae829375b9b2391a7a9] # to [ca7629f05596351ce401a93d3e0c66bec34f26b2] # # patch "cmd_automate.cc" # from [2e9e24cfbf1a87a3a02e8fd86296fe555681c6c9] # to [5fd48fa402aad2a8b4f24eec735eddaad7e17114] # # patch "cmd_netsync.cc" # from [4533379042014dbf02c238a72bbb2be0b1c4c3bc] # to [f5c7f34fb92c0b808a6c8e6fadf24022f122c36c] # # patch "network/automate_session.cc" # from [92d6e4f681d375b52f52f409efe9bc9abbd14ee5] # to [0248881838d553ea7132b68180d1367758f94487] # # patch "tests/serve-automate/__driver__.lua" # from [dd28640a1d0a9d17308750745e58249fd303af71] # to [9f91fdaf69c4dd84f49761a13312751c456bb38d] # ============================================================ --- cmd.hh 383cb296f13b9a2f5d2daae829375b9b2391a7a9 +++ cmd.hh ca7629f05596351ce401a93d3e0c66bec34f26b2 @@ -102,6 +102,7 @@ namespace commands class automate : public command { + bool stdio_ok; // This function is supposed to be called only after the requirements // for "automate" commands have been fulfilled. This is done by the // "exec" function defined below, which implements code shared among @@ -117,6 +118,7 @@ namespace commands public: automate(std::string const & name, + bool stdio_ok, std::string const & params, std::string const & abstract, std::string const & desc, @@ -130,6 +132,8 @@ namespace commands void exec(app_state & app, command_id const & execid, args_vector const & args) const; + + bool can_run_from_stdio() const; }; } @@ -248,7 +252,7 @@ void commands::cmd_ ## C::exec(app_state // command definition allows the description of input/output format, // error conditions, version when added, etc. 'desc' can later be // automatically built from these. -#define CMD_AUTOMATE(C, params, abstract, desc, opts) \ +#define _CMD_AUTOMATE2(C, stdio_ok, params, abstract, desc, opts) \ namespace commands { \ class automate_ ## C : public automate \ { \ @@ -257,7 +261,8 @@ namespace commands { args_vector const & args, \ std::ostream & output) const; \ public: \ - automate_ ## C() : automate(#C, params, abstract, desc, \ + automate_ ## C() : automate(#C, stdio_ok, params, \ + abstract, desc, \ options::options_type() | opts) \ {} \ }; \ @@ -269,6 +274,12 @@ void commands::automate_ ## C :: exec_fr args_vector const & args, \ std::ostream & output) const +#define CMD_AUTOMATE(C, params, abstract, desc, opts) \ + _CMD_AUTOMATE2(C, true, params, abstract, desc, opts) + +#define CMD_AUTOMATE_NO_STDIO(C, params, abstract, desc, opts) \ + _CMD_AUTOMATE2(C, false, params, abstract, desc, opts) + CMD_FWD_DECL(__root__); CMD_FWD_DECL(automation); CMD_FWD_DECL(conflicts); ============================================================ --- cmd_automate.cc 2e9e24cfbf1a87a3a02e8fd86296fe555681c6c9 +++ cmd_automate.cc 5fd48fa402aad2a8b4f24eec735eddaad7e17114 @@ -38,6 +38,7 @@ namespace commands { namespace commands { automate::automate(string const & name, + bool stdio_ok, string const & params, string const & abstract, string const & desc, @@ -47,7 +48,8 @@ namespace commands { // commands need a database, and they expect to get the database // name from the workspace options, even if they don't need a // workspace for anything else. - desc, true, opts, false) + desc, true, opts, false), + stdio_ok(stdio_ok) { } @@ -68,6 +70,12 @@ namespace commands { { exec(app, execid, args, std::cout); } + + bool + automate::can_run_from_stdio() const + { + return stdio_ok; + } } // This number is only raised once, during the process of releasing a new @@ -138,10 +146,10 @@ CMD_AUTOMATE(interface_version, "", -CMD_AUTOMATE(stdio, "", - N_("Automates several commands in one run"), - "", - options::opts::automate_stdio_size) +CMD_AUTOMATE_NO_STDIO(stdio, "", + N_("Automates several commands in one run"), + "", + options::opts::automate_stdio_size) { E(args.empty(), origin::user, F("no arguments needed")); @@ -237,6 +245,10 @@ CMD_AUTOMATE(stdio, "", { automate const * acmd = dynamic_cast< automate const * >(cmd); I(acmd); + + E(acmd->can_run_from_stdio(), origin::network, + F("sorry, that can't be run remotely or over stdio")); + acmd->exec_from_automate(app, id, args, os); // set app.opts to the originally given options // so the next command has an identical setup ============================================================ --- cmd_netsync.cc 4533379042014dbf02c238a72bbb2be0b1c4c3bc +++ cmd_netsync.cc f5c7f34fb92c0b808a6c8e6fadf24022f122c36c @@ -229,12 +229,12 @@ extract_client_connection_info(options & need_key); } -CMD_AUTOMATE(remote_stdio, - N_("[ADDRESS[:PORTNUMBER]"), - N_("Opens an 'automate stdio' connection to a remote server"), - "", - options::opts::max_netsync_version | - options::opts::min_netsync_version) +CMD_AUTOMATE_NO_STDIO(remote_stdio, + N_("[ADDRESS[:PORTNUMBER]"), + N_("Opens an 'automate stdio' connection to a remote server"), + "", + options::opts::max_netsync_version | + options::opts::min_netsync_version) { if (args.size() != 1) throw usage(execid); ============================================================ --- network/automate_session.cc 92d6e4f681d375b52f52f409efe9bc9abbd14ee5 +++ network/automate_session.cc 0248881838d553ea7132b68180d1367758f94487 @@ -160,8 +160,12 @@ bool automate_session::do_work(transacti command const * cmd = CMD_REF(automate)->find_command(id); I(cmd != NULL); - automate const * acmd = reinterpret_cast< automate const * >(cmd); + automate const * acmd = dynamic_cast< automate const * >(cmd); + I(acmd); + E(acmd->can_run_from_stdio(), origin::network, + F("sorry, that can't be run remotely or over stdio")); + opts = options::opts::globals() | acmd->opts(); if (cmd->use_workspace_options()) ============================================================ --- tests/serve-automate/__driver__.lua dd28640a1d0a9d17308750745e58249fd303af71 +++ tests/serve-automate/__driver__.lua 9f91fdaf69c4dd84f49761a13312751c456bb38d @@ -31,4 +31,8 @@ check(qgrep("^1:0:l:41:", "stdout")) check(qgrep("^0:0:l:", "stdout")) check(qgrep("^1:0:l:41:", "stdout")) +check(mtn2("automate", "remote_stdio", server.address), 0, true, false, + "l5:stdioe") +check(qgrep("can't be run", "stdout")) + server:stop()