1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/dda514ffa5e9/ Changeset: dda514ffa5e9 User: greg Date: 2014-04-25 16:58:15 Summary: Add support for 3 new tool dependency installation recipe action tag types: assert_directory_exists, assert_file_exists and assert_file_executable. Affected #: 4 files diff -r 2edce562ccaa8bdd12e40b2263646f7b9cf93966 -r dda514ffa5e99b1b13bc3d88dbf35c1fb336742d lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py --- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py @@ -4,6 +4,8 @@ from galaxy import eggs eggs.require( 'Fabric' ) +eggs.require( 'ssh' ) +eggs.require( 'paramiko' ) from fabric.api import env from fabric.api import lcd diff -r 2edce562ccaa8bdd12e40b2263646f7b9cf93966 -r dda514ffa5e99b1b13bc3d88dbf35c1fb336742d lib/tool_shed/galaxy_install/tool_dependencies/recipe/recipe_manager.py --- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/recipe_manager.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/recipe_manager.py @@ -13,6 +13,8 @@ # TODO: eliminate the use of fabric here. from galaxy import eggs eggs.require( 'Fabric' ) +eggs.require( 'ssh' ) +eggs.require( 'paramiko' ) from fabric.operations import _AttributeString from fabric import state @@ -412,7 +414,10 @@ return tool_dependency, filtered_actions, dir def load_step_handlers( self ): - step_handlers_by_type = dict( autoconf=step_handler.Autoconf(), + step_handlers_by_type = dict( assert_directory_exists=step_handler.AssertDirectoryExists(), + assert_file_executable=step_handler.AssertFileExecutable(), + assert_file_exists=step_handler.AssertFileExists(), + autoconf=step_handler.Autoconf(), change_directory=step_handler.ChangeDirectory(), chmod=step_handler.Chmod(), download_binary=step_handler.DownloadBinary(), diff -r 2edce562ccaa8bdd12e40b2263646f7b9cf93966 -r dda514ffa5e99b1b13bc3d88dbf35c1fb336742d lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py --- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py @@ -14,6 +14,9 @@ # TODO: eliminate the use of fabric here. from galaxy import eggs eggs.require( 'Fabric' ) +eggs.require( 'ssh' ) +eggs.require( 'paramiko' ) + from fabric.api import settings from fabric.api import lcd @@ -33,6 +36,105 @@ raise "Unimplemented Method" +class AssertDirectoryExists( RecipeStep ): + + def __init__( self ): + self.type = 'assert_directory_exists' + + def execute_step( self, app, tool_dependency, package_name, actions, action_dict, filtered_actions, env_file_builder, + install_environment, work_dir, install_dir, current_dir=None, initial_download=False ): + """ + Make sure a directory on disk exists. Since this class is not used in the initial download stage, + no recipe step filtering is performed here, and None values are always returned for filtered_actions + and dir. + """ + if os.path.isabs( action_dict[ 'full_path' ] ): + full_path = action_dict[ 'full_path' ] + else: + full_path = os.path.join( current_dir, action_dict[ 'full_path' ] ) + if not td_common_util.assert_directory_exists( full_path=full_path ): + status = app.install_model.ToolDependency.installation_status.ERROR + error_message = 'The required directory %s does not exist.' % str( full_path ) + tool_dependency = tool_dependency_util.set_tool_dependency_attributes( app, + tool_dependency, + status=status, + error_message=error_message, + remove_from_disk=False ) + return tool_dependency, None, None + + def prepare_step( self, app, tool_dependency, action_elem, action_dict, install_dir, is_binary_download ): + # <action type="make_directory">$INSTALL_DIR/mira</action> + if action_elem.text: + action_dict[ 'full_path' ] = td_common_util.evaluate_template( action_elem.text, install_dir ) + return action_dict + + +class AssertFileExecutable( RecipeStep ): + + def __init__( self ): + self.type = 'assert_file_executable' + + def execute_step( self, app, tool_dependency, package_name, actions, action_dict, filtered_actions, env_file_builder, + install_environment, work_dir, install_dir, current_dir=None, initial_download=False ): + """ + Make sure a file on disk exists and is executable. Since this class is not used in the initial + download stage, no recipe step filtering is performed here, and None values are always returned + for filtered_actions and dir. + """ + if os.path.isabs( action_dict[ 'full_path' ] ): + full_path = action_dict[ 'full_path' ] + else: + full_path = os.path.join( current_dir, action_dict[ 'full_path' ] ) + if not td_common_util.assert_file_executable( full_path=full_path ): + status = app.install_model.ToolDependency.installation_status.ERROR + error_message = 'The file %s is not executable by the owner.' % str( full_path ) + tool_dependency = tool_dependency_util.set_tool_dependency_attributes( app, + tool_dependency, + status=status, + error_message=error_message, + remove_from_disk=False ) + return tool_dependency, None, None + + def prepare_step( self, app, tool_dependency, action_elem, action_dict, install_dir, is_binary_download ): + # <action type="assert_executable">$INSTALL_DIR/mira/my_file</action> + if action_elem.text: + action_dict[ 'full_path' ] = td_common_util.evaluate_template( action_elem.text, install_dir ) + return action_dict + + +class AssertFileExists( RecipeStep ): + + def __init__( self ): + self.type = 'assert_file_exists' + + def execute_step( self, app, tool_dependency, package_name, actions, action_dict, filtered_actions, env_file_builder, + install_environment, work_dir, install_dir, current_dir=None, initial_download=False ): + """ + Make sure a file on disk exists. Since this class is not used in the initial download stage, + no recipe step filtering is performed here, and None values are always returned for + filtered_actions and dir. + """ + if os.path.isabs( action_dict[ 'full_path' ] ): + full_path = action_dict[ 'full_path' ] + else: + full_path = os.path.join( current_dir, action_dict[ 'full_path' ] ) + if not td_common_util.assert_file_exists( full_path=full_path ): + status = app.install_model.ToolDependency.installation_status.ERROR + error_message = 'The required file %s does not exist.' % str( full_path ) + tool_dependency = tool_dependency_util.set_tool_dependency_attributes( app, + tool_dependency, + status=status, + error_message=error_message, + remove_from_disk=False ) + return tool_dependency, None, None + + def prepare_step( self, app, tool_dependency, action_elem, action_dict, install_dir, is_binary_download ): + # <action type="assert_on_path">$INSTALL_DIR/mira/my_file</action> + if action_elem.text: + action_dict[ 'full_path' ] = td_common_util.evaluate_template( action_elem.text, install_dir ) + return action_dict + + class Autoconf( RecipeStep ): def __init__( self ): diff -r 2edce562ccaa8bdd12e40b2263646f7b9cf93966 -r dda514ffa5e99b1b13bc3d88dbf35c1fb336742d lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py --- a/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/td_common_util.py @@ -2,6 +2,7 @@ import os import re import shutil +import stat import sys import tarfile import time @@ -110,6 +111,31 @@ def open_zip( self, filepath, mode ): return zipfile.ZipFile( filepath, mode ) +def assert_directory_exists( full_path ): + """Return True if a directory exists and is not a symbolic link.""" + if os.path.islink( full_path ): + return False + if os.path.is_dir( full_path ): + return True + return False + +def assert_file_exists( full_path ): + """Return True if a file exists. This will work for both symbolic linke and files.""" + if os.path.exists( full_path ): + return True + return False + +def assert_file_executable( full_path ): + """Return True if a file exists and is executable.""" + if os.path.islink( full_path ): + return False + if os.path.is_file( full_path ): + # Make sure the owner has execute permission on the file. + # See http://docs.python.org/2/library/stat.html + if stat.S_IXUSR & os.stat( full_path )[ stat.ST_MODE ] == 64: + return True + return False + def create_env_var_dict( elem, tool_dependency_install_dir=None, tool_shed_repository_install_dir=None ): env_var_name = elem.get( 'name', 'PATH' ) env_var_action = elem.get( 'action', 'prepend_to' ) @@ -155,6 +181,10 @@ regex = regex.replace( r"\'", "'" ) return regex +def evaluate_template( text, install_dir ): + """ Substitute variables defined in XML blocks from dependencies file.""" + return Template( text ).safe_substitute( get_env_var_values( install_dir ) ) + def format_traceback(): ex_type, ex, tb = sys.exc_info() return ''.join( traceback.format_tb( tb ) ) @@ -444,6 +474,10 @@ continue return actions_elem_tuples +def __shellquote( s ): + """Quote and escape the supplied string for use in shell expressions.""" + return "'" + s.replace( "'", "'\\''" ) + "'" + def url_download( install_dir, downloaded_file_name, download_url, extract=True ): file_path = os.path.join( install_dir, downloaded_file_name ) src = None @@ -494,11 +528,3 @@ if not member_path.startswith( basename ): return False return True - -def __shellquote(s): - """Quote and escape the supplied string for use in shell expressions.""" - return "'" + s.replace( "'", "'\\''" ) + "'" - -def evaluate_template( text, install_dir ): - """ Substitute variables defined in XML blocks from dependencies file.""" - return Template( text ).safe_substitute( get_env_var_values( install_dir ) ) Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.