mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Add support for 3 new tool dependency installation recipe action tag types: assert_directory_exists, assert_file_exists and assert_file_executable.
This commit is contained in:
@@ -4,6 +4,8 @@ import os
|
||||
from galaxy import eggs
|
||||
|
||||
eggs.require( 'Fabric' )
|
||||
eggs.require( 'ssh' )
|
||||
eggs.require( 'paramiko' )
|
||||
|
||||
from fabric.api import env
|
||||
from fabric.api import lcd
|
||||
|
||||
@@ -13,6 +13,8 @@ from contextlib import contextmanager
|
||||
# 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 @@ class RecipeManager( object ):
|
||||
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(),
|
||||
|
||||
@@ -14,6 +14,9 @@ from tool_shed.galaxy_install.tool_dependencies import td_common_util
|
||||
# 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 @@ class RecipeStep( object ):
|
||||
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 ):
|
||||
|
||||
@@ -2,6 +2,7 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import stat
|
||||
import sys
|
||||
import tarfile
|
||||
import time
|
||||
@@ -110,6 +111,31 @@ class CompressedFile( object ):
|
||||
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 @@ def egrep_escape( text ):
|
||||
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 @@ def parse_package_elem( package_elem, platform_info_dict=None, include_after_ins
|
||||
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 @@ def zipfile_ok( path_to_archive ):
|
||||
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 ) )
|
||||
|
||||
Reference in New Issue
Block a user