galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
May 2014
- 1 participants
- 242 discussions
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2aafaa6a9159/
Changeset: 2aafaa6a9159
User: jmchilton
Date: 2014-05-28 18:58:33
Summary: Remove invalid comment.
Affected #: 1 file
diff -r 23aac3b3c0e2cfe784d8c5dfd94cc3b6ccff7b7c -r 2aafaa6a915977f2f5970e01ccfbf51dc3db7c14 static/scripts/galaxy.tools.js
--- a/static/scripts/galaxy.tools.js
+++ b/static/scripts/galaxy.tools.js
@@ -30,7 +30,7 @@
'min_option_count': 2 // Don't show multiple select switch if only
// one dataset available.
},
- 'select_collection': { // NOT YET IMPLEMENTED
+ 'select_collection': {
'icon_class': 'fa-folder-o',
'select_by': 'Run tool in parallel across dataset collection',
'allow_remap': false
https://bitbucket.org/galaxy/galaxy-central/commits/a763290e92ad/
Changeset: a763290e92ad
User: jmchilton
Date: 2014-05-28 18:58:33
Summary: Improvements to workflow extraction tests.
Affected #: 1 file
diff -r 2aafaa6a915977f2f5970e01ccfbf51dc3db7c14 -r a763290e92adb2215f4cba507e3eb9fe52618d2c test/api/test_workflows.py
--- a/test/api/test_workflows.py
+++ b/test/api/test_workflows.py
@@ -75,11 +75,12 @@
@skip_without_tool( "cat1" )
def test_extract_from_history( self ):
+ # Run the simple test workflow and extract it back out from history
workflow = self.workflow_populator.load_workflow( name="test_for_extract" )
workflow_request, history_id = self._setup_workflow_run( workflow )
contents_response = self._get( "histories/%s/contents" % history_id )
self._assert_status_code_is( contents_response, 200 )
- hda_ids = map( lambda c: c[ "hid" ], contents_response.json() )
+ input_hids = map( lambda c: c[ "hid" ], contents_response.json() )
run_workflow_response = self._post( "workflows", data=workflow_request )
self._assert_status_code_is( run_workflow_response, 200 )
@@ -89,23 +90,16 @@
jobs_response = self._get( "jobs", data=data )
self._assert_status_code_is( jobs_response, 200 )
cat1_job_id = jobs_response.json()[ 0 ][ "id" ]
-
- contents_response = self._get( "history/%s/contents", data=data )
- create_from_data = dict(
+ downloaded_workflow = self._extract_and_download_workflow(
from_history_id=history_id,
- dataset_ids=dumps( hda_ids ),
+ dataset_ids=dumps( input_hids ),
job_ids=dumps( [ cat1_job_id ] ),
workflow_name="test import from history",
)
- create_workflow_response = self._post( "workflows", data=create_from_data )
- self._assert_status_code_is( create_workflow_response, 200 )
-
- new_workflow_id = create_workflow_response.json()[ "id" ]
- download_response = self._get( "workflows/%s/download" % new_workflow_id )
- self._assert_status_code_is( download_response, 200 )
- downloaded_workflow = download_response.json()
self.assertEquals( downloaded_workflow[ "name" ], "test import from history" )
assert len( downloaded_workflow[ "steps" ] ) == 3
+ self._get_steps_of_type( downloaded_workflow, "data_input", expected_len=2 )
+ self._get_steps_of_type( downloaded_workflow, "tool", expected_len=1 )
@skip_without_tool( "collection_paired_test" )
def test_extract_workflows_with_dataset_collections( self ):
@@ -241,7 +235,8 @@
def _get_steps_of_type( self, downloaded_workflow, type, expected_len=None ):
steps = [ s for s in downloaded_workflow[ "steps" ].values() if s[ "type" ] == type ]
if expected_len is not None:
- assert len( steps ) == expected_len
+ n = len( steps )
+ assert n == expected_len, "Expected %d steps of type %s, found %d" % ( expected_len, type, n )
return steps
@skip_without_tool( "random_lines1" )
https://bitbucket.org/galaxy/galaxy-central/commits/7fd77febf6bb/
Changeset: 7fd77febf6bb
User: jmchilton
Date: 2014-05-28 18:58:33
Summary: Workflow extraction test from copied datasets.
Detailed some bugs I found in the test case and recorded them here https://trello.com/c/mKzLbM2P.
Affected #: 1 file
diff -r a763290e92adb2215f4cba507e3eb9fe52618d2c -r 7fd77febf6bb8aa7a6acde9c3a31429f7b1ee99f test/api/test_workflows.py
--- a/test/api/test_workflows.py
+++ b/test/api/test_workflows.py
@@ -1,6 +1,7 @@
from base import api
from json import dumps
from json import loads
+import operator
import time
from .helpers import WorkflowPopulator
from .helpers import DatasetPopulator
@@ -75,21 +76,11 @@
@skip_without_tool( "cat1" )
def test_extract_from_history( self ):
+ history_id = self.dataset_populator.new_history()
# Run the simple test workflow and extract it back out from history
- workflow = self.workflow_populator.load_workflow( name="test_for_extract" )
- workflow_request, history_id = self._setup_workflow_run( workflow )
+ cat1_job_id = self.__setup_and_run_cat1_workflow( history_id=history_id )
contents_response = self._get( "histories/%s/contents" % history_id )
- self._assert_status_code_is( contents_response, 200 )
- input_hids = map( lambda c: c[ "hid" ], contents_response.json() )
-
- run_workflow_response = self._post( "workflows", data=workflow_request )
- self._assert_status_code_is( run_workflow_response, 200 )
-
- self.dataset_populator.wait_for_history( history_id, assert_ok=True )
- data = dict( history_id=history_id, tool_id="cat1" )
- jobs_response = self._get( "jobs", data=data )
- self._assert_status_code_is( jobs_response, 200 )
- cat1_job_id = jobs_response.json()[ 0 ][ "id" ]
+ input_hids = map( lambda c: c[ "hid" ], contents_response.json()[ 0:2 ] )
downloaded_workflow = self._extract_and_download_workflow(
from_history_id=history_id,
dataset_ids=dumps( input_hids ),
@@ -97,9 +88,74 @@
workflow_name="test import from history",
)
self.assertEquals( downloaded_workflow[ "name" ], "test import from history" )
+ self.__assert_looks_like_cat1_example_workflow( downloaded_workflow )
+
+ def test_extract_with_copied_inputs( self ):
+ old_history_id = self.dataset_populator.new_history()
+ # Run the simple test workflow and extract it back out from history
+ self.__setup_and_run_cat1_workflow( history_id=old_history_id )
+
+ history_id = self.dataset_populator.new_history()
+
+ # Bug cannot mess up hids or these don't extract correctly. See Trello card here:
+ # https://trello.com/c/mKzLbM2P
+ # # create dummy dataset to complicate hid mapping
+ # self.dataset_populator.new_dataset( history_id, content="dummydataset" )
+ # offset = 1
+
+ offset = 0
+ old_contents = self._get( "histories/%s/contents" % old_history_id ).json()
+ for old_dataset in old_contents:
+ payload = dict(
+ source="hda",
+ content=old_dataset["id"]
+ )
+ response = self._post( "histories/%s/contents/datasets" % history_id, payload )
+ self._assert_status_code_is( response, 200 )
+ new_contents = self._get( "histories/%s/contents" % history_id ).json()
+ input_hids = map( lambda c: c[ "hid" ], new_contents[ (offset + 0):(offset + 2) ] )
+ cat1_job_id = self.__job_id( history_id, new_contents[ (offset + 2) ][ "id" ] )
+ downloaded_workflow = self._extract_and_download_workflow(
+ from_history_id=history_id,
+ dataset_ids=dumps( input_hids ),
+ job_ids=dumps( [ cat1_job_id ] ),
+ workflow_name="test import from history",
+ )
+ self.__assert_looks_like_cat1_example_workflow( downloaded_workflow )
+
+ def __assert_looks_like_cat1_example_workflow( self, downloaded_workflow ):
assert len( downloaded_workflow[ "steps" ] ) == 3
- self._get_steps_of_type( downloaded_workflow, "data_input", expected_len=2 )
- self._get_steps_of_type( downloaded_workflow, "tool", expected_len=1 )
+ input_steps = self._get_steps_of_type( downloaded_workflow, "data_input", expected_len=2 )
+ tool_step = self._get_steps_of_type( downloaded_workflow, "tool", expected_len=1 )[ 0 ]
+
+ input1 = tool_step[ "input_connections" ][ "input1" ]
+ input2 = tool_step[ "input_connections" ][ "queries_0|input2" ]
+
+ print downloaded_workflow
+ self.assertEquals( input_steps[ 0 ][ "id" ], input1[ "id" ] )
+ self.assertEquals( input_steps[ 1 ][ "id" ], input2[ "id" ] )
+
+ def __setup_and_run_cat1_workflow( self, history_id ):
+ workflow = self.workflow_populator.load_workflow( name="test_for_extract" )
+ workflow_request, history_id = self._setup_workflow_run( workflow, history_id=history_id )
+ run_workflow_response = self._post( "workflows", data=workflow_request )
+ self._assert_status_code_is( run_workflow_response, 200 )
+
+ self.dataset_populator.wait_for_history( history_id, assert_ok=True, timeout=10 )
+ return self.__cat_job_id( history_id )
+
+ def __cat_job_id( self, history_id ):
+ data = dict( history_id=history_id, tool_id="cat1" )
+ jobs_response = self._get( "jobs", data=data )
+ self._assert_status_code_is( jobs_response, 200 )
+ cat1_job_id = jobs_response.json()[ 0 ][ "id" ]
+ return cat1_job_id
+
+ def __job_id( self, history_id, dataset_id ):
+ url = "histories/%s/contents/%s/provenance" % ( history_id, dataset_id )
+ prov_response = self._get( url, data=dict( follow=False ) )
+ self._assert_status_code_is( prov_response, 200 )
+ return prov_response.json()[ "job_id" ]
@skip_without_tool( "collection_paired_test" )
def test_extract_workflows_with_dataset_collections( self ):
@@ -237,7 +293,7 @@
if expected_len is not None:
n = len( steps )
assert n == expected_len, "Expected %d steps of type %s, found %d" % ( expected_len, type, n )
- return steps
+ return sorted( steps, key=operator.itemgetter("id") )
@skip_without_tool( "random_lines1" )
def test_run_replace_params_by_tool( self ):
@@ -316,7 +372,7 @@
# renamed to 'the_new_name'.
assert "the_new_name" in map( lambda hda: hda[ "name" ], contents )
- def _setup_workflow_run( self, workflow ):
+ def _setup_workflow_run( self, workflow, history_id=None ):
uploaded_workflow_id = self.workflow_populator.create_workflow( workflow )
workflow_inputs = self._workflow_inputs( uploaded_workflow_id )
step_1 = step_2 = None
@@ -326,7 +382,8 @@
step_1 = key
if label == "WorkflowInput2":
step_2 = key
- history_id = self.dataset_populator.new_history()
+ if not history_id:
+ history_id = self.dataset_populator.new_history()
hda1 = self.dataset_populator.new_dataset( history_id, content="1 2 3" )
hda2 = self.dataset_populator.new_dataset( history_id, content="4 5 6" )
workflow_request = dict(
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.
1
0
commit/galaxy-central: greg: Handle Tool Shed category administration in the Tool Shed's repository registry.
by commits-noreply@bitbucket.org 28 May '14
by commits-noreply@bitbucket.org 28 May '14
28 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/23aac3b3c0e2/
Changeset: 23aac3b3c0e2
User: greg
Date: 2014-05-28 18:08:04
Summary: Handle Tool Shed category administration in the Tool Shed's repository registry.
Affected #: 2 files
diff -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb -r 23aac3b3c0e2cfe784d8c5dfd94cc3b6ccff7b7c lib/galaxy/webapps/tool_shed/controllers/admin.py
--- a/lib/galaxy/webapps/tool_shed/controllers/admin.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/admin.py
@@ -132,6 +132,8 @@
category = trans.app.model.Category( name=name, description=description )
trans.sa_session.add( category )
trans.sa_session.flush()
+ # Update the Tool Shed's repository registry.
+ trans.app.repository_registry.add_category_entry( category )
message = "Category '%s' has been created" % category.name
status = 'done'
trans.response.send_redirect( web.url_for( controller='admin',
@@ -224,21 +226,32 @@
message=message,
status='error' ) )
category = suc.get_category( trans, id )
+ original_category_name = str( category.name )
+ original_category_description = str( category.description )
if kwd.get( 'edit_category_button', False ):
+ flush_needed = False
new_name = kwd.get( 'name', '' ).strip()
new_description = kwd.get( 'description', '' ).strip()
- if category.name != new_name or category.description != new_description:
+ if original_category_name != new_name:
if not new_name:
message = 'Enter a valid name'
status = 'error'
- elif category.name != new_name and suc.get_category_by_name( trans, new_name ):
+ elif original_category_name != new_name and suc.get_category_by_name( trans, new_name ):
message = 'A category with that name already exists'
status = 'error'
else:
category.name = new_name
+ flush_needed = True
+ if original_category_description != new_description:
category.description = new_description
+ if not flus_needed:
+ flush_needed = True
+ if flush_needed:
trans.sa_session.add( category )
trans.sa_session.flush()
+ if original_category_name != new_name:
+ # Update the Tool Shed's repository registry.
+ trans.app.repository_registry.edit_category_entry( original_category_name, new_name )
message = "The information has been saved for category '%s'" % ( category.name )
status = 'done'
return trans.response.send_redirect( web.url_for( controller='admin',
@@ -403,6 +416,8 @@
category.deleted = True
trans.sa_session.add( category )
trans.sa_session.flush()
+ # Update the Tool Shed's repository registry.
+ trans.app.repository_registry.remove_category_entry( category )
message += " %s " % category.name
else:
message = "No category ids received for deleting."
@@ -459,6 +474,8 @@
category.deleted = False
trans.sa_session.add( category )
trans.sa_session.flush()
+ # Update the Tool Shed's repository registry.
+ trans.app.repository_registry.add_category_entry( category )
count += 1
undeleted_categories += " %s" % category.name
message = "Undeleted %d categories: %s" % ( count, undeleted_categories )
diff -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb -r 23aac3b3c0e2cfe784d8c5dfd94cc3b6ccff7b7c lib/tool_shed/repository_registry.py
--- a/lib/tool_shed/repository_registry.py
+++ b/lib/tool_shed/repository_registry.py
@@ -41,6 +41,21 @@
self.load_viewable_repositories_and_suites_by_category()
self.load_repository_and_suite_tuples()
+ def add_category_entry( self, category ):
+ category_name = str( category.name )
+ if category_name not in self.viewable_repositories_and_suites_by_category:
+ self.viewable_repositories_and_suites_by_category[ category_name ] = 0
+ if category_name not in self.viewable_suites_by_category:
+ self.viewable_suites_by_category[ category_name ] = 0
+ if category_name not in self.viewable_valid_repositories_and_suites_by_category:
+ self.viewable_valid_repositories_and_suites_by_category[ category_name ] = 0
+ if category_name not in self.viewable_valid_suites_by_category:
+ self.viewable_valid_suites_by_category[ category_name ] = 0
+ if category_name not in self.certified_level_one_viewable_repositories_and_suites_by_category:
+ self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] = 0
+ if category_name not in self.certified_level_one_viewable_suites_by_category:
+ self.certified_level_one_viewable_suites_by_category[ category_name ] = 0
+
def add_entry( self, repository ):
try:
if repository:
@@ -88,6 +103,44 @@
# will be corrected at next server start.
log.exception( "Handled error adding entry to repository registry: %s." % str( e ) )
+ def edit_category_entry( self, old_name, new_name ):
+ if old_name in self.viewable_repositories_and_suites_by_category:
+ val = self.viewable_repositories_and_suites_by_category[ old_name ]
+ del self.viewable_repositories_and_suites_by_category[ old_name ]
+ self.viewable_repositories_and_suites_by_category[ new_name ] = val
+ else:
+ self.viewable_repositories_and_suites_by_category[ new_name ] = 0
+ if old_name in self.viewable_valid_repositories_and_suites_by_category:
+ val = self.viewable_valid_repositories_and_suites_by_category[ old_name ]
+ del self.viewable_valid_repositories_and_suites_by_category[ old_name ]
+ self.viewable_valid_repositories_and_suites_by_category[ new_name ] = val
+ else:
+ self.viewable_valid_repositories_and_suites_by_category[ new_name ] = 0
+ if old_name in self.viewable_suites_by_category:
+ val = self.viewable_suites_by_category[ old_name ]
+ del self.viewable_suites_by_category[ old_name ]
+ self.viewable_suites_by_category[ new_name ] = val
+ else:
+ self.viewable_suites_by_category[ new_name ] = 0
+ if old_name in self.viewable_valid_suites_by_category:
+ val = self.viewable_valid_suites_by_category[ old_name ]
+ del self.viewable_valid_suites_by_category[ old_name ]
+ self.viewable_valid_suites_by_category[ new_name ] = val
+ else:
+ self.viewable_valid_suites_by_category[ new_name ] = 0
+ if old_name in self.certified_level_one_viewable_repositories_and_suites_by_category:
+ val = self.certified_level_one_viewable_repositories_and_suites_by_category[ old_name ]
+ del self.certified_level_one_viewable_repositories_and_suites_by_category[ old_name ]
+ self.certified_level_one_viewable_repositories_and_suites_by_category[ new_name ] = val
+ else:
+ self.certified_level_one_viewable_repositories_and_suites_by_category[ new_name ] = 0
+ if old_name in self.certified_level_one_viewable_suites_by_category:
+ val = self.certified_level_one_viewable_suites_by_category[ old_name ]
+ del self.certified_level_one_viewable_suites_by_category[ old_name ]
+ self.certified_level_one_viewable_suites_by_category[ new_name ] = val
+ else:
+ self.certified_level_one_viewable_suites_by_category[ new_name ] = 0
+
def get_certified_level_one_clause_list( self ):
certified_level_one_tuples = []
clause_list = []
@@ -266,6 +319,21 @@
if repository.type in [ rt_util.REPOSITORY_SUITE_DEFINITION ]:
self.certified_level_one_viewable_suites_by_category[ category_name ] += 1
+ def remove_category_entry( self, category ):
+ catgeory_name = str( category.name )
+ if catgeory_name in self.viewable_repositories_and_suites_by_category:
+ del self.viewable_repositories_and_suites_by_category[ catgeory_name ]
+ if catgeory_name in self.viewable_valid_repositories_and_suites_by_category:
+ del self.viewable_valid_repositories_and_suites_by_category[ catgeory_name ]
+ if catgeory_name in self.viewable_suites_by_category:
+ del self.viewable_suites_by_category[ catgeory_name ]
+ if catgeory_name in self.viewable_valid_suites_by_category:
+ del self.viewable_valid_suites_by_category[ catgeory_name ]
+ if catgeory_name in self.certified_level_one_viewable_repositories_and_suites_by_category:
+ del self.certified_level_one_viewable_repositories_and_suites_by_category[ catgeory_name ]
+ if catgeory_name in self.certified_level_one_viewable_suites_by_category:
+ del self.certified_level_one_viewable_suites_by_category[ catgeory_name ]
+
def remove_entry( self, repository ):
try:
if repository:
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.
1
0
commit/galaxy-central: greg: Continued down-sizing of the Tool Shed's shed_util_common module by moving certain functions to more appropriate locations. Some fixes for adding and removing entries to the Tool Shed's repository registry.
by commits-noreply@bitbucket.org 28 May '14
by commits-noreply@bitbucket.org 28 May '14
28 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/dbc3d5c3506e/
Changeset: dbc3d5c3506e
User: greg
Date: 2014-05-28 17:17:50
Summary: Continued down-sizing of the Tool Shed's shed_util_common module by moving certain functions to more appropriate locations. Some fixes for adding and removing entries to the Tool Shed's repository registry.
Affected #: 36 files
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
--- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
+++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
@@ -11,6 +11,7 @@
from tool_shed.galaxy_install import repository_util
from tool_shed.util import common_util
from tool_shed.util import encoding_util
+from tool_shed.util import hg_util
from tool_shed.util import metadata_util
from tool_shed.util import workflow_util
from tool_shed.util import tool_util
@@ -108,7 +109,7 @@
changeset_revisions = json.from_json_string( raw_text )
if len( changeset_revisions ) >= 1:
return changeset_revisions[ -1 ]
- return suc.INITIAL_CHANGELOG_HASH
+ return hg_util.INITIAL_CHANGELOG_HASH
def __get_value_mapper( self, trans, tool_shed_repository ):
value_mapper={ 'id' : trans.security.encode_id( tool_shed_repository.id ),
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -462,8 +462,8 @@
err_msg = ''
tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository
# Get the tool_dependencies.xml file from the repository.
- tool_dependencies_config = suc.get_config_from_disk( rt_util.TOOL_DEPENDENCY_DEFINITION_FILENAME,
- tool_shed_repository.repo_path( trans.app ) )
+ tool_dependencies_config = hg_util.get_config_from_disk( rt_util.TOOL_DEPENDENCY_DEFINITION_FILENAME,
+ tool_shed_repository.repo_path( trans.app ) )
installed_tool_dependencies = \
common_install_util.install_specified_packages( app=trans.app,
tool_shed_repository=tool_shed_repository,
@@ -505,7 +505,7 @@
'repository/get_latest_downloadable_changeset_revision%s' % params )
raw_text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
latest_downloadable_revision = json.from_json_string( raw_text )
- if latest_downloadable_revision == suc.INITIAL_CHANGELOG_HASH:
+ if latest_downloadable_revision == hg_util.INITIAL_CHANGELOG_HASH:
message = 'Error retrieving the latest downloadable revision for this repository via the url <b>%s</b>.' % url
status = 'error'
else:
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/galaxy/webapps/tool_shed/api/repositories.py
--- a/lib/galaxy/webapps/tool_shed/api/repositories.py
+++ b/lib/galaxy/webapps/tool_shed/api/repositories.py
@@ -13,6 +13,7 @@
import tool_shed.repository_types.util as rt_util
import tool_shed.util.shed_util_common as suc
from tool_shed.galaxy_install import repository_util
+from tool_shed.util import basic_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import import_util
@@ -279,7 +280,7 @@
repository_status_info_dict,
import_results_tups )
import_util.check_status_and_reset_downloadable( trans, import_results_tups )
- suc.remove_dir( file_path )
+ basic_util.remove_dir( file_path )
# NOTE: the order of installation is defined in import_results_tups, but order will be lost
# when transferred to return_dict.
return_dict = {}
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -15,6 +15,7 @@
from galaxy.util import json
from galaxy.model.orm import and_
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import basic_util
from tool_shed.util import common_util
from tool_shed.util import container_util
from tool_shed.util import encoding_util
@@ -1146,7 +1147,7 @@
# server account's .hgrc file to include the following setting:
# [web]
# allow_archive = bz2, gz, zip
- file_type_str = suc.get_file_type_str( changeset_revision, file_type )
+ file_type_str = export_util.get_file_type_str( changeset_revision, file_type )
repository.times_downloaded += 1
trans.sa_session.add( repository )
trans.sa_session.flush()
@@ -1188,7 +1189,7 @@
# Make sure the file is removed from disk after the contents have been downloaded.
os.unlink( repositories_archive.name )
repositories_archive_path, file_name = os.path.split( repositories_archive.name )
- suc.remove_dir( repositories_archive_path )
+ basic_util.remove_dir( repositories_archive_path )
return opened_archive
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, repository_id, changeset_revision )
metadata = repository_metadata.metadata
@@ -1312,7 +1313,10 @@
return self.install_matched_repository_grid( trans, **kwd )
else:
kwd[ 'message' ] = "tool id: <b>%s</b><br/>tool name: <b>%s</b><br/>tool version: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
- ( suc.stringify( tool_ids ), suc.stringify( tool_names ), suc.stringify( tool_versions ), str( exact_matches_checked ) )
+ ( basic_util.stringify( tool_ids ),
+ basic_util.stringify( tool_names ),
+ basic_util.stringify( tool_versions ),
+ str( exact_matches_checked ) )
self.matched_repository_grid.title = "Repositories with matching tools"
return self.matched_repository_grid( trans, **kwd )
else:
@@ -1320,9 +1324,9 @@
status = "error"
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
return trans.fill_template( '/webapps/tool_shed/repository/find_tools.mako',
- tool_id=suc.stringify( tool_ids ),
- tool_name=suc.stringify( tool_names ),
- tool_version=suc.stringify( tool_versions ),
+ tool_id=basic_util.stringify( tool_ids ),
+ tool_name=basic_util.stringify( tool_names ),
+ tool_version=basic_util.stringify( tool_versions ),
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
@@ -1396,7 +1400,7 @@
return self.install_matched_repository_grid( trans, **kwd )
else:
kwd[ 'message' ] = "workflow name: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
- ( suc.stringify( workflow_names ), str( exact_matches_checked ) )
+ ( basic_util.stringify( workflow_names ), str( exact_matches_checked ) )
self.matched_repository_grid.title = "Repositories with matching workflows"
return self.matched_repository_grid( trans, **kwd )
else:
@@ -1407,7 +1411,7 @@
workflow_names = []
exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
return trans.fill_template( '/webapps/tool_shed/repository/find_workflows.mako',
- workflow_name=suc.stringify( workflow_names ),
+ workflow_name=basic_util.stringify( workflow_names ),
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
@@ -1666,7 +1670,7 @@
if repository:
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
return suc.get_latest_downloadable_changeset_revision( trans.app, repository, repo )
- return suc.INITIAL_CHANGELOG_HASH
+ return hg_util.INITIAL_CHANGELOG_HASH
@web.json
def get_readme_files( self, trans, **kwd ):
@@ -1832,7 +1836,7 @@
#manafest.
repo_dir = repository.repo_path( trans.app )
# Get the tool_dependencies.xml file from disk.
- tool_dependencies_config = suc.get_config_from_disk( rt_util.TOOL_DEPENDENCY_DEFINITION_FILENAME, repo_dir )
+ tool_dependencies_config = hg_util.get_config_from_disk( rt_util.TOOL_DEPENDENCY_DEFINITION_FILENAME, repo_dir )
# Return the encoded contents of the tool_dependencies.xml file.
if tool_dependencies_config:
tool_dependencies_config_file = open( tool_dependencies_config, 'rb' )
@@ -1982,7 +1986,7 @@
repository_status_info_dict,
import_results_tups )
import_util.check_status_and_reset_downloadable( trans, import_results_tups )
- suc.remove_dir( file_path )
+ basic_util.remove_dir( file_path )
return trans.fill_template( '/webapps/tool_shed/repository/import_capsule_results.mako',
export_info_dict=export_info_dict,
import_results_tups=import_results_tups,
@@ -2318,7 +2322,7 @@
is_malicious = False
skip_tool_test = None
repository_dependencies = None
- if changeset_revision != suc.INITIAL_CHANGELOG_HASH:
+ if changeset_revision != hg_util.INITIAL_CHANGELOG_HASH:
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, id, changeset_revision )
if repository_metadata:
revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=False )
@@ -2328,8 +2332,8 @@
# There is no repository_metadata defined for the changeset_revision, so see if it was defined in a previous
# changeset in the changelog.
previous_changeset_revision = \
- suc.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=False )
- if previous_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
+ metadata_util.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=False )
+ if previous_changeset_revision != hg_util.INITIAL_CHANGELOG_HASH:
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, id, previous_changeset_revision )
if repository_metadata:
revision_label = hg_util.get_revision_label( trans, repository, previous_changeset_revision, include_date=False )
@@ -2390,7 +2394,7 @@
changeset_revision,
repository_dependencies,
repository_metadata )
- heads = suc.get_repository_heads( repo )
+ heads = hg_util.get_repository_heads( repo )
deprecated_repository_dependency_tups = \
repository_dependency_util.get_repository_dependency_tups_from_repository_metadata( trans.app,
repository_metadata,
@@ -2432,7 +2436,7 @@
repository = suc.get_repository_in_tool_shed( trans, id )
changeset_revision = kwd.get( 'changeset_revision', repository.tip( trans.app ) )
metadata = None
- if changeset_revision != suc.INITIAL_CHANGELOG_HASH:
+ if changeset_revision != hg_util.INITIAL_CHANGELOG_HASH:
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, id, changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
@@ -2441,11 +2445,11 @@
# in a previous changeset in the changelog.
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
previous_changeset_revision = \
- suc.get_previous_metadata_changeset_revision( repository,
- repo,
- changeset_revision,
- downloadable=False )
- if previous_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
+ metadata_util.get_previous_metadata_changeset_revision( repository,
+ repo,
+ changeset_revision,
+ downloadable=False )
+ if previous_changeset_revision != hg_util.INITIAL_CHANGELOG_HASH:
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app,
id,
previous_changeset_revision )
@@ -2602,10 +2606,15 @@
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
# Get the lower bound changeset revision.
- lower_bound_changeset_revision = suc.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=True )
+ lower_bound_changeset_revision = metadata_util.get_previous_metadata_changeset_revision( repository,
+ repo,
+ changeset_revision,
+ downloadable=True )
# Build the list of changeset revision hashes.
changeset_hashes = []
- for changeset in suc.reversed_lower_upper_bounded_changelog( repo, lower_bound_changeset_revision, changeset_revision ):
+ for changeset in hg_util.reversed_lower_upper_bounded_changelog( repo,
+ lower_bound_changeset_revision,
+ changeset_revision ):
changeset_hashes.append( str( repo.changectx( changeset ) ) )
if changeset_hashes:
changeset_hashes_str = ','.join( changeset_hashes )
@@ -3117,7 +3126,7 @@
for diff in patch.diff( repo, node1=ctx_parent.node(), node2=ctx.node(), opts=diffopts ):
if len( diff ) > suc.MAXDIFFSIZE:
diff = util.shrink_string_by_size( diff, suc.MAXDIFFSIZE )
- diffs.append( suc.to_html_string( diff ) )
+ diffs.append( basic_util.to_html_string( diff ) )
modified, added, removed, deleted, unknown, ignored, clean = repo.status( node1=ctx_parent.node(), node2=ctx.node() )
anchors = modified + added + removed + deleted + unknown + ignored + clean
metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans, id, ctx_str, metadata_only=True )
@@ -3236,7 +3245,7 @@
status = 'warning'
else:
metadata = None
- is_malicious = suc.changeset_is_malicious( trans.app, id, repository.tip( trans.app ) )
+ is_malicious = metadata_util.is_malicious( trans.app, id, repository.tip( trans.app ) )
if is_malicious:
if trans.app.security_agent.can_push( trans.app, trans.user, repository ):
message += malicious_error_can_push
@@ -3249,7 +3258,7 @@
repository_dependencies,
repository_metadata )
repository_type_select_field = rt_util.build_repository_type_select_field( trans, repository=repository )
- heads = suc.get_repository_heads( repo )
+ heads = hg_util.get_repository_heads( repo )
return trans.fill_template( '/webapps/tool_shed/repository/view_repository.mako',
repo=repo,
heads=heads,
@@ -3320,7 +3329,7 @@
work_dir )
if message:
status = 'error'
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
break
if guid:
tool_lineage = tool_util.get_version_lineage_for_tool( trans, repository_id, repository_metadata, guid )
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/galaxy/webapps/tool_shed/controllers/repository_review.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
@@ -470,7 +470,7 @@
metadata_revision_hashes = [ metadata_revision.changeset_revision for metadata_revision in repository.metadata_revisions ]
reviewed_revision_hashes = [ review.changeset_revision for review in repository.reviews ]
reviews_dict = odict()
- for changeset in suc.get_reversed_changelog_changesets( repo ):
+ for changeset in hg_util.get_reversed_changelog_changesets( repo ):
ctx = repo.changectx( changeset )
changeset_revision = str( ctx )
if changeset_revision in metadata_revision_hashes or changeset_revision in reviewed_revision_hashes:
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/galaxy/webapps/tool_shed/controllers/upload.py
--- a/lib/galaxy/webapps/tool_shed/controllers/upload.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py
@@ -10,6 +10,7 @@
from galaxy.datatypes import checkers
import tool_shed.repository_types.util as rt_util
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import basic_util
from tool_shed.util import commit_util
from tool_shed.util import hg_util
from tool_shed.util import metadata_util
@@ -64,9 +65,9 @@
try:
commands.clone( hg_util.get_configured_ui(), repo_url, uploaded_directory )
except Exception, e:
- message = 'Error uploading via mercurial clone: %s' % suc.to_html_string( str( e ) )
+ message = 'Error uploading via mercurial clone: %s' % basic_util.to_html_string( str( e ) )
status = 'error'
- suc.remove_dir( uploaded_directory )
+ basic_util.remove_dir( uploaded_directory )
uploaded_directory = None
elif url:
valid_url = True
@@ -296,7 +297,7 @@
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
tool_util.reset_tool_data_tables( trans.app )
if uploaded_directory:
- suc.remove_dir( uploaded_directory )
+ basic_util.remove_dir( uploaded_directory )
trans.response.send_redirect( web.url_for( controller='repository',
action='browse_repository',
id=repository_id,
@@ -305,7 +306,7 @@
status=status ) )
else:
if uploaded_directory:
- suc.remove_dir( uploaded_directory )
+ basic_util.remove_dir( uploaded_directory )
status = 'error'
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
tool_util.reset_tool_data_tables( trans.app )
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -9,6 +9,7 @@
from galaxy import web
from galaxy.model.orm import or_
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import basic_util
from tool_shed.util import common_util
from tool_shed.util import common_install_util
from tool_shed.util import container_util
@@ -448,7 +449,7 @@
files_dir = relative_install_dir
if shed_config_dict.get( 'tool_path' ):
files_dir = os.path.join( shed_config_dict[ 'tool_path' ], files_dir )
- datatypes_config = suc.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, files_dir )
+ datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, files_dir )
# Load data types required by tools.
converter_path, display_path = \
datatype_util.alter_config_and_load_prorietary_datatypes( trans.app, datatypes_config, files_dir, override=False )
@@ -620,14 +621,14 @@
tool_shed_repository,
trans.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from the repository.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', install_dir )
+ tool_dependencies_config = hg_util.get_config_from_disk( 'tool_dependencies.xml', install_dir )
installed_tool_dependencies = \
common_install_util.install_specified_packages( app=trans.app,
tool_shed_repository=tool_shed_repository,
tool_dependencies_config=tool_dependencies_config,
tool_dependencies=tool_shed_repository.tool_dependencies,
from_tool_migration_manager=False )
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
suc.update_tool_shed_repository_status( trans.app,
tool_shed_repository,
trans.install_model.ToolShedRepository.installation_status.INSTALLED )
@@ -878,7 +879,7 @@
repository,
trans.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from the repository.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repository.repo_path( trans.app ) )
+ tool_dependencies_config = hg_util.get_config_from_disk( 'tool_dependencies.xml', repository.repo_path( trans.app ) )
installed_tool_dependencies = \
common_install_util.install_specified_packages( app=trans.app,
tool_shed_repository=repository,
@@ -888,7 +889,7 @@
for installed_tool_dependency in installed_tool_dependencies:
if installed_tool_dependency.status in [ trans.install_model.ToolDependency.installation_status.ERROR ]:
repair_dict = add_repair_dict_entry( repository.name, installed_tool_dependency.error_message )
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
suc.update_tool_shed_repository_status( trans.app, repository, trans.install_model.ToolShedRepository.installation_status.INSTALLED )
return repair_dict
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
@@ -405,7 +405,7 @@
package_name=package_name,
package_version=package_version,
tool_dependencies_config=config_to_use )
- suc.remove_file( tmp_filename )
+ self.remove_file( tmp_filename )
else:
message = "Unable to locate required tool shed repository named %s owned by %s with revision %s." % \
( str( required_repository_name ), str( required_repository_owner ), str( default_required_repository_changeset_revision ) )
@@ -429,6 +429,15 @@
print "Error installing tool dependency for required repository: %s" % str( rd_tool_dependency.error_message )
return tool_dependency, proceed_with_install, action_elem_tuples
+ def remove_file( self, file_name ):
+ """Attempt to remove a file from disk."""
+ if file_name:
+ if os.path.exists( file_name ):
+ try:
+ os.remove( file_name )
+ except:
+ pass
+
class SetEnvironment( RecipeTag ):
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -11,6 +11,7 @@
from galaxy import util
from galaxy.tools import ToolSection
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import basic_util
from tool_shed.util import common_install_util
from tool_shed.util import common_util
from tool_shed.util import datatype_util
@@ -251,13 +252,13 @@
def get_guid( self, repository_clone_url, relative_install_dir, tool_config ):
if self.shed_config_dict.get( 'tool_path' ):
relative_install_dir = os.path.join( self.shed_config_dict[ 'tool_path' ], relative_install_dir )
- tool_config_filename = suc.strip_path( tool_config )
+ tool_config_filename = basic_util.strip_path( tool_config )
for root, dirs, files in os.walk( relative_install_dir ):
if root.find( '.hg' ) < 0 and root.find( 'hgrc' ) < 0:
if '.hg' in dirs:
dirs.remove( '.hg' )
for name in files:
- filename = suc.strip_path( name )
+ filename = basic_util.strip_path( name )
if filename == tool_config_filename:
full_path = str( os.path.abspath( os.path.join( root, name ) ) )
tool = self.toolbox.load_tool( full_path )
@@ -444,7 +445,7 @@
tool_shed_repository,
self.app.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from disk.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repo_install_dir )
+ tool_dependencies_config = hg_util.get_config_from_disk( 'tool_dependencies.xml', repo_install_dir )
installed_tool_dependencies = \
common_install_util.install_specified_packages( app=self.app,
tool_shed_repository=tool_shed_repository,
@@ -462,7 +463,7 @@
self.app.install_model.context.add( tool_shed_repository )
self.app.install_model.context.flush()
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-hrc" )
- datatypes_config = suc.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, repo_install_dir )
+ datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, repo_install_dir )
# Load proprietary data types required by tools. The value of override is not important here since the Galaxy server will be started
# after this installation completes.
converter_path, display_path = datatype_util.alter_config_and_load_prorietary_datatypes( self.app, datatypes_config, repo_install_dir, override=False ) #repo_install_dir was relative_install_dir
@@ -481,7 +482,7 @@
if display_path:
# Load proprietary datatype display applications
self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
def install_repository( self, repository_elem, tool_shed_repository, install_dependencies, is_repository_dependency=False ):
"""Install a single repository, loading contained tools into the tool panel."""
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -98,7 +98,7 @@
def get_value( self, trans, grid, repository ):
"""Display the current repository heads."""
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
- heads = suc.get_repository_heads( repo )
+ heads = hg_util.get_repository_heads( repo )
multiple_heads = len( heads ) > 1
if multiple_heads:
heads_str = '<font color="red">'
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/grids/util.py
--- a/lib/tool_shed/grids/util.py
+++ b/lib/tool_shed/grids/util.py
@@ -5,6 +5,7 @@
from galaxy.web.form_builder import SelectField
from tool_shed.util import hg_util
+from tool_shed.util import metadata_util
from tool_shed.util import shed_util_common as suc
log = logging.getLogger( __name__ )
@@ -178,8 +179,11 @@
return repository_metadata
return None
except:
- latest_downloadable_revision = suc.get_previous_metadata_changeset_revision( repository, repo, tip_ctx, downloadable=True )
- if latest_downloadable_revision == suc.INITIAL_CHANGELOG_HASH:
+ latest_downloadable_revision = metadata_util.get_previous_metadata_changeset_revision( repository,
+ repo,
+ tip_ctx,
+ downloadable=True )
+ if latest_downloadable_revision == hg_util.INITIAL_CHANGELOG_HASH:
return None
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app,
encoded_repository_id,
@@ -225,8 +229,11 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, encoded_repository_id, tip_ctx )
return repository_metadata
except:
- latest_downloadable_revision = suc.get_previous_metadata_changeset_revision( repository, repo, tip_ctx, downloadable=False )
- if latest_downloadable_revision == suc.INITIAL_CHANGELOG_HASH:
+ latest_downloadable_revision = metadata_util.get_previous_metadata_changeset_revision( repository,
+ repo,
+ tip_ctx,
+ downloadable=False )
+ if latest_downloadable_revision == hg_util.INITIAL_CHANGELOG_HASH:
return None
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app,
encoded_repository_id,
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/repository_registry.py
--- a/lib/tool_shed/repository_registry.py
+++ b/lib/tool_shed/repository_registry.py
@@ -50,17 +50,35 @@
for rca in repository.categories:
category = rca.category
category_name = str( category.name )
- self.viewable_repositories_and_suites_by_category[ category_name ] += 1
+ if category_name in self.viewable_repositories_and_suites_by_category:
+ self.viewable_repositories_and_suites_by_category[ category_name ] += 1
+ else:
+ self.viewable_repositories_and_suites_by_category[ category_name ] = 1
if is_valid:
- self.viewable_valid_repositories_and_suites_by_category[ category_name ] += 1
+ if category_name in self.viewable_valid_repositories_and_suites_by_category:
+ self.viewable_valid_repositories_and_suites_by_category[ category_name ] += 1
+ else:
+ self.viewable_valid_repositories_and_suites_by_category[ category_name ] = 1
if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION:
- self.viewable_suites_by_category[ category_name ] += 1
+ if category_name in self.viewable_suites_by_category:
+ self.viewable_suites_by_category[ category_name ] += 1
+ else:
+ self.viewable_suites_by_category[ category_name ] = 1
if is_valid:
- self.viewable_valid_suites_by_category[ category_name ] += 1
+ if category_name in self.viewable_valid_suites_by_category:
+ self.viewable_valid_suites_by_category[ category_name ] += 1
+ else:
+ self.viewable_valid_suites_by_category[ category_name ] = 1
if is_level_one_certified:
- self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] += 1
+ if category_name in self.certified_level_one_viewable_repositories_and_suites_by_category:
+ self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] += 1
+ else:
+ self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] = 1
if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION:
- self.certified_level_one_viewable_suites_by_category[ category_name ] += 1
+ if category_name in self.certified_level_one_viewable_suites_by_category:
+ self.certified_level_one_viewable_suites_by_category[ category_name ] += 1
+ else:
+ self.certified_level_one_viewable_suites_by_category[ category_name ] = 1
self.load_repository_and_suite_tuple( repository )
if is_level_one_certified:
self.load_certified_level_one_repository_and_suite_tuple( repository )
@@ -97,7 +115,7 @@
repo = hg_util.get_repo_for_repository( self.app, repository=repository, repo_path=None, create=False )
# Get the latest installable changeset revision since that is all that is currently configured for testing.
latest_installable_changeset_revision = suc.get_latest_downloadable_changeset_revision( self.app, repository, repo )
- if latest_installable_changeset_revision not in [ None, suc.INITIAL_CHANGELOG_HASH ]:
+ if latest_installable_changeset_revision not in [ None, hg_util.INITIAL_CHANGELOG_HASH ]:
encoded_repository_id = self.app.security.encode_id( repository.id )
repository_metadata = suc.get_repository_metadata_by_changeset_revision( self.app,
encoded_repository_id,
@@ -168,7 +186,7 @@
name = str( repository.name )
owner = str( repository.user.username )
tip_changeset_hash = repository.tip( self.app )
- if tip_changeset_hash != suc.INITIAL_CHANGELOG_HASH:
+ if tip_changeset_hash != hg_util.INITIAL_CHANGELOG_HASH:
certified_level_one_tuple = ( name, owner, tip_changeset_hash )
if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION:
if certified_level_one_tuple not in self.certified_level_one_suite_tuples:
@@ -257,17 +275,41 @@
for rca in repository.categories:
category = rca.category
category_name = str( category.name )
- self.viewable_repositories_and_suites_by_category[ category_name ] -= 1
+ if category_name in self.viewable_repositories_and_suites_by_category:
+ if self.viewable_repositories_and_suites_by_category[ category_name ] > 0:
+ self.viewable_repositories_and_suites_by_category[ category_name ] -= 1
+ else:
+ self.viewable_repositories_and_suites_by_category[ category_name ] = 0
if is_valid:
- self.viewable_valid_repositories_and_suites_by_category[ category_name ] -= 1
+ if category_name in self.viewable_valid_repositories_and_suites_by_category:
+ if self.viewable_valid_repositories_and_suites_by_category[ category_name ] > 0:
+ self.viewable_valid_repositories_and_suites_by_category[ category_name ] -= 1
+ else:
+ self.viewable_valid_repositories_and_suites_by_category[ category_name ] = 0
if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION:
- self.viewable_suites_by_category[ category_name ] -= 1
+ if category_name in self.viewable_suites_by_category:
+ if self.viewable_suites_by_category[ category_name ] > 0:
+ self.viewable_suites_by_category[ category_name ] -= 1
+ else:
+ self.viewable_suites_by_category[ category_name ] = 0
if is_valid:
- self.viewable_valid_suites_by_category[ category_name ] -= 1
+ if category_name in self.viewable_valid_suites_by_category:
+ if self.viewable_valid_suites_by_category[ category_name ] > 0:
+ self.viewable_valid_suites_by_category[ category_name ] -= 1
+ else:
+ self.viewable_valid_suites_by_category[ category_name ] = 0
if is_level_one_certified:
- self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] -= 1
+ if category_name in self.certified_level_one_viewable_repositories_and_suites_by_category:
+ if self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] > 0:
+ self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] -= 1
+ else:
+ self.certified_level_one_viewable_repositories_and_suites_by_category[ category_name ] = 0
if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION:
- self.certified_level_one_viewable_suites_by_category[ category_name ] -= 1
+ if category_name in self.certified_level_one_viewable_suites_by_category:
+ if self.certified_level_one_viewable_suites_by_category[ category_name ] > 0:
+ self.certified_level_one_viewable_suites_by_category[ category_name ] -= 1
+ else:
+ self.certified_level_one_viewable_suites_by_category[ category_name ] = 0
self.unload_repository_and_suite_tuple( repository )
if is_level_one_certified:
self.unload_certified_level_one_repository_and_suite_tuple( repository )
@@ -286,7 +328,7 @@
name = str( repository.name )
owner = str( repository.user.username )
tip_changeset_hash = repository.tip( self.app )
- if tip_changeset_hash != suc.INITIAL_CHANGELOG_HASH:
+ if tip_changeset_hash != hg_util.INITIAL_CHANGELOG_HASH:
certified_level_one_tuple = ( name, owner, tip_changeset_hash )
if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION:
if certified_level_one_tuple in self.certified_level_one_suite_tuples:
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/repository_types/repository_suite_definition.py
--- a/lib/tool_shed/repository_types/repository_suite_definition.py
+++ b/lib/tool_shed/repository_types/repository_suite_definition.py
@@ -1,7 +1,7 @@
import logging
from tool_shed.repository_types.metadata import TipOnly
import tool_shed.repository_types.util as rt_util
-import tool_shed.util.shed_util_common as suc
+from tool_shed.util import basic_util
from galaxy import eggs
eggs.require( 'mercurial' )
@@ -35,7 +35,7 @@
# is named repository_dependencies.xml.
files_changed_in_changeset = ctx.files()
for file_path in files_changed_in_changeset:
- file_name = suc.strip_path( file_path )
+ file_name = basic_util.strip_path( file_path )
if file_name not in self.valid_file_names:
return False
return True
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/repository_types/tool_dependency_definition.py
--- a/lib/tool_shed/repository_types/tool_dependency_definition.py
+++ b/lib/tool_shed/repository_types/tool_dependency_definition.py
@@ -1,7 +1,7 @@
import logging
from tool_shed.repository_types.metadata import TipOnly
import tool_shed.repository_types.util as rt_util
-import tool_shed.util.shed_util_common as suc
+from tool_shed.util import basic_util
from galaxy import eggs
eggs.require( 'mercurial' )
@@ -34,7 +34,7 @@
# Inspect all files in the changeset (in sorted order) to make sure there is only one and it is named tool_dependencies.xml.
files_changed_in_changeset = ctx.files()
for file_path in files_changed_in_changeset:
- file_name = suc.strip_path( file_path )
+ file_name = basic_util.strip_path( file_path )
if file_name not in self.valid_file_names:
return False
return True
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/scripts/api/common.py
--- a/lib/tool_shed/scripts/api/common.py
+++ b/lib/tool_shed/scripts/api/common.py
@@ -8,11 +8,8 @@
new_path.extend( sys.path[ 1: ] )
sys.path = new_path
-import tool_shed.util.shed_util_common as suc
from tool_shed.util import common_util
-
-from galaxy import eggs
-import pkg_resources
+from tool_shed.util import hg_util
def delete( api_key, url, data, return_formatted=True ):
"""
@@ -115,7 +112,7 @@
return None, error_message
if len( changeset_revisions ) >= 1:
return changeset_revisions[ -1 ], error_message
- return suc.INITIAL_CHANGELOG_HASH, error_message
+ return hg_util.INITIAL_CHANGELOG_HASH, error_message
def get_repository_dict( url, repository_dict ):
"""
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/scripts/api/export.py
--- a/lib/tool_shed/scripts/api/export.py
+++ b/lib/tool_shed/scripts/api/export.py
@@ -17,17 +17,6 @@
CHUNK_SIZE = 2**20 # 1Mb
-def get_file_type_str( changeset_revision, file_type ):
- if file_type == 'zip':
- file_type_str = '%s.zip' % changeset_revision
- elif file_type == 'bz2':
- file_type_str = '%s.tar.bz2' % changeset_revision
- elif file_type == 'gz':
- file_type_str = '%s.tar.gz' % changeset_revision
- else:
- file_type_str = ''
- return file_type_str
-
def string_as_bool( string ):
if str( string ).lower() in ( 'true', 'yes', 'on' ):
return True
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/scripts/api/get_filtered_repository_revisions.py
--- a/lib/tool_shed/scripts/api/get_filtered_repository_revisions.py
+++ b/lib/tool_shed/scripts/api/get_filtered_repository_revisions.py
@@ -34,7 +34,7 @@
from galaxy.util import asbool
from galaxy.util.json import from_json_string
-import tool_shed.util.shed_util_common as suc
+from tool_shed.util import hg_util
def main( options ):
base_tool_shed_url = options.tool_shed_url.rstrip( '/' )
@@ -71,12 +71,12 @@
repository_dicts.append( baseline_repository_dict )
else:
# Don't test empty repositories.
- changeset_revision = baseline_repository_dict.get( 'changeset_revision', suc.INITIAL_CHANGELOG_HASH )
- if changeset_revision != suc.INITIAL_CHANGELOG_HASH:
+ changeset_revision = baseline_repository_dict.get( 'changeset_revision', hg_util.INITIAL_CHANGELOG_HASH )
+ if changeset_revision != hg_util.INITIAL_CHANGELOG_HASH:
# Merge the dictionary returned from /api/repository_revisions with the detailed repository_dict and
# append it to the list of repository_dicts to install and test.
if latest_revision_only:
- latest_revision = repository_dict.get( 'latest_revision', suc.INITIAL_CHANGELOG_HASH )
+ latest_revision = repository_dict.get( 'latest_revision', hg_util.INITIAL_CHANGELOG_HASH )
if changeset_revision == latest_revision:
repository_dicts.append( dict( repository_dict.items() + baseline_repository_dict.items() ) )
else:
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/basic_util.py
--- /dev/null
+++ b/lib/tool_shed/util/basic_util.py
@@ -0,0 +1,57 @@
+import logging
+import os
+
+from galaxy.util import unicodify
+
+from galaxy import eggs
+
+eggs.require( 'markupsafe' )
+import markupsafe
+
+log = logging.getLogger( __name__ )
+
+MAX_DISPLAY_SIZE = 32768
+
+def remove_dir( dir ):
+ """Attempt to remove a directory from disk."""
+ if dir:
+ if os.path.exists( dir ):
+ try:
+ shutil.rmtree( dir )
+ except:
+ pass
+
+def size_string( raw_text, size=MAX_DISPLAY_SIZE ):
+ """Return a subset of a string (up to MAX_DISPLAY_SIZE) translated to a safe string for display in a browser."""
+ if raw_text and len( raw_text ) >= size:
+ large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( size )
+ raw_text = '%s%s' % ( raw_text[ 0:size ], large_str )
+ return raw_text or ''
+
+def stringify( list ):
+ if list:
+ return ','.join( list )
+ return ''
+
+def strip_path( fpath ):
+ """Attempt to strip the path from a file name."""
+ if not fpath:
+ return fpath
+ try:
+ file_path, file_name = os.path.split( fpath )
+ except:
+ file_name = fpath
+ return file_name
+
+def to_html_string( text ):
+ """Translates the characters in text to an html string"""
+ if text:
+ try:
+ text = unicodify( text )
+ except UnicodeDecodeError, e:
+ return "Error decoding string: %s" % str( e )
+ text = unicode( markupsafe.escape( text ) )
+ text = text.replace( '\n', '<br/>' )
+ text = text.replace( ' ', ' ' )
+ text = text.replace( ' ', ' ' )
+ return text
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/commit_util.py
--- a/lib/tool_shed/util/commit_util.py
+++ b/lib/tool_shed/util/commit_util.py
@@ -345,7 +345,7 @@
if repository:
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
lastest_installable_changeset_revision = suc.get_latest_downloadable_changeset_revision( trans.app, repository, repo )
- if lastest_installable_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
+ if lastest_installable_changeset_revision != hg_util.INITIAL_CHANGELOG_HASH:
elem.attrib[ 'changeset_revision' ] = lastest_installable_changeset_revision
revised = True
else:
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/datatype_util.py
--- a/lib/tool_shed/util/datatype_util.py
+++ b/lib/tool_shed/util/datatype_util.py
@@ -3,6 +3,8 @@
import tempfile
from galaxy import eggs
from galaxy.util import asbool
+from tool_shed.util import basic_util
+from tool_shed.util import hg_util
from tool_shed.util import tool_util
from tool_shed.util import xml_util
import tool_shed.util.shed_util_common as suc
@@ -127,7 +129,7 @@
for converter in elem.findall( 'converter' ):
converter_config = converter.get( 'file', None )
if converter_config:
- converter_config_file_name = suc.strip_path( converter_config )
+ converter_config_file_name = basic_util.strip_path( converter_config )
for root, dirs, files in os.walk( relative_install_dir ):
if root.find( '.hg' ) < 0:
for name in files:
@@ -144,7 +146,7 @@
for display_app in elem.findall( 'display' ):
display_config = display_app.get( 'file', None )
if display_config:
- display_config_file_name = suc.strip_path( display_config )
+ display_config_file_name = basic_util.strip_path( display_config )
for root, dirs, files in os.walk( relative_install_dir ):
if root.find( '.hg' ) < 0:
for name in files:
@@ -166,7 +168,7 @@
# Load proprietary datatypes and return information needed for loading proprietary datatypes converters and display applications later.
metadata = repository.metadata
repository_dict = None
- datatypes_config = suc.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
+ datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
if datatypes_config:
converter_path, display_path = alter_config_and_load_prorietary_datatypes( app, datatypes_config, relative_install_dir, deactivate=deactivate )
if converter_path or display_path:
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/export_util.py
--- a/lib/tool_shed/util/export_util.py
+++ b/lib/tool_shed/util/export_util.py
@@ -11,6 +11,7 @@
from galaxy import eggs
from galaxy import web
from galaxy.util.odict import odict
+from tool_shed.util import basic_util
from tool_shed.util import commit_util
from tool_shed.util import common_install_util
from tool_shed.util import common_util
@@ -101,7 +102,7 @@
attributes, sub_elements = get_repository_attributes_and_sub_elements( ordered_repository, archive_name )
elem = xml_util.create_element( 'repository', attributes=attributes, sub_elements=sub_elements )
exported_repository_registry.exported_repository_elems.append( elem )
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
# Keep information about the export in a file name export_info.xml in the archive.
sub_elements = generate_export_elem( tool_shed_url, repository, changeset_revision, export_repository_dependencies, api )
export_elem = xml_util.create_element( 'export_info', attributes=None, sub_elements=sub_elements )
@@ -127,7 +128,7 @@
return repositories_archive, error_messages
def generate_repository_archive( trans, work_dir, tool_shed_url, repository, changeset_revision, file_type ):
- file_type_str = suc.get_file_type_str( changeset_revision, file_type )
+ file_type_str = get_file_type_str( changeset_revision, file_type )
file_name = '%s-%s' % ( repository.name, file_type_str )
return_code, error_message = archive_repository_revision( trans, ui, repository, work_dir, changeset_revision )
if return_code:
@@ -172,7 +173,7 @@
def generate_repository_archive_filename( tool_shed_url, name, owner, changeset_revision, file_type,
export_repository_dependencies=False, use_tmp_archive_dir=False ):
tool_shed = remove_protocol_from_tool_shed_url( tool_shed_url )
- file_type_str = suc.get_file_type_str( changeset_revision, file_type )
+ file_type_str = get_file_type_str( changeset_revision, file_type )
if export_repository_dependencies:
repositories_archive_filename = '%s_%s_%s_%s_%s' % ( CAPSULE_WITH_DEPENDENCIES_FILENAME, tool_shed, name, owner, file_type_str )
else:
@@ -210,6 +211,17 @@
return repository, repository_metadata.changeset_revision
return None, None
+def get_file_type_str( changeset_revision, file_type ):
+ if file_type == 'zip':
+ file_type_str = '%s.zip' % changeset_revision
+ elif file_type == 'bz2':
+ file_type_str = '%s.tar.bz2' % changeset_revision
+ elif file_type == 'gz':
+ file_type_str = '%s.tar.gz' % changeset_revision
+ else:
+ file_type_str = ''
+ return file_type_str
+
def get_repo_info_dict_for_import( encoded_repository_id, encoded_repository_ids, repo_info_dicts ):
"""
The received encoded_repository_ids and repo_info_dicts are lists that contain associated elements at each
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/hg_util.py
--- a/lib/tool_shed/util/hg_util.py
+++ b/lib/tool_shed/util/hg_util.py
@@ -1,4 +1,6 @@
import logging
+import os
+
from datetime import datetime
from time import gmtime
from time import strftime
@@ -12,8 +14,12 @@
from mercurial import hg
from mercurial import ui
+from tool_shed.util import basic_util
+
log = logging.getLogger( __name__ )
+INITIAL_CHANGELOG_HASH = '000000000000'
+
def clone_repository( repository_clone_url, repository_file_dir, ctx_rev ):
"""
Clone the repository up to the specified changeset_revision. No subsequent revisions will be
@@ -32,6 +38,22 @@
log.debug( error_message )
return False, error_message
+def copy_file_from_manifest( repo, ctx, filename, dir ):
+ """
+ Copy the latest version of the file named filename from the repository manifest to the directory
+ to which dir refers.
+ """
+ for changeset in reversed_upper_bounded_changelog( repo, ctx ):
+ changeset_ctx = repo.changectx( changeset )
+ fctx = get_file_context_from_ctx( changeset_ctx, filename )
+ if fctx and fctx not in [ 'DELETED' ]:
+ file_path = os.path.join( dir, filename )
+ fh = open( file_path, 'wb' )
+ fh.write( fctx.data() )
+ fh.close()
+ return file_path
+ return None
+
def get_changectx_for_changeset( repo, changeset_revision, **kwd ):
"""Retrieve a specified changectx from a repository."""
for changeset in repo.changelog:
@@ -40,6 +62,25 @@
return ctx
return None
+def get_config( config_file, repo, ctx, dir ):
+ """Return the latest version of config_filename from the repository manifest."""
+ config_file = basic_util.strip_path( config_file )
+ for changeset in reversed_upper_bounded_changelog( repo, ctx ):
+ changeset_ctx = repo.changectx( changeset )
+ for ctx_file in changeset_ctx.files():
+ ctx_file_name = basic_util.strip_path( ctx_file )
+ if ctx_file_name == config_file:
+ return get_named_tmpfile_from_ctx( changeset_ctx, ctx_file, dir )
+ return None
+
+def get_config_from_disk( config_file, relative_install_dir ):
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == config_file:
+ return os.path.abspath( os.path.join( root, name ) )
+ return None
+
def get_configured_ui():
"""Configure any desired ui settings."""
_ui = ui.ui()
@@ -50,6 +91,44 @@
_ui.setconfig( 'ui', 'quiet', True )
return _ui
+def get_ctx_file_path_from_manifest( filename, repo, changeset_revision ):
+ """
+ Get the ctx file path for the latest revision of filename from the repository manifest up
+ to the value of changeset_revision.
+ """
+ stripped_filename = basic_util.strip_path( filename )
+ for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
+ manifest_changeset_revision = str( repo.changectx( changeset ) )
+ manifest_ctx = repo.changectx( changeset )
+ for ctx_file in manifest_ctx.files():
+ ctx_file_name = basic_util.strip_path( ctx_file )
+ if ctx_file_name == stripped_filename:
+ return manifest_ctx, ctx_file
+ return None, None
+
+def get_file_context_from_ctx( ctx, filename ):
+ """Return the mercurial file context for a specified file."""
+ # We have to be careful in determining if we found the correct file because multiple files with
+ # the same name may be in different directories within ctx if the files were moved within the change
+ # set. For example, in the following ctx.files() list, the former may have been moved to the latter:
+ # ['tmap_wrapper_0.0.19/tool_data_table_conf.xml.sample', 'tmap_wrapper_0.3.3/tool_data_table_conf.xml.sample'].
+ # Another scenario is that the file has been deleted.
+ deleted = False
+ filename = basic_util.strip_path( filename )
+ for ctx_file in ctx.files():
+ ctx_file_name = basic_util.strip_path( ctx_file )
+ if filename == ctx_file_name:
+ try:
+ # If the file was moved, its destination will be returned here.
+ fctx = ctx[ ctx_file ]
+ return fctx
+ except LookupError, e:
+ # Set deleted for now, and continue looking in case the file was moved instead of deleted.
+ deleted = True
+ if deleted:
+ return 'DELETED'
+ return None
+
def get_mercurial_default_options_dict( command, command_table=None, **kwd ):
'''Borrowed from repoman - get default parameters for a mercurial command.'''
if command_table is None:
@@ -62,6 +141,32 @@
default_options_dict[ option ] = kwd[ option ]
return default_options_dict
+def get_named_tmpfile_from_ctx( ctx, filename, dir ):
+ """
+ Return a named temporary file created from a specified file with a given name included in a repository
+ changeset revision.
+ """
+ filename = basic_util.strip_path( filename )
+ for ctx_file in ctx.files():
+ ctx_file_name = basic_util.strip_path( ctx_file )
+ if filename == ctx_file_name:
+ try:
+ # If the file was moved, its destination file contents will be returned here.
+ fctx = ctx[ ctx_file ]
+ except LookupError, e:
+ # Continue looking in case the file was moved.
+ fctx = None
+ continue
+ if fctx:
+ fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-gntfc", dir=dir )
+ tmp_filename = fh.name
+ fh.close()
+ fh = open( tmp_filename, 'wb' )
+ fh.write( fctx.data() )
+ fh.close()
+ return tmp_filename
+ return None
+
def get_readable_ctx_date( ctx ):
"""Convert the date of the changeset (the received ctx) to a human-readable date."""
t, tz = ctx.date()
@@ -75,6 +180,18 @@
if repo_path is not None:
return hg.repository( get_configured_ui(), repo_path, create=create )
+def get_repository_heads( repo ):
+ """Return current repository heads, which are changesets with no child changesets."""
+ heads = [ repo[ h ] for h in repo.heads( None ) ]
+ return heads
+
+def get_reversed_changelog_changesets( repo ):
+ """Return a list of changesets in reverse order from that provided by the repository manifest."""
+ reversed_changelog = []
+ for changeset in repo.changelog:
+ reversed_changelog.insert( 0, changeset )
+ return reversed_changelog
+
def get_revision_label( trans, repository, changeset_revision, include_date=True, include_hash=True ):
"""
Return a string consisting of the human read-able changeset rev and the changeset revision string
@@ -146,6 +263,38 @@
label = "-1:%s" % changeset_revision
return rev, label
+def reversed_lower_upper_bounded_changelog( repo, excluded_lower_bounds_changeset_revision, included_upper_bounds_changeset_revision ):
+ """
+ Return a reversed list of changesets in the repository changelog after the excluded_lower_bounds_changeset_revision,
+ but up to and including the included_upper_bounds_changeset_revision. The value of excluded_lower_bounds_changeset_revision
+ will be the value of INITIAL_CHANGELOG_HASH if no valid changesets exist before included_upper_bounds_changeset_revision.
+ """
+ # To set excluded_lower_bounds_changeset_revision, calling methods should do the following, where the value
+ # of changeset_revision is a downloadable changeset_revision.
+ # excluded_lower_bounds_changeset_revision = \
+ # metadata_util.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=? )
+ if excluded_lower_bounds_changeset_revision == INITIAL_CHANGELOG_HASH:
+ appending_started = True
+ else:
+ appending_started = False
+ reversed_changelog = []
+ for changeset in repo.changelog:
+ changeset_hash = str( repo.changectx( changeset ) )
+ if appending_started:
+ reversed_changelog.insert( 0, changeset )
+ if changeset_hash == excluded_lower_bounds_changeset_revision and not appending_started:
+ appending_started = True
+ if changeset_hash == included_upper_bounds_changeset_revision:
+ break
+ return reversed_changelog
+
+def reversed_upper_bounded_changelog( repo, included_upper_bounds_changeset_revision ):
+ """
+ Return a reversed list of changesets in the repository changelog up to and including the
+ included_upper_bounds_changeset_revision.
+ """
+ return reversed_lower_upper_bounded_changelog( repo, INITIAL_CHANGELOG_HASH, included_upper_bounds_changeset_revision )
+
def update_repository( repo, ctx_rev=None ):
"""
Update the cloned repository to changeset_revision. It is critical that the installed repository is updated to the desired
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -13,6 +13,7 @@
import tool_shed.util.shed_util_common as suc
from tool_shed.repository_types.metadata import TipOnly
+from tool_shed.util import basic_util
from tool_shed.util import common_util
from tool_shed.util import common_install_util
from tool_shed.util import container_util
@@ -526,7 +527,7 @@
tool_config = sub_elem.attrib[ 'file' ]
target_datatype = sub_elem.attrib[ 'target_datatype' ]
# Parse the tool_config to get the guid.
- tool_config_path = suc.get_config_from_disk( tool_config, repository_files_dir )
+ tool_config_path = hg_util.get_config_from_disk( tool_config, repository_files_dir )
full_path = os.path.abspath( tool_config_path )
tool, valid, error_message = tool_util.load_tool_from_config( app, app.security.encode_id( repository.id ), full_path )
if tool is None:
@@ -632,7 +633,7 @@
app.config.tool_data_path = work_dir #FIXME: Thread safe?
app.config.tool_data_table_config_path = work_dir
# Handle proprietary datatypes, if any.
- datatypes_config = suc.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, files_dir )
+ datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, files_dir )
if datatypes_config:
metadata_dict = generate_datatypes_metadata( app, repository, repository_clone_url, files_dir, datatypes_config, metadata_dict )
# Get the relative path to all sample files included in the repository for storage in the repository's metadata.
@@ -749,14 +750,14 @@
metadata_dict = generate_data_manager_metadata( app,
repository,
files_dir,
- suc.get_config_from_disk( suc.REPOSITORY_DATA_MANAGER_CONFIG_FILENAME, files_dir ),
+ hg_util.get_config_from_disk( suc.REPOSITORY_DATA_MANAGER_CONFIG_FILENAME, files_dir ),
metadata_dict,
shed_config_dict=shed_config_dict )
if readme_files:
metadata_dict[ 'readme_files' ] = readme_files
# This step must be done after metadata for tools has been defined.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', files_dir )
+ tool_dependencies_config = hg_util.get_config_from_disk( 'tool_dependencies.xml', files_dir )
if tool_dependencies_config:
metadata_dict, error_message = generate_tool_dependency_metadata( app,
repository,
@@ -772,7 +773,7 @@
# Reset the value of the app's tool_data_path and tool_data_table_config_path to their respective original values.
app.config.tool_data_path = original_tool_data_path
app.config.tool_data_table_config_path = original_tool_data_table_config_path
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
return metadata_dict, invalid_file_tups
def generate_package_dependency_metadata( app, elem, valid_tool_dependencies_dict, invalid_tool_dependencies_dict ):
@@ -1006,7 +1007,7 @@
outputs = []
for output in ttb.outputs:
name, file_name, extra = output
- outputs.append( ( name, suc.strip_path( file_name ) if file_name else None ) )
+ outputs.append( ( name, basic_util.strip_path( file_name ) if file_name else None ) )
if file_name not in required_files and file_name is not None:
required_files.append( file_name )
test_dict = dict( name=str( ttb.name ),
@@ -1078,6 +1079,29 @@
# The tool did not change through all of the changeset revisions.
return old_id
+def get_previous_metadata_changeset_revision( repository, repo, before_changeset_revision, downloadable=True ):
+ """
+ Return the changeset_revision in the repository changelog that has associated metadata prior to
+ the changeset to which before_changeset_revision refers. If there isn't one, return the hash value
+ of an empty repository changelog, hg_util.INITIAL_CHANGELOG_HASH.
+ """
+ changeset_revisions = suc.get_ordered_metadata_changeset_revisions( repository, repo, downloadable=downloadable )
+ if len( changeset_revisions ) == 1:
+ changeset_revision = changeset_revisions[ 0 ]
+ if changeset_revision == before_changeset_revision:
+ return hg_util.INITIAL_CHANGELOG_HASH
+ return changeset_revision
+ previous_changeset_revision = None
+ for changeset_revision in changeset_revisions:
+ if changeset_revision == before_changeset_revision:
+ if previous_changeset_revision:
+ return previous_changeset_revision
+ else:
+ # Return the hash value of an empty repository changelog - note that this will not be a valid changeset revision.
+ return hg_util.INITIAL_CHANGELOG_HASH
+ else:
+ previous_changeset_revision = changeset_revision
+
def get_relative_path_to_repository_file( root, name, relative_install_dir, work_dir, shed_config_dict, resetting_all_metadata_on_repository ):
if resetting_all_metadata_on_repository:
full_path_to_file = os.path.join( root, name )
@@ -1344,6 +1368,13 @@
return True
return False
+def is_malicious( app, id, changeset_revision, **kwd ):
+ """Check the malicious flag in repository metadata for a specified change set revision."""
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( app, id, changeset_revision )
+ if repository_metadata:
+ return repository_metadata.malicious
+ return False
+
def new_datatypes_metadata_required( trans, repository_metadata, metadata_dict ):
"""
Compare the last saved metadata for each datatype in the repository with the new metadata in metadata_dict to determine if a new
@@ -1821,7 +1852,7 @@
changeset_revisions.append( metadata_changeset_revision )
ancestor_changeset_revision = None
ancestor_metadata_dict = None
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
# Delete all repository_metadata records for this repository that do not have a changeset_revision
# value in changeset_revisions.
clean_repository_metadata( trans, id, changeset_revisions )
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/readme_util.py
--- a/lib/tool_shed/util/readme_util.py
+++ b/lib/tool_shed/util/readme_util.py
@@ -10,6 +10,7 @@
from galaxy.util import unicodify
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import basic_util
from tool_shed.util import common_util
from tool_shed.util import hg_util
@@ -46,7 +47,7 @@
log.exception( "Error reading README file '%s' from disk: %s" % ( str( relative_path_to_readme_file ), str( e ) ) )
text = None
if text:
- text_of_reasonable_length = suc.size_string( text )
+ text_of_reasonable_length = basic_util.size_string( text )
if text_of_reasonable_length.find( '.. image:: ' ) >= 0:
# Handle image display for README files that are contained in repositories in the tool shed or installed into Galaxy.
lock = threading.Lock()
@@ -69,17 +70,17 @@
host_url=web.url_for( '/', qualified=True ) )
text_of_reasonable_length = unicodify( text_of_reasonable_length )
else:
- text_of_reasonable_length = suc.to_html_string( text_of_reasonable_length )
+ text_of_reasonable_length = basic_util.to_html_string( text_of_reasonable_length )
readme_files_dict[ readme_file_name ] = text_of_reasonable_length
else:
# We must be in the tool shed and have an old changeset_revision, so we need to retrieve the file contents from the repository manifest.
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
if ctx:
- fctx = suc.get_file_context_from_ctx( ctx, readme_file_name )
+ fctx = hg_util.get_file_context_from_ctx( ctx, readme_file_name )
if fctx and fctx not in [ 'DELETED' ]:
try:
text = unicodify( fctx.data() )
- readme_files_dict[ readme_file_name ] = suc.size_string( text )
+ readme_files_dict[ readme_file_name ] = basic_util.size_string( text )
except Exception, e:
log.exception( "Error reading README file '%s' from repository manifest: %s" % \
( str( relative_path_to_readme_file ), str( e ) ) )
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/review_util.py
--- a/lib/tool_shed/util/review_util.py
+++ b/lib/tool_shed/util/review_util.py
@@ -55,7 +55,7 @@
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
reviewed_revision_hashes = [ review.changeset_revision for review in repository.reviews ]
previous_reviews_dict = odict()
- for changeset in suc.reversed_upper_bounded_changelog( repo, changeset_revision ):
+ for changeset in hg_util.reversed_upper_bounded_changelog( repo, changeset_revision ):
previous_changeset_revision = str( repo.changectx( changeset ) )
if previous_changeset_revision in reviewed_revision_hashes:
previous_rev, previous_changeset_revision_label = hg_util.get_rev_label_from_changeset_revision( repo, previous_changeset_revision )
@@ -89,7 +89,7 @@
"""Determine if a repository has a changeset revision review prior to the received changeset revision."""
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
reviewed_revision_hashes = [ review.changeset_revision for review in repository.reviews ]
- for changeset in suc.reversed_upper_bounded_changelog( repo, changeset_revision ):
+ for changeset in hg_util.reversed_upper_bounded_changelog( repo, changeset_revision ):
previous_changeset_revision = str( repo.changectx( changeset ) )
if previous_changeset_revision in reviewed_revision_hashes:
return True
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -7,13 +7,13 @@
from galaxy import util
from galaxy.util import asbool
from galaxy.util import json
-from galaxy.util import unicodify
from galaxy.web import url_for
from galaxy.web.form_builder import SelectField
from galaxy.datatypes import checkers
from galaxy.model.orm import and_
from galaxy.model.orm import or_
import sqlalchemy.orm.exc
+from tool_shed.util import basic_util
from tool_shed.util import common_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
@@ -22,18 +22,11 @@
from xml.etree import ElementTree as XmlET
from urllib2 import HTTPError
-from galaxy import eggs
-
-eggs.require( 'markupsafe' )
-import markupsafe
-
log = logging.getLogger( __name__ )
CHUNK_SIZE = 2**20 # 1Mb
-INITIAL_CHANGELOG_HASH = '000000000000'
MAX_CONTENT_SIZE = 1048576
MAXDIFFSIZE = 8000
-MAX_DISPLAY_SIZE = 32768
DATATYPES_CONFIG_FILENAME = 'datatypes_conf.xml'
REPOSITORY_DATA_MANAGER_CONFIG_FILENAME = 'data_manager_conf.xml'
@@ -124,13 +117,6 @@
tool_dependencies_select_field.add_option( option_label, option_value )
return tool_dependencies_select_field
-def changeset_is_malicious( app, id, changeset_revision, **kwd ):
- """Check the malicious flag in repository metadata for a specified change set"""
- repository_metadata = get_repository_metadata_by_changeset_revision( app, id, changeset_revision )
- if repository_metadata:
- return repository_metadata.malicious
- return False
-
def check_or_update_tool_shed_status_for_installed_repository( trans, repository ):
updated = False
tool_shed_status_dict = get_tool_shed_status_for_installed_repository( trans.app, repository )
@@ -157,19 +143,6 @@
shutil.move( filename, os.path.abspath( config_filename ) )
os.chmod( config_filename, 0644 )
-def copy_file_from_manifest( repo, ctx, filename, dir ):
- """Copy the latest version of the file named filename from the repository manifest to the directory to which dir refers."""
- for changeset in reversed_upper_bounded_changelog( repo, ctx ):
- changeset_ctx = repo.changectx( changeset )
- fctx = get_file_context_from_ctx( changeset_ctx, filename )
- if fctx and fctx not in [ 'DELETED' ]:
- file_path = os.path.join( dir, filename )
- fh = open( file_path, 'wb' )
- fh.write( fctx.data() )
- fh.close()
- return file_path
- return None
-
def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url,
metadata_dict, status, current_changeset_revision=None, owner='', dist_to_shed=False ):
"""
@@ -337,7 +310,7 @@
for tool_dict in metadata[ 'tools' ]:
guid = tool_dict[ 'guid' ]
tool_config = tool_dict[ 'tool_config' ]
- file_name = strip_path( tool_config )
+ file_name = basic_util.strip_path( tool_config )
guids_and_configs[ guid ] = file_name
# Parse the shed_tool_conf file in which all of this repository's tools are defined and generate the tool_panel_dict.
tree, error_message = xml_util.parse_xml( shed_tool_conf )
@@ -389,7 +362,7 @@
def get_absolute_path_to_file_in_repository( repo_files_dir, file_name ):
"""Return the absolute path to a specified disk file contained in a repository."""
- stripped_file_name = strip_path( file_name )
+ stripped_file_name = basic_util.strip_path( file_name )
file_path = None
for root, dirs, files in os.walk( repo_files_dir ):
if root.find( '.hg' ) < 0:
@@ -416,25 +389,6 @@
except sqlalchemy.orm.exc.NoResultFound:
return None
-def get_config( config_file, repo, ctx, dir ):
- """Return the latest version of config_filename from the repository manifest."""
- config_file = strip_path( config_file )
- for changeset in reversed_upper_bounded_changelog( repo, ctx ):
- changeset_ctx = repo.changectx( changeset )
- for ctx_file in changeset_ctx.files():
- ctx_file_name = strip_path( ctx_file )
- if ctx_file_name == config_file:
- return get_named_tmpfile_from_ctx( changeset_ctx, ctx_file, dir )
- return None
-
-def get_config_from_disk( config_file, relative_install_dir ):
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == config_file:
- return os.path.abspath( os.path.join( root, name ) )
- return None
-
def get_ctx_rev( app, tool_shed_url, name, owner, changeset_revision ):
"""
Send a request to the tool shed to retrieve the ctx_rev for a repository defined by the
@@ -447,21 +401,6 @@
ctx_rev = common_util.tool_shed_get( app, tool_shed_url, url )
return ctx_rev
-def get_ctx_file_path_from_manifest( filename, repo, changeset_revision ):
- """
- Get the ctx file path for the latest revision of filename from the repository manifest up
- to the value of changeset_revision.
- """
- stripped_filename = strip_path( filename )
- for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
- manifest_changeset_revision = str( repo.changectx( changeset ) )
- manifest_ctx = repo.changectx( changeset )
- for ctx_file in manifest_ctx.files():
- ctx_file_name = strip_path( ctx_file )
- if ctx_file_name == stripped_filename:
- return manifest_ctx, ctx_file
- return None, None
-
def get_current_repository_metadata_for_changeset_revision( app, repository, changeset_revision ):
encoded_repository_id = app.security.encode_id( repository.id )
repository_metadata = get_repository_metadata_by_changeset_revision( app,
@@ -537,40 +476,6 @@
dependent_downloadable_revisions.append( downloadable_revision )
return dependent_downloadable_revisions
-def get_file_context_from_ctx( ctx, filename ):
- """Return the mercurial file context for a specified file."""
- # We have to be careful in determining if we found the correct file because multiple files with
- # the same name may be in different directories within ctx if the files were moved within the change
- # set. For example, in the following ctx.files() list, the former may have been moved to the latter:
- # ['tmap_wrapper_0.0.19/tool_data_table_conf.xml.sample', 'tmap_wrapper_0.3.3/tool_data_table_conf.xml.sample'].
- # Another scenario is that the file has been deleted.
- deleted = False
- filename = strip_path( filename )
- for ctx_file in ctx.files():
- ctx_file_name = strip_path( ctx_file )
- if filename == ctx_file_name:
- try:
- # If the file was moved, its destination will be returned here.
- fctx = ctx[ ctx_file ]
- return fctx
- except LookupError, e:
- # Set deleted for now, and continue looking in case the file was moved instead of deleted.
- deleted = True
- if deleted:
- return 'DELETED'
- return None
-
-def get_file_type_str( changeset_revision, file_type ):
- if file_type == 'zip':
- file_type_str = '%s.zip' % changeset_revision
- elif file_type == 'bz2':
- file_type_str = '%s.tar.bz2' % changeset_revision
- elif file_type == 'gz':
- file_type_str = '%s.tar.gz' % changeset_revision
- else:
- file_type_str = ''
- return file_type_str
-
def get_ids_of_tool_shed_repositories_being_installed( trans, as_string=False ):
installing_repository_ids = []
new_status = trans.install_model.ToolShedRepository.installation_status.NEW
@@ -603,7 +508,7 @@
changeset_revisions = get_ordered_metadata_changeset_revisions( repository, repo, downloadable=False )
if changeset_revisions:
return changeset_revisions[ -1 ]
- return INITIAL_CHANGELOG_HASH
+ return hg_util.INITIAL_CHANGELOG_HASH
def get_latest_downloadable_changeset_revision( app, repository, repo ):
repository_tip = repository.tip( app )
@@ -613,30 +518,7 @@
changeset_revisions = get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True )
if changeset_revisions:
return changeset_revisions[ -1 ]
- return INITIAL_CHANGELOG_HASH
-
-def get_named_tmpfile_from_ctx( ctx, filename, dir ):
- """Return a named temporary file created from a specified file with a given name included in a repository changeset revision."""
- filename = strip_path( filename )
- for ctx_file in ctx.files():
- ctx_file_name = strip_path( ctx_file )
- if filename == ctx_file_name:
- try:
- # If the file was moved, its destination file contents will be returned here.
- fctx = ctx[ ctx_file ]
- except LookupError, e:
- # Continue looking in case the file was moved.
- fctx = None
- continue
- if fctx:
- fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-gntfc", dir=dir )
- tmp_filename = fh.name
- fh.close()
- fh = open( tmp_filename, 'wb' )
- fh.write( fctx.data() )
- fh.close()
- return tmp_filename
- return None
+ return hg_util.INITIAL_CHANGELOG_HASH
def get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision ):
"""
@@ -737,28 +619,6 @@
sorted_changeset_revisions = [ str( changeset_tup[ 1 ] ) for changeset_tup in sorted_changeset_tups ]
return sorted_changeset_revisions
-def get_previous_metadata_changeset_revision( repository, repo, before_changeset_revision, downloadable=True ):
- """
- Return the changeset_revision in the repository changelog that has associated metadata prior to the changeset to which
- before_changeset_revision refers. If there isn't one, return the hash value of an empty repository changelog, INITIAL_CHANGELOG_HASH.
- """
- changeset_revisions = get_ordered_metadata_changeset_revisions( repository, repo, downloadable=downloadable )
- if len( changeset_revisions ) == 1:
- changeset_revision = changeset_revisions[ 0 ]
- if changeset_revision == before_changeset_revision:
- return INITIAL_CHANGELOG_HASH
- return changeset_revision
- previous_changeset_revision = None
- for changeset_revision in changeset_revisions:
- if changeset_revision == before_changeset_revision:
- if previous_changeset_revision:
- return previous_changeset_revision
- else:
- # Return the hash value of an empty repository changelog - note that this will not be a valid changeset revision.
- return INITIAL_CHANGELOG_HASH
- else:
- previous_changeset_revision = changeset_revision
-
def get_prior_import_or_install_required_dict( trans, tsr_ids, repo_info_dicts ):
"""
This method is used in the Tool Shed when exporting a repository and its dependencies, and in Galaxy when a repository and its dependencies
@@ -974,7 +834,7 @@
else:
safe_str = ''
for i, line in enumerate( open( file_path ) ):
- safe_str = '%s%s' % ( safe_str, to_html_string( line ) )
+ safe_str = '%s%s' % ( safe_str, basic_util.to_html_string( line ) )
# Stop reading after string is larger than MAX_CONTENT_SIZE.
if len( safe_str ) > MAX_CONTENT_SIZE:
large_str = \
@@ -982,13 +842,17 @@
util.nice_size( MAX_CONTENT_SIZE )
safe_str = '%s%s' % ( safe_str, large_str )
break
- if len( safe_str ) > MAX_DISPLAY_SIZE:
- # Eliminate the middle of the file to display a file no larger than MAX_DISPLAY_SIZE. This may not be ideal if the file is larger
- # than MAX_CONTENT_SIZE.
+ if len( safe_str ) > basic_util.MAX_DISPLAY_SIZE:
+ # Eliminate the middle of the file to display a file no larger than basic_util.MAX_DISPLAY_SIZE.
+ # This may not be ideal if the file is larger than MAX_CONTENT_SIZE.
join_by_str = \
"<br/><br/>...some text eliminated here because file size is larger than maximum viewing size of %s...<br/><br/>" % \
- util.nice_size( MAX_DISPLAY_SIZE )
- safe_str = util.shrink_string_by_size( safe_str, MAX_DISPLAY_SIZE, join_by=join_by_str, left_larger=True, beginning_on_size_error=True )
+ util.nice_size( basic_util.MAX_DISPLAY_SIZE )
+ safe_str = util.shrink_string_by_size( safe_str,
+ basic_util.MAX_DISPLAY_SIZE,
+ join_by=join_by_str,
+ left_larger=True,
+ beginning_on_size_error=True )
return safe_str
def get_repository_files( trans, folder_path ):
@@ -1023,11 +887,6 @@
# This should never be reached - raise an exception?
return v, None
-def get_repository_heads( repo ):
- """Return current repository heads, which are changesets with no child changesets."""
- heads = [ repo[ h ] for h in repo.heads( None ) ]
- return heads
-
def get_repository_ids_requiring_prior_import_or_install( trans, tsr_ids, repository_dependencies ):
"""
This method is used in the Tool Shed when exporting a repository and its dependencies, and in Galaxy when a repository and its dependencies
@@ -1131,20 +990,13 @@
repository_tools_tups.append( ( relative_path, guid, tool ) )
return repository_tools_tups
-def get_reversed_changelog_changesets( repo ):
- """Return a list of changesets in reverse order from that provided by the repository manifest."""
- reversed_changelog = []
- for changeset in repo.changelog:
- reversed_changelog.insert( 0, changeset )
- return reversed_changelog
-
def get_shed_tool_conf_dict( app, shed_tool_conf ):
"""Return the in-memory version of the shed_tool_conf file, which is stored in the config_elems entry in the shed_tool_conf_dict associated with the file."""
for index, shed_tool_conf_dict in enumerate( app.toolbox.shed_tool_confs ):
if shed_tool_conf == shed_tool_conf_dict[ 'config_filename' ]:
return index, shed_tool_conf_dict
else:
- file_name = strip_path( shed_tool_conf_dict[ 'config_filename' ] )
+ file_name = basic_util.strip_path( shed_tool_conf_dict[ 'config_filename' ] )
if shed_tool_conf == file_name:
return index, shed_tool_conf_dict
@@ -1188,7 +1040,7 @@
if config_filename == shed_tool_conf:
return shed_tool_conf_dict[ 'tool_path' ]
else:
- file_name = strip_path( config_filename )
+ file_name = basic_util.strip_path( config_filename )
if file_name == shed_tool_conf:
return shed_tool_conf_dict[ 'tool_path' ]
return None
@@ -1331,9 +1183,10 @@
repo = hg_util.get_repo_for_repository( trans.app, repository=repository, repo_path=None, create=False )
# Get the upper bound changeset revision.
upper_bound_changeset_revision = get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
- # Build the list of changeset revision hashes defining each available update up to, but excluding, upper_bound_changeset_revision.
+ # Build the list of changeset revision hashes defining each available update up to, but excluding
+ # upper_bound_changeset_revision.
changeset_hashes = []
- for changeset in reversed_lower_upper_bounded_changelog( repo, changeset_revision, upper_bound_changeset_revision ):
+ for changeset in hg_util.reversed_lower_upper_bounded_changelog( repo, changeset_revision, upper_bound_changeset_revision ):
# Make sure to exclude upper_bound_changeset_revision.
if changeset != upper_bound_changeset_revision:
changeset_hashes.append( str( repo.changectx( changeset ) ) )
@@ -1477,7 +1330,10 @@
return False
def open_repository_files_folder( trans, folder_path ):
- """Return a list of dictionaries, each of which contains information for a file or directory contained within a directory in a repository file hierarchy."""
+ """
+ Return a list of dictionaries, each of which contains information for a file or directory contained
+ within a directory in a repository file hierarchy.
+ """
try:
files_list = get_repository_files( trans, folder_path )
except OSError, e:
@@ -1499,28 +1355,6 @@
folder_contents.append( node )
return folder_contents
-def pretty_print( dict=None ):
- if dict is not None:
- return json.to_json_string( dict, sort_keys=True, indent=4 )
-
-def remove_dir( dir ):
- """Attempt to remove a directory from disk."""
- if dir:
- if os.path.exists( dir ):
- try:
- shutil.rmtree( dir )
- except:
- pass
-
-def remove_file( file_name ):
- """Attempt to remove a file from disk."""
- if file_name:
- if os.path.exists( file_name ):
- try:
- os.remove( file_name )
- except:
- pass
-
def repository_was_previously_installed( trans, tool_shed_url, repository_name, repo_info_tuple ):
"""
Find out if a repository is already installed into Galaxy - there are several scenarios where this
@@ -1584,34 +1418,6 @@
trans.install_model.context.add( repository )
trans.install_model.context.flush()
-def reversed_lower_upper_bounded_changelog( repo, excluded_lower_bounds_changeset_revision, included_upper_bounds_changeset_revision ):
- """
- Return a reversed list of changesets in the repository changelog after the excluded_lower_bounds_changeset_revision, but up to and
- including the included_upper_bounds_changeset_revision. The value of excluded_lower_bounds_changeset_revision will be the value of
- INITIAL_CHANGELOG_HASH if no valid changesets exist before included_upper_bounds_changeset_revision.
- """
- # To set excluded_lower_bounds_changeset_revision, calling methods should do the following, where the value of changeset_revision
- # is a downloadable changeset_revision.
- # excluded_lower_bounds_changeset_revision = get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=? )
- if excluded_lower_bounds_changeset_revision == INITIAL_CHANGELOG_HASH:
- appending_started = True
- else:
- appending_started = False
- reversed_changelog = []
- for changeset in repo.changelog:
- changeset_hash = str( repo.changectx( changeset ) )
- if appending_started:
- reversed_changelog.insert( 0, changeset )
- if changeset_hash == excluded_lower_bounds_changeset_revision and not appending_started:
- appending_started = True
- if changeset_hash == included_upper_bounds_changeset_revision:
- break
- return reversed_changelog
-
-def reversed_upper_bounded_changelog( repo, included_upper_bounds_changeset_revision ):
- """Return a reversed list of changesets in the repository changelog up to and including the included_upper_bounds_changeset_revision."""
- return reversed_lower_upper_bounded_changelog( repo, INITIAL_CHANGELOG_HASH, included_upper_bounds_changeset_revision )
-
def set_image_paths( app, encoded_repository_id, text ):
"""
Handle tool help image display for tools that are contained in repositories in the tool shed or installed into Galaxy as well as image
@@ -1666,41 +1472,6 @@
return str( required_rd_tup[ 4 ] )
return 'False'
-def size_string( raw_text, size=MAX_DISPLAY_SIZE ):
- """Return a subset of a string (up to MAX_DISPLAY_SIZE) translated to a safe string for display in a browser."""
- if raw_text and len( raw_text ) >= size:
- large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( size )
- raw_text = '%s%s' % ( raw_text[ 0:size ], large_str )
- return raw_text or ''
-
-def stringify( list ):
- if list:
- return ','.join( list )
- return ''
-
-def strip_path( fpath ):
- """Attempt to strip the path from a file name."""
- if not fpath:
- return fpath
- try:
- file_path, file_name = os.path.split( fpath )
- except:
- file_name = fpath
- return file_name
-
-def to_html_string( text ):
- """Translates the characters in text to an html string"""
- if text:
- try:
- text = unicodify( text )
- except UnicodeDecodeError, e:
- return "Error decoding string: %s" % str( e )
- text = unicode( markupsafe.escape( text ) )
- text = text.replace( '\n', '<br/>' )
- text = text.replace( ' ', ' ' )
- text = text.replace( ' ', ' ' )
- return text
-
def tool_shed_from_repository_clone_url( repository_clone_url ):
"""Given a repository clone URL, return the tool shed that contains the repository."""
return common_util.remove_protocol_and_user_from_clone_url( repository_clone_url ).split( '/repos/' )[ 0 ].rstrip( '/' )
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/tool_dependency_util.py
--- a/lib/tool_shed/util/tool_dependency_util.py
+++ b/lib/tool_shed/util/tool_dependency_util.py
@@ -7,6 +7,8 @@
from galaxy.model.orm import or_
import tool_shed.util.shed_util_common as suc
import tool_shed.repository_types.util as rt_util
+from tool_shed.util import basic_util
+from tool_shed.util import hg_util
from tool_shed.util import xml_util
from tool_shed.galaxy_install.tool_dependencies import td_common_util
@@ -85,7 +87,7 @@
if shed_config_dict.get( 'tool_path' ):
relative_install_dir = os.path.join( shed_config_dict.get( 'tool_path' ), relative_install_dir )
# Get the tool_dependencies.xml file from the repository.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', relative_install_dir )
+ tool_dependencies_config = hg_util.get_config_from_disk( 'tool_dependencies.xml', relative_install_dir )
tree, error_message = xml_util.parse_xml( tool_dependencies_config )
if tree is None:
return tool_dependency_objects
@@ -629,7 +631,7 @@
error_message += ' prepared for re-installation.'
print error_message
tool_dependency.status = app.install_model.ToolDependency.installation_status.NEVER_INSTALLED
- suc.remove_dir( tool_dependency_install_dir )
+ basic_util.remove_dir( tool_dependency_install_dir )
can_install_tool_dependency = True
sa_session.add( tool_dependency )
sa_session.flush()
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb lib/tool_shed/util/tool_util.py
--- a/lib/tool_shed/util/tool_util.py
+++ b/lib/tool_shed/util/tool_util.py
@@ -13,6 +13,7 @@
from galaxy.util.expressions import ExpressionContext
from galaxy.web.form_builder import SelectField
from galaxy.tools.actions.upload import UploadToolAction
+from tool_shed.util import basic_util
from tool_shed.util import common_util
from tool_shed.util import hg_util
from tool_shed.util import xml_util
@@ -119,7 +120,7 @@
return False
if changeset_revision == repository.tip( trans.app ):
return True
- file_name = suc.strip_path( file_path )
+ file_name = basic_util.strip_path( file_path )
latest_version_of_file = get_latest_tool_config_revision_from_repository_manifest( repo, file_name, changeset_revision )
can_use_disk_file = filecmp.cmp( file_path, latest_version_of_file )
try:
@@ -142,7 +143,7 @@
if options and isinstance( options, dynamic_options.DynamicOptions ):
if options.tool_data_table or options.missing_tool_data_table_name:
# Make sure the repository contains a tool_data_table_conf.xml.sample file.
- sample_tool_data_table_conf = suc.get_config_from_disk( 'tool_data_table_conf.xml.sample', repo_dir )
+ sample_tool_data_table_conf = hg_util.get_config_from_disk( 'tool_data_table_conf.xml.sample', repo_dir )
if sample_tool_data_table_conf:
error, correction_msg = handle_sample_tool_data_table_conf_file( app, sample_tool_data_table_conf )
if error:
@@ -158,10 +159,10 @@
if options.index_file or options.missing_index_file:
# Make sure the repository contains the required xxx.loc.sample file.
index_file = options.index_file or options.missing_index_file
- index_file_name = suc.strip_path( index_file )
+ index_file_name = basic_util.strip_path( index_file )
sample_found = False
for sample_file in sample_files:
- sample_file_name = suc.strip_path( sample_file )
+ sample_file_name = basic_util.strip_path( sample_file )
if sample_file_name == '%s.sample' % index_file_name:
options.index_file = index_file_name
options.missing_index_file = None
@@ -206,7 +207,7 @@
"""
if dest_path is None:
dest_path = os.path.abspath( app.config.tool_data_path )
- sample_file_name = suc.strip_path( filename )
+ sample_file_name = basic_util.strip_path( filename )
copied_file = sample_file_name.replace( '.sample', '' )
full_source_path = os.path.abspath( filename )
full_destination_path = os.path.join( dest_path, sample_file_name )
@@ -312,7 +313,7 @@
{<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>}]}
"""
tool_panel_dict = {}
- file_name = suc.strip_path( tool_config )
+ file_name = basic_util.strip_path( tool_config )
tool_section_dicts = generate_tool_section_dicts( tool_config=file_name, tool_sections=tool_sections )
tool_panel_dict[ guid ] = tool_section_dicts
return tool_panel_dict
@@ -412,11 +413,11 @@
This method is restricted to tool_config files rather than any file since it is likely that, with the exception of tool config files,
multiple files will have the same name in various directories within the repository.
"""
- stripped_filename = suc.strip_path( filename )
- for changeset in suc.reversed_upper_bounded_changelog( repo, changeset_revision ):
+ stripped_filename = basic_util.strip_path( filename )
+ for changeset in hg_util.reversed_upper_bounded_changelog( repo, changeset_revision ):
manifest_ctx = repo.changectx( changeset )
for ctx_file in manifest_ctx.files():
- ctx_file_name = suc.strip_path( ctx_file )
+ ctx_file_name = basic_util.strip_path( ctx_file )
if ctx_file_name == stripped_filename:
try:
fctx = manifest_ctx[ ctx_file ]
@@ -442,14 +443,14 @@
"""
deleted_sample_files = []
sample_files = []
- for changeset in suc.reversed_upper_bounded_changelog( repo, ctx ):
+ for changeset in hg_util.reversed_upper_bounded_changelog( repo, ctx ):
changeset_ctx = repo.changectx( changeset )
for ctx_file in changeset_ctx.files():
- ctx_file_name = suc.strip_path( ctx_file )
+ ctx_file_name = basic_util.strip_path( ctx_file )
# If we decide in the future that files deleted later in the changelog should not be used, we can use the following if statement.
# if ctx_file_name.endswith( '.sample' ) and ctx_file_name not in sample_files and ctx_file_name not in deleted_sample_files:
if ctx_file_name.endswith( '.sample' ) and ctx_file_name not in sample_files:
- fctx = suc.get_file_context_from_ctx( changeset_ctx, ctx_file )
+ fctx = hg_util.get_file_context_from_ctx( changeset_ctx, ctx_file )
if fctx in [ 'DELETED' ]:
# Since the possibly future used if statement above is commented out, the same file that was initially added will be
# discovered in an earlier changeset in the change log and fall through to the else block below. In other words, if
@@ -536,7 +537,7 @@
version_lineage = [ guid ]
# Get all ancestor guids of the received guid.
current_child_guid = guid
- for changeset in suc.reversed_upper_bounded_changelog( repo, repository_metadata.changeset_revision ):
+ for changeset in hg_util.reversed_upper_bounded_changelog( repo, repository_metadata.changeset_revision ):
ctx = repo.changectx( changeset )
rm = suc.get_repository_metadata_by_changeset_revision( trans.app, repository_id, str( ctx ) )
if rm:
@@ -546,9 +547,9 @@
current_child_guid = parent_guid
# Get all descendant guids of the received guid.
current_parent_guid = guid
- for changeset in suc.reversed_lower_upper_bounded_changelog( repo,
- repository_metadata.changeset_revision,
- repository.tip( trans.app ) ):
+ for changeset in hg_util.reversed_lower_upper_bounded_changelog( repo,
+ repository_metadata.changeset_revision,
+ repository.tip( trans.app ) ):
ctx = repo.changectx( changeset )
rm = suc.get_repository_metadata_by_changeset_revision( trans.app, repository_id, str( ctx ) )
if rm:
@@ -574,7 +575,7 @@
break
if missing_data_table_entry:
# The repository must contain a tool_data_table_conf.xml.sample file that includes all required entries for all tools in the repository.
- sample_tool_data_table_conf = suc.get_config_from_disk( 'tool_data_table_conf.xml.sample', relative_install_dir )
+ sample_tool_data_table_conf = hg_util.get_config_from_disk( 'tool_data_table_conf.xml.sample', relative_install_dir )
if sample_tool_data_table_conf:
# Add entries to the ToolDataTableManager's in-memory data_tables dictionary.
error, message = handle_sample_tool_data_table_conf_file( app, sample_tool_data_table_conf, persist=True )
@@ -598,11 +599,11 @@
params_with_missing_index_file = repository_tool.params_with_missing_index_file
for param in params_with_missing_index_file:
options = param.options
- missing_file_name = suc.strip_path( options.missing_index_file )
+ missing_file_name = basic_util.strip_path( options.missing_index_file )
if missing_file_name not in sample_files_copied:
# The repository must contain the required xxx.loc.sample file.
for sample_file in sample_files:
- sample_file_name = suc.strip_path( sample_file )
+ sample_file_name = basic_util.strip_path( sample_file )
if sample_file_name == '%s.sample' % missing_file_name:
copy_sample_file( app, sample_file )
if options.tool_data_table and options.tool_data_table.missing_index_file:
@@ -643,7 +644,7 @@
error, message = handle_sample_tool_data_table_conf_file( trans.app, tool_data_table_config )
if error:
log.debug( message )
- manifest_ctx, ctx_file = suc.get_ctx_file_path_from_manifest( tool_config_filename, repo, changeset_revision )
+ manifest_ctx, ctx_file = hg_util.get_ctx_file_path_from_manifest( tool_config_filename, repo, changeset_revision )
if manifest_ctx and ctx_file:
tool, message2 = load_tool_from_tmp_config( trans, repo, repository_id, manifest_ctx, ctx_file, work_dir )
message = concat_messages( message, message2 )
@@ -885,7 +886,7 @@
message = concat_messages( message, message2 )
else:
tool, message, sample_files = handle_sample_files_and_load_tool_from_tmp_config( trans, repo, repository_id, changeset_revision, tool_config_filename, work_dir )
- suc.remove_dir( work_dir )
+ basic_util.remove_dir( work_dir )
trans.app.config.tool_data_path = original_tool_data_path
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
reset_tool_data_tables( trans.app )
@@ -911,7 +912,7 @@
def load_tool_from_tmp_config( trans, repo, repository_id, ctx, ctx_file, work_dir ):
tool = None
message = ''
- tmp_tool_config = suc.get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
+ tmp_tool_config = hg_util.get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
if tmp_tool_config:
element_tree, error_message = xml_util.parse_xml( tmp_tool_config )
if element_tree is None:
@@ -921,7 +922,7 @@
tmp_code_files = []
for code_elem in element_tree_root.findall( 'code' ):
code_file_name = code_elem.get( 'file' )
- tmp_code_file_name = suc.copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
+ tmp_code_file_name = hg_util.copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
if tmp_code_file_name:
tmp_code_files.append( tmp_code_file_name )
tool, valid, message = load_tool_from_config( trans.app, repository_id, tmp_tool_config )
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb templates/admin/review_tool_migration_stages.mako
--- a/templates/admin/review_tool_migration_stages.mako
+++ b/templates/admin/review_tool_migration_stages.mako
@@ -35,7 +35,7 @@
</p></div><table class="grid">
- <% from tool_shed.util.shed_util_common import to_html_string %>
+ <% from tool_shed.util.basic_util import to_html_string %>
%for stage in migration_stages_dict.keys():
<%
migration_command = 'sh ./scripts/migrate_tools/%04d_tools.sh' % stage
diff -r f6aa2d17d38430e92beb9da80f53c9989dd504ee -r dbc3d5c3506ed833dc453faa4f00797d95b8a8bb templates/admin/tool_shed_repository/manage_repository_tool_dependencies.mako
--- a/templates/admin/tool_shed_repository/manage_repository_tool_dependencies.mako
+++ b/templates/admin/tool_shed_repository/manage_repository_tool_dependencies.mako
@@ -31,7 +31,7 @@
%for tool_dependency in repository.tool_dependencies:
<%
if tool_dependency.error_message:
- from tool_shed.util.shed_util_common import to_html_string
+ from tool_shed.util.basic_util import to_html_string
error_message = to_html_string( tool_dependency.error_message )
else:
error_message = ''
This diff is so big that we needed to truncate the remainder.
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.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/eed45027e219/
Changeset: eed45027e219
Branch: next-stable
User: carlfeberhard
Date: 2014-05-28 15:24:01
Summary: Bug fix: allow tags to be added in display_base.mako by swapping the load order of autocomplete plugins (autocomplete still not working)
Affected #: 2 files
diff -r 26952d141e42bd936eab9465c2761325204f9531 -r eed45027e219df9c4fc87fcfc788380ecc500b1a templates/display_base.mako
--- a/templates/display_base.mako
+++ b/templates/display_base.mako
@@ -32,10 +32,19 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "libs/jquery/jstorage", "libs/jquery/jquery.autocomplete", "libs/jquery/jquery.rating",
- "galaxy.autocom_tagging" )}
- ${h.js( "galaxy.panels", "libs/jquery/jstorage", "libs/jquery/jquery.event.drag", "libs/jquery/jquery.event.hover",
- "libs/jquery/jquery.mousewheel", "libs/jquery/jquery-ui", "libs/require", "libs/farbtastic" )}
+ ${h.js(
+ "libs/jquery/jstorage",
+ "libs/jquery/jquery.rating",
+ "galaxy.panels",
+ "libs/jquery/jquery.event.drag",
+ "libs/jquery/jquery.event.hover",
+ "libs/jquery/jquery.mousewheel",
+ "libs/jquery/jquery-ui",
+ "libs/require",
+ "libs/farbtastic",
+ "libs/jquery/jquery.autocomplete",
+ "galaxy.autocom_tagging"
+ )}
<script type="text/javascript">
diff -r 26952d141e42bd936eab9465c2761325204f9531 -r eed45027e219df9c4fc87fcfc788380ecc500b1a templates/tagging_common.mako
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -211,7 +211,7 @@
use_toggle_link: ${iff( use_toggle_link, 'true', 'false' )}
};
- $('#${elt_id}').find( 'input' ).autocomplete_tagging(options);
+ $('#${elt_id}').autocomplete_tagging(options);
</script>
## Use style to hide/display the tag area.
https://bitbucket.org/galaxy/galaxy-central/commits/f6aa2d17d384/
Changeset: f6aa2d17d384
User: carlfeberhard
Date: 2014-05-28 15:25:23
Summary: merge
Affected #: 2 files
diff -r 950e68808ba693d8eeec87b4be9ce78e4b864456 -r f6aa2d17d38430e92beb9da80f53c9989dd504ee templates/display_base.mako
--- a/templates/display_base.mako
+++ b/templates/display_base.mako
@@ -32,10 +32,19 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "libs/jquery/jstorage", "libs/jquery/jquery.autocomplete", "libs/jquery/jquery.rating",
- "galaxy.autocom_tagging" )}
- ${h.js( "galaxy.panels", "libs/jquery/jstorage", "libs/jquery/jquery.event.drag", "libs/jquery/jquery.event.hover",
- "libs/jquery/jquery.mousewheel", "libs/jquery/jquery-ui", "libs/require", "libs/farbtastic" )}
+ ${h.js(
+ "libs/jquery/jstorage",
+ "libs/jquery/jquery.rating",
+ "galaxy.panels",
+ "libs/jquery/jquery.event.drag",
+ "libs/jquery/jquery.event.hover",
+ "libs/jquery/jquery.mousewheel",
+ "libs/jquery/jquery-ui",
+ "libs/require",
+ "libs/farbtastic",
+ "libs/jquery/jquery.autocomplete",
+ "galaxy.autocom_tagging"
+ )}
<script type="text/javascript">
diff -r 950e68808ba693d8eeec87b4be9ce78e4b864456 -r f6aa2d17d38430e92beb9da80f53c9989dd504ee templates/tagging_common.mako
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -211,7 +211,7 @@
use_toggle_link: ${iff( use_toggle_link, 'true', 'false' )}
};
- $('#${elt_id}').find( 'input' ).autocomplete_tagging(options);
+ $('#${elt_id}').autocomplete_tagging(options);
</script>
## Use style to hide/display the tag area.
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.
1
0
commit/galaxy-central: jgoecks: Remove jStorage from Trackster requirements because it is not used.
by commits-noreply@bitbucket.org 27 May '14
by commits-noreply@bitbucket.org 27 May '14
27 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/950e68808ba6/
Changeset: 950e68808ba6
User: jgoecks
Date: 2014-05-27 23:42:10
Summary: Remove jStorage from Trackster requirements because it is not used.
Affected #: 1 file
diff -r be58520000c71329d6e63830fc5776604c7b8382 -r 950e68808ba693d8eeec87b4be9ce78e4b864456 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -8,7 +8,6 @@
[
// load js libraries
'utils/utils',
- 'libs/jquery/jstorage',
'libs/jquery/jquery.event.drag',
'libs/jquery/jquery.event.hover',
'libs/jquery/jquery.mousewheel',
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.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/26952d141e42/
Changeset: 26952d141e42
Branch: next-stable
User: dannon
Date: 2014-05-27 23:11:01
Summary: Fix dep_value being undefined at use. Someone needs to look at the logic here, this is purely an operational fix preventing a crash -- there's logic that still needs to happen somewhere in the chain here.
Affected #: 1 file
diff -r 7a6ce727849489c03fbf766bc98357af52d4ffb8 -r 26952d141e42bd936eab9465c2761325204f9531 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -894,6 +894,10 @@
# If we got this far, we can actually look at the dependencies
# to see if their values will not be available until runtime.
for dep_name in self.get_dependencies():
+ # This may not be completely correct, but it's possible to go
+ # through the layers indicated below without assigning dep_value,
+ # which is even worse. TODO fix it?
+ dep_value = None
if dep_name in context:
dep_value = context[ dep_name ]
else:
@@ -1063,7 +1067,7 @@
'value': value
})
return d
-
+
def _get_dbkey_names( self, trans=None ):
if not self.tool:
# Hack for unit tests, since we have no tool
@@ -1735,7 +1739,7 @@
field_name = "%s%s" % ( self.name, suffix )
field = form_builder.SelectField( field_name, multiple, None, self.refresh_on_change, refresh_on_change_values=self.refresh_on_change_values )
-
+
dataset_collection_matcher = DatasetCollectionMatcher( dataset_matcher )
for history_dataset_collection in history.active_dataset_collections:
https://bitbucket.org/galaxy/galaxy-central/commits/be58520000c7/
Changeset: be58520000c7
User: dannon
Date: 2014-05-27 23:11:13
Summary: merge next-stable.
Affected #: 1 file
diff -r fefcf6f47abe795b392348fbb901ffdf7b5c61ab -r be58520000c71329d6e63830fc5776604c7b8382 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -894,6 +894,10 @@
# If we got this far, we can actually look at the dependencies
# to see if their values will not be available until runtime.
for dep_name in self.get_dependencies():
+ # This may not be completely correct, but it's possible to go
+ # through the layers indicated below without assigning dep_value,
+ # which is even worse. TODO fix it?
+ dep_value = None
if dep_name in context:
dep_value = context[ dep_name ]
else:
@@ -1063,7 +1067,7 @@
'value': value
})
return d
-
+
def _get_dbkey_names( self, trans=None ):
if not self.tool:
# Hack for unit tests, since we have no tool
@@ -1735,7 +1739,7 @@
field_name = "%s%s" % ( self.name, suffix )
field = form_builder.SelectField( field_name, multiple, None, self.refresh_on_change, refresh_on_change_values=self.refresh_on_change_values )
-
+
dataset_collection_matcher = DatasetCollectionMatcher( dataset_matcher )
for history_dataset_collection in history.active_dataset_collections:
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.
1
0
8 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7d0451a2b957/
Changeset: 7d0451a2b957
Branch: next-stable
User: jmchilton
Date: 2014-05-27 19:52:41
Summary: Bugfix: Hadn't implemented clean way to iterate of collection element names in tools.
Perhaps stretching the definition of bugfix here to get this in next-stable.
Affected #: 2 files
diff -r bdff5a8cc4b91ec6deff722884bde7357e67e6ef -r 7d0451a2b957b1b39439eb8c47df8eb7ed7a82b0 lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -272,6 +272,12 @@
def is_collection( self ):
return True
+ def __getitem__( self, key ):
+ if isinstance( key, int ):
+ return self.element_instance_list[ key ]
+ else:
+ return self.element_instances[ key ]
+
def __getattr__( self, key ):
return self.element_instances[ key ]
diff -r bdff5a8cc4b91ec6deff722884bde7357e67e6ef -r 7d0451a2b957b1b39439eb8c47df8eb7ed7a82b0 test/functional/tools/collection_paired_test.xml
--- a/test/functional/tools/collection_paired_test.xml
+++ b/test/functional/tools/collection_paired_test.xml
@@ -1,6 +1,6 @@
<tool id="collection_paired_test" name="paired_test" version="0.1.0"><command>
- cat $f1.forward $f1.reverse >> $out1;
+ cat $f1.forward $f1['reverse'] >> $out1;
</command><inputs><param name="f1" type="data_collection" collection_type="paired" />
https://bitbucket.org/galaxy/galaxy-central/commits/b9a3482a1a3f/
Changeset: b9a3482a1a3f
Branch: next-stable
User: jmchilton
Date: 2014-05-27 19:52:41
Summary: Bugfix: Workflow editor mapping icon bug.
Affected #: 1 file
diff -r 7d0451a2b957b1b39439eb8c47df8eb7ed7a82b0 -r b9a3482a1a3fbde50674f7c65a72bf8a8ecfe51d static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -133,11 +133,11 @@
onMouseEnter: function( e ) {
var model = this.model;
if( ! model.terminal.connected() && model.mapOver.isCollection ) {
- this.$el.color( "red" );
+ this.$el.css( "color", "red" );
}
},
onMouseLeave: function( e ) {
- this.$el.color( "blue" );
+ this.$el.css( "color", "black" );
},
onClick: function( e ) {
var model = this.model;
https://bitbucket.org/galaxy/galaxy-central/commits/d08a3430dc15/
Changeset: d08a3430dc15
Branch: next-stable
User: jmchilton
Date: 2014-05-27 19:52:41
Summary: Bugfix: More left/right -> forward/reverse fixes.
Affected #: 1 file
diff -r b9a3482a1a3fbde50674f7c65a72bf8a8ecfe51d -r d08a3430dc152b4c98ac304377ede5582e2bd450 test/functional/tools/collection_nested_test.xml
--- a/test/functional/tools/collection_nested_test.xml
+++ b/test/functional/tools/collection_nested_test.xml
@@ -16,8 +16,8 @@
<collection type="list:paired"><element name="i1"><collection type="paired">
- <element name="left" value="simple_line.txt" />
- <element name="right" value="simple_line_alternative.txt" />
+ <element name="forward" value="simple_line.txt" />
+ <element name="reverse" value="simple_line_alternative.txt" /></collection></element></collection>
@@ -37,8 +37,8 @@
<test><param name="f1"><collection type="paired">
- <element name="left" value="simple_line.txt" />
- <element name="right" value="simple_line_alternative.txt" />
+ <element name="forward" value="simple_line.txt" />
+ <element name="reverse" value="simple_line_alternative.txt" /></collection></param><output name="out1">
https://bitbucket.org/galaxy/galaxy-central/commits/aec79a7e67a4/
Changeset: aec79a7e67a4
Branch: next-stable
User: jmchilton
Date: 2014-05-27 19:52:41
Summary: Unit tests (would have prevented bug in 4044a2a and similar bugs).
Affected #: 1 file
diff -r d08a3430dc152b4c98ac304377ede5582e2bd450 -r aec79a7e67a4ea73054a868162074a793338a982 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -482,6 +482,17 @@
var c = new Connector( outputTerminal, terminal );
return c;
+ },
+ connectAttachedMappedOutput: function( ) {
+ this.view.addDataInput( { name: "TestName", extensions: [ "txt" ], input_type: "dataset_collection" } );
+ var terminal = this.view.node.input_terminals[ "TestName" ];
+
+ var outputTerminal = new OutputTerminal( { name: "TestOuptut", datatypes: [ "txt" ] } );
+ outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; } };
+ outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: new CollectionTypeDescription( "list" ) };
+ var c = new Connector( outputTerminal, terminal );
+
+ return c;
}
} );
@@ -519,6 +530,14 @@
ok( connector.handle2 === terminal );
} );
+ test( "replacing mapped terminal on data collection input update preserves connections", function() {
+ var connector = this.connectAttachedMappedOutput();
+ var newElement = $("<div class='inputs'></div>");
+ this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset_collection" }, newElement );
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector.handle2 === terminal );
+ } );
+
test( "replacing terminal on data input destroys invalid connections", function() {
var connector = this.connectAttachedTerminal( "txt", "txt" );
var newElement = $("<div class='inputs'></div>");
@@ -529,6 +548,26 @@
ok( connector_destroy_spy.called );
} );
+ test( "replacing terminal on data input with collection changes mapping view type", function() {
+ var connector = this.connectAttachedTerminal( "txt", "txt" );
+ var newElement = $("<div class='inputs'></div>");
+ var connector_destroy_spy = sinon.spy( connector, "destroy" );
+ this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset_collection" }, newElement );
+ // Input type changed to dataset_collection - old connections are reset.
+ // Would be nice to preserve these connections and make them map over.
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector_destroy_spy.called );
+ } );
+
+ test( "replacing terminal on data collection input with simple input changes mapping view type", function() {
+ var connector = this.connectAttachedMappedOutput();
+ var newElement = $("<div class='inputs'></div>");
+ var connector_destroy_spy = sinon.spy( connector, "destroy" );
+ this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset" }, newElement );
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector_destroy_spy.called );
+ } );
+
/* global InputTerminalView */
module( "Input terminal view", {
setup: function() {
https://bitbucket.org/galaxy/galaxy-central/commits/289e48b4f3b2/
Changeset: 289e48b4f3b2
Branch: next-stable
User: jmchilton
Date: 2014-05-27 19:52:41
Summary: Bugfix: Fix another attachable bug related to collections and multiple inputs (like 1882eff).
With unit tests that would have prevented both bugs.
Affected #: 2 files
diff -r aec79a7e67a4ea73054a868162074a793338a982 -r 289e48b4f3b20eca95063f3dcd6a8cfb9d3407e5 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -398,6 +398,9 @@
var thisMapOver = this.mapOver();
if( otherCollectionType.isCollection ) {
if( this.multiple ) {
+ if( this.connected() ) {
+ return false;
+ }
if( otherCollectionType.rank == 1 ) {
return this._producesAcceptableDatatype( other );
} else {
diff -r aec79a7e67a4ea73054a868162074a793338a982 -r 289e48b4f3b20eca95063f3dcd6a8cfb9d3407e5 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -917,6 +917,24 @@
this.verifyNotAttachable( inputTerminal1, "list:paired" );
} );
+ test( "unconnected multiple inputs can be connected to rank 1 collections", function() {
+ var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
+ this.verifyAttachable( inputTerminal1, "list" );
+ } );
+
+ test( "connected multiple input cannot be connected to collections", function() {
+ var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
+ var connectedInput1 = this.addConnectedInput( inputTerminal1 );
+ this.addConnectedOutput( connectedInput1 );
+ // Normally could do this reduction, but cannot because input already connected.
+ this.verifyNotAttachable( connectedInput1, "list" );
+ } );
+
+ test( "unconnected multiple inputs cannot be connected to rank > 1 collections (yet...)", function() {
+ var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
+ this.verifyNotAttachable( inputTerminal1, "list:paired" );
+ } );
+
test( "resetMappingIfNeeded does nothing if not mapped", function() {
var inputTerminal1 = this.newInputTerminal();
inputTerminal1.resetMappingIfNeeded();
https://bitbucket.org/galaxy/galaxy-central/commits/df97683f7ee0/
Changeset: df97683f7ee0
Branch: next-stable
User: jmchilton
Date: 2014-05-27 19:52:41
Summary: Bugfix: Workflow editor would unnessecarily leave nodes in mapped over state when no connections force it.
Other small code harmonizations to do this cleanly.
Affected #: 2 files
diff -r 289e48b4f3b20eca95063f3dcd6a8cfb9d3407e5 -r df97683f7ee0c4370161f26ce862b83283b92219 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -226,7 +226,16 @@
},
resetMappingIfNeeded: function( ) {
- if( ! this.node.hasMappedOverInputTerminals() ) {
+ // If inputs were only mapped over to preserve
+ // an output just disconnected reset these...
+ if( ! this.node.hasConnectedOutputTerminals() && ! this.node.hasConnectedMappedInputTerminals()){
+ _.each( this.node.mappedInputTerminals(), function( mappedInput ) {
+ mappedInput.resetMappingIfNeeded();
+ } );
+ }
+
+ var noMappedInputs = ! this.node.hasMappedOverInputTerminals();
+ if( noMappedInputs ) {
this.resetMapping();
}
},
@@ -654,13 +663,16 @@
this.tool_errors = {};
},
connectedOutputTerminals: function() {
- var connected_outputs = [];
- $.each( this.output_terminals, function( _, t ) {
+ return this._connectedTerminals( this.output_terminals );
+ },
+ _connectedTerminals: function( terminals ) {
+ var connectedTerminals = [];
+ $.each( terminals, function( _, t ) {
if( t.connectors.length > 0 ) {
- connected_outputs.push( t );
+ connectedTerminals.push( t );
}
} );
- return connected_outputs;
+ return connectedTerminals;
},
hasConnectedOutputTerminals: function() {
// return this.connectedOutputTerminals().length > 0; <- optimized this
@@ -686,9 +698,9 @@
}
return false;
},
- _connectedMappedTerminals: function( all_terminals ) {
+ _connectedMappedTerminals: function( terminals ) {
var mapped_outputs = [];
- $.each( all_terminals, function( _, t ) {
+ $.each( terminals, function( _, t ) {
var mapOver = t.mapOver();
if( mapOver.isCollection ) {
if( t.connectors.length > 0 ) {
@@ -698,6 +710,19 @@
});
return mapped_outputs;
},
+ mappedInputTerminals: function() {
+ return this._mappedTerminals( this.input_terminals );
+ },
+ _mappedTerminals: function( terminals ) {
+ var mappedTerminals = [];
+ $.each( terminals, function( _, t ) {
+ var mapOver = t.mapOver();
+ if( mapOver.isCollection ) {
+ mappedTerminals.push( t );
+ }
+ } );
+ return mappedTerminals;
+ },
hasMappedOverInputTerminals: function() {
var found = false;
_.each( this.input_terminals, function( t ) {
@@ -708,11 +733,6 @@
} );
return found;
},
- forceDisconnectOutputs: function() {
- _.each( this.output_terminals, function( terminal ) {
- terminal.disconnectAll();
- } );
- },
redraw : function () {
$.each( this.input_terminals, function( _, t ) {
t.redraw();
diff -r 289e48b4f3b20eca95063f3dcd6a8cfb9d3407e5 -r df97683f7ee0c4370161f26ce862b83283b92219 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -477,7 +477,7 @@
var terminal = this.view.node.input_terminals[ "TestName" ];
var outputTerminal = new OutputTerminal( { name: "TestOuptut", datatypes: [ outputType ] } );
- outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; } };
+ outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; }, hasConnectedOutputTerminals: function() { return true; } };
outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: NULL_COLLECTION_TYPE_DESCRIPTION };
var c = new Connector( outputTerminal, terminal );
@@ -488,7 +488,7 @@
var terminal = this.view.node.input_terminals[ "TestName" ];
var outputTerminal = new OutputTerminal( { name: "TestOuptut", datatypes: [ "txt" ] } );
- outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; } };
+ outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; }, hasConnectedOutputTerminals: function() { return true; } };
outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: new CollectionTypeDescription( "list" ) };
var c = new Connector( outputTerminal, terminal );
https://bitbucket.org/galaxy/galaxy-central/commits/7a6ce7278494/
Changeset: 7a6ce7278494
Branch: next-stable
User: jmchilton
Date: 2014-05-27 19:53:06
Summary: Pack scripts.
Affected #: 1 file
diff -r df97683f7ee0c4370161f26ce862b83283b92219 -r 7a6ce727849489c03fbf766bc98357af52d4ffb8 static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.color("red")}},onMouseLeave:function(a){this.$el.color("blue")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasMappedOverInputTerminals()){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(!this.connected()){a=false}else{var b=this.connectors[0].handle1;if(b===null){a=false}else{if(b.isDataCollectionInput||b.isMappedOver()||b.datatypes.indexOf("input_collection")>0){a=true}else{a=false}}}}else{a=true}}return a},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){var a=[];$.each(this.output_terminals,function(b,c){if(c.connectors.length>0){a.push(c)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},forceDisconnectOutputs:function(){_.each(this.output_terminals,function(a){a.disconnectAll()})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(a,b){b.proxy.terminal.connectors[0].destroy();$(b.proxy).remove();$(b.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.css("color","red")}},onMouseLeave:function(a){this.$el.css("color","black")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasConnectedOutputTerminals()&&!this.node.hasConnectedMappedInputTerminals()){_.each(this.node.mappedInputTerminals(),function(b){b.resetMappingIfNeeded()})}var a=!this.node.hasMappedOverInputTerminals();if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(!this.connected()){a=false}else{var b=this.connectors[0].handle1;if(b===null){a=false}else{if(b.isDataCollectionInput||b.isMappedOver()||b.datatypes.indexOf("input_collection")>0){a=true}else{a=false}}}}else{a=true}}return a},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(this.connected()){return false}if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(b){var a=[];$.each(b,function(c,d){if(d.connectors.length>0){a.push(d)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){a.push(d)}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(a,b){b.proxy.terminal.connectors[0].destroy();$(b.proxy).remove();$(b.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/fefcf6f47abe/
Changeset: fefcf6f47abe
User: jmchilton
Date: 2014-05-27 19:53:20
Summary: Merge next-stable.
Affected #: 6 files
diff -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc -r fefcf6f47abe795b392348fbb901ffdf7b5c61ab lib/galaxy/tools/wrappers.py
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -272,6 +272,12 @@
def is_collection( self ):
return True
+ def __getitem__( self, key ):
+ if isinstance( key, int ):
+ return self.element_instance_list[ key ]
+ else:
+ return self.element_instances[ key ]
+
def __getattr__( self, key ):
return self.element_instances[ key ]
diff -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc -r fefcf6f47abe795b392348fbb901ffdf7b5c61ab static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -133,11 +133,11 @@
onMouseEnter: function( e ) {
var model = this.model;
if( ! model.terminal.connected() && model.mapOver.isCollection ) {
- this.$el.color( "red" );
+ this.$el.css( "color", "red" );
}
},
onMouseLeave: function( e ) {
- this.$el.color( "blue" );
+ this.$el.css( "color", "black" );
},
onClick: function( e ) {
var model = this.model;
@@ -226,7 +226,16 @@
},
resetMappingIfNeeded: function( ) {
- if( ! this.node.hasMappedOverInputTerminals() ) {
+ // If inputs were only mapped over to preserve
+ // an output just disconnected reset these...
+ if( ! this.node.hasConnectedOutputTerminals() && ! this.node.hasConnectedMappedInputTerminals()){
+ _.each( this.node.mappedInputTerminals(), function( mappedInput ) {
+ mappedInput.resetMappingIfNeeded();
+ } );
+ }
+
+ var noMappedInputs = ! this.node.hasMappedOverInputTerminals();
+ if( noMappedInputs ) {
this.resetMapping();
}
},
@@ -398,6 +407,9 @@
var thisMapOver = this.mapOver();
if( otherCollectionType.isCollection ) {
if( this.multiple ) {
+ if( this.connected() ) {
+ return false;
+ }
if( otherCollectionType.rank == 1 ) {
return this._producesAcceptableDatatype( other );
} else {
@@ -651,13 +663,16 @@
this.tool_errors = {};
},
connectedOutputTerminals: function() {
- var connected_outputs = [];
- $.each( this.output_terminals, function( _, t ) {
+ return this._connectedTerminals( this.output_terminals );
+ },
+ _connectedTerminals: function( terminals ) {
+ var connectedTerminals = [];
+ $.each( terminals, function( _, t ) {
if( t.connectors.length > 0 ) {
- connected_outputs.push( t );
+ connectedTerminals.push( t );
}
} );
- return connected_outputs;
+ return connectedTerminals;
},
hasConnectedOutputTerminals: function() {
// return this.connectedOutputTerminals().length > 0; <- optimized this
@@ -683,9 +698,9 @@
}
return false;
},
- _connectedMappedTerminals: function( all_terminals ) {
+ _connectedMappedTerminals: function( terminals ) {
var mapped_outputs = [];
- $.each( all_terminals, function( _, t ) {
+ $.each( terminals, function( _, t ) {
var mapOver = t.mapOver();
if( mapOver.isCollection ) {
if( t.connectors.length > 0 ) {
@@ -695,6 +710,19 @@
});
return mapped_outputs;
},
+ mappedInputTerminals: function() {
+ return this._mappedTerminals( this.input_terminals );
+ },
+ _mappedTerminals: function( terminals ) {
+ var mappedTerminals = [];
+ $.each( terminals, function( _, t ) {
+ var mapOver = t.mapOver();
+ if( mapOver.isCollection ) {
+ mappedTerminals.push( t );
+ }
+ } );
+ return mappedTerminals;
+ },
hasMappedOverInputTerminals: function() {
var found = false;
_.each( this.input_terminals, function( t ) {
@@ -705,11 +733,6 @@
} );
return found;
},
- forceDisconnectOutputs: function() {
- _.each( this.output_terminals, function( terminal ) {
- terminal.disconnectAll();
- } );
- },
redraw : function () {
$.each( this.input_terminals, function( _, t ) {
t.redraw();
diff -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc -r fefcf6f47abe795b392348fbb901ffdf7b5c61ab static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.color("red")}},onMouseLeave:function(a){this.$el.color("blue")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasMappedOverInputTerminals()){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(!this.connected()){a=false}else{var b=this.connectors[0].handle1;if(b===null){a=false}else{if(b.isDataCollectionInput||b.isMappedOver()||b.datatypes.indexOf("input_collection")>0){a=true}else{a=false}}}}else{a=true}}return a},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){var a=[];$.each(this.output_terminals,function(b,c){if(c.connectors.length>0){a.push(c)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},forceDisconnectOutputs:function(){_.each(this.output_terminals,function(a){a.disconnectAll()})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(a,b){b.proxy.terminal.connectors[0].destroy();$(b.proxy).remove();$(b.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.css("color","red")}},onMouseLeave:function(a){this.$el.css("color","black")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasConnectedOutputTerminals()&&!this.node.hasConnectedMappedInputTerminals()){_.each(this.node.mappedInputTerminals(),function(b){b.resetMappingIfNeeded()})}var a=!this.node.hasMappedOverInputTerminals();if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(!this.connected()){a=false}else{var b=this.connectors[0].handle1;if(b===null){a=false}else{if(b.isDataCollectionInput||b.isMappedOver()||b.datatypes.indexOf("input_collection")>0){a=true}else{a=false}}}}else{a=true}}return a},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(this.connected()){return false}if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(b){var a=[];$.each(b,function(c,d){if(d.connectors.length>0){a.push(d)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){a.push(d)}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(a,b){b.proxy.terminal.connectors[0].destroy();$(b.proxy).remove();$(b.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
diff -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc -r fefcf6f47abe795b392348fbb901ffdf7b5c61ab test/functional/tools/collection_nested_test.xml
--- a/test/functional/tools/collection_nested_test.xml
+++ b/test/functional/tools/collection_nested_test.xml
@@ -16,8 +16,8 @@
<collection type="list:paired"><element name="i1"><collection type="paired">
- <element name="left" value="simple_line.txt" />
- <element name="right" value="simple_line_alternative.txt" />
+ <element name="forward" value="simple_line.txt" />
+ <element name="reverse" value="simple_line_alternative.txt" /></collection></element></collection>
@@ -37,8 +37,8 @@
<test><param name="f1"><collection type="paired">
- <element name="left" value="simple_line.txt" />
- <element name="right" value="simple_line_alternative.txt" />
+ <element name="forward" value="simple_line.txt" />
+ <element name="reverse" value="simple_line_alternative.txt" /></collection></param><output name="out1">
diff -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc -r fefcf6f47abe795b392348fbb901ffdf7b5c61ab test/functional/tools/collection_paired_test.xml
--- a/test/functional/tools/collection_paired_test.xml
+++ b/test/functional/tools/collection_paired_test.xml
@@ -1,6 +1,6 @@
<tool id="collection_paired_test" name="paired_test" version="0.1.0"><command>
- cat $f1.forward $f1.reverse >> $out1;
+ cat $f1.forward $f1['reverse'] >> $out1;
</command><inputs><param name="f1" type="data_collection" collection_type="paired" />
diff -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc -r fefcf6f47abe795b392348fbb901ffdf7b5c61ab test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -477,11 +477,22 @@
var terminal = this.view.node.input_terminals[ "TestName" ];
var outputTerminal = new OutputTerminal( { name: "TestOuptut", datatypes: [ outputType ] } );
- outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; } };
+ outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; }, hasConnectedOutputTerminals: function() { return true; } };
outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: NULL_COLLECTION_TYPE_DESCRIPTION };
var c = new Connector( outputTerminal, terminal );
return c;
+ },
+ connectAttachedMappedOutput: function( ) {
+ this.view.addDataInput( { name: "TestName", extensions: [ "txt" ], input_type: "dataset_collection" } );
+ var terminal = this.view.node.input_terminals[ "TestName" ];
+
+ var outputTerminal = new OutputTerminal( { name: "TestOuptut", datatypes: [ "txt" ] } );
+ outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; }, hasConnectedOutputTerminals: function() { return true; } };
+ outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: new CollectionTypeDescription( "list" ) };
+ var c = new Connector( outputTerminal, terminal );
+
+ return c;
}
} );
@@ -519,6 +530,14 @@
ok( connector.handle2 === terminal );
} );
+ test( "replacing mapped terminal on data collection input update preserves connections", function() {
+ var connector = this.connectAttachedMappedOutput();
+ var newElement = $("<div class='inputs'></div>");
+ this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset_collection" }, newElement );
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector.handle2 === terminal );
+ } );
+
test( "replacing terminal on data input destroys invalid connections", function() {
var connector = this.connectAttachedTerminal( "txt", "txt" );
var newElement = $("<div class='inputs'></div>");
@@ -529,6 +548,26 @@
ok( connector_destroy_spy.called );
} );
+ test( "replacing terminal on data input with collection changes mapping view type", function() {
+ var connector = this.connectAttachedTerminal( "txt", "txt" );
+ var newElement = $("<div class='inputs'></div>");
+ var connector_destroy_spy = sinon.spy( connector, "destroy" );
+ this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset_collection" }, newElement );
+ // Input type changed to dataset_collection - old connections are reset.
+ // Would be nice to preserve these connections and make them map over.
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector_destroy_spy.called );
+ } );
+
+ test( "replacing terminal on data collection input with simple input changes mapping view type", function() {
+ var connector = this.connectAttachedMappedOutput();
+ var newElement = $("<div class='inputs'></div>");
+ var connector_destroy_spy = sinon.spy( connector, "destroy" );
+ this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset" }, newElement );
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector_destroy_spy.called );
+ } );
+
/* global InputTerminalView */
module( "Input terminal view", {
setup: function() {
@@ -878,6 +917,24 @@
this.verifyNotAttachable( inputTerminal1, "list:paired" );
} );
+ test( "unconnected multiple inputs can be connected to rank 1 collections", function() {
+ var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
+ this.verifyAttachable( inputTerminal1, "list" );
+ } );
+
+ test( "connected multiple input cannot be connected to collections", function() {
+ var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
+ var connectedInput1 = this.addConnectedInput( inputTerminal1 );
+ this.addConnectedOutput( connectedInput1 );
+ // Normally could do this reduction, but cannot because input already connected.
+ this.verifyNotAttachable( connectedInput1, "list" );
+ } );
+
+ test( "unconnected multiple inputs cannot be connected to rank > 1 collections (yet...)", function() {
+ var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
+ this.verifyNotAttachable( inputTerminal1, "list:paired" );
+ } );
+
test( "resetMappingIfNeeded does nothing if not mapped", function() {
var inputTerminal1 = this.newInputTerminal();
inputTerminal1.resetMappingIfNeeded();
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.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bdff5a8cc4b9/
Changeset: bdff5a8cc4b9
Branch: next-stable
User: greg
Date: 2014-05-27 19:32:49
Summary: Improve exception handling for generated Tool Shed URLs.
Affected #: 4 files
diff -r 2cab30fd7436a0e38bb3d60eea5b5fa929f62244 -r bdff5a8cc4b91ec6deff722884bde7357e67e6ef lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -383,6 +383,11 @@
"""
repository = suc.get_installed_tool_shed_repository( trans, repository_id )
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( trans.app, str( repository.tool_shed ) )
+ if tool_shed_url is None or repository_name is None or repository_owner is None or changeset_revision is None:
+ message = "Unable to retrieve tool dependencies from the Tool Shed because one or more of the following required "
+ message += "parameters is None: tool_shed_url: %s, repository_name: %s, repository_owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( repository_name, repository_owner, changeset_revision )
url = common_util.url_join( tool_shed_url,
'repository/get_tool_dependencies%s' % params )
@@ -403,6 +408,11 @@
"""
repository = suc.get_installed_tool_shed_repository( trans, repository_id )
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( trans.app, str( repository.tool_shed ) )
+ if tool_shed_url is None or repository_name is None or repository_owner is None or changeset_revision is None:
+ message = "Unable to retrieve updated repository information from the Tool Shed because one or more of the following "
+ message += "required parameters is None: tool_shed_url: %s, repository_name: %s, repository_owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( str( repository_name ),
str( repository_owner ),
changeset_revision )
diff -r 2cab30fd7436a0e38bb3d60eea5b5fa929f62244 -r bdff5a8cc4b91ec6deff722884bde7357e67e6ef lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
@@ -161,6 +161,11 @@
def create_temporary_tool_dependencies_config( self, app, tool_shed_url, name, owner, changeset_revision ):
"""Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
+ if tool_shed_url is None or name is None or owner is None or changeset_revision is None:
+ message = "Unable to retrieve required tool_dependencies.xml file from the Tool Shed because one or more of the "
+ message += "following required parameters is None: tool_shed_url: %s, name: %s, owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( name ), str( owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
url = common_util.url_join( tool_shed_url,
'repository/get_tool_dependencies_config_contents%s' % params )
@@ -175,7 +180,7 @@
fh.close()
return tmp_filename
else:
- message = "Unable to retrieve required tool_dependencies.xml file from the tool shed for revision "
+ message = "Unable to retrieve required tool_dependencies.xml file from the Tool Shed for revision "
message += "%s of installed repository %s owned by %s." % ( str( changeset_revision ), str( name ), str( owner ) )
raise Exception( message )
return None
diff -r 2cab30fd7436a0e38bb3d60eea5b5fa929f62244 -r bdff5a8cc4b91ec6deff722884bde7357e67e6ef lib/tool_shed/util/common_util.py
--- a/lib/tool_shed/util/common_util.py
+++ b/lib/tool_shed/util/common_util.py
@@ -107,7 +107,7 @@
def generate_clone_url_for_installed_repository( app, repository ):
"""Generate the URL for cloning a repository that has been installed into a Galaxy instance."""
tool_shed_url = get_tool_shed_url_from_tool_shed_registry( app, str( repository.tool_shed ) )
- return url_join( tool_shed_url, 'repos', repository.owner, repository.name )
+ return url_join( tool_shed_url, 'repos', str( repository.owner ), str( repository.name ) )
def generate_clone_url_for_repository_in_tool_shed( trans, repository ):
"""Generate the URL for cloning a repository that is in the tool shed."""
@@ -316,5 +316,6 @@
"""Return a valid URL produced by appending a base URL and a set of request parameters."""
parts = []
for arg in args:
- parts.append( arg.strip( '/' ) )
+ if arg is not None:
+ parts.append( arg.strip( '/' ) )
return '/'.join( parts )
diff -r 2cab30fd7436a0e38bb3d60eea5b5fa929f62244 -r bdff5a8cc4b91ec6deff722884bde7357e67e6ef lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -942,6 +942,11 @@
"""
# This method is used only in Galaxy, not the Tool Shed. We store the port (if one exists) in the database.
tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
+ if tool_shed is None or name is None or owner is None or changeset_revision is None:
+ message = "Unable to retrieve the repository record from the database because one or more of the following "
+ message += "required parameters is None: tool_shed: %s, name: %s, owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed ), str( name ), str( owner ), str( changeset_revision ) )
+ raise Exception( message )
repository = get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app=app,
tool_shed=tool_shed,
name=name,
@@ -1356,6 +1361,11 @@
the received tool_shed_url / name / owner combination.
"""
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
+ if tool_shed_url is None or name is None or owner is None or changeset_revision is None:
+ message = "Unable to get updated changeset revisions from the Tool Shed because one or more of the following "
+ message += "required parameters is None: tool_shed_url: %s, name: %s, owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( name ), str( owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
url = common_util.url_join( tool_shed_url,
'repository/updated_changeset_revisions%s' % params )
https://bitbucket.org/galaxy/galaxy-central/commits/472fa62aaf72/
Changeset: 472fa62aaf72
User: greg
Date: 2014-05-27 19:33:16
Summary: Merged next-stable
Affected #: 4 files
diff -r 44df8d9c9aa11acf796f88203551a92ac03c559d -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -377,6 +377,11 @@
"""
repository = suc.get_installed_tool_shed_repository( trans, repository_id )
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( trans.app, str( repository.tool_shed ) )
+ if tool_shed_url is None or repository_name is None or repository_owner is None or changeset_revision is None:
+ message = "Unable to retrieve tool dependencies from the Tool Shed because one or more of the following required "
+ message += "parameters is None: tool_shed_url: %s, repository_name: %s, repository_owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( repository_name, repository_owner, changeset_revision )
url = common_util.url_join( tool_shed_url,
'repository/get_tool_dependencies%s' % params )
@@ -397,6 +402,11 @@
"""
repository = suc.get_installed_tool_shed_repository( trans, repository_id )
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( trans.app, str( repository.tool_shed ) )
+ if tool_shed_url is None or repository_name is None or repository_owner is None or changeset_revision is None:
+ message = "Unable to retrieve updated repository information from the Tool Shed because one or more of the following "
+ message += "required parameters is None: tool_shed_url: %s, repository_name: %s, repository_owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( repository_name ), str( repository_owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( str( repository_name ),
str( repository_owner ),
changeset_revision )
diff -r 44df8d9c9aa11acf796f88203551a92ac03c559d -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/tag_handler.py
@@ -161,6 +161,11 @@
def create_temporary_tool_dependencies_config( self, app, tool_shed_url, name, owner, changeset_revision ):
"""Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
+ if tool_shed_url is None or name is None or owner is None or changeset_revision is None:
+ message = "Unable to retrieve required tool_dependencies.xml file from the Tool Shed because one or more of the "
+ message += "following required parameters is None: tool_shed_url: %s, name: %s, owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( name ), str( owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
url = common_util.url_join( tool_shed_url,
'repository/get_tool_dependencies_config_contents%s' % params )
@@ -175,7 +180,7 @@
fh.close()
return tmp_filename
else:
- message = "Unable to retrieve required tool_dependencies.xml file from the tool shed for revision "
+ message = "Unable to retrieve required tool_dependencies.xml file from the Tool Shed for revision "
message += "%s of installed repository %s owned by %s." % ( str( changeset_revision ), str( name ), str( owner ) )
raise Exception( message )
return None
diff -r 44df8d9c9aa11acf796f88203551a92ac03c559d -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc lib/tool_shed/util/common_util.py
--- a/lib/tool_shed/util/common_util.py
+++ b/lib/tool_shed/util/common_util.py
@@ -107,7 +107,7 @@
def generate_clone_url_for_installed_repository( app, repository ):
"""Generate the URL for cloning a repository that has been installed into a Galaxy instance."""
tool_shed_url = get_tool_shed_url_from_tool_shed_registry( app, str( repository.tool_shed ) )
- return url_join( tool_shed_url, 'repos', repository.owner, repository.name )
+ return url_join( tool_shed_url, 'repos', str( repository.owner ), str( repository.name ) )
def generate_clone_url_for_repository_in_tool_shed( trans, repository ):
"""Generate the URL for cloning a repository that is in the tool shed."""
@@ -316,5 +316,6 @@
"""Return a valid URL produced by appending a base URL and a set of request parameters."""
parts = []
for arg in args:
- parts.append( arg.strip( '/' ) )
+ if arg is not None:
+ parts.append( arg.strip( '/' ) )
return '/'.join( parts )
diff -r 44df8d9c9aa11acf796f88203551a92ac03c559d -r 472fa62aaf72a1b7c8a2520665efdc833d2ab5fc lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -929,6 +929,11 @@
"""
# This method is used only in Galaxy, not the Tool Shed. We store the port (if one exists) in the database.
tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
+ if tool_shed is None or name is None or owner is None or changeset_revision is None:
+ message = "Unable to retrieve the repository record from the database because one or more of the following "
+ message += "required parameters is None: tool_shed: %s, name: %s, owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed ), str( name ), str( owner ), str( changeset_revision ) )
+ raise Exception( message )
repository = get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app=app,
tool_shed=tool_shed,
name=name,
@@ -1343,6 +1348,11 @@
the received tool_shed_url / name / owner combination.
"""
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
+ if tool_shed_url is None or name is None or owner is None or changeset_revision is None:
+ message = "Unable to get updated changeset revisions from the Tool Shed because one or more of the following "
+ message += "required parameters is None: tool_shed_url: %s, name: %s, owner: %s, changeset_revision: %s " % \
+ ( str( tool_shed_url ), str( name ), str( owner ), str( changeset_revision ) )
+ raise Exception( message )
params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
url = common_util.url_join( tool_shed_url,
'repository/updated_changeset_revisions%s' % params )
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.
1
0
commit/galaxy-central: carlfeberhard: Style fix: remove manual height setting on empty annotation fields
by commits-noreply@bitbucket.org 27 May '14
by commits-noreply@bitbucket.org 27 May '14
27 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/44df8d9c9aa1/
Changeset: 44df8d9c9aa1
User: carlfeberhard
Date: 2014-05-27 18:14:50
Summary: Style fix: remove manual height setting on empty annotation fields
Affected #: 2 files
diff -r 6934f4ceed4572bffde39303c2ca9a993f1ffc55 -r 44df8d9c9aa11acf796f88203551a92ac03c559d static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1663,7 +1663,6 @@
.hda.dataset .dataset-body .dataset-actions .right .icon-btn{margin-left:2px}
.hda.dataset .dataset-body .tags-display{display:none;margin-bottom:8px}.hda.dataset .dataset-body .tags-display .select2-container{min-width:0px}.hda.dataset .dataset-body .tags-display .select2-container .select2-choices{border-radius:3px}
.hda.dataset .dataset-body .annotation-display{display:none;margin-bottom:8px}.hda.dataset .dataset-body .annotation-display .annotation{border-radius:3px;border:1px solid rgba(153,153,153,0.30000000000000004);padding:4px;white-space:pre-line;overflow:auto}
-.hda.dataset .dataset-body .annotation-display .annotation:empty{height:22px}
.hda.dataset .dataset-body .annotation-display .annotation:empty:after{position:relative;top:-4px;font-size:10px;font-style:italic;color:grey;content:'Click here to edit annotation'}
.hda.dataset .dataset-body .annotation-display textarea{margin:0px 0px 2px 0px;display:block;border-radius:3px;width:100%}
.hda.dataset .dataset-body .dataset-display-applications .display-application:last-child{margin-bottom:8px}
@@ -1693,7 +1692,6 @@
.history-panel .history-controls .tags-display .select2-container{min-width:0px}.history-panel .history-controls .tags-display .select2-container .select2-choices{border-radius:3px}
.history-panel .history-controls .tags-display input{border-radius:3px}
.history-panel .history-controls .annotation-display .annotation{border-radius:3px;border:1px solid rgba(153,153,153,0.5);padding:4px;white-space:pre-line;overflow:auto}
-.history-panel .history-controls .annotation-display .annotation:empty{height:22px}
.history-panel .history-controls .annotation-display .annotation:empty:after{position:relative;top:-4px;font-size:10px;font-style:italic;color:grey;content:'Click here to edit annotation'}
.history-panel .history-controls .annotation-display textarea{margin:0px 0px 2px 0px;display:block;border-radius:3px;width:100%}
.history-panel .history-controls .history-dataset-actions{display:none}.history-panel .history-controls .history-dataset-actions:before,.history-panel .history-controls .history-dataset-actions:after{content:" ";display:table;}
diff -r 6934f4ceed4572bffde39303c2ca9a993f1ffc55 -r 44df8d9c9aa11acf796f88203551a92ac03c559d static/style/src/less/history.less
--- a/static/style/src/less/history.less
+++ b/static/style/src/less/history.less
@@ -311,9 +311,6 @@
white-space: pre-line;
overflow: auto;
}
- .annotation:empty {
- height: @icon-btn-size;
- }
// fake placeholder for editable text annotation
.annotation:empty:after {
position: relative;
@@ -490,9 +487,6 @@
white-space: pre-line;
overflow: auto;
}
- .annotation:empty {
- height: @icon-btn-size;
- }
// fake placeholder for editable text annotation
.annotation:empty:after {
position: relative;
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.
1
0
commit/galaxy-central: carlfeberhard: Style fix: use scrolling overflow for long history annotation lines
by commits-noreply@bitbucket.org 27 May '14
by commits-noreply@bitbucket.org 27 May '14
27 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6934f4ceed45/
Changeset: 6934f4ceed45
User: carlfeberhard
Date: 2014-05-27 17:54:12
Summary: Style fix: use scrolling overflow for long history annotation lines
Affected #: 2 files
diff -r 14c8fee2aedba44f1a21f233bc87412edcbc00aa -r 6934f4ceed4572bffde39303c2ca9a993f1ffc55 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1692,7 +1692,7 @@
.history-panel .history-controls .tags-display label:after,.history-panel .history-controls .annotation-display label:after{content:':'}
.history-panel .history-controls .tags-display .select2-container{min-width:0px}.history-panel .history-controls .tags-display .select2-container .select2-choices{border-radius:3px}
.history-panel .history-controls .tags-display input{border-radius:3px}
-.history-panel .history-controls .annotation-display .annotation{border-radius:3px;border:1px solid rgba(153,153,153,0.5);padding:4px;white-space:pre-line}
+.history-panel .history-controls .annotation-display .annotation{border-radius:3px;border:1px solid rgba(153,153,153,0.5);padding:4px;white-space:pre-line;overflow:auto}
.history-panel .history-controls .annotation-display .annotation:empty{height:22px}
.history-panel .history-controls .annotation-display .annotation:empty:after{position:relative;top:-4px;font-size:10px;font-style:italic;color:grey;content:'Click here to edit annotation'}
.history-panel .history-controls .annotation-display textarea{margin:0px 0px 2px 0px;display:block;border-radius:3px;width:100%}
diff -r 14c8fee2aedba44f1a21f233bc87412edcbc00aa -r 6934f4ceed4572bffde39303c2ca9a993f1ffc55 static/style/src/less/history.less
--- a/static/style/src/less/history.less
+++ b/static/style/src/less/history.less
@@ -488,6 +488,7 @@
border: 1px solid fadeout( @layout-border-color, 50% );
padding: 4px;
white-space: pre-line;
+ overflow: auto;
}
.annotation:empty {
height: @icon-btn-size;
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.
1
0