# # # add_dir "tests/default_command_options" # # add_file "tests/default_command_options/__driver__.lua" # content [524306e088768186ee550179e9cd8bebd3b7fec0] # # add_file "tests/default_command_options/default_options.lua" # content [c66ceeb9cfcd88be99aa2de5c9d5445e1046a3cc] # # patch "NEWS" # from [6590b732872ac909ad2ebebb7011c98ea44e3b2f] # to [39ccea1dbe42ec528279fe9bc29507ab288f9480] # # patch "lua_hooks.cc" # from [c20c2f1a435898af47853fc2f62a85f746125d57] # to [6db24bd9d204496a7bd2211151ccfba892046457] # # patch "lua_hooks.hh" # from [b5cd54bb2cc7139b2fa3a508af726c4197826e1d] # to [eb7235af2f81fcce2921725bfd150df2ba3bfc65] # # patch "monotone.cc" # from [266c0426128307bdcaf51fe1f8dd24cb8729b070] # to [358d6a44595cfe80e8e9bff0ba752038e31fa593] # # patch "monotone.texi" # from [1a661908b431d3d64907a218b196f3ed58bfa5fe] # to [fe19d162d15d4f25397c4734ee026a47daafe83c] # # patch "std_hooks.lua" # from [f70deee23a8637fbc54f7eddd5275165258b103e] # to [7e22137903335a8b7dd2ce7bc9969b8962ff85be] # ============================================================ --- tests/default_command_options/__driver__.lua 524306e088768186ee550179e9cd8bebd3b7fec0 +++ tests/default_command_options/__driver__.lua 524306e088768186ee550179e9cd8bebd3b7fec0 @@ -0,0 +1,13 @@ + +mtn_setup() + +check(get("default_options.lua")) + +check(mtn("version", "--full"), 0, true, false) +rename("stdout", "fullversion") + +check(mtn("version", "--rcfile=default_options.lua"), 0, true, false) +check(samefile("stdout", "fullversion")) + +check(mtn("status", "--rcfile=default_options.lua"), 1, false, false) + ============================================================ --- tests/default_command_options/default_options.lua c66ceeb9cfcd88be99aa2de5c9d5445e1046a3cc +++ tests/default_command_options/default_options.lua c66ceeb9cfcd88be99aa2de5c9d5445e1046a3cc @@ -0,0 +1,12 @@ + +function get_default_command_options(command) + local default_opts = {} + if (command[1] == "version") then + table.insert(default_opts, "--full") + end + -- should trigger an invalid option error + if (command[1] == "status") then + table.insert(default_opts, "--foobarbaz") + end + return default_opts +end ============================================================ --- NEWS 6590b732872ac909ad2ebebb7011c98ea44e3b2f +++ NEWS 39ccea1dbe42ec528279fe9bc29507ab288f9480 @@ -39,6 +39,11 @@ New features + - New 'get_default_command_options' lua hook which lets you + specify default options for a given, triggered command. + Useful f.e. if you always want to have your 'mtn add' + command executed with '-R' / '--recursive' + - Add 'automate show_conflicts' command - Add 'automate get_workspace_root' command ============================================================ --- lua_hooks.cc c20c2f1a435898af47853fc2f62a85f746125d57 +++ lua_hooks.cc 6db24bd9d204496a7bd2211151ccfba892046457 @@ -560,6 +560,41 @@ bool } bool +lua_hooks::hook_get_default_command_options(commands::command_id const & cmd, + args_vector & args) +{ + Lua ll(st); + ll.func("get_default_command_options"); + + ll.push_table(); + int k = 1; + + // skip the first ID part, the command group, since this is mostly + // useless for the hook implementor + vector::const_iterator i = cmd.begin(); + i++; + + for ( ; i != cmd.end(); ++i) + { + ll.push_int(k); + ll.push_str((*i)()); + ll.set_table(); + k++; + } + + ll.call(1, 1); + + ll.begin(); + while (ll.next()) + { + std::string arg; + ll.extract_str(arg).pop(); + args.push_back(arg_type(arg)); + } + return ll.ok(); +} + +bool lua_hooks::hook_use_inodeprints() { bool use = false, exec_ok = false; ============================================================ --- lua_hooks.hh b5cd54bb2cc7139b2fa3a508af726c4197826e1d +++ lua_hooks.hh eb7235af2f81fcce2921725bfd150df2ba3bfc65 @@ -20,6 +20,7 @@ #include "option.hh" #include "vocab.hh" #include "paths.hh" +#include "commands.hh" struct uri; class app_state; @@ -117,6 +118,9 @@ public: bool hook_get_encloser_pattern(file_path const & path, std::string & pattern); + bool hook_get_default_command_options(commands::command_id const & cmd, + args_vector & args); + // workspace hooks bool hook_use_inodeprints(); ============================================================ --- monotone.cc 266c0426128307bdcaf51fe1f8dd24cb8729b070 +++ monotone.cc 358d6a44595cfe80e8e9bff0ba752038e31fa593 @@ -110,7 +110,7 @@ read_global_options(options & opts, args option::concrete_option_set optset = options::opts::all_options().instantiate(&opts); optset.from_command_line(args); - + return optset; } @@ -166,7 +166,7 @@ cpp_main(int argc, char ** argv) // Set up the global sanity object. No destructor is needed and // therefore no wrapper object is needed either. global_sanity.initialize(argc, argv, setlocale(LC_ALL, 0)); - + // Set up secure memory allocation etc Botan::LibraryInitializer acquire_botan("thread_safe=0 selftest=0 " "seed_rng=1 use_engines=0 " @@ -176,11 +176,11 @@ cpp_main(int argc, char ** argv) pipe_cache_cleanup acquire_botan_pipe_caching; unfiltered_pipe = new Botan::Pipe; new (unfiltered_pipe_cleanup_mem) cached_botan_pipe(unfiltered_pipe); - + // Record where we are. This has to happen before any use of // paths.hh objects. save_initial_path(); - + // decode all argv values into a UTF-8 array args_vector args; for (int i = 1; i < argc; ++i) @@ -231,6 +231,11 @@ cpp_main(int argc, char ** argv) // this needs to happen after the monotonercs have been read commands::command_id cmd = read_options(app.opts, optset, opt_args); + // check if the user specified default arguments for this command + args_vector default_args; + if (app.lua.hook_get_default_command_options(cmd, default_args)) + optset.from_command_line(default_args, false); + if (workspace::found) { bookkeeping_path dump_path; ============================================================ --- monotone.texi 1a661908b431d3d64907a218b196f3ed58bfa5fe +++ monotone.texi fe19d162d15d4f25397c4734ee026a47daafe83c @@ -9208,6 +9208,20 @@ @subsection User Defaults @address@hidden overrides any value returned from this hook function. address@hidden get_default_command_options(@var{command}) + +Returns a table of program options, either valid for the given command or +valid global options. The @var{command} argument is given as a table of command +parts, i.e. for commands with subcommands like @command{automate} or @command{db} +this argument contains at least two elements. + +Note that there is no way to "override" these default options via a given +command-line option once they've been set. This is especially true if you +specify options with arguments in this hook such as address@hidden@var{path}} - no subsequent command-line argument or address@hidden option argument will be able to replace or remove the +already excluded @var{path}. + @item get_passphrase (@var{keypair_id}) Returns a string which is the passphrase used to encrypt the private ============================================================ --- std_hooks.lua f70deee23a8637fbc54f7eddd5275165258b103e +++ std_hooks.lua 7e22137903335a8b7dd2ce7bc9969b8962ff85be @@ -123,23 +123,23 @@ function ignore_file(name) for i, line in pairs(ignored_files) do if (line ~= nil) then - local pcallstatus, result = pcall(function() - return regex.search(line, name) - end) + local pcallstatus, result = pcall(function() + return regex.search(line, name) + end) if pcallstatus == true then -- no error from the regex.search call if result == true then return true end else - -- regex.search had a problem, warn the user their + -- regex.search had a problem, warn the user their -- .mtn-ignore file syntax is wrong - if not warn_reported_file then - io.stderr:write("mtn: warning: while matching file '" - .. name .. "':\n") - warn_reported_file = true - end + if not warn_reported_file then + io.stderr:write("mtn: warning: while matching file '" + .. name .. "':\n") + warn_reported_file = true + end io.stderr:write(".mtn-ignore:" .. i .. ": warning: " .. result - .. "\n\t- skipping this regex for " - .. "all remaining files.\n") + .. "\n\t- skipping this regex for " + .. "all remaining files.\n") ignored_files[i] = nil end end @@ -424,27 +424,27 @@ mergers.vim = { mergers.vim = { cmd = function (tbl) function execute_diff3(mine, yours, out) - local diff3_args = { - "diff3", - "--merge", - "--easy-only", - } - table.insert(diff3_args, string.gsub(mine, "\\", "/") .. "") - table.insert(diff3_args, string.gsub(tbl.afile, "\\", "/") .. "") - table.insert(diff3_args, string.gsub(yours, "\\", "/") .. "") - - return execute_redirected("", string.gsub(out, "\\", "/"), "", unpack(diff3_args)) + local diff3_args = { + "diff3", + "--merge", + "--easy-only", + } + table.insert(diff3_args, string.gsub(mine, "\\", "/") .. "") + table.insert(diff3_args, string.gsub(tbl.afile, "\\", "/") .. "") + table.insert(diff3_args, string.gsub(yours, "\\", "/") .. "") + + return execute_redirected("", string.gsub(out, "\\", "/"), "", unpack(diff3_args)) end io.write (string.format("\nWARNING: 'vim' was choosen to perform external 3-way merge.\n".. "You should merge all changes to *LEFT* file due to limitation of program\n".. "arguments.\n\n")) - + local vim if os.getenv ("DISPLAY") ~= nil and program_exists_in_path ("gvim") then - vim = "gvim" + vim = "gvim" else - vim = "vim" + vim = "vim" end local lfile_merged = tbl.lfile .. ".merged" @@ -455,7 +455,7 @@ mergers.vim = { if ret == 2 then io.write(string.format(gettext("Error running diff3 for merger '%s'\n"), vim)) os.remove(lfile_merged) - return false + return false end -- now merge rfile using diff3 @@ -464,12 +464,12 @@ mergers.vim = { io.write(string.format(gettext("Error running diff3 for merger '%s'\n"), vim)) os.remove(lfile_merged) os.remove(rfile_merged) - return false + return false end - + os.rename(lfile_merged, tbl.lfile) os.rename(rfile_merged, tbl.rfile) - + local ret = execute(vim, "-f", "-d", "-c", string.format("file %s", tbl.outfile), tbl.lfile, tbl.rfile) if (ret ~= 0) then @@ -480,19 +480,19 @@ mergers.vim = { end , available = function () - return program_exists_in_path("diff3") and + return program_exists_in_path("diff3") and (program_exists_in_path("vim") or - program_exists_in_path("gvim")) + program_exists_in_path("gvim")) end , wanted = function () - local editor = os.getenv("EDITOR") - if editor and - not (string.find(editor, "vim") or - string.find(editor, "gvim")) then - return false - end - return true + local editor = os.getenv("EDITOR") + if editor and + not (string.find(editor, "vim") or + string.find(editor, "gvim")) then + return false + end + return true end } @@ -518,9 +518,9 @@ mergers.rcsmerge = { end, available = function () - local merge = os.getenv("MTN_RCSMERGE") - return merge and - program_exists_in_path(merge) and program_exists_in_path("vim") + local merge = os.getenv("MTN_RCSMERGE") + return merge and + program_exists_in_path(merge) and program_exists_in_path("vim") end , wanted = function () return os.getenv("MTN_RCSMERGE") ~= nil end } @@ -631,7 +631,7 @@ mergers.diffutils = { -- assume it is requested (if it is available at all) return true end -} +} mergers.emacs = { cmd = function (tbl) @@ -658,18 +658,18 @@ mergers.emacs = { end, available = function () - return program_exists_in_path("xemacs") or - program_exists_in_path("emacs") + return program_exists_in_path("xemacs") or + program_exists_in_path("emacs") end , wanted = function () - local editor = os.getenv("EDITOR") - if editor and - not (string.find(editor, "emacs") or - string.find(editor, "gnu")) then - return false - end - return true + local editor = os.getenv("EDITOR") + if editor and + not (string.find(editor, "emacs") or + string.find(editor, "gnu")) then + return false + end + return true end } @@ -841,17 +841,17 @@ function merge3 (anc_path, left_path, ri end end else - if mkey then - io.write (string.format("The possible commands for the "..mkey.." merger aren't available.\n".. + if mkey then + io.write (string.format("The possible commands for the "..mkey.." merger aren't available.\n".. "You may want to check that $MTN_MERGE or the lua variable `merger' is set\n".. "to something available. If you want to use vim or emacs, you can also\n".. - "set $EDITOR to something appropriate.\n")) - else - io.write (string.format("No external 3-way merge command found.\n".. + "set $EDITOR to something appropriate.\n")) + else + io.write (string.format("No external 3-way merge command found.\n".. "You may want to check that $EDITOR is set to an editor that supports 3-way\n".. "merge, set this explicitly in your get_preferred_merge3_command hook,\n".. "or add a 3-way merge program to your path.\n")) - end + end end end @@ -1144,6 +1144,12 @@ end return "mtn" end +function get_default_command_options(command) + local default_args = {} + return default_args +end + + function get_remote_unix_socket_command(host) return "socat" end @@ -1178,12 +1184,12 @@ do local s = "continue" local v = nil for _,n in pairs(hook_functions) do - if n[f] then - s,v = n[f](...) - end - if s ~= "continue" then - break - end + if n[f] then + s,v = n[f](...) + end + if s ~= "continue" then + break + end end return v end @@ -1217,38 +1223,38 @@ do function add_hook_functions(functions, precedence) if type(functions) ~= "table" or type(precedence) ~= "number" then - return false, "Invalid type" + return false, "Invalid type" end if hook_functions[precedence] then - return false, "Precedence already taken" + return false, "Precedence already taken" end local unknown_items = "" local warning = nil local is_member = - function (s,t) - for k,v in pairs(t) do if s == v then return true end end - return false - end + function (s,t) + for k,v in pairs(t) do if s == v then return true end end + return false + end for n,f in pairs(functions) do - if type(n) == "string" then - if not is_member(n, supported_items) then - if unknown_items ~= "" then - unknown_items = unknown_items .. "," - end - unknown_items = unknown_items .. n - end - if type(f) ~= "function" then - return false, "Value for functions item "..n.." isn't a function" - end - else - warning = "Non-string item keys found in functions table" - end + if type(n) == "string" then + if not is_member(n, supported_items) then + if unknown_items ~= "" then + unknown_items = unknown_items .. "," + end + unknown_items = unknown_items .. n + end + if type(f) ~= "function" then + return false, "Value for functions item "..n.." isn't a function" + end + else + warning = "Non-string item keys found in functions table" + end end if warning == nil and unknown_items ~= "" then - warning = "Unknown item(s) " .. unknown_items .. " in functions table" + warning = "Unknown item(s) " .. unknown_items .. " in functions table" end hook_functions[precedence] = functions