Galaxy Tool Shed enhancements

1. Rename Galaxy Community Space to Galaxy Tool Shed
2. Add the ability to upload an archive consisting of a suite of tools in addition to a single tool archive.
3. Miscellaneous code cleanup including elimination of all sniffer related code.
This commit is contained in:
Greg Von Kuster
2010-07-22 16:43:32 -04:00
parent d63c89c283
commit 763d9bd607
16 changed files with 581 additions and 227 deletions
+1 -3
View File
@@ -2,8 +2,6 @@
<datatypes>
<registration>
<datatype extension="tool" type="galaxy.webapps.community.datatypes:Tool" model="galaxy.webapps.community.model:Tool"/>
<datatype extension="toolsuite" type="galaxy.webapps.community.datatypes:ToolSuite" model="galaxy.webapps.community.model:Tool"/>
</registration>
<sniffers>
<sniffer type="galaxy.webapps.community.datatypes:Tool"/>
</sniffers>
</datatypes>
@@ -299,7 +299,7 @@ class GroupListGrid( grids.Grid ):
class AdminToolListGrid( ToolListGrid ):
class StateColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool ):
state = tool.state()
state = tool.state
if state == 'approved':
state_color = 'ok'
elif state == 'rejected':
@@ -441,7 +441,7 @@ class AdminController( BaseController, Admin ):
# Called from the ToolStateColumn link
tool_id = kwd.get( 'id', None )
tool = get_tool( trans, tool_id )
kwd[ 'f-state' ] = tool.state()
kwd[ 'f-state' ] = tool.state
elif operation == "tools_by_category":
# Eliminate the current filters if any exist.
for k, v in kwd.items():
@@ -547,7 +547,7 @@ class AdminController( BaseController, Admin ):
# If we're approving a tool, all previously approved versions must be set to archived
for version in get_versions( tool ):
# TODO: get latest approved version instead of all versions
if version != tool and version.is_approved():
if version != tool and version.is_approved:
# Create an event with state ARCHIVED for the previously approved version of this tool
self.__create_tool_event( trans,
version,
@@ -799,30 +799,30 @@ def get_tools_by_state( trans, state ):
ids = []
if state == trans.model.Tool.states.NEW:
for tool in get_tools( trans ):
if tool.is_new():
if tool.is_new:
ids.append( tool.id )
elif state == trans.model.Tool.states.ERROR:
for tool in get_tools( trans ):
if tool.is_error():
if tool.is_error:
ids.append( tool.id )
elif state == trans.model.Tool.states.DELETED:
for tool in get_tools( trans ):
if tool.is_deleted():
if tool.is_deleted:
ids.append( tool.id )
elif state == trans.model.Tool.states.WAITING:
for tool in get_tools( trans ):
if tool.is_waiting():
if tool.is_waiting:
ids.append( tool.id )
elif state == trans.model.Tool.states.APPROVED:
for tool in get_tools( trans ):
if tool.is_approved():
if tool.is_approved:
ids.append( tool.id )
elif state == trans.model.Tool.states.REJECTED:
for tool in get_tools( trans ):
if tool.is_rejected():
if tool.is_rejected:
ids.append( tool.id )
elif state == trans.model.Tool.states.ARCHIVED:
for tool in get_tools( trans ):
if tool.is_archived():
if tool.is_archived:
ids.append( tool.id )
return ids
@@ -14,6 +14,11 @@ class ToolListGrid( grids.Grid ):
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool ):
return tool.name
class TypeColumn( grids.GridColumn ):
def get_value( self, trans, grid, tool ):
if tool.is_suite:
return 'Suite'
return 'Tool'
class VersionColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool ):
return tool.version
@@ -60,6 +65,10 @@ class ToolListGrid( grids.Grid ):
model_class=model.Tool,
attach_popup=False
),
TypeColumn( "Type",
key="suite",
model_class=model.Tool,
attach_popup=False ),
VersionColumn( "Version",
key="version",
model_class=model.Tool,
@@ -229,7 +238,7 @@ class CommonController( BaseController ):
in_categories.append( ( category.id, category.name ) )
else:
out_categories.append( ( category.id, category.name ) )
if tool.is_rejected():
if tool.is_rejected:
# Include the comments regarding the reason for rejection
reason_for_rejection = get_most_recent_event( tool ).comment
else:
@@ -283,7 +292,7 @@ class CommonController( BaseController ):
visible_versions = trans.app.security_agent.get_visible_versions( trans.user, trans.user_is_admin(), cntrller, tool )
categories = [ tca.category for tca in tool.categories ]
tool_file_contents = tarfile.open( tool.file_name, 'r' ).getnames()
if tool.is_rejected():
if tool.is_rejected:
# Include the comments regarding the reason for rejection
reason_for_rejection = get_most_recent_event( tool ).comment
else:
@@ -15,7 +15,7 @@ class ApprovedToolListGrid( ToolListGrid ):
class MyToolsListGrid( ToolListGrid ):
class StateColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool ):
state = tool.state()
state = tool.state
if state == 'approved':
state_color = 'ok'
elif state == 'rejected':
@@ -64,7 +64,7 @@ class ToolCategoryListGrid( CategoryListGrid ):
viewable_tools = 0
for tca in category.tools:
tool = tca.tool
if tool.is_approved():
if tool.is_approved:
viewable_tools += 1
return viewable_tools
return 0
@@ -2,6 +2,7 @@ import sys, os, shutil, logging, urllib2
from galaxy.web.base.controller import *
from galaxy.web.framework.helpers import time_ago, iff, grids
from galaxy.model.orm import *
from galaxy.web.form_builder import SelectField
from galaxy.webapps.community import datatypes
from common import get_categories, get_category, get_versions
@@ -25,12 +26,13 @@ class UploadController( BaseController ):
replace_id = params.get( 'replace_id', None )
replace_version = None
uploaded_file = None
upload_type = params.get( 'upload_type', 'tool' )
categories = get_categories( trans )
if not categories:
return trans.response.send_redirect( web.url_for( controller='tool',
action='browse_tools',
cntrller='tool',
message='No categories have been configured in this instance of the Galaxy Community. An administrator needs to create some via the Administrator control panel before anything can be uploaded',
message='No categories have been configured in this instance of the Galaxy Tool Shed. An administrator needs to create some via the Administrator control panel before anything can be uploaded',
status='error' ) )
if params.get( 'upload_button', False ):
url_paste = params.get( 'url', '' ).strip()
@@ -50,8 +52,6 @@ class UploadController( BaseController ):
elif file_data not in ( '', None ):
uploaded_file = file_data.file
if uploaded_file:
# TODO: tool should no longer be the default when we upload histories and workflows
upload_type = params.get( 'upload_type', 'tool' )
datatype = trans.app.datatypes_registry.get_datatype_by_extension( upload_type )
if datatype is None:
message = 'An unknown file type was selected. This should not be possible, please report the error.'
@@ -62,6 +62,7 @@ class UploadController( BaseController ):
meta = datatype.verify( uploaded_file )
meta.user = trans.user
meta.guid = trans.app.security.get_new_guid()
meta.suite = upload_type == 'toolsuite'
obj = datatype.create_model_object( meta )
trans.sa_session.add( obj )
if isinstance( obj, trans.app.model.Tool ):
@@ -71,25 +72,32 @@ class UploadController( BaseController ):
if replace_id:
replace_version = trans.sa_session.query( trans.app.model.Tool ).get( trans.security.decode_id( replace_id ) )
if existing and not replace_id:
raise UploadError( 'A tool with the same ID already exists. If you are trying to update this tool to a new version, please use the upload form on the "Edit Tool" page. Otherwise, please choose a new ID.' )
raise UploadError( 'A %s with the same Id already exists. If you are trying to update this %s to a new version, use the upload form on the "Edit Tool" page. Otherwise, change the Id in the %s config.' % \
( obj.label, obj.label, obj.label ) )
elif replace_id and not existing:
raise UploadError( 'Tool ids must match when uploading a new version of a tool. The new tool id does not match the old tool id (%s). Check the tool XML files.' % str( replace_version.tool_id ) )
raise UploadError( 'The new %s id (%s) does not match the old %s id (%s). Check the %s config files.' % \
( obj.label, str( meta.id ), obj.label, str( replace_version.tool_id ), obj.label ) )
elif existing and replace_id:
if replace_version.newer_version:
# If the user has picked an old version, switch to the newest version
replace_version = get_versions( replace_version )[0]
if replace_version.tool_id != meta.id:
raise UploadError( 'Tool ids must match when uploading a new version of a tool. The new tool id (%s) does not match the old tool id (%s). Check the tool XML files.' % ( str( meta.id ), str( replace_version.tool_id ) ) )
raise UploadError( 'The new %s id (%s) does not match the old %s id (%s). Check the %s config files.' % \
( obj.label, str( meta.id ), obj.label, str( replace_version.tool_id ), obj.label ) )
for old_version in get_versions( replace_version ):
if old_version.version == meta.version:
raise UploadError( 'The new version (%s) matches an old version. Check your version in the tool XML file.' % str( meta.version ) )
if old_version.is_new():
raise UploadError( 'There is an existing version of this tool which has not yet been submitted for approval, so either <a href="%s">submit or delete it</a> before uploading a new version.' % url_for( controller='common',
action='view_tool',
cntrller='tool',
id=trans.security.encode_id( old_version.id ) ) )
if old_version.is_waiting():
raise UploadError( 'There is an existing version of this tool which is waiting for administrative approval, so contact an administrator for help.' )
raise UploadError( 'The new version (%s) matches an old version. Check your version in the %s config file.' % \
( str( meta.version ), obj.label ) )
if old_version.is_new:
raise UploadError( 'There is an existing version of this %s which has not yet been submitted for approval, so either <a href="%s">submit it or delete it</a> before uploading a new version.' % \
( obj.label,
url_for( controller='common',
action='view_tool',
cntrller='tool',
id=trans.security.encode_id( old_version.id ) ) ) )
if old_version.is_waiting:
raise UploadError( 'There is an existing version of this %s which is waiting for administrative approval, so contact an administrator for help.' % \
obj.label )
# Defer setting the id since the newer version id doesn't exist until the new Tool object is flushed
if category_ids:
for category_id in category_ids:
@@ -128,10 +136,10 @@ class UploadController( BaseController ):
replace_version = trans.sa_session.query( trans.app.model.Tool ).get( int( trans.app.security.decode_id( replace_id ) ) )
old_version = None
for old_version in get_versions( replace_version ):
if old_version.is_new():
if old_version.is_new:
message = 'There is an existing version of this tool which has not been submitted for approval, so either submit or delete it before uploading a new version.'
break
if old_version.is_waiting():
if old_version.is_waiting:
message = 'There is an existing version of this tool which is waiting for administrative approval, so contact an administrator for help.'
break
else:
@@ -143,13 +151,23 @@ class UploadController( BaseController ):
id=trans.app.security.encode_id( old_version.id ),
message=message,
status='error' ) )
selected_upload_type = params.get( 'type', 'tool' )
selected_categories = [ trans.security.decode_id( id ) for id in category_ids ]
datatype_labels=trans.app.datatypes_registry.get_datatype_labels()
type_ids = [ tup[0] for tup in datatype_labels ]
upload_type_select_list = SelectField( 'upload_type',
refresh_on_change=True,
refresh_on_change_values=type_ids )
for type_id, type_label in datatype_labels:
if type_id == upload_type:
upload_type_select_list.add_option( type_label, type_id, selected = True )
else:
upload_type_select_list.add_option( type_label, type_id, selected = False )
return trans.fill_template( '/webapps/community/upload/upload.mako',
message=message,
status=status,
selected_upload_type=selected_upload_type,
upload_types=trans.app.datatypes_registry.get_datatypes_for_select_list(),
selected_upload_type=upload_type,
upload_type_select_list=upload_type_select_list,
datatype_labels=trans.app.datatypes_registry.get_datatype_labels(),
replace_id=replace_id,
selected_categories=selected_categories,
categories=get_categories( trans ) )
@@ -17,7 +17,6 @@ class DatatypeVerificationError( Exception ):
class Registry( object ):
def __init__( self, root_dir=None, config=None ):
self.datatypes_by_extension = {}
self.sniff_order = []
if root_dir and config:
# Parse datatypes_conf.xml
tree = galaxy.util.parse_xml( config )
@@ -50,98 +49,143 @@ class Registry( object ):
log.debug( 'Added model class: %s to datatype: %s' % ( model_class, dtype ) )
except Exception, e:
log.warning( 'Error loading datatype "%s", problem: %s' % ( extension, str( e ) ) )
# Load datatype sniffers from the config
sniff_order = []
sniffers = root.find( 'sniffers' )
for elem in sniffers.findall( 'sniffer' ):
dtype = elem.get( 'type', None )
if dtype:
sniff_order.append( dtype )
for dtype in sniff_order:
try:
fields = dtype.split( ":" )
datatype_module = fields[0]
datatype_class = fields[1]
fields = datatype_module.split( "." )
module = __import__( fields.pop(0) )
for mod in fields:
module = getattr( module, mod )
aclass = getattr( module, datatype_class )()
included = False
for atype in self.sniff_order:
if not issubclass( atype.__class__, aclass.__class__ ) and isinstance( atype, aclass.__class__ ):
included = True
break
if not included:
self.sniff_order.append( aclass )
log.debug( 'Loaded sniffer for datatype: %s' % dtype )
except Exception, exc:
log.warning( 'Error appending datatype %s to sniff_order, problem: %s' % ( dtype, str( exc ) ) )
def get_datatype_by_extension( self, ext ):
return self.datatypes_by_extension.get( ext, None )
def get_datatypes_for_select_list( self ):
def get_datatype_labels( self ):
rval = []
for ext, datatype in self.datatypes_by_extension.items():
rval.append( ( ext, datatype.select_name ) )
rval.append( ( ext, datatype.label ) )
return rval
def sniff( self, fname ):
for datatype in sniff_order:
try:
datatype.sniff( fname )
return datatype.file_ext
except:
pass
class Tool( object ):
select_name = 'Tool'
def __init__( self, model_object=None ):
self.model_object = model_object
def verify( self, file ):
msg = ''
self.label = 'Tool'
def verify( self, f, xml_files=[], tool_tags={} ):
# xml_files and tool_tags will only be received if we're called from the ToolSuite.verify() method.
try:
tar = tarfile.open( file.name )
tar = tarfile.open( f.name )
except tarfile.ReadError:
raise DatatypeVerificationError( 'The tool file is not a readable tar file' )
xml_names = filter( lambda x: x.lower().endswith( '.xml' ), tar.getnames() )
if not xml_names:
raise DatatypeVerificationError( 'The tool file does not contain an XML file' )
for xml_name in xml_names:
raise DatatypeVerificationError( 'The archive is not a readable tar file.' )
if not xml_files:
# Make sure we're not uploading a tool suite
if filter( lambda x: x.lower() == 'tool_suite.xml', tar.getnames() ):
raise DatatypeVerificationError( 'The archive includes a tool_suite.xml file, so set the upload type to "Tool Suite".' )
xml_files = filter( lambda x: x.lower().endswith( '.xml' ), tar.getnames() )
if not xml_files:
raise DatatypeVerificationError( 'The archive does not contain any xml config files.' )
for xml_file in xml_files:
try:
tree = ElementTree.parse( tar.extractfile( xml_name ) )
tree = ElementTree.parse( tar.extractfile( xml_file ) )
root = tree.getroot()
except:
log.exception( 'fail:' )
continue
if root.tag == 'tool':
rval = Bunch()
try:
rval.id = root.attrib['id']
rval.name = root.attrib['name']
rval.version = root.attrib['version']
except KeyError, e:
raise DatatypeVerificationError( 'Tool XML file does not conform to the specification. Missing required &lt;tool&gt; tag attribute: %s' % e )
rval.description = ''
desc_tag = root.find( 'description' )
if desc_tag is not None:
description = desc_tag.text
if description:
rval.description = description.strip()
rval.message = 'Tool: %s %s, Version: %s, ID: %s' % ( str( rval.name ), str( rval.description ), str( rval.version ), str( rval.id ) )
return rval
else:
raise DatatypeVerificationError( 'Unable to find a properly formatted tool XML file' )
if tool_tags:
# We are verifying the tools inside a tool suite, so the current tag should have been found in the suite_config.xml
# file parsed in the ToolSuite verify() method. The tool_tags dictionary should include a key matching the current
# tool Id, and a tuple value matching the tool name and version.
if root.attrib[ 'id' ] not in tool_tags:
raise DatatypeVerificationError( 'Tool Id (%s) is not included in the suite_config.xml file.' % \
( str( root.attrib[ 'id' ] ) ) )
tup = tool_tags[ root.attrib[ 'id' ] ]
if root.attrib[ 'name' ] != tup[ 0 ]:
raise DatatypeVerificationError( 'Tool name (%s) differs between suite_config.xml and the tool config file for tool Id (%s).' % \
( str( root.attrib[ 'name' ] ), str( root.attrib[ 'id' ] ) ) )
if root.attrib[ 'version' ] != tup[ 1 ]:
raise DatatypeVerificationError( 'Tool version (%s) differs between suite_config.xml and the tool config file for tool Id (%s).' % \
( str( root.attrib[ 'version' ] ), str( root.attrib[ 'id' ] ) ) )
else:
# We are not verifying a tool suite, so we'll create a bunch for returning to the caller.
tool_bunch = Bunch()
try:
tool_bunch.id = root.attrib['id']
tool_bunch.name = root.attrib['name']
tool_bunch.version = root.attrib['version']
except KeyError, e:
raise DatatypeVerificationError( 'Tool XML file does not conform to the specification. Missing required &lt;tool&gt; tag attribute: %s' % str( e ) )
tool_bunch.description = ''
desc_tag = root.find( 'description' )
if desc_tag is not None:
description = desc_tag.text
if description:
tool_bunch.description = description.strip()
tool_bunch.message = 'Tool: %s %s, Version: %s, Id: %s' % \
( str( tool_bunch.name ), str( tool_bunch.description ), str( tool_bunch.version ), str( tool_bunch.id ) )
return tool_bunch
else:
# TODO: should we verify files that are not tool configs?
log.debug( "The file named (%s) is not a tool config, so skipping verification." % str( xml_file ) )
def create_model_object( self, datatype_bunch ):
if self.model_object is None:
raise Exception( 'No model object configured for %s, please check the datatype configuration file' % self.__class__.__name__ )
raise Exception( 'No model object configured for %s, check the datatype configuration file' % self.__class__.__name__ )
if datatype_bunch is None:
# TODO: do it automatically
raise Exception( 'Unable to create %s model object without passing in data' % self.__class__.__name__ )
o = self.model_object()
o.create_from_datatype( datatype_bunch )
return o
def sniff( self, fname ):
class ToolSuite( Tool ):
def __init__( self, model_object=None ):
self.model_object = model_object
self.label = 'Tool Suite'
def verify( self, f ):
"""
A sample tool suite config:
<suite id="onto_toolkit" name="ONTO Toolkit" version="1.0">
<description>ONTO-Toolkit is a collection of Galaxy tools which support the manipulation of bio-ontologies.</description>
<tool id="get_ancestor_terms" name="Get the ancestor terms of a given OBO term" version="1.0.0">
<description>Collects the ancestor terms from a given term in the given OBO ontology</description>
</tool>
<tool id="get_child_terms" name="Get the child terms of a given OBO term" version="1.0.0">
<description>Collects the child terms from a given term in the given OBO ontology</description>
</tool>
</suite>
"""
try:
self.verify( open( fname, 'r' ) )
return True
tar = tarfile.open( f.name )
except tarfile.ReadError:
raise DatatypeVerificationError( 'The archive is not a readable tar file.' )
suite_config = filter( lambda x: x.lower() == 'tool_suite.xml', tar.getnames() )
if not suite_config:
raise DatatypeVerificationError( 'The archive does not contain the required tool_suite.xml config file. If you are uploading a single tool archive, set the upload type to "Tool".' )
suite_config = suite_config[ 0 ]
# Parse and verify suite_config
archive_ok = False
try:
tree = ElementTree.parse( tar.extractfile( suite_config ) )
root = tree.getroot()
archive_ok = True
except:
return False
log.exception( 'fail:' )
if archive_ok and root.tag == 'suite':
suite_bunch = Bunch()
try:
suite_bunch.id = root.attrib['id']
suite_bunch.name = root.attrib['name']
suite_bunch.version = root.attrib['version']
except KeyError, e:
raise DatatypeVerificationError( 'The file named tool-suite.xml does not conform to the specification. Missing required &lt;suite&gt; tag attribute: %s' % str( e ) )
suite_bunch.description = ''
desc_tag = root.find( 'description' )
if desc_tag is not None:
description = desc_tag.text
if description:
suite_bunch.description = description.strip()
suite_bunch.message = 'Tool suite: %s %s, Version: %s, Id: %s' % \
( str( suite_bunch.name ), str( suite_bunch.description ), str( suite_bunch.version ), str( suite_bunch.id ) )
# Create a dictionary of the tools in the suite where the keys are tool_ids and the
# values are tuples of tool name and version
tool_tags = {}
for elem in root.findall( 'tool' ):
tool_tags[ elem.attrib['id'] ] = ( elem.attrib['name'], elem.attrib['version'] )
else:
raise DatatypeVerificationError( "The file named %s is not a valid tool suite config." % str( suite_config ) )
# Verify all included tool config files
xml_files = filter( lambda x: x.lower().endswith( '.xml' ) and x.lower() != 'tool_suite.xml', tar.getnames() )
if not xml_files:
raise DatatypeVerificationError( 'The archive does not contain any tool config (xml) files.' )
Tool.verify( self, f, xml_files=xml_files, tool_tags=tool_tags )
return suite_bunch
+47 -23
View File
@@ -1,5 +1,5 @@
"""
Galaxy Community Space data model classes
Galaxy Tool Shed data model classes
Naming: try to use class names that have a distinct plural form so that
the relationship cardinalities are obvious (e.g. prefer Dataset to Data)
@@ -95,7 +95,7 @@ class Tool( object ):
REJECTED = 'rejected',
ARCHIVED = 'archived' )
def __init__( self, guid=None, tool_id=None, name=None, description=None, user_description=None,
category=None, version=None, user_id=None, external_filename=None ):
category=None, version=None, user_id=None, external_filename=None, suite=False ):
self.guid = guid
self.tool_id = tool_id
self.name = name or "Unnamed tool"
@@ -106,6 +106,7 @@ class Tool( object ):
self.external_filename = external_filename
self.deleted = False
self.__extension = None
self.suite = suite
def get_file_name( self ):
if not self.external_filename:
assert self.id is not None, "ID must be set before filename used (commit the object)"
@@ -133,6 +134,8 @@ class Tool( object ):
self.description = datatype_bunch.description
self.version = datatype_bunch.version
self.user_id = datatype_bunch.user.id
self.suite = datatype_bunch.suite
@property
def state( self ):
if self.events:
# Sort the events in ascending order by update_time
@@ -150,35 +153,47 @@ class Tool( object ):
else:
return ''
return 'No comment'
# Tool states
@property
def is_new( self ):
return self.state() == self.states.NEW
return self.state == self.states.NEW
@property
def is_error( self ):
return self.state() == self.states.ERROR
return self.state == self.states.ERROR
@property
def is_deleted( self ):
return self.state() == self.states.DELETED
return self.state == self.states.DELETED
@property
def is_waiting( self ):
return self.state() == self.states.WAITING
return self.state == self.states.WAITING
@property
def is_approved( self ):
return self.state() == self.states.APPROVED
return self.state == self.states.APPROVED
@property
def is_rejected( self ):
return self.state() == self.states.REJECTED
return self.state == self.states.REJECTED
@property
def is_archived( self ):
return self.state() == self.states.ARCHIVED
return self.state == self.states.ARCHIVED
def get_state_message( self ):
if self.is_new():
return '<font color="red"><b><i>This is an unsubmitted version of this tool</i></b></font>'
if self.is_error():
return '<font color="red"><b><i>This tool is in an error state</i></b></font>'
if self.is_deleted():
return '<font color="red"><b><i>This is a deleted version of this tool</i></b></font>'
if self.is_waiting():
return '<font color="red"><b><i>This version of this tool is awaiting administrative approval</i></b></font>'
if self.is_approved():
return '<b><i>This is the latest approved version of this tool</i></b>'
if self.is_rejected():
return '<font color="red"><b><i>This version of this tool has been rejected by an administrator</i></b></font>'
if self.is_archived():
return '<font color="red"><b><i>This is an archived version of this tool</i></b></font>'
if self.is_suite:
label = 'tool suite'
else:
label = 'tool'
if self.is_new:
return '<font color="red"><b><i>This is an unsubmitted version of this %s</i></b></font>' % label
if self.is_error:
return '<font color="red"><b><i>This %s is in an error state</i></b></font>' % label
if self.is_deleted:
return '<font color="red"><b><i>This is a deleted version of this %s</i></b></font>' % label
if self.is_waiting:
return '<font color="red"><b><i>This version of this %s is awaiting administrative approval</i></b></font>' % label
if self.is_approved:
return '<b><i>This is the latest approved version of this %s</i></b>' % label
if self.is_rejected:
return '<font color="red"><b><i>This version of this %s has been rejected by an administrator</i></b></font>' % label
if self.is_archived:
return '<font color="red"><b><i>This is an archived version of this %s</i></b></font>' % label
@property
def extension( self ):
# if instantiated via a query, this unmapped property won't exist
@@ -202,6 +217,15 @@ class Tool( object ):
self.__extension = 'tar'
return self.__extension
@property
def is_suite( self ):
return self.suite
@property
def label( self ):
if self.is_suite:
return 'tool suite'
else:
return 'tool'
@property
def download_file_name( self ):
return '%s_%s.%s' % ( self.tool_id, self.version, self.extension )
@property
@@ -113,7 +113,8 @@ Tool.table = Table( "tool", metadata,
Column( "version", TrimmedString( 255 ) ),
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
Column( "external_filename" , TEXT ),
Column( "deleted", Boolean, index=True, default=False ) )
Column( "deleted", Boolean, index=True, default=False ),
Column( "suite", Boolean, default=False, index=True ) )
Category.table = Table( "category", metadata,
Column( "id", Integer, primary_key=True ),
@@ -0,0 +1,48 @@
"""
Migration script to add the suite column to the tool table.
"""
from sqlalchemy import *
from sqlalchemy.orm import *
from migrate import *
from migrate.changeset import *
import logging
log = logging.getLogger( __name__ )
metadata = MetaData( migrate_engine )
db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
def upgrade():
print __doc__
metadata.reflect()
# Create and initialize imported column in job table.
Tool_table = Table( "tool", metadata, autoload=True )
c = Column( "suite", Boolean, default=False, index=True )
try:
# Create
c.create( Tool_table )
assert c is Tool_table.c.suite
# Initialize.
if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
default_false = "0"
elif migrate_engine.name == 'postgres':
default_false = "false"
db_session.execute( "UPDATE tool SET suite=%s" % default_false )
except Exception, e:
print "Adding suite column to the tool table failed: %s" % str( e )
log.debug( "Adding suite column to the tool table failed: %s" % str( e ) )
def downgrade():
metadata.reflect()
# Drop imported column from job table.
Tool_table = Table( "tool", metadata, autoload=True )
try:
Tool_table.c.suite.drop()
except Exception, e:
print "Dropping column suite from the tool table failed: %s" % str( e )
log.debug( "Dropping column suite from the tool table failed: %s" % str( e ) )
@@ -1,5 +1,5 @@
"""
Galaxy Community Space Security
Galaxy Tool Shed Security
"""
import logging, socket, operator
from datetime import datetime, timedelta
@@ -167,14 +167,14 @@ class CommunityRBACAgent( RBACAgent ):
def can_approve_or_reject( self, user, user_is_admin, cntrller, item ):
# The current user can approve or reject the item if the user
# is an admin, and the item's state is WAITING.
return user and user_is_admin and cntrller=='admin' and item.is_waiting()
return user and user_is_admin and cntrller=='admin' and item.is_waiting
def can_delete( self, user, user_is_admin, cntrller, item ):
# The current user can delete the item if they are an admin or if they uploaded the
# item and in either case the item's state is not DELETED.
if user and user_is_admin and cntrller == 'admin':
can_delete = not item.is_deleted()
can_delete = not item.is_deleted
elif cntrller in [ 'tool' ]:
can_delete = user==item.user and not item.is_deleted()
can_delete = user==item.user and not item.is_deleted
else:
can_delete = False
return can_delete
@@ -184,7 +184,7 @@ class CommunityRBACAgent( RBACAgent ):
if user and user_is_admin and cntrller == 'admin':
return True
elif cntrller in [ 'tool' ]:
can_download = not( item.is_new() or item.is_waiting() )
can_download = not( item.is_new or item.is_waiting )
else:
can_download = False
return can_download
@@ -194,7 +194,7 @@ class CommunityRBACAgent( RBACAgent ):
if user and user_is_admin and cntrller == 'admin':
return True
if cntrller in [ 'tool' ]:
return user and user==item.user and ( item.is_new() or item.is_rejected() )
return user and user==item.user and ( item.is_new or item.is_rejected )
return False
def can_purge( self, user, user_is_admin, cntrller ):
# The current user can purge the item if they are an admin.
@@ -206,7 +206,7 @@ class CommunityRBACAgent( RBACAgent ):
versions = get_versions( item )
state_ok = True
for version in versions:
if version.is_new() or version.is_waiting():
if version.is_new or version.is_waiting:
state_ok = False
break
return state_ok
@@ -215,7 +215,7 @@ class CommunityRBACAgent( RBACAgent ):
# or if the item's state is APPROVED.
if user and user_is_admin and cntrller == 'admin':
return True
if cntrller in [ 'tool' ] and item.is_approved():
if cntrller in [ 'tool' ] and item.is_approved:
return True
return user and user==item.user
def get_all_action_permissions( self, user, user_is_admin, cntrller, item ):
@@ -236,7 +236,7 @@ class CommunityRBACAgent( RBACAgent ):
elif cntrller in [ 'tool' ]:
visible_versions = []
for version in get_versions( item ):
if version.is_approved() or version.is_archived() or version.user == user:
if version.is_approved or version.is_archived or version.user == user:
visible_versions.append( version )
else:
visible_versions = []
+1 -1
View File
@@ -1,7 +1,7 @@
<%inherit file="/webapps/community/base_panels.mako"/>
## Default title
<%def name="title()">Galaxy Community Space Administration</%def>
<%def name="title()">Galaxy Tool Shed Administration</%def>
<%def name="stylesheets()">
${parent.stylesheets()}
+2 -2
View File
@@ -1,7 +1,7 @@
<%inherit file="/base_panels.mako"/>
## Default title
<%def name="title()">Galaxy Community Space</%def>
<%def name="title()">Galaxy Tool Shed</%def>
## Masthead
<%def name="masthead()">
@@ -94,7 +94,7 @@
<div class="title" style="position: absolute; top: 0; left: 0;">
<a href="${app.config.get( 'logo_url', '/' )}">
<img border="0" src="${h.url_for('/static/images/galaxyIcon_noText.png')}" style="width: 26px; vertical-align: top;">
Galaxy Community
Galaxy Tool Shed
%if app.config.brand:
<span class='brand'>/ ${app.config.brand}</span>
%endif
@@ -93,7 +93,7 @@ ${tool.get_state_message()}
%if can_edit:
<form id="edit_tool" name="edit_tool" action="${h.url_for( controller='common', action='edit_tool' )}" method="post">
%if tool.is_rejected():
%if tool.is_rejected:
<div class="toolForm">
<div class="toolFormTitle">Reason for rejection</div>
<div class="toolFormBody">
@@ -169,7 +169,7 @@ ${tool.get_state_message()}
</div>
</div>
<p/>
%if tool.is_new() or tool.is_rejected():
%if tool.is_new or tool.is_rejected:
<div class="toolForm">
<div class="toolFormTitle">Get approval for publishing</div>
<div class="toolFormBody">
+110 -69
View File
@@ -17,35 +17,87 @@
${render_msg( message, status )}
%endif
<h3>Uploading Tools</h3>
<p><strong>Tool File Format</strong></p>
<p/>
<div class="toolFormTitle">Creating an archive containing a tool or a suite of tools</div>
<p>
A tool file is a tar-format (bzipped or gzipped tar are valid) archive
containing all the files necessary to load the tool in Galaxy. At the very
least, it must contain a
<a href="http://bitbucket.org/galaxy/galaxy-central/wiki/ToolConfigSyntax" target="_blank">Tool XML File</a>,
and will probably also include a tool script. If any steps are necessary
to install your tool beyond the basic instructions below, please include a
README file which details these steps. If the tool (or parts of it) are
written in C, the source code can be included (or put links to the source
in the README). Please do not include precompiled binaries without source,
since Galaxy is run on a wide variety of platforms. Also, if you are only
wrapping or providing a Galaxy config for a tool that is not your own,
please be sure the license allows for redistribution before including any
part of that tool in the tar archive!
A tool or tool suite archive is a tar-format file (bzipped or gzipped tar are valid)
containing all the files necessary to load the tool(s) into a Galaxy instance.
</p>
<h3>Tool Suite Archive</h3>
<p>
A tools suite must include a file named <code>suite_config.xml</code> which provides information about the id, name,
version and description of the tool suite, as well as the id, name, version and description of each tool
in the suite. Here is an example <code>suite_config.xml</code> file.
</p>
<p>
There are no requirements about the directory structure inside the tar
archive, but for ease of use, it's generally a good idea to put everything
inside of a subdirectory, instead of directly at the top level.
<pre>
&lt;suite id="lastz_toolsuite" name="Suite of Lastz tools" version="1.0.0"&gt;
&lt;description&gt;This suite contains all of my Lastz tools for Galaxy&lt;/description&gt;
&lt;tool id="lastz_wrapper_2" name="Lastz" version="1.1.0"&gt;
&lt;description&gt; map short reads against reference sequence&lt;/description&gt;
&lt;/tool&gt;
&lt;tool id="lastz_paired_reads_wrapper" name="Lastz paired reads" version="1.0.0"&gt;
&lt;description&gt; map short paired reads against reference sequence&lt;/description&gt;
&lt;/tool&gt;
&lt;/suite&gt;
</pre>
</p>
</p>
<p><strong>Tool File Example</strong></p>
<p>
To package up the LASTZ tool's config file, Galaxy wrapper, and the C source:
<pre>
New versions of the suite can be uploaded, replacing an older version of the suite, but the version attribute
of the <suite> tag must be altered the same way that the version attribute of a single tool config must be altered
if uploading a new version of a tool.
</p>
<p>
The id, name and version attributes of each <tool> tag in the <code>suite_config.xml</code> file must exactly match the same
attributes in each associated tool config in the archive or you will not be allowed to upload the archive.
</p>
<p>
In addition to the <code>suite_config.xml</code> file, the archive must include all
<a href="http://bitbucket.org/galaxy/galaxy-central/wiki/ToolConfigSyntax" target="_blank">tool config files</a>,
executables, functional test data (if your tool config includes functional tests) and other files needed for each
of the tools in your suite to function within Galaxy. See the information about single tool archives below for
additional hints to enable ease-of-use when others download your suite of tools.
</p>
<p>
For example, to package the above Lastz suite of tools:
<pre>
user@host:~% tar jcvf ~/Desktop/galaxy_lastz_toolsuite.tar.bz2 lastzsuite
lastzsuite/
lastzsuite/README
lastzsuite/suite_config.xml
lastzsuite/lastz_paired_reads_wrapper.py
lastzsuite/lastz_paired_reads_wrapper.xml
lastzsuite/lastz_wrapper.py
lastzsuite/lastz_wrapper.xml
lastzsuite/lastz-distrib-1.02.00/
lastzsuite/lastz-distrib-1.02.00/src/
lastzsuite/lastz-distrib-1.02.00/src/Makefile
lastzsuite/lastz-distrib-1.02.00/src/version.mak
lastzsuite/lastz-distrib-1.02.00/src/lastz.c
lastzsuite/lastz-distrib-1.02.00/src/lastz.h
...
</pre>
~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded.
</p>
<h3>Single Tool Archive</h3>
<p>
A single tool archive must include a
<a href="http://bitbucket.org/galaxy/galaxy-central/wiki/ToolConfigSyntax" target="_blank">tool config file</a>
and will probably also include a tool script. If any steps are necessary to install your tool beyond the basic
instructions below, include a README file to provide details. If the tool (or parts of it) are written in C,
the source code can be included (or put links to the source in the README). Do not include pre-compiled binaries
without source since Galaxy is run on a wide variety of platforms. Also, if you are only wrapping or providing a
Galaxy config for a tool that is not your own, be sure the license allows for redistribution before including any
part of that tool in the archive.
</p>
<p>
There are no requirements about the directory structure inside the archive, but for ease of use it's generally
a good idea to put everything inside a sub-directory, instead of directly at the top level.
</p>
<p>
For example, to package the Lastz tool's config file, Galaxy wrapper, and the C source:
<pre>
user@host:~% tar jcvf ~/Desktop/galaxy_lastz_tool.tar.bz2 lastz
lastz/
lastz/README
@@ -58,68 +110,57 @@
lastz/lastz-distrib-1.02.00/src/lastz.c
lastz/lastz-distrib-1.02.00/src/lastz.h
...
</pre>
<code>~/Desktop/galaxy_lastz_tool.tar.bz2</code> is now ready to be uploaded.
</pre>
~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded.
</p>
<p><strong>Editing Information, Categories, and Submitting For Approval</strong></p>
<h3>Editing Information, Categories, and Submitting For Approval</h3>
<p>
Simply uploading a tool to the Community will not allow other users to find
and download your tool. It will need to be approved by an administrator
before it appears in the tool list.
Simply uploading a tool to the Galaxy too shed will not allow other users to find and download your tool. It will
need to be approved by an administrator before it appears in the tool list.
</p>
<p>
After the tool has successfully uploaded, you will be redirected to the
Edit Tool page. Please provide a detailed description of what the tool
does - this will be used by administrators to understand the tool before
approving it for display on the site. Once approved, this information will
be displayed to users who view your tool. In addition, the site
administrators will have configured a number of categories with which you
can associate your tool to make it easily findable by users looking to
solve specific problems. Please associate as many categories as are
relevant to your tool. You may change the description and associated
categories as often as you'd like until you click the "<strong>Submit for
approval</strong>" button. Once submitted, the tool will be approved or
rejected by an administrator. Once approved, it will be visible to
everyone. At that point, the description and associated categories can
only be changed by an administrator.
After your archive has successfully uploaded, you will be redirected to the Edit Tool page. Provide a detailed
description of what the tool does - this will be used by administrators to understand the tool before approving it
for display on the site. Once approved, this information will be displayed to users who view your tool. In addition,
the site administrators will have configured a number of categories with which you can associate your tool to make it
easy to find by users looking to solve specific problems. Associate as many categories as are relevant to your tool.
You may change the description and associated categories as often as you'd like until you click the "<strong>Submit for
approval</strong>" button. Once submitted, the tool will be approved or rejected by an administrator. If the tool is
rejected, you will see information about why it was rejected, and you can make appropriate changes to the archive and
re-submit it for approval. When it is approved, your archive will be visible to everyone. At that point, the description
and associated categories can only be changed by an administrator.
</p>
<p>
Once the tool has been approved or rejected, you may upload a new version
by browsing to the tool's "View Tool" page, clicking the context menu to
the right of the tool's name, and selecting "Upload a new version."
When the tool has been approved or rejected, you may upload a new version by browsing to the tool's "View Tool" page,
clicking the "Tool actions" menu in the upper right corner of the page, and selecting "Upload a new version" from the
menu.
</p>
<hr/>
<h3>Downloading and Installing Tools</h3>
<p>
A tool's download link will send you the tool tar archive. Once
downloaded, unpack the tool on your local Galaxy instance's server:
<pre>
user@host:~% tar xvf galaxy_tool.tar
A tool's download link will send you the tool archive. Once downloaded, unpack the tool on your local Galaxy instance's server:
<pre>
user@host:~% tar xvf galaxy_lastz_tool.tar
...
user@host:~% tar zxvf galaxy_tool.tar.gz
user@host:~% tar zxvf galaxy_lastz_tool.tar.gz
...
user@host:~% tar jxvf galaxy_tool.tar.bz2
user@host:~% tar jxvf galaxy_lastz_tool.tar.bz2
...
</pre>
If the tar archive includes a README file, consult it for installation
instructions. If not, follow these basic steps:
</pre>
If the archive includes a README file, consult it for installation instructions. If not, follow these basic steps:
<ol>
<li>Create a directory under <code>galaxy_dist/tools/</code> to house downloaded tool(s).</li>
<li>In the new directory, place the XML and any script file(s) which were contained in the tar archive.</li>
<li>If the tool includes binaries, you'll need to copy them to a directory on your <code>$PATH</code>. If the tool depends on C binaries but does not come with them (only source), you'll need to compile the source first.</li>
<li>In the new directory, place the XML and any script file(s) which were contained in the archive.</li>
<li>
If the tool includes binaries, you'll need to copy them to a directory on your <code>$PATH</code>. If the tool depends on
C binaries but does not come with them (only source), you'll need to compile the source first.
</li>
<li>Add the tool to <code>galaxy_dist/tool_conf.xml</code>.</li>
<li>Restart the Galaxy server process.</li>
<li>Restart your Galaxy server process.</li>
</ol>
</p>
<p>
We plan to implement a more direct method to install tools via the Galaxy
administrator user interface instead of placing files on the filesystem and
managing the <code>tool_conf.xml</code> file by hand. In the meantime,
this is the process.
In the near future, we plan to implement a more direct method to install tools via the Galaxy administrator user interface instead
of placing files on the filesystem and manually managing the <code>tool_conf.xml</code> file.
</p>
@@ -85,7 +85,7 @@ ${tool.get_state_message()}
%endif
%if can_view:
%if tool.is_rejected():
%if tool.is_rejected:
<div class="toolForm">
<div class="toolFormTitle">Reason for rejection</div>
<div class="toolFormBody">
@@ -168,7 +168,7 @@ ${tool.get_state_message()}
<div class="toolFormBody">
<div class="form-row">
<ul class="toolFile">
<li><a href="${h.url_for( controller='tool', action='download_tool', id=trans.app.security.encode_id( tool.id ) )}">${tool.download_file_name}</a></li>
<li><a href="${h.url_for( controller='common', action='download_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">${tool.download_file_name}</a></li>
<ul class="fileBrowser">
%for name in tool_file_contents:
<li><a href="${h.url_for( controller='tool', action='view_tool_file', id=trans.app.security.encode_id( tool.id ), file_name=quote_plus( name ) )}">${name}</a></li>
+184 -13
View File
@@ -9,16 +9,43 @@
%>
<%inherit file="${inherit(context)}"/>
<%def name="title()">Upload</%def>
<%def name="javascripts()">
${parent.javascripts()}
<script type="text/javascript">
$( function() {
$( "select[refresh_on_change='true']").change( function() {
$( "#upload_form" ).submit();
});
});
</script>
</%def>
<h2>Upload</h2>
<%def name="title()">
%if selected_upload_type == 'tool':
Upload a tool archive
%elif selected_upload_type == 'toolsuite':
Upload a tool suite archive
%endif
</%def>
<h2>
%if selected_upload_type == 'tool':
Upload a tool archive
%elif selected_upload_type == 'toolsuite':
Upload a tool suite archive
%endif
</h2>
%if message:
${render_msg( message, status )}
%endif
<div class="toolForm">
<div class="toolFormTitle">Upload</div>
%if selected_upload_type == 'tool':
<div class="toolFormTitle">Upload a single tool archive</div>
%else:
<div class="toolFormTitle">Upload a tool suite archive</div>
%endif
<div class="toolFormBody">
## TODO: nginx
<form id="upload_form" name="upload_form" action="${h.url_for( controller='upload', action='upload' )}" enctype="multipart/form-data" method="post">
@@ -28,18 +55,14 @@
<div class="form-row">
<label>Upload Type</label>
<div class="form-row-input">
<select name="upload_type">
%for type_id, type_name in upload_types:
%if type_id == selected_upload_type:
<option value="${type_id}" selected>${type_name}</option>
%else:
<option value="${type_id}">${type_name}</option>
%endif
%endfor
</select>
${upload_type_select_list.get_html()}
</div>
<div class="toolParamHelp" style="clear: both;">
Need help creating a tool file? See the <a href="${h.url_for( controller='tool', action='help' )}">Tool Help</a> page.
%if selected_upload_type == 'tool':
Need help creating a single tool archive? See details below.
%elif selected_upload_type == 'toolsuite':
Need help creating a tool suite archive? See details below.
%endif
</div>
<div style="clear: both"></div>
</div>
@@ -77,3 +100,151 @@
</form>
</div>
</div>
<p/>
<div class="toolFormTitle">Creating an archive containing a tool or a suite of tools</div>
<p>
A tool or tool suite archive is a tar-format file (bzipped or gzipped tar are valid)
containing all the files necessary to load the tool(s) into a Galaxy instance.
</p>
%if selected_upload_type == 'toolsuite':
<h3>Tool Suite Archive</h3>
<p>
A tools suite must include a file named <code>suite_config.xml</code> which provides information about the id, name,
version and description of the tool suite, as well as the id, name, version and description of each tool
in the suite. Here is an example <code>suite_config.xml</code> file.
</p>
<p>
<pre>
&lt;suite id="lastz_toolsuite" name="Suite of Lastz tools" version="1.0.0"&gt;
&lt;description&gt;This suite contains all of my Lastz tools for Galaxy&lt;/description&gt;
&lt;tool id="lastz_wrapper_2" name="Lastz" version="1.1.0"&gt;
&lt;description&gt; map short reads against reference sequence&lt;/description&gt;
&lt;/tool&gt;
&lt;tool id="lastz_paired_reads_wrapper" name="Lastz paired reads" version="1.0.0"&gt;
&lt;description&gt; map short paired reads against reference sequence&lt;/description&gt;
&lt;/tool&gt;
&lt;/suite&gt;
</pre>
</p>
</p>
<p>
New versions of the suite can be uploaded, replacing an older version of the suite, but the version attribute
of the <suite> tag must be altered the same way that the version attribute of a single tool config must be altered
if uploading a new version of a tool.
</p>
<p>
The id, name and version attributes of each <tool> tag in the <code>suite_config.xml</code> file must exactly match the same
attributes in each associated tool config in the archive or you will not be allowed to upload the archive.
</p>
<p>
In addition to the <code>suite_config.xml</code> file, the archive must include all
<a href="http://bitbucket.org/galaxy/galaxy-central/wiki/ToolConfigSyntax" target="_blank">tool config files</a>,
executables, functional test data (if your tool config includes functional tests) and other files needed for each
of the tools in your suite to function within Galaxy. See the information about single tool archives below for
additional hints to enable ease-of-use when others download your suite of tools.
</p>
<p>
For example, to package the above Lastz suite of tools:
<pre>
user@host:~% tar jcvf ~/Desktop/galaxy_lastz_toolsuite.tar.bz2 lastzsuite
lastzsuite/
lastzsuite/README
lastzsuite/suite_config.xml
lastzsuite/lastz_paired_reads_wrapper.py
lastzsuite/lastz_paired_reads_wrapper.xml
lastzsuite/lastz_wrapper.py
lastzsuite/lastz_wrapper.xml
lastzsuite/lastz-distrib-1.02.00/
lastzsuite/lastz-distrib-1.02.00/src/
lastzsuite/lastz-distrib-1.02.00/src/Makefile
lastzsuite/lastz-distrib-1.02.00/src/version.mak
lastzsuite/lastz-distrib-1.02.00/src/lastz.c
lastzsuite/lastz-distrib-1.02.00/src/lastz.h
...
</pre>
~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded.
</p>
%endif
<h3>Single Tool Archive</h3>
<p>
A single tool archive must include a
<a href="http://bitbucket.org/galaxy/galaxy-central/wiki/ToolConfigSyntax" target="_blank">tool config file</a>
and will probably also include a tool script. If any steps are necessary to install your tool beyond the basic
instructions below, include a README file to provide details. If the tool (or parts of it) are written in C,
the source code can be included (or put links to the source in the README). Do not include pre-compiled binaries
without source since Galaxy is run on a wide variety of platforms. Also, if you are only wrapping or providing a
Galaxy config for a tool that is not your own, be sure the license allows for redistribution before including any
part of that tool in the archive.
</p>
<p>
There are no requirements about the directory structure inside the archive, but for ease of use it's generally
a good idea to put everything inside a sub-directory, instead of directly at the top level.
</p>
<p>
For example, to package the Lastz tool's config file, Galaxy wrapper, and the C source:
<pre>
user@host:~% tar jcvf ~/Desktop/galaxy_lastz_tool.tar.bz2 lastz
lastz/
lastz/README
lastz/lastz_wrapper.py
lastz/lastz_wrapper.xml
lastz/lastz-distrib-1.02.00/
lastz/lastz-distrib-1.02.00/src/
lastz/lastz-distrib-1.02.00/src/Makefile
lastz/lastz-distrib-1.02.00/src/version.mak
lastz/lastz-distrib-1.02.00/src/lastz.c
lastz/lastz-distrib-1.02.00/src/lastz.h
...
</pre>
~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded.
</p>
<h3>Editing Information, Categories, and Submitting For Approval</h3>
<p>
Simply uploading a tool to the Galaxy too shed will not allow other users to find and download your tool. It will
need to be approved by an administrator before it appears in the tool list.
</p>
<p>
After your archive has successfully uploaded, you will be redirected to the Edit Tool page. Provide a detailed
description of what the tool does - this will be used by administrators to understand the tool before approving it
for display on the site. Once approved, this information will be displayed to users who view your tool. In addition,
the site administrators will have configured a number of categories with which you can associate your tool to make it
easy to find by users looking to solve specific problems. Associate as many categories as are relevant to your tool.
You may change the description and associated categories as often as you'd like until you click the "<strong>Submit for
approval</strong>" button. Once submitted, the tool will be approved or rejected by an administrator. If the tool is
rejected, you will see information about why it was rejected, and you can make appropriate changes to the archive and
re-submit it for approval. When it is approved, your archive will be visible to everyone. At that point, the description
and associated categories can only be changed by an administrator.
</p>
<p>
When the tool has been approved or rejected, you may upload a new version by browsing to the tool's "View Tool" page,
clicking the "Tool actions" menu in the upper right corner of the page, and selecting "Upload a new version" from the
menu.
</p>
<hr/>
<h3>Downloading and Installing Tools</h3>
<p>
A tool's download link will send you the tool archive. Once downloaded, unpack the tool on your local Galaxy instance's server:
<pre>
user@host:~% tar xvf galaxy_lastz_tool.tar
...
user@host:~% tar zxvf galaxy_lastz_tool.tar.gz
...
user@host:~% tar jxvf galaxy_lastz_tool.tar.bz2
...
</pre>
If the archive includes a README file, consult it for installation instructions. If not, follow these basic steps:
<ol>
<li>Create a directory under <code>galaxy_dist/tools/</code> to house downloaded tool(s).</li>
<li>In the new directory, place the XML and any script file(s) which were contained in the archive.</li>
<li>
If the tool includes binaries, you'll need to copy them to a directory on your <code>$PATH</code>. If the tool depends on
C binaries but does not come with them (only source), you'll need to compile the source first.
</li>
<li>Add the tool to <code>galaxy_dist/tool_conf.xml</code>.</li>
<li>Restart your Galaxy server process.</li>
</ol>
</p>
<p>
In the near future, we plan to implement a more direct method to install tools via the Galaxy administrator user interface instead
of placing files on the filesystem and manually managing the <code>tool_conf.xml</code> file.
</p>