From 5ba64a437938b549df7809517cb31e8db3b4724a Mon Sep 17 00:00:00 2001 From: Peter Melnichenko Date: Tue, 12 Jul 2016 15:28:38 +0300 Subject: [PATCH] Implement activation scripts for POSIX-enough shells When creating an environment write activation scripts into $PREFIX/bin. An activation script, when sourced, adds $PREFIX/bin to $PATH and adds 'deactivate-lua' function that removes it. Activating an environment automatically deactivates previous one. Supported shells: * bash, zsh, dash: $PREFIX/bin/activate * fish: $PREFIX/bin/activate.fish * csh, tcsh: $PREFIX/bin/activate.csh Also fixed compilation error for location paths containing double quotes. TODO: add activation scripts for Windoss (powershell and batch). Ref #23. --- hererocks.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++-- setup.cfg | 3 +- 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/hererocks.py b/hererocks.py index 7857621..dda3a8a 100755 --- a/hererocks.py +++ b/hererocks.py @@ -37,6 +37,97 @@ __all__ = ["main"] opts = None temp_dir = None +activation_script_templates = { + "get_deactivated_path.lua": """ + local path = os.getenv("PATH") + local hererocks_path = "#LOCATION_DQ#/bin" + local new_path_parts = {} + local for_fish = arg[1] == "--fish" + + if for_fish then + io.stdout:write("set -gx PATH ") + end + + for path_part in (path .. ":"):gmatch("([^:]*):") do + if path_part ~= hererocks_path then + if for_fish then + path_part = "'" .. path_part:gsub("'", [['\'']]) .. "'" + end + + table.insert(new_path_parts, path_part) + end + end + + io.stdout:write(table.concat(new_path_parts, for_fish and " " or ":")) + """, + "activate": """ + if declare -f -F deactivate-lua >/dev/null; then + deactivate-lua + fi + + deactivate-lua () { + if [ -x '#LOCATION_SQ#/bin/lua' ]; then + PATH=`'#LOCATION_SQ#/bin/lua' '#LOCATION_SQ#/bin/get_deactivated_path.lua'` + export PATH + + # Need to rehash under bash and zsh so that new PATH is taken into account. + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ]; then + hash -r 2>/dev/null + fi + fi + + unset -f deactivate-lua + } + + PATH='#LOCATION_SQ#/bin':"$PATH" + export PATH + + # As in deactivate-lua, rehash after changing PATH. + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ]; then + hash -r 2>/dev/null + fi + """, + "activate.csh": """ + which deactivate-lua >&/dev/null && deactivate-lua + + alias deactivate-lua 'if ( -x '\\''#LOCATION_NESTED_SQ#/bin/lua'\\'' ) then; setenv PATH `'\\''#LOCATION_NESTED_SQ#/bin/lua'\\'' '\\''#LOCATION_NESTED_SQ#/bin/get_deactivated_path.lua'\\''`; rehash; endif; unalias deactivate-lua' + + setenv PATH '#LOCATION_SQ#/bin':"$PATH" + rehash + """, + "activate.fish": """ + if functions -q deactivate-lua + deactivate-lua + end + + function deactivate-lua + if test -x '#LOCATION_SQ#/bin/lua' + eval ('#LOCATION_SQ#/bin/lua' '#LOCATION_SQ#/bin/get_deactivated_path.lua' --fish) + end + + functions -e deactivate-lua + end + + set -gx PATH '#LOCATION_SQ#/bin' $PATH + """ +} + +def write_activation_scripts(): + template_names = ["get_deactivated_path.lua", "activate", "activate.csh", "activate.fish"] + + replacements = { + "LOCATION_DQ": opts.location.replace("\\", "\\\\").replace('"', '\\"'), + "LOCATION_SQ": opts.location.replace("'", "'\\''"), + "LOCATION_NESTED_SQ": opts.location.replace("'", "'\\''").replace("'", "'\\''") + } + + for template_name in template_names: + with open(os.path.join(opts.location, "bin", template_name), "w") as script_handle: + template = activation_script_templates[template_name][1:] + template = textwrap.dedent(template) + script = re.sub(r'#([a-zA-Z_]+)#', lambda match: replacements[match.group(1)], template) + script_handle.write(script) + def is_executable(path): return (os.path.exists(path) and os.access(path, os.F_OK | os.X_OK) and @@ -551,8 +642,8 @@ class Lua(Program): self.package_cpath = ";".join(cmodule_path_parts) def add_package_paths_redefines(self): - package_path = self.package_path.replace("\\", "\\\\") - package_cpath = self.package_cpath.replace("\\", "\\\\") + package_path = self.package_path.replace("\\", "\\\\").replace('"', '\\"') + package_cpath = self.package_cpath.replace("\\", "\\\\").replace('"', '\\"') self.redefines.extend([ "#undef LUA_PATH_DEFAULT", "#undef LUA_CPATH_DEFAULT", @@ -1710,6 +1801,8 @@ def main(argv=None): if not os.path.exists(opts.location): os.makedirs(opts.location) + write_activation_scripts() + if opts.lua: if "LuaJIT" in identifiers: del identifiers["LuaJIT"] diff --git a/setup.cfg b/setup.cfg index a9fa730..bd1dcaf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,2 @@ [pep8] -ignore = E203,E302 -max-line-length = 119 +ignore = E203,E302,E501