# # # patch "ChangeLog" # from [bcab3efd1a17c25cdc1ffc19109b943e88e88e0f] # to [300b559791cef066840566f720746320b832a0fd] # # patch "cmd_automate.cc" # from [2a30a70b095966dcbef804dcc8b1fb3524756f4f] # to [9b296637f7264070e5f07e3cabcd4b31bcd62ad4] # # patch "monotone.texi" # from [5790199cf92c6d31f3de1a901c78a457e6399e71] # to [868d245cec03da10c9e8d3e7bd7348985cc5a39b] # # patch "option.cc" # from [5f0054153bf1a32737a543bd8498acbf50390be3] # to [b19ae0c7ea62dddb5460c79f1eb1323250e89c95] # # patch "option.hh" # from [5d01ff49f79434cff28bc077861b76e705c298a2] # to [ca74ed997995c5adee202ccf474d9ef487dfefea] # # patch "options_list.hh" # from [861b5fc7a146a5618c60b5bbbb588e22517d6e73] # to [645384dc6be8e8ad8698c5b70fc529d19d2ae124] # # patch "tests/automate_stdio/__driver__.lua" # from [d3d28f9b0c0c443874d7fce17861bc231bb8c4b1] # to [81b4962edeaa532641858a4a6deb5fda47d129d7] # ============================================================ --- ChangeLog bcab3efd1a17c25cdc1ffc19109b943e88e88e0f +++ ChangeLog 300b559791cef066840566f720746320b832a0fd @@ -1,3 +1,10 @@ +2006-11-02 Timothy Brownawell + + Allow automate commands to take options. Change "automate stdio" + error handling (exit instead of returning usage information when + given an invalid command line) and bump automate version. Increase + default "automate stdio" blocksize to 32k. + 2006-11-01 Richard Levitte * po/sv.po: A fuzzy to fix. ============================================================ --- cmd_automate.cc 2a30a70b095966dcbef804dcc8b1fb3524756f4f +++ cmd_automate.cc 9b296637f7264070e5f07e3cabcd4b31bcd62ad4 @@ -13,8 +13,11 @@ #include "cmd.hh" +using std::istream; +using std::make_pair; using std::map; using std::ostream; +using std::pair; using std::string; using std::vector; @@ -51,7 +54,7 @@ automate_command(utf8 cmd, vector i->second->run(args, root_cmd_name, app, output); } -static string const interface_version = "3.1"; +static string const interface_version = "4.0"; // Name: interface_version // Arguments: none @@ -113,8 +116,8 @@ class automate_reader class automate_reader { - std::istream & in; - enum location {cmd, none, eof}; + istream & in; + enum location {opt, cmd, none, eof}; location loc; bool get_string(std::string & out) { @@ -163,12 +166,13 @@ class automate_reader { if (loc == eof) return; - std::string starters("l"); - std::string foo; + string starters("ol"); + string whitespace(" \r\n\t"); + string foo; while (loc != none) get_string(foo); char c('e'); - while (starters.find(c) == std::string::npos) + while (whitespace.find(c) != std::string::npos) { if (read(&c, 1, true) == 0) { @@ -176,21 +180,37 @@ class automate_reader return; } } + if (read(&c, 1, true) == 0) + { + loc = eof; + return; + } switch (c) { + case 'o': loc = opt; break; case 'l': loc = cmd; break; + default: E(false, F("Bad input to automate stdio")); } } public: - automate_reader(std::istream & is) : in(is), loc(none) + automate_reader(istream & is) : in(is), loc(none) {} - bool get_command(std::vector & cmdline) + bool get_command(vector > & params, + vector & cmdline) { + params.clear(); cmdline.clear(); while (loc == none) go_to_next_item(); if (loc == eof) return false; + else if (loc == opt) + { + string key, val; + while(get_string(key) && get_string(val)) + params.push_back(make_pair(key, val)); + go_to_next_item(); + } E(loc == cmd, F("Bad input to automate stdio")); string item; while (get_string(item)) @@ -306,8 +326,9 @@ AUTOMATE(stdio, "") throw usage(help_name); automate_ostream os(output, app.opts.automate_stdio_size); automate_reader ar(std::cin); + vector > params; vector cmdline; - while(ar.get_command(cmdline))//while(!EOF) + while(ar.get_command(params, cmdline))//while(!EOF) { utf8 cmd; vector args; @@ -320,13 +341,11 @@ AUTOMATE(stdio, "") } try { + option::concrete_option_set opts; + opts = options::opts::all_options().instantiate(&app.opts); + opts.from_key_value_pairs(params); automate_command(cmd, args, help_name, app, os); } - catch(usage &) - { - os.set_err(1); - commands::explain_usage(help_name, os); - } catch(informative_failure & f) { os.set_err(2); @@ -341,7 +360,8 @@ CMD_PARAMS_FN(automate, N_("automation") CMD_PARAMS_FN(automate, N_("automation"), N_("automation interface"), - options::opts::automate_stdio_size) + /*options::opts::automate_stdio_size*/ + options::opts::all_options) { if (args.size() == 0) throw usage(name); ============================================================ --- monotone.texi 5790199cf92c6d31f3de1a901c78a457e6399e71 +++ monotone.texi 868d245cec03da10c9e8d3e7bd7348985cc5a39b @@ -6291,6 +6291,15 @@ @section Automation 1.0 address@hidden Modifications: address@hidden @strong address@hidden 3.1 + +Added the 'o' item to the recognized input. This change should not +break anything. + address@hidden table + @item Purpose: Allow multiple automate commands to be run from one instance of monotone. @@ -6300,15 +6309,26 @@ @section Automation @verbatim l6:leavese l7:parents40:0e3171212f34839c2e3263e7282cdeea22fc5378e +o6:author7:Timothye l6:commite @end verbatim @item Input format: -The input is a series of commands of the form 'l' [ ...] 'e', -where = colon . Characters between the ending 'e' -of one commad and the beginning 'l' of the next are ignored, but characters -other than '\n' should not be present as this space is reserved. address@hidden +[ 'o' [ [ ... ] ] 'e' ] +'l' [ [ ... ] ] 'e' address@hidden verbatim +The input is a series of commands. The command name plus arguments are +provided as 'l' [ ...] 'e', where = colon + . This may optionally be preceeded by a set of key=value pairs +(command options) as 'o' [ ...] 'e', where +strings come in pairs, key followed by value. + +The space between the ending 'e' of one group of strings and the beginning +'l' or 'o' of the next is reserved. Any characters other than whitespace +will cause an error. + @item Sample output: @verbatim @@ -6322,6 +6342,9 @@ @section Automation @item Output format: +The output consists of one or more packets for each command. +A packet looks like: + :::: is a decimal number specifying which command this output @@ -6334,22 +6357,19 @@ @section Automation is the number of bytes in the output. - is the output of the command. This will never exceed the -maximum chunk size, which is 1024 bytes per default and can be -adjusted using the @option{--automate-stdio-size} option. If a -command produces more bytes of output than fit into one chunk, it will -be split into multiple pieces, with all but the last having the - field set to 'm'. + is a piece of the output of the command. +All but the last packet for a given command will have the + field set to 'm'. + @item Error conditions: -If a badly formatted command is received, prints an error message to +If a badly formatted or invalid command is received, or a command is +given with invalid arguments or options, prints an error message to standard error and exits with nonzero status. Errors in the commands run through this interface do not affect the exit status. Instead, the field in the output is set to 2, and the output of the command becomes -whatever error message would have been given. The output of an invalid -command line will have an error code of 1, and the output text will be a help -message. +whatever error message would have been given. @end table ============================================================ --- option.cc 5f0054153bf1a32737a543bd8498acbf50390be3 +++ option.cc b19ae0c7ea62dddb5460c79f1eb1323250e89c95 @@ -252,8 +252,8 @@ getopt(map cons throw option::unknown_option(name); } -void concrete_option_set::from_command_line(std::vector & args, - bool allow_xargs) +static map +get_by_name(std::set const & options) { map by_name; for (std::set::const_iterator i = options.begin(); @@ -264,7 +264,14 @@ void concrete_option_set::from_command_l if (!i->shortname.empty()) by_name.insert(make_pair(i->shortname, *i)); } + return by_name; +} +void concrete_option_set::from_command_line(std::vector & args, + bool allow_xargs) +{ + map by_name = get_by_name(options); + bool seen_dashdash = false; for (unsigned int i = 0; i < args.size(); ++i) { @@ -374,6 +381,37 @@ void concrete_option_set::from_command_l } } +void concrete_option_set::from_key_value_pairs(vector > const & keyvals) +{ + map by_name = get_by_name(options); + + for (vector >::const_iterator i = keyvals.begin(); + i != keyvals.end(); ++i) + { + string const & key(i->first); + string const & value(i->second); + + concrete_option o = getopt(by_name, key); + + try + { + if (o.setter) + o.setter(value); + } + catch (boost::bad_lexical_cast) + { + throw bad_arg(o.longname, value); + } + catch (bad_arg_internal & e) + { + if (e.reason == "") + throw bad_arg(o.longname, value); + else + throw bad_arg(o.longname, value, e.reason); + } + } +} + static vector wordwrap(string str, unsigned int width) { vector out; ============================================================ --- option.hh 5d01ff49f79434cff28bc077861b76e705c298a2 +++ option.hh ca74ed997995c5adee202ccf474d9ef487dfefea @@ -98,6 +98,7 @@ namespace option { std::string get_usage_str() const; void from_command_line(std::vector & args, bool allow_xargs = true); void from_command_line(int argc, char const * const * argv); + void from_key_value_pairs(std::vector > const & keyvals); }; concrete_option_set operator | (concrete_option const & a, concrete_option const & b); ============================================================ --- options_list.hh 861b5fc7a146a5618c60b5bbbb588e22517d6e73 +++ options_list.hh 645384dc6be8e8ad8698c5b70fc529d19d2ae124 @@ -23,7 +23,7 @@ OPT(author, "author", utf8, , gettext_no } #endif -OPT(automate_stdio_size, "automate-stdio-size", size_t, 1024, +OPT(automate_stdio_size, "automate-stdio-size", size_t, 32768, gettext_noop("block size in bytes for \"automate stdio\" output")) #ifdef option_bodies { @@ -264,6 +264,15 @@ GOPT(help, "help,h", bool, false, gettex } #endif +OPTVAR(include, std::vector, include_patterns, ) +OPTION(include, include, true, "include", + gettext_noop("include anything described by its argument")) +#ifdef option_bodies +{ + include_patterns.push_back(utf8(arg)); +} +#endif + OPTVAR(key, rsa_keypair_id, signing_key, ) OPTION(globals, key, true, "key,k", gettext_noop("set key for signatures")) #ifdef option_bodies @@ -375,7 +384,7 @@ GOPT(nostd, "nostd", bool, false, nostd = true; } #endif - + GOPT(pidfile, "pid-file", system_path, , gettext_noop("record process id of server")) #ifdef option_bodies ============================================================ --- tests/automate_stdio/__driver__.lua d3d28f9b0c0c443874d7fce17861bc231bb8c4b1 +++ tests/automate_stdio/__driver__.lua 81b4962edeaa532641858a4a6deb5fda47d129d7 @@ -5,7 +5,13 @@ check(mtn("automate", "stdio"), 1, false check(mtn("automate", "stdio"), 1, false, false, "l") check(mtn("automate", "stdio"), 1, false, false, "l5:a") check(mtn("automate", "stdio"), 1, false, false, "l5:aaaaaaaa") +check(mtn("automate", "stdio"), 1, false, false, "xl6:leavese") +check(mtn("automate", "stdio"), 1, false, false, "o3:key0:exl6:leavese") +check(mtn("automate", "stdio"), 1, false, false, "o3:ke0:el6:leavese") +-- not broken +check(mtn("automate", "stdio"), 0, false, false, "o3:key0:el6:leavese") + function parse_stdio(dat, which) local got = {} while true do