diff -up -urwbB monotone-0.18-orig/lua.cc monotone-0.18/lua.cc --- monotone-0.18-orig/lua.cc 2005-03-26 00:35:32.000000000 -0500 +++ monotone-0.18/lua.cc 2005-04-18 08:35:58.000000000 -0400 @@ -89,6 +89,14 @@ extern "C" } static int + monotone_is_executable_for_lua(lua_State *L) + { + const char *path = lua_tostring(L, -1); + lua_pushboolean(L, is_executable(path)); + return 1; + } + + static int monotone_make_executable_for_lua(lua_State *L) { const char *path = lua_tostring(L, -1); @@ -168,6 +176,7 @@ lua_hooks::lua_hooks() // add monotone-specific functions lua_register(st, "mkstemp", monotone_mkstemp_for_lua); lua_register(st, "existsonpath", monotone_existsonpath_for_lua); + lua_register(st, "is_executable", monotone_is_executable_for_lua); lua_register(st, "make_executable", monotone_make_executable_for_lua); lua_register(st, "spawn", monotone_spawn_for_lua); lua_register(st, "wait", monotone_wait_for_lua); @@ -918,6 +927,21 @@ lua_hooks::hook_get_netsync_write_permit return exec_ok && permitted; } +bool +lua_hooks::hook_init_attributes(string const & attr, + file_path const & filename, + std::string & value) +{ + return Lua(st) + .push_str("attr_init_functions") + .get_tab() + .push_str(attr) + .get_fn(-2) + .push_str(filename()) + .call(1,1) + .extract_str(value) + .ok(); +} bool lua_hooks::hook_apply_attribute(string const & attr, diff -up -urwbB monotone-0.18-orig/lua.hh monotone-0.18/lua.hh --- monotone-0.18-orig/lua.hh 2005-03-26 00:35:32.000000000 -0500 +++ monotone-0.18/lua.hh 2005-04-18 08:35:00.000000000 -0400 @@ -95,6 +95,9 @@ public: file_path & res); // attribute hooks + bool hook_init_attributes(std::string const & attr, + file_path const & filename, + std::string & value); bool hook_apply_attribute(std::string const & attr, file_path const & filename, std::string const & value); diff -up -urwbB monotone-0.18-orig/platform.hh monotone-0.18/platform.hh --- monotone-0.18-orig/platform.hh 2005-04-14 22:33:58.000000000 -0400 +++ monotone-0.18/platform.hh 2005-04-17 21:51:53.000000000 -0400 @@ -15,6 +15,7 @@ void read_password(std::string const & prompt, char * buf, size_t bufsz); void get_system_flavour(std::string & ident); +bool is_executable(const char *path); // For LUA int existsonpath(const char *exe); diff -up -urwbB monotone-0.18-orig/std_hooks.lua monotone-0.18/std_hooks.lua --- monotone-0.18-orig/std_hooks.lua 2005-03-26 00:35:32.000000000 -0500 +++ monotone-0.18/std_hooks.lua 2005-04-18 08:38:46.000000000 -0400 @@ -28,6 +28,19 @@ end -- manifest). each (f,k,v) triple in an atribute file turns into a -- call to attr_functions[k](f,v) in lua. +if (attr_init_functions == nil) then + attr_init_functions = {} +end + +attr_init_functions["execute"] = + function(filename) + if (is_executable(filename)) then + return "true" + else + return nil + end + end + if (attr_functions == nil) then attr_functions = {} end diff -up -urwbB monotone-0.18-orig/unix/process.cc monotone-0.18/unix/process.cc --- monotone-0.18-orig/unix/process.cc 2005-04-14 22:33:58.000000000 -0400 +++ monotone-0.18/unix/process.cc 2005-04-14 22:38:22.000000000 -0400 @@ -29,6 +29,16 @@ int existsonpath(const char *exe) return -1; } +bool is_executable(const char *path) +{ + struct stat s; + + int rc = stat(path, &s); + N(rc != -1, F("stat() error on file %s)") % path); + + return s.st_mode & S_IXUSR; +} + int make_executable(const char *path) { mode_t mode; diff -up -urwbB monotone-0.18-orig/win32/process.cc monotone-0.18/win32/process.cc --- monotone-0.18-orig/win32/process.cc 2005-04-14 22:33:58.000000000 -0400 +++ monotone-0.18/win32/process.cc 2005-04-14 19:58:32.000000000 -0400 @@ -16,6 +16,11 @@ int existsonpath(const char *exe) return 0; } +bool is_executable(const char *path) +{ + return false; /* Basically meaningless on win32 */ +} + int make_executable(const char *path) { return 0; /* Basically meaningless on win32 */ diff -up -urwbB monotone-0.18-orig/work.cc monotone-0.18/work.cc --- monotone-0.18-orig/work.cc 2005-04-14 22:33:58.000000000 -0400 +++ monotone-0.18/work.cc 2005-04-18 08:51:03.000000000 -0400 @@ -29,11 +29,13 @@ addition_builder app_state & app; change_set::path_rearrangement & pr; path_set ps; + path_set & ps_executable; public: addition_builder(app_state & a, change_set::path_rearrangement & pr, - path_set & p) - : app(a), pr(pr), ps(p) + path_set & p, + path_set & pe) + : app(a), pr(pr), ps(p), ps_executable(pe) {} virtual void visit_file(file_path const & path); }; @@ -56,6 +58,12 @@ addition_builder::visit_file(file_path c P(F("adding %s to working copy add set\n") % path); ps.insert(path); pr.added_files.insert(path); + + std::string value; + if (app.lua.hook_init_attributes ("execute", path, value)) + { + if (value == "true") ps_executable.insert (path); + } } void @@ -68,10 +76,11 @@ build_additions(vector const change_set cs_new; path_set ps; + path_set ps_executable; extract_path_set(man, ps); apply_path_rearrangement(pr, ps); - addition_builder build(app, pr_new, ps); + addition_builder build(app, pr_new, ps, ps_executable); for (vector::const_iterator i = paths.begin(); i != paths.end(); ++i) { @@ -82,6 +91,42 @@ build_additions(vector const walk_tree(*i, build); } + if (ps_executable.size () > 0) + { + // add .mt-attrs to manifest if not already registered + file_path attr_path; + get_attr_path(attr_path); + + if ((man.find(attr_path) == man.end ()) && + (pr_new.added_files.find(attr_path) == pr_new.added_files.end())) + { + P(F("registering %s file in working copy\n") % attr_path); + pr.added_files.insert(attr_path); + } + + // read attribute map if available + data attr_data; + attr_map attrs; + + if (file_exists(attr_path)) + { + read_data(attr_path, attr_data); + read_attr_map(attr_data, attrs); + } + + // add new execute entries + for (path_set::const_iterator i = ps_executable.begin(); + i != ps_executable.end(); ++i) + { + P(F("adding executable file %s to .mt_attrs\n") % (*i)); + attrs[(*i)]["execute"] = "true"; + } + + // write out updated map + write_attr_map(attr_data, attrs); + write_data(attr_path, attr_data); + } + normalize_path_rearrangement(pr_new); concatenate_rearrangements(pr, pr_new, pr_concatenated); pr = pr_concatenated;