monotone

monotone Mtn Source Tree

Root/lua.cc

1// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
2// all rights reserved.
3// licensed to the public under the terms of the GNU GPL (>= 2)
4// see the file COPYING for details
5
6#include "config.h"
7
8extern "C" {
9#include <lua.h>
10#include <lualib.h>
11}
12
13#include <errno.h>
14#include <stdlib.h>
15#include <string.h>
16#include <stdarg.h>
17#include <signal.h>
18#include <boost/lexical_cast.hpp>
19#include <boost/filesystem/path.hpp>
20#include <boost/filesystem/operations.hpp>
21
22#include <set>
23#include <map>
24
25#include "app_state.hh"
26#include "file_io.hh"
27#include "lua.hh"
28#include "mkstemp.hh"
29#include "sanity.hh"
30#include "vocab.hh"
31#include "platform.hh"
32
33// defined in {std,test}_hooks.lua, converted
34#include "test_hooks.h"
35#include "std_hooks.h"
36
37using namespace std;
38using boost::lexical_cast;
39
40/*
41static int panic_thrower(lua_State * st)
42{
43 throw oops("lua panic");
44}
45*/
46
47extern "C"
48{
49 static int
50 monotone_mkstemp_for_lua(lua_State *L)
51 {
52 int fd = -1;
53 FILE **pf = NULL;
54 char const *filename = lua_tostring (L, -1);
55 std::string dup(filename);
56
57 fd = monotone_mkstemp(dup);
58
59 if (fd == -1)
60 return 0;
61
62 // this magic constructs a lua object which the lua io library
63 // will enjoy working with
64 pf = static_cast<FILE **>(lua_newuserdata(L, sizeof(FILE *)));
65 *pf = fdopen(fd, "r+");
66 lua_pushstring(L, "FILE*");
67 lua_rawget(L, LUA_REGISTRYINDEX);
68 lua_setmetatable(L, -2);
69
70 lua_pushstring(L, dup.c_str());
71
72 if (*pf == NULL)
73 {
74 lua_pushnil(L);
75 lua_pushfstring(L, "%s", strerror(errno));
76 lua_pushnumber(L, errno);
77 return 3;
78 }
79 else
80 return 2;
81 }
82
83 static int
84 monotone_existsonpath_for_lua(lua_State *L)
85 {
86 const char *exe = lua_tostring(L, -1);
87 lua_pushnumber(L, existsonpath(exe));
88 return 1;
89 }
90
91 static int
92 monotone_is_executable_for_lua(lua_State *L)
93 {
94 const char *path = lua_tostring(L, -1);
95 lua_pushboolean(L, is_executable(path));
96 return 1;
97 }
98
99 static int
100 monotone_make_executable_for_lua(lua_State *L)
101 {
102 const char *path = lua_tostring(L, -1);
103 lua_pushnumber(L, make_executable(path));
104 return 1;
105 }
106
107 static int
108 monotone_spawn_for_lua(lua_State *L)
109 {
110 int n = lua_gettop(L);
111 const char *path = lua_tostring(L, -n);
112 char **argv = (char**)malloc((n+1)*sizeof(char*));
113 int ret, i;
114 if (argv==NULL)
115 return 0;
116 argv[0] = (char*)path;
117 for (i=1; i<n; i++) argv[i] = (char*)lua_tostring(L, -(n - i));
118 argv[i] = NULL;
119 ret = process_spawn(argv);
120 free(argv);
121 lua_pushnumber(L, ret);
122 return 1;
123 }
124
125 static int
126 monotone_wait_for_lua(lua_State *L)
127 {
128 int pid = (int)lua_tonumber(L, -1);
129 int res;
130 int ret;
131 ret = process_wait(pid, &res);
132 lua_pushnumber(L, res);
133 lua_pushnumber(L, ret);
134 return 2;
135 }
136
137 static int
138 monotone_kill_for_lua(lua_State *L)
139 {
140 int n = lua_gettop(L);
141 int pid = (int)lua_tonumber(L, -2);
142 int sig;
143 if (n>1)
144 sig = (int)lua_tonumber(L, -1);
145 else
146 sig = SIGTERM;
147 lua_pushnumber(L, process_kill(pid, sig));
148 return 1;
149 }
150
151 static int
152 monotone_sleep_for_lua(lua_State *L)
153 {
154 int seconds = (int)lua_tonumber(L, -1);
155 lua_pushnumber(L, process_sleep(seconds));
156 return 1;
157 }
158}
159
160
161lua_hooks::lua_hooks()
162{
163 st = lua_open ();
164 I(st);
165
166 // no atpanic support in 4.x
167 // lua_atpanic (st, &panic_thrower);
168
169 luaopen_base(st);
170 luaopen_io(st);
171 luaopen_string(st);
172 luaopen_math(st);
173 luaopen_table(st);
174 luaopen_debug(st);
175
176 // add monotone-specific functions
177 lua_register(st, "mkstemp", monotone_mkstemp_for_lua);
178 lua_register(st, "existsonpath", monotone_existsonpath_for_lua);
179 lua_register(st, "is_executable", monotone_is_executable_for_lua);
180 lua_register(st, "make_executable", monotone_make_executable_for_lua);
181 lua_register(st, "spawn", monotone_spawn_for_lua);
182 lua_register(st, "wait", monotone_wait_for_lua);
183 lua_register(st, "kill", monotone_kill_for_lua);
184 lua_register(st, "sleep", monotone_sleep_for_lua);
185}
186
187lua_hooks::~lua_hooks()
188{
189 if (st)
190 lua_close (st);
191}
192
193
194// This Lua object represents a single imperative transaction with the lua
195// interpreter. if it fails at any point, all further commands in the
196// transaction are ignored. it cleans the lua stack up when it is
197// destructed, so no need to pop values when you're done.
198
199struct
200Lua
201{
202 lua_State * st;
203 bool failed;
204 static std::set<string> missing_functions;
205
206 Lua(lua_State * s) :
207 st(s), failed(false)
208 {}
209
210 ~Lua()
211 {
212 lua_settop(st, 0);
213 }
214
215 bool ok()
216 {
217 return !failed;
218 }
219
220 // getters
221
222 Lua & get(int idx = LUA_GLOBALSINDEX)
223 {
224 if (failed) return *this;
225 if (!lua_istable (st, idx))
226 {
227 L(F("lua istable() failed\n"));
228 failed = true;
229 return *this;
230 }
231 if (lua_gettop (st) < 1)
232 {
233 L(F("lua stack top > 0 failed\n"));
234 failed = true;
235 return *this;
236 }
237 lua_gettable(st, idx);
238 return *this;
239 }
240
241 Lua & get_fn(int idx = LUA_GLOBALSINDEX)
242 {
243 if (failed) return *this;
244 get(idx);
245 if (!lua_isfunction (st, -1))
246 {
247 L(F("lua isfunction() failed in get_fn\n"));
248 failed = true;
249 }
250 return *this;
251 }
252
253 Lua & get_tab(int idx = LUA_GLOBALSINDEX)
254 {
255 if (failed) return *this;
256 get(idx);
257 if (!lua_istable (st, -1))
258 {
259 L(F("lua istable() failed in get_tab\n"));
260 failed = true;
261 }
262 return *this;
263 }
264
265 Lua & get_str(int idx = LUA_GLOBALSINDEX)
266 {
267 if (failed) return *this;
268 get(idx);
269 if (!lua_isstring (st, -1))
270 {
271 L(F("lua isstring() failed in get_str\n"));
272 failed = true;
273 }
274 return *this;
275 }
276
277 Lua & get_num(int idx = LUA_GLOBALSINDEX)
278 {
279 if (failed) return *this;
280 get(idx);
281 if (!lua_isnumber (st, -1))
282 {
283 L(F("lua isnumber() failed in get_num\n"));
284 failed = true;
285 }
286 return *this;
287 }
288
289 Lua & get_bool(int idx = LUA_GLOBALSINDEX)
290 {
291 if (failed) return *this;
292 get(idx);
293 if (!lua_isboolean (st, -1))
294 {
295 L(F("lua isboolean() failed in get_bool\n"));
296 failed = true;
297 }
298 return *this;
299 }
300
301 // extractors
302
303 Lua & extract_str(string & str)
304 {
305 if (failed) return *this;
306 if (!lua_isstring (st, -1))
307 {
308 L(F("lua isstring() failed in extract_str\n"));
309 failed = true;
310 return *this;
311 }
312 str = string(lua_tostring(st, -1), lua_strlen(st, -1));
313 return *this;
314 }
315
316 Lua & extract_int(int & i)
317 {
318 if (failed) return *this;
319 if (!lua_isnumber (st, -1))
320 {
321 L(F("lua isnumber() failed in extract_int\n"));
322 failed = true;
323 return *this;
324 }
325 i = static_cast<int>(lua_tonumber(st, -1));
326 return *this;
327 }
328
329 Lua & extract_double(double & i)
330 {
331 if (failed) return *this;
332 if (!lua_isnumber (st, -1))
333 {
334 L(F("lua isnumber() failed in extract_double\n"));
335 failed = true;
336 return *this;
337 }
338 i = lua_tonumber(st, -1);
339 return *this;
340 }
341
342
343 Lua & extract_bool(bool & i)
344 {
345 if (failed) return *this;
346 if (!lua_isboolean (st, -1))
347 {
348 L(F("lua isboolean() failed in extract_bool\n"));
349 failed = true;
350 return *this;
351 }
352 i = (lua_toboolean(st, -1) == 1);
353 return *this;
354 }
355
356
357 // table iteration
358
359 Lua & begin()
360 {
361 if (failed) return *this;
362 if (!lua_istable(st, -1))
363 {
364 L(F("lua istable() failed in begin\n"));
365 failed = true;
366 return *this;
367 }
368 I(lua_checkstack (st, 1));
369 lua_pushnil(st);
370 return *this;
371 }
372
373 bool next()
374 {
375 if (failed) return false;
376 if (!lua_istable(st, -2))
377 {
378 L(F("lua istable() failed in next\n"));
379 failed = true;
380 return false;
381 }
382 I(lua_checkstack (st, 1));
383 if (lua_next(st, -2) != 0)
384 {
385 return true;
386 }
387 pop();
388 return false;
389 }
390
391 // pushers
392
393 Lua & push_str(string const & str)
394 {
395 if (failed) return *this;
396 I(lua_checkstack (st, 1));
397 lua_pushlstring(st, str.c_str(), str.size());
398 return *this;
399 }
400
401 Lua & push_int(int num)
402 {
403 if (failed) return *this;
404 I(lua_checkstack (st, 1));
405 lua_pushnumber(st, num);
406 return *this;
407 }
408
409 Lua & push_int(double num)
410 {
411 if (failed) return *this;
412 I(lua_checkstack (st, 1));
413 lua_pushnumber(st, num);
414 return *this;
415 }
416
417 Lua & push_bool(bool b)
418 {
419 if (failed) return *this;
420 I(lua_checkstack (st, 1));
421 lua_pushboolean(st, b);
422 return *this;
423 }
424
425 Lua & push_nil()
426 {
427 if (failed) return *this;
428 I(lua_checkstack (st, 1));
429 lua_pushnil(st);
430 return *this;
431 }
432
433 Lua & push_table()
434 {
435 if (failed) return *this;
436 I(lua_checkstack (st, 1));
437 lua_newtable(st);
438 return *this;
439 }
440
441 Lua & set_table(int idx = -3)
442 {
443 if (failed) return *this;
444 I(lua_checkstack (st, 1));
445 lua_settable(st, idx);
446 return *this;
447 }
448
449
450 Lua & call(int in, int out)
451 {
452 if (failed) return *this;
453 I(lua_checkstack (st, out));
454 if (lua_pcall(st, in, out, 0) != 0)
455 {
456 I(lua_isstring (st, -1));
457 string err = string(lua_tostring(st, -1), lua_strlen(st, -1));
458 L(F("lua pcall() failed: %s\n") % err);
459 lua_pop(st, 1);
460 failed = true;
461 }
462 return *this;
463 }
464
465 Lua & pop(int count = 1)
466 {
467 if (failed) return *this;
468 if (lua_gettop (st) < count)
469 {
470 L(F("lua stack top >= count failed\n"));
471 failed = true;
472 return *this;
473 }
474 lua_pop(st, count);
475 return *this;
476 }
477
478 Lua & func(string const & fname)
479 {
480 if (!failed)
481 {
482if (missing_functions.find(fname) != missing_functions.end())
483 failed = true;
484else
485 {
486 push_str(fname);
487 get_fn();
488 if (failed)
489 missing_functions.insert(fname);
490 }
491 }
492 return *this;
493 }
494
495};
496
497std::set<string> Lua::missing_functions;
498
499static bool
500run_string(lua_State * st, string const &str)
501{
502 I(st);
503 return
504 Lua(st)
505 .func("loadstring")
506 .push_str(str)
507 .call(1,1)
508 .call(0,0)
509 .ok();
510}
511
512static bool
513run_file(lua_State * st, string const &filename)
514{
515 I(st);
516 return
517 Lua(st)
518 .func("loadfile")
519 .push_str(filename)
520 .call(1,1)
521 .call(0,0)
522 .ok();
523}
524
525
526#ifdef BUILD_UNIT_TESTS
527void
528lua_hooks::add_test_hooks()
529{
530 if (!run_string(st, test_hooks_constant))
531 throw oops("lua error while setting up testing hooks");
532}
533#endif
534
535void
536lua_hooks::add_std_hooks()
537{
538 if (!run_string(st, std_hooks_constant))
539 throw oops("lua error while setting up standard hooks");
540}
541
542void
543lua_hooks::default_rcfilename(fs::path & file)
544{
545 file = mkpath(get_homedir()) / mkpath(".monotone/monotonerc");
546}
547
548void
549lua_hooks::working_copy_rcfilename(fs::path & file)
550{
551 file = mkpath(book_keeping_dir) / mkpath("monotonerc");
552}
553
554
555void
556lua_hooks::load_rcfile(fs::path const & rc, bool required)
557{
558 I(st);
559 if (fs::exists(rc))
560 {
561 L(F("opening rcfile '%s' ...\n") % rc.string());
562 N(run_file(st, rc.string()),
563 F("lua error while loading '%s'") % rc.string());
564 L(F("'%s' is ok\n") % rc.string());
565 }
566 else
567 {
568 N(!required, F("rcfile '%s' does not exist") % rc.string());
569 L(F("skipping nonexistent rcfile '%s'\n") % rc.string());
570 }
571}
572
573
574// concrete hooks
575
576// nb: if you're hooking lua to return your passphrase, you don't care if we
577// keep a couple extra temporaries of your passphrase around.
578bool
579lua_hooks::hook_get_passphrase(rsa_keypair_id const & k, string & phrase)
580{
581 return Lua(st)
582 .func("get_passphrase")
583 .push_str(k())
584 .call(1,1)
585 .extract_str(phrase)
586 .ok();
587}
588
589bool
590lua_hooks::hook_persist_phrase_ok()
591{
592 bool persist_ok = false;
593 bool executed_ok = Lua(st)
594 .func("persist_phrase_ok")
595 .call(0,1)
596 .extract_bool(persist_ok)
597 .ok();
598 return executed_ok && persist_ok;
599}
600
601bool
602lua_hooks::hook_expand_selector(std::string const & sel,
603 std::string & exp)
604{
605 return Lua(st)
606 .func("expand_selector")
607 .push_str(sel)
608 .call(1,1)
609 .extract_str(exp)
610 .ok();
611}
612
613bool
614lua_hooks::hook_get_branch_key(cert_value const & branchname,
615 rsa_keypair_id & k)
616{
617 string key;
618 bool ok = Lua(st)
619 .func("get_branch_key")
620 .push_str(branchname())
621 .call(1,1)
622 .extract_str(key)
623 .ok();
624
625 k = key;
626 return ok;
627}
628
629bool
630lua_hooks::hook_get_priv_key(rsa_keypair_id const & k,
631 base64< arc4<rsa_priv_key> > & priv_key )
632{
633 string key;
634 bool ok = Lua(st)
635 .func("get_priv_key")
636 .push_str(k())
637 .call(1,1)
638 .extract_str(key)
639 .ok();
640
641 priv_key = key;
642 return ok;
643}
644
645bool
646lua_hooks::hook_get_author(cert_value const & branchname,
647 string & author)
648{
649 return Lua(st)
650 .func("get_author")
651 .push_str(branchname())
652 .call(1,1)
653 .extract_str(author)
654 .ok();
655}
656
657bool
658lua_hooks::hook_edit_comment(string const & commentary,
659 string const & user_log_message,
660 string & result)
661{
662 return Lua(st)
663 .func("edit_comment")
664 .push_str(commentary)
665 .push_str(user_log_message)
666 .call(2,1)
667 .extract_str(result)
668 .ok();
669}
670
671bool
672lua_hooks::hook_ignore_file(file_path const & p)
673{
674 bool ignore_it = false;
675 bool exec_ok = Lua(st)
676 .func("ignore_file")
677 .push_str(p())
678 .call(1,1)
679 .extract_bool(ignore_it)
680 .ok();
681 return exec_ok && ignore_it;
682}
683
684bool
685lua_hooks::hook_ignore_branch(std::string const & branch)
686{
687 bool ignore_it = false;
688 bool exec_ok = Lua(st)
689 .func("ignore_branch")
690 .push_str(branch)
691 .call(1,1)
692 .extract_bool(ignore_it)
693 .ok();
694 return exec_ok && ignore_it;
695}
696
697bool
698lua_hooks::hook_non_blocking_rng_ok()
699{
700 bool ok = false;
701 bool exec_ok = Lua(st)
702 .func("non_blocking_rng_ok")
703 .call(0,1)
704 .extract_bool(ok)
705 .ok();
706 return exec_ok && ok;
707}
708
709static inline bool
710shared_trust_function_body(Lua & ll,
711 std::set<rsa_keypair_id> const & signers,
712 hexenc<id> const & id,
713 cert_name const & name,
714 cert_value const & val)
715{
716 ll.push_table();
717
718 int k = 0;
719 for (set<rsa_keypair_id>::const_iterator v = signers.begin();
720 v != signers.end(); ++v)
721 {
722 ll.push_int(k);
723 ll.push_str((*v)());
724 ll.set_table();
725 ++k;
726 }
727
728 bool ok;
729 bool exec_ok = ll
730 .push_str(id())
731 .push_str(name())
732 .push_str(val())
733 .call(4, 1)
734 .extract_bool(ok)
735 .ok();
736
737 return exec_ok && ok;
738}
739
740bool
741lua_hooks::hook_get_revision_cert_trust(std::set<rsa_keypair_id> const & signers,
742 hexenc<id> const & id,
743 cert_name const & name,
744 cert_value const & val)
745{
746 Lua ll(st);
747 ll.func("get_revision_cert_trust");
748 return shared_trust_function_body(ll, signers, id, name, val);
749}
750
751bool
752lua_hooks::hook_get_manifest_cert_trust(std::set<rsa_keypair_id> const & signers,
753 hexenc<id> const & id,
754 cert_name const & name,
755 cert_value const & val)
756{
757 Lua ll(st);
758 ll.func("get_manifest_cert_trust");
759 return shared_trust_function_body(ll, signers, id, name, val);
760}
761
762bool
763lua_hooks::hook_accept_testresult_change(map<rsa_keypair_id, bool> const & old_results,
764 map<rsa_keypair_id, bool> const & new_results)
765{
766 Lua ll(st);
767 ll
768 .func("accept_testresult_change")
769 .push_table();
770
771 for (map<rsa_keypair_id, bool>::const_iterator i = old_results.begin();
772 i != old_results.end(); ++i)
773 {
774 ll.push_str(i->first());
775 ll.push_bool(i->second);
776 ll.set_table();
777 }
778
779 ll.push_table();
780
781 for (map<rsa_keypair_id, bool>::const_iterator i = new_results.begin();
782 i != new_results.end(); ++i)
783 {
784 ll.push_str(i->first());
785 ll.push_bool(i->second);
786 ll.set_table();
787 }
788
789 bool ok;
790 bool exec_ok = ll
791 .call(2, 1)
792 .extract_bool(ok)
793 .ok();
794
795 return exec_ok && ok;
796}
797
798
799
800bool
801lua_hooks::hook_merge2(file_path const & left_path,
802 file_path const & right_path,
803 file_path const & merged_path,
804 data const & left,
805 data const & right,
806 data & result)
807{
808 string res;
809 bool ok = Lua(st)
810 .func("merge2")
811 .push_str(left_path())
812 .push_str(right_path())
813 .push_str(merged_path())
814 .push_str(left())
815 .push_str(right())
816 .call(5,1)
817 .extract_str(res)
818 .ok();
819 result = res;
820 return ok;
821}
822
823bool
824lua_hooks::hook_merge3(file_path const & anc_path,
825 file_path const & left_path,
826 file_path const & right_path,
827 file_path const & merged_path,
828 data const & ancestor,
829 data const & left,
830 data const & right,
831 data & result)
832{
833 string res;
834 bool ok = Lua(st)
835 .func("merge3")
836 .push_str(anc_path())
837 .push_str(left_path())
838 .push_str(right_path())
839 .push_str(merged_path())
840 .push_str(ancestor())
841 .push_str(left())
842 .push_str(right())
843 .call(7,1)
844 .extract_str(res)
845 .ok();
846 result = res;
847 return ok;
848}
849
850bool
851lua_hooks::hook_resolve_file_conflict(file_path const & anc,
852 file_path const & a,
853 file_path const & b,
854 file_path & res)
855{
856 string tmp;
857 bool ok = Lua(st)
858 .func("resolve_file_conflict")
859 .push_str(anc())
860 .push_str(a())
861 .push_str(b())
862 .call(3,1)
863 .extract_str(tmp)
864 .ok();
865 res = tmp;
866 return ok;
867}
868
869bool
870lua_hooks::hook_resolve_dir_conflict(file_path const & anc,
871 file_path const & a,
872 file_path const & b,
873 file_path & res)
874{
875 string tmp;
876 bool ok = Lua(st)
877 .func("resolve_dir_conflict")
878 .push_str(anc())
879 .push_str(a())
880 .push_str(b())
881 .call(3,1)
882 .extract_str(tmp)
883 .ok();
884 res = tmp;
885 return ok;
886}
887
888
889bool
890lua_hooks::hook_use_inodeprints()
891{
892 bool use = false, exec_ok = false;
893
894 exec_ok = Lua(st)
895 .func("use_inodeprints")
896 .call(0, 1)
897 .extract_bool(use)
898 .ok();
899 return use && exec_ok;
900}
901
902bool
903lua_hooks::hook_get_netsync_read_permitted(std::string const & collection,
904 rsa_keypair_id const & identity)
905{
906 bool permitted = false, exec_ok = false;
907
908 exec_ok = Lua(st)
909 .func("get_netsync_read_permitted")
910 .push_str(collection)
911 .push_str(identity())
912 .call(2,1)
913 .extract_bool(permitted)
914 .ok();
915
916 return exec_ok && permitted;
917}
918
919bool
920lua_hooks::hook_get_netsync_anonymous_read_permitted(std::string const & collection)
921{
922 bool permitted = false, exec_ok = false;
923
924 exec_ok = Lua(st)
925 .func("get_netsync_anonymous_read_permitted")
926 .push_str(collection)
927 .call(1,1)
928 .extract_bool(permitted)
929 .ok();
930
931 return exec_ok && permitted;
932}
933
934bool
935lua_hooks::hook_get_netsync_write_permitted(std::string const & collection,
936 rsa_keypair_id const & identity)
937{
938 bool permitted = false, exec_ok = false;
939
940 exec_ok = Lua(st)
941 .func("get_netsync_write_permitted")
942 .push_str(collection)
943 .push_str(identity())
944 .call(2,1)
945 .extract_bool(permitted)
946 .ok();
947
948 return exec_ok && permitted;
949}
950
951bool
952lua_hooks::hook_init_attributes(file_path const & filename,
953 std::map<std::string, std::string> & attrs)
954{
955 Lua ll(st);
956
957 ll
958 .push_str("attr_init_functions")
959 .get_tab()
960 .push_nil();
961
962 while (ll.next())
963 {
964 ll.push_str(filename());
965 ll.call(1, 1);
966
967 if (lua_isstring(st, -1))
968 {
969 string key, value;
970
971 ll.extract_str(value);
972 ll.pop();
973 ll.extract_str(key);
974
975 attrs[key] = value;
976 }
977 else
978 ll.pop();
979 }
980
981 return ll.pop().ok();
982}
983
984bool
985lua_hooks::hook_apply_attribute(string const & attr,
986 file_path const & filename,
987 string const & value)
988{
989 return Lua(st)
990 .push_str("attr_functions")
991 .get_tab()
992 .push_str(attr)
993 .get_fn(-2)
994 .push_str(filename())
995 .push_str(value)
996 .call(2,0)
997 .ok();
998}
999
1000
1001bool
1002lua_hooks::hook_get_system_linesep(string & linesep)
1003{
1004 return Lua(st)
1005 .func("get_system_linesep")
1006 .call(0,1)
1007 .extract_str(linesep)
1008 .ok();
1009}
1010
1011bool
1012lua_hooks::hook_get_charset_conv(file_path const & p,
1013 std::string & db,
1014 std::string & ext)
1015{
1016 Lua ll(st);
1017 ll
1018 .func("get_charset_conv")
1019 .push_str(p())
1020 .call(1,1)
1021 .begin();
1022
1023 ll.next();
1024 ll.extract_str(db).pop();
1025
1026 ll.next();
1027 ll.extract_str(ext).pop();
1028 return ll.ok();
1029}
1030
1031bool
1032lua_hooks::hook_get_linesep_conv(file_path const & p,
1033 std::string & db,
1034 std::string & ext)
1035{
1036 Lua ll(st);
1037 ll
1038 .func("get_linesep_conv")
1039 .push_str(p())
1040 .call(1,1)
1041 .begin();
1042
1043 ll.next();
1044 ll.extract_str(db).pop();
1045
1046 ll.next();
1047 ll.extract_str(ext).pop();
1048 return ll.ok();
1049}
1050
1051bool
1052lua_hooks::hook_note_commit(revision_id const & new_id,
1053 map<cert_name, cert_value> const & certs)
1054{
1055 Lua ll(st);
1056 ll
1057 .func("note_commit")
1058 .push_str(new_id.inner()());
1059
1060 ll.push_table();
1061
1062 for (map<cert_name, cert_value>::const_iterator i = certs.begin();
1063 i != certs.end(); ++i)
1064 {
1065 ll.push_str(i->first());
1066 ll.push_str(i->second());
1067 ll.set_table();
1068 }
1069
1070 ll.call(2, 0);
1071 return ll.ok();
1072}

Archive Download this file

Branches

Tags

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