Do not remove tools from other installed revisions when uninstalling TS repo

Multiple installed revisions of a repository can provide the same version of
a tool, e.g. for the repository

https://toolshed.g2.bx.psu.edu/view/nilesh/rseqc

only one tool out of 22 has a different version in revision 57 with
respect to revision 56.

In this case, when uninstalling one repository, the tools with the same guid
were removed also from the other repository revisions in the
`shed_tool_conf` file. This can be prevented by checking also the tool path.
This commit is contained in:
Nicola Soranzo
2019-02-05 02:36:09 +00:00
parent 87d4904189
commit ab03de44e8
3 changed files with 26 additions and 15 deletions
@@ -372,7 +372,7 @@ class ToolPanelManager(object):
new_tool_panel_section_label=new_tool_panel_section_label)
return tool_section, tool_panel_section_key
def remove_from_shed_tool_config(self, shed_tool_conf_dict, guids_to_remove):
def remove_from_shed_tool_config(self, shed_tool_conf_dict, metadata):
"""
A tool shed repository is being uninstalled so change the
shed_tool_conf file. Parse the config file to generate the entire list
@@ -380,6 +380,13 @@ class ToolPanelManager(object):
subset of the entire list if one or more repositories have been
deactivated.
"""
if 'tools' not in metadata:
return
# We need to use the tool path to uniquely identify the tools to remove,
# since multiple installable revisions of a repository can provide the
# same version of a tool (i.e. there may be another tool with the same
# guid that we should not remove from shed_tool_conf).
guid_paths_to_remove = [(_['guid'], _['tool_config']) for _ in metadata['tools']]
shed_tool_conf = shed_tool_conf_dict['config_filename']
tool_path = shed_tool_conf_dict['tool_path']
config_elems = []
@@ -393,7 +400,7 @@ class ToolPanelManager(object):
if config_elem.tag == 'section':
tool_elems_to_remove = []
for tool_elem in config_elem:
if tool_elem.get('guid') in guids_to_remove:
if (tool_elem.get('guid'), tool_elem.get('file')) in guid_paths_to_remove:
tool_elems_to_remove.append(tool_elem)
for tool_elem in tool_elems_to_remove:
# Remove all of the appropriate tool sub-elements from the section element.
@@ -402,7 +409,7 @@ class ToolPanelManager(object):
# Keep a list of all empty section elements so they can be removed.
config_elems_to_remove.append(config_elem)
elif config_elem.tag == 'tool':
if config_elem.get('guid') in guids_to_remove:
if (tool_elem.get('guid'), tool_elem.get('file')) in guid_paths_to_remove:
config_elems_to_remove.append(config_elem)
for config_elem in config_elems_to_remove:
config_elems.remove(config_elem)
@@ -424,18 +431,15 @@ class ToolPanelManager(object):
# Create a list of guids for all tools that will be removed from the in-memory tool panel
# and config file on disk.
guids_to_remove = list(tool_panel_dict.keys())
self.remove_guids(guids_to_remove, shed_tool_conf, uninstall)
def remove_guids(self, guids_to_remove, shed_tool_conf, uninstall):
toolbox = self.app.toolbox
# Remove the tools from the toolbox's tools_by_id dictionary.
for guid_to_remove in guids_to_remove:
# remove_from_tool_panel to false, will handling that logic below.
toolbox.remove_tool_by_id(guid_to_remove, remove_from_panel=False)
shed_tool_conf_dict = self.get_shed_tool_conf_dict(shed_tool_conf)
# Always remove from the shed_tool_conf file on disk. Used to test for uninstall, not sure there is a legitimate use for this?!
if uninstall:
self.remove_from_shed_tool_config(shed_tool_conf_dict, guids_to_remove)
# Remove from the shed_tool_conf file on disk.
self.remove_from_shed_tool_config(shed_tool_conf_dict, repository.metadata)
def update_tool_panel_dict(self, tool_panel_dict, tool_panel_section_mapping, repository_tools_tups):
for tool_guid in tool_panel_dict:
@@ -128,7 +128,7 @@ class ToolPanelManagerTestCase(BaseToolBoxTestCase):
assert "github.com/galaxyproject/example/test_tool/0.2" not in open(os.path.join(self.test_directory, "tool_conf.xml"), "r").read()
self._verify_tool_confs()
self._remove_guids(["github.com/galaxyproject/example/test_tool/0.1"], uninstall=True)
self._remove_repository_contents("github.com/galaxyproject/example/test_tool/0.1", uninstall=True)
# Now no versions of this tool are returned by new toolbox.
new_toolbox = self.get_new_toolbox()
@@ -144,7 +144,7 @@ class ToolPanelManagerTestCase(BaseToolBoxTestCase):
self._setup_two_versions_in_config(section=True)
self._setup_two_versions()
self.toolbox
self._remove_guids(["github.com/galaxyproject/example/test_tool/0.2"], uninstall=uninstall)
self._remove_repository_contents("github.com/galaxyproject/example/test_tool/0.2", uninstall=uninstall)
def _verify_version_2_removed_from_panel(self, section=True):
# Check that test_tool now only has one version...
@@ -164,9 +164,11 @@ class ToolPanelManagerTestCase(BaseToolBoxTestCase):
next(iter(self.toolbox._tool_panel.values())).id == "github.com/galaxyproject/example/test_tool/0.1"
assert "github.com/galaxyproject/example/test_tool/0.2" not in new_toolbox._integrated_tool_panel
def _remove_guids(self, guids, uninstall, shed_tool_conf="tool_conf.xml"):
self.tpm.remove_guids(
guids_to_remove=guids,
def _remove_repository_contents(self, guid, uninstall, shed_tool_conf="tool_conf.xml"):
tool = self.toolbox.get_tool(guid)
repository = tool.tool_shed_repository
self.tpm.remove_repository_contents(
repository=repository,
shed_tool_conf=shed_tool_conf,
uninstall=uninstall,
)
+7 -2
View File
@@ -71,7 +71,13 @@ class BaseToolBoxTestCase(unittest.TestCase, UsesApp, UsesTools):
self.config_files = []
def _repo_install(self, changeset, config_filename=None):
metadata = {}
metadata = {
'tools': [{
'add_to_tool_panel': False, # to have repository.includes_tools_for_display_in_tool_panel=False in InstalledRepositoryManager.activate_repository()
'guid': "github.com/galaxyproject/example/test_tool/0.%s" % changeset,
'tool_config': 'tool.xml'
}],
}
if config_filename:
metadata['shed_config_filename'] = config_filename
repository = tool_shed_install.ToolShedRepository(metadata=metadata)
@@ -98,7 +104,6 @@ class BaseToolBoxTestCase(unittest.TestCase, UsesApp, UsesTools):
version2 = tool_shed_install.ToolVersion()
version2.tool_id = "github.com/galaxyproject/example/test_tool/0.2"
version2.repository = repository2
self.app.install_model.context.add(version2)
self.app.install_model.context.flush()