# # # patch "cmd_automate.cc" # from [a674b97589137be5fae539f6e87e4e8582280bf0] # to [e03b031b0762fe400b75f75d00fbcd1aaab0a11a] # # patch "tests/user_commands/__driver__.lua" # from [b2a9ae5bcde22f99c5db0b98bdecaaec2a02b697] # to [ff5eea4fe5641b42b3e76fdda36cacd7fe3d35f6] # # patch "tests/user_commands/extra_rc" # from [7a46f41a2aefec5e01d16e1251c7939b23ba8648] # to [94c90e2f0259bc9905f6be3fcc2580f0c8c2714d] # ============================================================ --- cmd_automate.cc a674b97589137be5fae539f6e87e4e8582280bf0 +++ cmd_automate.cc e03b031b0762fe400b75f75d00fbcd1aaab0a11a @@ -409,50 +409,56 @@ LUAEXT(mtn_automate, ) args.push_back(next_arg); } - // disable user prompts, f.e. for password decryption - app_p->opts.non_interactive = true; + commands::command_id id; + { + for (args_vector::const_iterator iter = args.begin(); + iter != args.end(); iter++) + id.push_back(*iter); - options::options_type opts; - opts = options::opts::all_options() - options::opts::globals(); - opts.instantiate(&app_p->opts).reset(); + E(!id.empty(), origin::user, F("no command found")); - // the arguments for a command are read from app.opts.args which - // is already cleaned from all options. this variable, however, still - // contains the original arguments with which the user function was - // called. Since we're already in lua context, it makes no sense to - // preserve them for the outside world, so we're just clearing them. - app_p->opts.args.clear(); + set< commands::command_id > matches = + CMD_REF(automate)->complete_command(id); - commands::command_id id; - for (args_vector::const_iterator iter = args.begin(); - iter != args.end(); iter++) - id.push_back(*iter); + if (matches.empty()) + { + E(false, origin::user, F("no completions for this command")); + } + else if (matches.size() > 1) + { + E(false, origin::user, + F("multiple completions possible for this command")); + } - E(!id.empty(), origin::user, F("no command found")); + id = *matches.begin(); + } + commands::command const * cmd = CMD_REF(automate)->find_command(id); + I(cmd != NULL); - set< commands::command_id > matches = - CMD_REF(automate)->complete_command(id); - if (matches.empty()) - { - E(false, origin::user, F("no completions for this command")); - } - else if (matches.size() > 1) - { - E(false, origin::user, - F("multiple completions possible for this command")); - } + // reset and recalcualte the options + options::opts::all_options().instantiate(&app_p->opts).reset(); - id = *matches.begin(); + option::concrete_option_set orig_optset + = (options::opts::globals() + | commands::command_options(app_p->reset_info.cmd)) + .instantiate(&app_p->opts); + orig_optset.from_command_line(app_p->reset_info.default_args, false); - I(args.size() >= id.size()); - for (commands::command_id::size_type i = 0; i < id.size(); i++) - args.erase(args.begin()); + // get default options for the current (sub-)command here + option::concrete_option_set my_optset + = (options::opts::globals() | cmd->opts()) + .instantiate(&app_p->opts); + args_vector my_defaults; + { + 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)); + app_p->lua.hook_get_default_command_options(my_id_for_hook, my_defaults); + } + my_optset.from_command_line(my_defaults, false); - commands::command const * cmd = CMD_REF(automate)->find_command(id); - I(cmd != NULL); - opts = options::opts::globals() | cmd->opts(); - if (cmd->use_workspace_options()) { // Re-read the ws options file, rather than just copying @@ -462,7 +468,21 @@ LUAEXT(mtn_automate, ) workspace::get_options(app_p->opts); } - opts.instantiate(&app_p->opts).from_command_line(args, false); + orig_optset.from_command_line(app_p->reset_info.cmdline_args, false); + + // now add our given options and clean the arg list + app_p->opts.args.clear(); + my_optset.from_command_line(args, false); + I(app_p->opts.args.size() >= id.size()); + for (commands::command_id::size_type i = 0; i < id.size(); i++) + app_p->opts.args.erase(app_p->opts.args.begin()); + + // disable user prompts, f.e. for password decryption + app_p->opts.non_interactive = true; + + // done recalculating options + + args_vector & parsed_args = app_p->opts.args; commands::automate const * acmd ============================================================ --- tests/user_commands/__driver__.lua b2a9ae5bcde22f99c5db0b98bdecaaec2a02b697 +++ tests/user_commands/__driver__.lua ff5eea4fe5641b42b3e76fdda36cacd7fe3d35f6 @@ -20,6 +20,8 @@ rev_b = base_revision() -- b) options given to mtn_automate are parsed correctly (see extra_rc) -- c) outer command line arguments are not passed to the inner mtn_automate -- calls (otherwise both revisions would lead to path restriction errors) -check(mtn("diff_two_revs", "--rcfile=extra_rc", rev_a, rev_b), 0, false, false) +check(mtn("diff_two_revs", "--rcfile=extra_rc", rev_a, rev_b), 0, true, false) +check(qgrep('add_file "bar"', "stdout")) +check(qgrep("\\+more random info", "stdout")) ============================================================ --- tests/user_commands/extra_rc 7a46f41a2aefec5e01d16e1251c7939b23ba8648 +++ tests/user_commands/extra_rc 94c90e2f0259bc9905f6be3fcc2580f0c8c2714d @@ -24,9 +24,19 @@ function diff_two_revs(rev_a, rev_b) io.stderr:write("automate call failed: " .. out .. "\n") return 1 end + io.stdout:write(out) return 0 end register_command("diff_two_revs", "", "Outputs the differences between two revs", "This is a bogus command used to demonstrate user commands with options.", "diff_two_revs") + +function get_default_command_options(command) + local ret = {} + if command[1] == "automate" and command[2] == "content_diff" + then + table.insert(ret, "--with-header") + end + return ret +end