monotone

monotone Mtn Source Tree

Root/lua.cc

1// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*-
2// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
3// all rights reserved.
4// licensed to the public under the terms of the GNU GPL (>= 2)
5// see the file COPYING for details
6
7#include "config.h"
8
9extern "C" {
10#include <lua.h>
11#include <lualib.h>
12#include <lauxlib.h>
13}
14
15#include <errno.h>
16#include <stdlib.h>
17#include <string.h>
18#include <stdarg.h>
19#include <signal.h>
20#include <boost/lexical_cast.hpp>
21#include <boost/filesystem/path.hpp>
22#include <boost/filesystem/operations.hpp>
23#include <boost/regex.hpp>
24
25#include <set>
26#include <map>
27#include <fstream>
28
29#include "app_state.hh"
30#include "file_io.hh"
31#include "lua.hh"
32#include "mkstemp.hh"
33#include "sanity.hh"
34#include "vocab.hh"
35#include "platform.hh"
36#include "transforms.hh"
37#include "paths.hh"
38
39// defined in {std,test}_hooks.lua, converted
40#include "test_hooks.h"
41#include "std_hooks.h"
42
43using namespace std;
44using boost::lexical_cast;
45
46static int panic_thrower(lua_State * st)
47{
48 throw oops("lua panic");
49}
50
51// adapted from "programming in lua", section 24.2.3
52// http://www.lua.org/pil/24.2.3.html
53// output is from bottom (least accessible) to top (most accessible, where
54// push and pop happen).
55static std::string
56dump_stack(lua_State * st)
57{
58 std::string out;
59 int i;
60 int top = lua_gettop(st);
61 for (i = 1; i <= top; i++) { /* repeat for each level */
62 int t = lua_type(st, i);
63 switch (t) {
64 case LUA_TSTRING: /* strings */
65 out += (boost::format("`%s'") % std::string(lua_tostring(st, i), lua_strlen(st, i))).str();
66 break;
67
68 case LUA_TBOOLEAN: /* booleans */
69 out += (lua_toboolean(st, i) ? "true" : "false");
70 break;
71
72 case LUA_TNUMBER: /* numbers */
73 out += (boost::format("%g") % lua_tonumber(st, i)).str();
74 break;
75
76 default: /* other values */
77 out += (boost::format("%s") % lua_typename(st, t)).str();
78 break;
79
80 }
81 out += " "; /* put a separator */
82 }
83 return out;
84}
85
86// This Lua object represents a single imperative transaction with the lua
87// interpreter. if it fails at any point, all further commands in the
88// transaction are ignored. it cleans the lua stack up when it is
89// destructed, so no need to pop values when you're done.
90
91struct
92Lua
93{
94 lua_State * st;
95 bool failed;
96 static std::set<string> missing_functions;
97
98 Lua(lua_State * s) :
99 st(s), failed(false)
100 {}
101
102 ~Lua()
103 {
104 lua_settop(st, 0);
105 }
106
107 void fail(std::string const & reason)
108 {
109 L(F("lua failure: %s; stack = %s\n") % reason % dump_stack(st));
110 failed = true;
111 }
112
113 bool ok()
114 {
115 L(F("Lua::ok(): failed = %i") % failed);
116 return !failed;
117 }
118
119 void report_error()
120 {
121 I(lua_isstring(st, -1));
122 string err = string(lua_tostring(st, -1), lua_strlen(st, -1));
123 W(boost::format("%s\n") % err);
124 L(F("lua stack: %s") % dump_stack(st));
125 lua_pop(st, 1);
126 failed = true;
127 }
128
129 // getters
130
131 Lua & get(int idx = LUA_GLOBALSINDEX)
132 {
133 if (failed) return *this;
134 if (!lua_istable (st, idx))
135 {
136 fail("istable() in get");
137 return *this;
138 }
139 if (lua_gettop (st) < 1)
140 {
141 fail("stack top > 0 in get");
142 return *this;
143 }
144 lua_gettable(st, idx);
145 return *this;
146 }
147
148 Lua & get_fn(int idx = LUA_GLOBALSINDEX)
149 {
150 if (failed) return *this;
151 get(idx);
152 if (!lua_isfunction (st, -1))
153 fail("isfunction() in get_fn");
154 return *this;
155 }
156
157 Lua & get_tab(int idx = LUA_GLOBALSINDEX)
158 {
159 if (failed) return *this;
160 get(idx);
161 if (!lua_istable (st, -1))
162 fail("istable() in get_tab");
163 return *this;
164 }
165
166 Lua & get_str(int idx = LUA_GLOBALSINDEX)
167 {
168 if (failed) return *this;
169 get(idx);
170 if (!lua_isstring (st, -1))
171 fail("isstring() in get_str");
172 return *this;
173 }
174
175 Lua & get_num(int idx = LUA_GLOBALSINDEX)
176 {
177 if (failed) return *this;
178 get(idx);
179 if (!lua_isnumber (st, -1))
180 fail("isnumber() in get_num");
181 return *this;
182 }
183
184 Lua & get_bool(int idx = LUA_GLOBALSINDEX)
185 {
186 if (failed) return *this;
187 get(idx);
188 if (!lua_isboolean (st, -1))
189 fail("isboolean() in get_bool");
190 return *this;
191 }
192
193 // extractors
194
195 Lua & extract_str(string & str)
196 {
197 if (failed) return *this;
198 if (!lua_isstring (st, -1))
199 {
200 fail("isstring() in extract_str");
201 return *this;
202 }
203 str = string(lua_tostring(st, -1), lua_strlen(st, -1));
204 L(F("lua: extracted string = %s") % str);
205 return *this;
206 }
207
208 Lua & extract_int(int & i)
209 {
210 if (failed) return *this;
211 if (!lua_isnumber (st, -1))
212 {
213 fail("isnumber() in extract_int");
214 return *this;
215 }
216 i = static_cast<int>(lua_tonumber(st, -1));
217 L(F("lua: extracted int = %i") % i);
218 return *this;
219 }
220
221 Lua & extract_double(double & i)
222 {
223 if (failed) return *this;
224 if (!lua_isnumber (st, -1))
225 {
226 fail("isnumber() in extract_double");
227 return *this;
228 }
229 i = lua_tonumber(st, -1);
230 L(F("lua: extracted double = %i") % i);
231 return *this;
232 }
233
234
235 Lua & extract_bool(bool & i)
236 {
237 if (failed) return *this;
238 if (!lua_isboolean (st, -1))
239 {
240 fail("isboolean() in extract_bool");
241 return *this;
242 }
243 i = (lua_toboolean(st, -1) == 1);
244 L(F("lua: extracted bool = %i") % i);
245 return *this;
246 }
247
248
249 // table iteration
250
251 Lua & begin()
252 {
253 if (failed) return *this;
254 if (!lua_istable(st, -1))
255 {
256 fail("istable() in begin");
257 return *this;
258 }
259 I(lua_checkstack (st, 1));
260 lua_pushnil(st);
261 return *this;
262 }
263
264 bool next()
265 {
266 if (failed) return false;
267 if (!lua_istable(st, -2))
268 {
269 fail("istable() in next");
270 return false;
271 }
272 I(lua_checkstack (st, 1));
273 if (lua_next(st, -2) != 0)
274 {
275 return true;
276 }
277 pop();
278 return false;
279 }
280
281 // pushers
282
283 Lua & push_str(string const & str)
284 {
285 if (failed) return *this;
286 I(lua_checkstack (st, 1));
287 lua_pushlstring(st, str.c_str(), str.size());
288 return *this;
289 }
290
291 Lua & push_int(int num)
292 {
293 if (failed) return *this;
294 I(lua_checkstack (st, 1));
295 lua_pushnumber(st, num);
296 return *this;
297 }
298
299 Lua & push_int(double num)
300 {
301 if (failed) return *this;
302 I(lua_checkstack (st, 1));
303 lua_pushnumber(st, num);
304 return *this;
305 }
306
307 Lua & push_bool(bool b)
308 {
309 if (failed) return *this;
310 I(lua_checkstack (st, 1));
311 lua_pushboolean(st, b);
312 return *this;
313 }
314
315 Lua & push_nil()
316 {
317 if (failed) return *this;
318 I(lua_checkstack (st, 1));
319 lua_pushnil(st);
320 return *this;
321 }
322
323 Lua & push_table()
324 {
325 if (failed) return *this;
326 I(lua_checkstack (st, 1));
327 lua_newtable(st);
328 return *this;
329 }
330
331 Lua & set_table(int idx = -3)
332 {
333 if (failed) return *this;
334 I(lua_checkstack (st, 1));
335 lua_settable(st, idx);
336 return *this;
337 }
338
339 Lua & call(int in, int out)
340 {
341 if (failed) return *this;
342 I(lua_checkstack (st, out));
343 if (lua_pcall(st, in, out, 0) != 0)
344 {
345 report_error();
346 }
347 return *this;
348 }
349
350 Lua & pop(int count = 1)
351 {
352 if (failed) return *this;
353 if (lua_gettop (st) < count)
354 {
355 fail("stack top is not >= count in pop");
356 return *this;
357 }
358 lua_pop(st, count);
359 return *this;
360 }
361
362 Lua & func(string const & fname)
363 {
364 L(F("loading lua hook %s") % fname);
365 if (!failed)
366 {
367 if (missing_functions.find(fname) != missing_functions.end())
368 failed = true;
369 else
370 {
371 push_str(fname);
372 get_fn();
373 if (failed)
374 missing_functions.insert(fname);
375 }
376 }
377 return *this;
378 }
379
380 Lua & loadstring(string const & str, string const & identity)
381 {
382 if (!failed)
383 {
384 if (luaL_loadbuffer(st, str.c_str(), str.size(), identity.c_str()))
385 {
386 report_error();
387 }
388 }
389 return *this;
390 }
391
392 Lua & loadfile(string const & filename)
393 {
394 if (!failed)
395 {
396 if (luaL_loadfile(st, filename.c_str()))
397 {
398 report_error();
399 }
400 }
401 return *this;
402 }
403};
404
405std::set<string> Lua::missing_functions;
406
407
408
409
410extern "C"
411{
412 static int
413 monotone_mkstemp_for_lua(lua_State *L)
414 {
415 int fd = -1;
416 FILE **pf = NULL;
417 char const *filename = lua_tostring (L, -1);
418 std::string dup(filename);
419
420 fd = monotone_mkstemp(dup);
421
422 if (fd == -1)
423 return 0;
424
425 // this magic constructs a lua object which the lua io library
426 // will enjoy working with
427 pf = static_cast<FILE **>(lua_newuserdata(L, sizeof(FILE *)));
428 *pf = fdopen(fd, "r+");
429 lua_pushstring(L, "FILE*");
430 lua_rawget(L, LUA_REGISTRYINDEX);
431 lua_setmetatable(L, -2);
432
433 lua_pushstring(L, dup.c_str());
434
435 if (*pf == NULL)
436 {
437 lua_pushnil(L);
438 lua_pushfstring(L, "%s", strerror(errno));
439 lua_pushnumber(L, errno);
440 return 3;
441 }
442 else
443 return 2;
444 }
445
446 static int
447 monotone_existsonpath_for_lua(lua_State *L)
448 {
449 const char *exe = lua_tostring(L, -1);
450 lua_pushnumber(L, existsonpath(exe));
451 return 1;
452 }
453
454 static int
455 monotone_is_executable_for_lua(lua_State *L)
456 {
457 const char *path = lua_tostring(L, -1);
458 lua_pushboolean(L, is_executable(path));
459 return 1;
460 }
461
462 static int
463 monotone_make_executable_for_lua(lua_State *L)
464 {
465 const char *path = lua_tostring(L, -1);
466 lua_pushnumber(L, make_executable(path));
467 return 1;
468 }
469
470 static int
471 monotone_spawn_for_lua(lua_State *L)
472 {
473 int n = lua_gettop(L);
474 const char *path = lua_tostring(L, -n);
475 char **argv = (char**)malloc((n+1)*sizeof(char*));
476 int i;
477 pid_t ret;
478 if (argv==NULL)
479 return 0;
480 argv[0] = (char*)path;
481 for (i=1; i<n; i++) argv[i] = (char*)lua_tostring(L, -(n - i));
482 argv[i] = NULL;
483 ret = process_spawn(argv);
484 free(argv);
485 lua_pushnumber(L, ret);
486 return 1;
487 }
488
489 static int
490 monotone_wait_for_lua(lua_State *L)
491 {
492 pid_t pid = (pid_t)lua_tonumber(L, -1);
493 int res;
494 int ret;
495 ret = process_wait(pid, &res);
496 lua_pushnumber(L, res);
497 lua_pushnumber(L, ret);
498 return 2;
499 }
500
501 static int
502 monotone_kill_for_lua(lua_State *L)
503 {
504 int n = lua_gettop(L);
505 pid_t pid = (pid_t)lua_tonumber(L, -2);
506 int sig;
507 if (n>1)
508 sig = (int)lua_tonumber(L, -1);
509 else
510 sig = SIGTERM;
511 lua_pushnumber(L, process_kill(pid, sig));
512 return 1;
513 }
514
515 static int
516 monotone_sleep_for_lua(lua_State *L)
517 {
518 int seconds = (int)lua_tonumber(L, -1);
519 lua_pushnumber(L, process_sleep(seconds));
520 return 1;
521 }
522
523 static int
524 monotone_guess_binary_file_contents_for_lua(lua_State *L)
525 {
526 const char *path = lua_tostring(L, -1);
527 N(path, F("%s called with an invalid parameter") % "guess_binary");
528
529 std::ifstream file(path, ios_base::binary);
530 if (!file)
531 {
532 lua_pushnil(L);
533 return 1;
534 }
535 const int bufsize = 8192;
536 char tmpbuf[bufsize];
537 string buf;
538 while (file.read(tmpbuf, sizeof tmpbuf))
539 {
540 I(file.gcount() <= static_cast<int>(sizeof tmpbuf));
541 buf.assign(tmpbuf, file.gcount());
542 if (guess_binary(buf))
543 {
544 lua_pushboolean(L, true);
545 return 1;
546 }
547 }
548 lua_pushboolean(L, false);
549 return 1;
550 }
551
552 static int
553 monotone_include_for_lua(lua_State *L)
554 {
555 const char *path = lua_tostring(L, -1);
556 N(path, F("%s called with an invalid parameter") % "Include");
557
558 bool res =Lua(L)
559 .loadfile(std::string(path, lua_strlen(L, -1)))
560 .call(0,1)
561 .ok();
562
563 lua_pushboolean(L, res);
564 return 1;
565 }
566
567 static int
568 monotone_includedir_for_lua(lua_State *L)
569 {
570 const char *pathstr = lua_tostring(L, -1);
571 N(pathstr, F("%s called with an invalid parameter") % "IncludeDir");
572
573 fs::path locpath(pathstr, fs::native);
574 N(fs::exists(locpath), F("Directory '%s' does not exists") % pathstr);
575 N(fs::is_directory(locpath), F("'%s' is not a directory") % pathstr);
576
577 // directory, iterate over it, skipping subdirs, taking every filename,
578 // sorting them and loading in sorted order
579 fs::directory_iterator it(locpath);
580 std::vector<fs::path> arr;
581 while (it != fs::directory_iterator())
582 {
583 if (!fs::is_directory(*it))
584 arr.push_back(*it);
585 ++it;
586 }
587 std::sort(arr.begin(), arr.end());
588 for (std::vector<fs::path>::iterator i= arr.begin(); i != arr.end(); ++i)
589 {
590 bool res =Lua(L)
591 .loadfile(i->string())
592 .call(0,1)
593 .ok();
594 N(res, F("lua error while loading rcfile '%s'") % i->string());
595 }
596
597 lua_pushboolean(L, true);
598 return 1;
599 }
600
601 static int
602 monotone_regex_search_for_lua(lua_State *L)
603 {
604 const char *re = lua_tostring(L, -2);
605 const char *str = lua_tostring(L, -1);
606 boost::cmatch what;
607
608 lua_pushboolean(L, boost::regex_search(str, what, boost::regex(re)));
609 return 1;
610 }
611
612 static int
613 monotone_gettext_for_lua(lua_State *L)
614 {
615 const char *msgid = lua_tostring(L, -1);
616 lua_pushstring(L, gettext(msgid));
617 return 1;
618 }
619}
620
621
622lua_hooks::lua_hooks()
623{
624 st = lua_open ();
625 I(st);
626
627 lua_atpanic (st, &panic_thrower);
628
629 luaopen_base(st);
630 luaopen_io(st);
631 luaopen_string(st);
632 luaopen_math(st);
633 luaopen_table(st);
634 luaopen_debug(st);
635
636 // add monotone-specific functions
637 lua_register(st, "mkstemp", monotone_mkstemp_for_lua);
638 lua_register(st, "existsonpath", monotone_existsonpath_for_lua);
639 lua_register(st, "is_executable", monotone_is_executable_for_lua);
640 lua_register(st, "make_executable", monotone_make_executable_for_lua);
641 lua_register(st, "spawn", monotone_spawn_for_lua);
642 lua_register(st, "wait", monotone_wait_for_lua);
643 lua_register(st, "kill", monotone_kill_for_lua);
644 lua_register(st, "sleep", monotone_sleep_for_lua);
645 lua_register(st, "guess_binary_file_contents", monotone_guess_binary_file_contents_for_lua);
646 lua_register(st, "include", monotone_include_for_lua);
647 lua_register(st, "includedir", monotone_includedir_for_lua);
648 lua_register(st, "gettext", monotone_gettext_for_lua);
649
650 // add regex functions:
651 lua_newtable(st);
652 lua_pushstring(st, "regex");
653 lua_pushvalue(st, -2);
654 lua_settable(st, LUA_GLOBALSINDEX);
655
656 lua_pushstring(st, "search");
657 lua_pushcfunction(st, monotone_regex_search_for_lua);
658 lua_settable(st, -3);
659
660 lua_pop(st, 1);
661}
662
663lua_hooks::~lua_hooks()
664{
665 if (st)
666 lua_close (st);
667}
668
669static bool
670run_string(lua_State * st, string const &str, string const & identity)
671{
672 I(st);
673 return
674 Lua(st)
675 .loadstring(str, identity)
676 .call(0,1)
677 .ok();
678}
679
680static bool
681run_file(lua_State * st, string const &filename)
682{
683 I(st);
684 return
685 Lua(st)
686 .loadfile(filename)
687 .call(0,1)
688 .ok();
689}
690
691
692#ifdef BUILD_UNIT_TESTS
693void
694lua_hooks::add_test_hooks()
695{
696 if (!run_string(st, test_hooks_constant, string("<test hooks>")))
697 throw oops("lua error while setting up testing hooks");
698}
699#endif
700
701void
702lua_hooks::add_std_hooks()
703{
704 if (!run_string(st, std_hooks_constant, string("<std hooks>")))
705 throw oops("lua error while setting up standard hooks");
706}
707
708void
709lua_hooks::default_rcfilename(system_path & file)
710{
711 file = system_path(get_homedir()) / ".monotone/monotonerc";
712}
713
714void
715lua_hooks::working_copy_rcfilename(bookkeeping_path & file)
716{
717 file = bookkeeping_root / "monotonerc";
718}
719
720
721void
722lua_hooks::load_rcfile(utf8 const & rc)
723{
724 I(st);
725 if (rc() != "-")
726 {
727 fs::path locpath(system_path(rc).as_external(), fs::native);
728 if (fs::exists(locpath) && fs::is_directory(locpath))
729 {
730 // directory, iterate over it, skipping subdirs, taking every filename,
731 // sorting them and loading in sorted order
732 fs::directory_iterator it(locpath);
733 std::vector<fs::path> arr;
734 while (it != fs::directory_iterator())
735 {
736 if (!fs::is_directory(*it))
737 arr.push_back(*it);
738 ++it;
739 }
740 std::sort(arr.begin(), arr.end());
741 for (std::vector<fs::path>::iterator i= arr.begin(); i != arr.end(); ++i)
742 {
743 load_rcfile(system_path(i->native_directory_string()), true);
744 }
745 return; // directory read, skip the rest ...
746 }
747 }
748 data dat;
749 L(F("opening rcfile '%s' ...\n") % rc);
750 read_data_for_command_line(rc, dat);
751 N(run_string(st, dat(), rc().c_str()),
752 F("lua error while loading rcfile '%s'") % rc);
753 L(F("'%s' is ok\n") % rc);
754}
755
756void
757lua_hooks::load_rcfile(any_path const & rc, bool required)
758{
759 I(st);
760 if (path_exists(rc))
761 {
762 L(F("opening rcfile '%s' ...\n") % rc);
763 N(run_file(st, rc.as_external()),
764 F("lua error while loading '%s'") % rc);
765 L(F("'%s' is ok\n") % rc);
766 }
767 else
768 {
769 N(!required, F("rcfile '%s' does not exist") % rc);
770 L(F("skipping nonexistent rcfile '%s'\n") % rc);
771 }
772}
773
774
775// concrete hooks
776
777// nb: if you're hooking lua to return your passphrase, you don't care if we
778// keep a couple extra temporaries of your passphrase around.
779bool
780lua_hooks::hook_get_passphrase(rsa_keypair_id const & k, string & phrase)
781{
782 return Lua(st)
783 .func("get_passphrase")
784 .push_str(k())
785 .call(1,1)
786 .extract_str(phrase)
787 .ok();
788}
789
790bool
791lua_hooks::hook_persist_phrase_ok()
792{
793 bool persist_ok = false;
794 bool executed_ok = Lua(st)
795 .func("persist_phrase_ok")
796 .call(0,1)
797 .extract_bool(persist_ok)
798 .ok();
799 return executed_ok && persist_ok;
800}
801
802bool
803lua_hooks::hook_expand_selector(std::string const & sel,
804 std::string & exp)
805{
806 return Lua(st)
807 .func("expand_selector")
808 .push_str(sel)
809 .call(1,1)
810 .extract_str(exp)
811 .ok();
812}
813
814bool
815lua_hooks::hook_expand_date(std::string const & sel,
816 std::string & exp)
817{
818 exp.clear();
819 bool res= Lua(st)
820 .func("expand_date")
821 .push_str(sel)
822 .call(1,1)
823 .extract_str(exp)
824 .ok();
825 return res && exp.size();
826}
827
828bool
829lua_hooks::hook_get_branch_key(cert_value const & branchname,
830 rsa_keypair_id & k)
831{
832 string key;
833 bool ok = Lua(st)
834 .func("get_branch_key")
835 .push_str(branchname())
836 .call(1,1)
837 .extract_str(key)
838 .ok();
839
840 k = key;
841 return ok;
842}
843
844bool
845lua_hooks::hook_get_priv_key(rsa_keypair_id const & k,
846 base64< arc4<rsa_priv_key> > & priv_key )
847{
848 string key;
849 bool ok = Lua(st)
850 .func("get_priv_key")
851 .push_str(k())
852 .call(1,1)
853 .extract_str(key)
854 .ok();
855
856 priv_key = key;
857 return ok;
858}
859
860bool
861lua_hooks::hook_get_author(cert_value const & branchname,
862 string & author)
863{
864 return Lua(st)
865 .func("get_author")
866 .push_str(branchname())
867 .call(1,1)
868 .extract_str(author)
869 .ok();
870}
871
872bool
873lua_hooks::hook_edit_comment(string const & commentary,
874 string const & user_log_message,
875 string & result)
876{
877 return Lua(st)
878 .func("edit_comment")
879 .push_str(commentary)
880 .push_str(user_log_message)
881 .call(2,1)
882 .extract_str(result)
883 .ok();
884}
885
886bool
887lua_hooks::hook_ignore_file(file_path const & p)
888{
889 bool ignore_it = false;
890 bool exec_ok = Lua(st)
891 .func("ignore_file")
892 .push_str(p.as_external())
893 .call(1,1)
894 .extract_bool(ignore_it)
895 .ok();
896 return exec_ok && ignore_it;
897}
898
899bool
900lua_hooks::hook_ignore_branch(std::string const & branch)
901{
902 bool ignore_it = false;
903 bool exec_ok = Lua(st)
904 .func("ignore_branch")
905 .push_str(branch)
906 .call(1,1)
907 .extract_bool(ignore_it)
908 .ok();
909 return exec_ok && ignore_it;
910}
911
912bool
913lua_hooks::hook_non_blocking_rng_ok()
914{
915 bool ok = false;
916 bool exec_ok = Lua(st)
917 .func("non_blocking_rng_ok")
918 .call(0,1)
919 .extract_bool(ok)
920 .ok();
921 return exec_ok && ok;
922}
923
924static inline bool
925shared_trust_function_body(Lua & ll,
926 std::set<rsa_keypair_id> const & signers,
927 hexenc<id> const & id,
928 cert_name const & name,
929 cert_value const & val)
930{
931 ll.push_table();
932
933 int k = 0;
934 for (set<rsa_keypair_id>::const_iterator v = signers.begin();
935 v != signers.end(); ++v)
936 {
937 ll.push_int(k);
938 ll.push_str((*v)());
939 ll.set_table();
940 ++k;
941 }
942
943 bool ok;
944 bool exec_ok = ll
945 .push_str(id())
946 .push_str(name())
947 .push_str(val())
948 .call(4, 1)
949 .extract_bool(ok)
950 .ok();
951
952 return exec_ok && ok;
953}
954
955bool
956lua_hooks::hook_get_revision_cert_trust(std::set<rsa_keypair_id> const & signers,
957 hexenc<id> const & id,
958 cert_name const & name,
959 cert_value const & val)
960{
961 Lua ll(st);
962 ll.func("get_revision_cert_trust");
963 return shared_trust_function_body(ll, signers, id, name, val);
964}
965
966bool
967lua_hooks::hook_get_manifest_cert_trust(std::set<rsa_keypair_id> const & signers,
968 hexenc<id> const & id,
969 cert_name const & name,
970 cert_value const & val)
971{
972 Lua ll(st);
973 ll.func("get_manifest_cert_trust");
974 return shared_trust_function_body(ll, signers, id, name, val);
975}
976
977bool
978lua_hooks::hook_accept_testresult_change(map<rsa_keypair_id, bool> const & old_results,
979 map<rsa_keypair_id, bool> const & new_results)
980{
981 Lua ll(st);
982 ll
983 .func("accept_testresult_change")
984 .push_table();
985
986 for (map<rsa_keypair_id, bool>::const_iterator i = old_results.begin();
987 i != old_results.end(); ++i)
988 {
989 ll.push_str(i->first());
990 ll.push_bool(i->second);
991 ll.set_table();
992 }
993
994 ll.push_table();
995
996 for (map<rsa_keypair_id, bool>::const_iterator i = new_results.begin();
997 i != new_results.end(); ++i)
998 {
999 ll.push_str(i->first());
1000 ll.push_bool(i->second);
1001 ll.set_table();
1002 }
1003
1004 bool ok;
1005 bool exec_ok = ll
1006 .call(2, 1)
1007 .extract_bool(ok)
1008 .ok();
1009
1010 return exec_ok && ok;
1011}
1012
1013
1014
1015bool
1016lua_hooks::hook_merge2(file_path const & left_path,
1017 file_path const & right_path,
1018 file_path const & merged_path,
1019 data const & left,
1020 data const & right,
1021 data & result)
1022{
1023 string res;
1024 bool ok = Lua(st)
1025 .func("merge2")
1026 .push_str(left_path.as_external())
1027 .push_str(right_path.as_external())
1028 .push_str(merged_path.as_external())
1029 .push_str(left())
1030 .push_str(right())
1031 .call(5,1)
1032 .extract_str(res)
1033 .ok();
1034 result = res;
1035 return ok;
1036}
1037
1038bool
1039lua_hooks::hook_merge3(file_path const & anc_path,
1040 file_path const & left_path,
1041 file_path const & right_path,
1042 file_path const & merged_path,
1043 data const & ancestor,
1044 data const & left,
1045 data const & right,
1046 data & result)
1047{
1048 string res;
1049 bool ok = Lua(st)
1050 .func("merge3")
1051 .push_str(anc_path.as_external())
1052 .push_str(left_path.as_external())
1053 .push_str(right_path.as_external())
1054 .push_str(merged_path.as_external())
1055 .push_str(ancestor())
1056 .push_str(left())
1057 .push_str(right())
1058 .call(7,1)
1059 .extract_str(res)
1060 .ok();
1061 result = res;
1062 return ok;
1063}
1064
1065bool
1066lua_hooks::hook_resolve_file_conflict(file_path const & anc,
1067 file_path const & a,
1068 file_path const & b,
1069 file_path & res)
1070{
1071 string tmp;
1072 bool ok = Lua(st)
1073 .func("resolve_file_conflict")
1074 .push_str(anc.as_external())
1075 .push_str(a.as_external())
1076 .push_str(b.as_external())
1077 .call(3,1)
1078 .extract_str(tmp)
1079 .ok();
1080 res = file_path_internal(tmp);
1081 return ok;
1082}
1083
1084bool
1085lua_hooks::hook_resolve_dir_conflict(file_path const & anc,
1086 file_path const & a,
1087 file_path const & b,
1088 file_path & res)
1089{
1090 string tmp;
1091 bool ok = Lua(st)
1092 .func("resolve_dir_conflict")
1093 .push_str(anc.as_external())
1094 .push_str(a.as_external())
1095 .push_str(b.as_external())
1096 .call(3,1)
1097 .extract_str(tmp)
1098 .ok();
1099 res = file_path_internal(tmp);
1100 return ok;
1101}
1102
1103bool
1104lua_hooks::hook_external_diff(file_path const & path,
1105 data const & data_old,
1106 data const & data_new,
1107 bool is_binary,
1108 bool diff_args_provided,
1109 std::string const & diff_args,
1110 std::string const & oldrev,
1111 std::string const & newrev)
1112{
1113 Lua ll(st);
1114
1115 ll
1116 .func("external_diff")
1117 .push_str(path.as_external());
1118
1119 if (oldrev.length() != 0)
1120 ll.push_str(data_old());
1121 else
1122 ll.push_nil();
1123
1124 ll.push_str(data_new());
1125
1126 ll.push_bool(is_binary);
1127
1128 if (diff_args_provided)
1129 ll.push_str(diff_args);
1130 else
1131 ll.push_nil();
1132
1133 ll.push_str(oldrev);
1134 ll.push_str(newrev);
1135
1136 return ll.call(7,0).ok();
1137}
1138
1139bool
1140lua_hooks::hook_use_inodeprints()
1141{
1142 bool use = false, exec_ok = false;
1143
1144 exec_ok = Lua(st)
1145 .func("use_inodeprints")
1146 .call(0, 1)
1147 .extract_bool(use)
1148 .ok();
1149 return use && exec_ok;
1150}
1151
1152bool
1153lua_hooks::hook_get_netsync_read_permitted(std::string const & branch,
1154 rsa_keypair_id const & identity)
1155{
1156 bool permitted = false, exec_ok = false;
1157
1158 exec_ok = Lua(st)
1159 .func("get_netsync_read_permitted")
1160 .push_str(branch)
1161 .push_str(identity())
1162 .call(2,1)
1163 .extract_bool(permitted)
1164 .ok();
1165
1166 return exec_ok && permitted;
1167}
1168
1169// Anonymous no-key version
1170bool
1171lua_hooks::hook_get_netsync_read_permitted(std::string const & branch)
1172{
1173 bool permitted = false, exec_ok = false;
1174
1175 exec_ok = Lua(st)
1176 .func("get_netsync_read_permitted")
1177 .push_str(branch)
1178 .push_nil()
1179 .call(2,1)
1180 .extract_bool(permitted)
1181 .ok();
1182
1183 return exec_ok && permitted;
1184}
1185
1186bool
1187lua_hooks::hook_get_netsync_write_permitted(rsa_keypair_id const & identity)
1188{
1189 bool permitted = false, exec_ok = false;
1190
1191 exec_ok = Lua(st)
1192 .func("get_netsync_write_permitted")
1193 .push_str(identity())
1194 .call(1,1)
1195 .extract_bool(permitted)
1196 .ok();
1197
1198 return exec_ok && permitted;
1199}
1200
1201bool
1202lua_hooks::hook_init_attributes(file_path const & filename,
1203 std::map<std::string, std::string> & attrs)
1204{
1205 Lua ll(st);
1206
1207 ll
1208 .push_str("attr_init_functions")
1209 .get_tab();
1210
1211 L(F("calling attr_init_function for %s") % filename);
1212 ll.begin();
1213 while (ll.next())
1214 {
1215 L(F(" calling an attr_init_function for %s") % filename);
1216 ll.push_str(filename.as_external());
1217 ll.call(1, 1);
1218
1219 if (lua_isstring(st, -1))
1220 {
1221 string key, value;
1222
1223 ll.extract_str(value);
1224 ll.pop();
1225 ll.extract_str(key);
1226
1227 attrs[key] = value;
1228 L(F(" added attr %s = %s") % key % value);
1229 }
1230 else
1231 {
1232 L(F(" no attr added"));
1233 ll.pop();
1234 }
1235 }
1236
1237 return ll.pop().ok();
1238}
1239
1240bool
1241lua_hooks::hook_apply_attribute(string const & attr,
1242 file_path const & filename,
1243 string const & value)
1244{
1245 return Lua(st)
1246 .push_str("attr_functions")
1247 .get_tab()
1248 .push_str(attr)
1249 .get_fn(-2)
1250 .push_str(filename.as_external())
1251 .push_str(value)
1252 .call(2,0)
1253 .ok();
1254}
1255
1256
1257bool
1258lua_hooks::hook_get_system_linesep(string & linesep)
1259{
1260 return Lua(st)
1261 .func("get_system_linesep")
1262 .call(0,1)
1263 .extract_str(linesep)
1264 .ok();
1265}
1266
1267bool
1268lua_hooks::hook_get_charset_conv(file_path const & p,
1269 std::string & db,
1270 std::string & ext)
1271{
1272 Lua ll(st);
1273 ll
1274 .func("get_charset_conv")
1275 .push_str(p.as_external())
1276 .call(1,1)
1277 .begin();
1278
1279 ll.next();
1280 ll.extract_str(db).pop();
1281
1282 ll.next();
1283 ll.extract_str(ext).pop();
1284 return ll.ok();
1285}
1286
1287bool
1288lua_hooks::hook_get_linesep_conv(file_path const & p,
1289 std::string & db,
1290 std::string & ext)
1291{
1292 Lua ll(st);
1293 ll
1294 .func("get_linesep_conv")
1295 .push_str(p.as_external())
1296 .call(1,1)
1297 .begin();
1298
1299 ll.next();
1300 ll.extract_str(db).pop();
1301
1302 ll.next();
1303 ll.extract_str(ext).pop();
1304 return ll.ok();
1305}
1306
1307bool
1308lua_hooks::hook_note_commit(revision_id const & new_id,
1309 revision_data const & rdat,
1310 map<cert_name, cert_value> const & certs)
1311{
1312 Lua ll(st);
1313 ll
1314 .func("note_commit")
1315 .push_str(new_id.inner()())
1316 .push_str(rdat.inner()());
1317
1318 ll.push_table();
1319
1320 for (map<cert_name, cert_value>::const_iterator i = certs.begin();
1321 i != certs.end(); ++i)
1322 {
1323 ll.push_str(i->first());
1324 ll.push_str(i->second());
1325 ll.set_table();
1326 }
1327
1328 ll.call(3, 0);
1329 return ll.ok();
1330}
1331
1332bool
1333lua_hooks::hook_note_netsync_revision_received(revision_id const & new_id,
1334 revision_data const & rdat,
1335 set<pair<rsa_keypair_id,
1336 pair<cert_name,
1337 cert_value> > > const & certs)
1338{
1339 Lua ll(st);
1340 ll
1341 .func("note_netsync_revision_received")
1342 .push_str(new_id.inner()())
1343 .push_str(rdat.inner()());
1344
1345 ll.push_table();
1346
1347 typedef set<pair<rsa_keypair_id, pair<cert_name, cert_value> > > cdat;
1348
1349 int n=0;
1350 for (cdat::const_iterator i = certs.begin(); i != certs.end(); ++i)
1351 {
1352 ll.push_int(n++);
1353 ll.push_table();
1354 ll.push_str("key");
1355 ll.push_str(i->first());
1356 ll.set_table();
1357 ll.push_str("name");
1358 ll.push_str(i->second.first());
1359 ll.set_table();
1360 ll.push_str("value");
1361 ll.push_str(i->second.second());
1362 ll.set_table();
1363 ll.set_table();
1364 }
1365
1366 ll.call(3, 0);
1367 return ll.ok();
1368}
1369
1370bool
1371lua_hooks::hook_note_netsync_pubkey_received(rsa_keypair_id const & kid)
1372{
1373 Lua ll(st);
1374 ll
1375 .func("note_netsync_pubkey_received")
1376 .push_str(kid());
1377
1378 ll.call(1, 0);
1379 return ll.ok();
1380}
1381
1382bool
1383lua_hooks::hook_note_netsync_cert_received(revision_id const & rid,
1384 rsa_keypair_id const & kid,
1385 cert_name const & name,
1386 cert_value const & value)
1387{
1388 Lua ll(st);
1389 ll
1390 .func("note_netsync_cert_received")
1391 .push_str(rid.inner()())
1392 .push_str(kid())
1393 .push_str(name())
1394 .push_str(value());
1395
1396 ll.call(4, 0);
1397 return ll.ok();
1398}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status