# # # patch "automate.cc" # from [598a04952daffa804d60dde204967b20e17fc37a] # to [881288755ce94308be92ab8c9e73491640b6a4d2] # # patch "lua_hooks.cc" # from [0476cf2512e471ca31d9a3b185968487fbeb9e8e] # to [af8016e477fd39f14de53b4c17e16eacb2692bf4] # # patch "lua_hooks.hh" # from [eb7235af2f81fcce2921725bfd150df2ba3bfc65] # to [a5ac6a6139a2672c9e8d16bb97162ac849179dda] # # patch "std_hooks.lua" # from [c4f02c95a5717f64d0a60251081ff5bd1a8038de] # to [602ac070879bb429d902af61e65bcf652857af90] # ============================================================ --- automate.cc 598a04952daffa804d60dde204967b20e17fc37a +++ automate.cc 881288755ce94308be92ab8c9e73491640b6a4d2 @@ -2276,6 +2276,35 @@ CMD_AUTOMATE(get_workspace_root, "", output << get_current_working_dir() << '\n'; } +CMD_AUTOMATE(lua, "LUA_FUNCTION [ARG1 [ARG2 [...]]]", + N_("Executes the given lua function and returns the result"), + "", + options::opts::none) +{ + N(args.size() >= 1, + F("wrong argument count")); + + std::string func = idx(args, 0)(); + + N(app.lua.hook_exists(func), + F("lua function '%s' does not exist") % func); + + std::vector func_args; + if (args.size() > 1) + { + for (unsigned int i=1; i const & args, + std::string & out) +{ + Lua ll(st); + ll.func("hook_wrapper") + .push_str(func_name) + .push_table(); + + int k=0; + for (std::vector::const_iterator i = args.begin(); + i != args.end(); ++i) + { + ll.push_int(++k) + .push_str(*i) + .set_table(); + } + + ll.call(2, 1); + ll.extract_str_nolog(out); + return ll.ok(); +} + bool lua_hooks::hook_use_inodeprints() { ============================================================ --- lua_hooks.hh eb7235af2f81fcce2921725bfd150df2ba3bfc65 +++ lua_hooks.hh a5ac6a6139a2672c9e8d16bb97162ac849179dda @@ -138,6 +138,11 @@ public: bool & validated, std::string & reason); + // meta hooks + bool hook_hook_wrapper(std::string const & func_name, + std::vector const & args, + std::string & out); + // notification hooks bool hook_note_commit(revision_id const & new_id, revision_data const & rdat, ============================================================ --- std_hooks.lua c4f02c95a5717f64d0a60251081ff5bd1a8038de +++ std_hooks.lua 602ac070879bb429d902af61e65bcf652857af90 @@ -1157,7 +1157,50 @@ end return default_args end +dump = {} +dump.depth = 0 +dump._string = function(s) return string.format("%q", s) end +dump._number = function(n) return tonumber(n) end +dump._boolean = function(b) if (b) then return "true" end return "false" end +dump._userdata = function(u) return "" end +dump._function = function(f) return "" end +dump._nil = function(n) return "nil" end +dump._thread = function(t) return "" end +dump._lightuserdata = function(l) return "" end +dump._table = function(t) + local buf = '' + if (dump.depth > 0) then + buf = buf .. '{\n' + end + dump.depth = dump.depth + 1; + for k,v in pairs(t) do + buf = buf..string.format('%s[%s] = %s;\n', + string.rep("\t", dump.depth - 1), + dump["_" .. type(k)](k), + dump["_" .. type(v)](v)) + end + dump.depth = dump.depth - 1; + if (dump.depth > 0) then + buf = buf .. string.rep("\t", dump.depth - 1) .. '}' + end + return buf +end + +function hook_wrapper(func_name, ...) + -- evaluate each single string argument to resolve types + -- like nil's, table's and others - the select('#', ...) syntax is + -- borrowed from http://lua-users.org/wiki/StoringNilsInTables to + -- let this code properly work for nil arguments as well + local args = {n=select('#',...), ...} + for i=2,args.n do + args[i] = assert(loadstring("return " .. args[i]))() + end + local res = { _G[func_name](unpack(unpack(args, 1, args.n))) } + return dump._table(res) +end + + function get_remote_unix_socket_command(host) return "socat" end