From 7183eabb52b3e899bc03e12a7d9d1d61da190978 Mon Sep 17 00:00:00 2001
From: Jeremy Goecks
- A tool or tool suite archive is a tar-format file (bzipped or gzipped tar are valid)
- containing all the files necessary to load the tool(s) into a Galaxy instance.
-
- A tools suite must include a file named
-
' )
- else:
+ elif c not in [ '\r' ]:
translated.append( 'X' )
return ''.join( translated )
def __build_allow_push_select_field( self, trans, current_push_list, selected_value='none' ):
diff --git a/lib/galaxy/webapps/community/controllers/upload.py b/lib/galaxy/webapps/community/controllers/upload.py
index be9c32aaa99..717cf79e526 100644
--- a/lib/galaxy/webapps/community/controllers/upload.py
+++ b/lib/galaxy/webapps/community/controllers/upload.py
@@ -60,12 +60,9 @@ class UploadController( BaseController ):
elif file_data not in ( '', None ):
uploaded_file = file_data.file
if uploaded_file:
- # TODO: our current support for browsing repo contents requires a copy
- # of the repository files in the repo root directory. To produce these
- # copies, we update without passing the -r null flag (see below). When
- # we're uploading more files, we have to clean out the repo root directory
- # so we can move them into it. We need to eliminate all this when we figure
- # out how to browse the repository files.
+ # Our current support for browsing repo contents requires a copy of the
+ # repository files in the repo root directory. To produce these copies,
+ # we update without passing the "-r null" flag.
os.chdir( repo_dir )
os.system( 'hg update -r null > /dev/null 2>&1' )
os.chdir( current_working_dir )
@@ -76,16 +73,16 @@ class UploadController( BaseController ):
tar = tarfile.open( uploaded_file.name )
istar = True
except tarfile.ReadError, e:
+ tar = None
istar = False
- if istar:
- ok, message = self.__check_archive( tar )
- if ok:
- if repository.is_new:
+ if repository.is_new:
+ if istar:
+ # We have an archive ( a tarball )
+ ok, message = self.__check_archive( tar )
+ if ok:
tar.extractall( path=repo_dir )
tar.close()
uploaded_file.close()
- # TODO: The following will only work on new, empty repos,
- # need to also handle repos with existing contents
for root, dirs, files in os.walk( repo_dir, topdown=False ):
# Don't visit .hg directories and don't include hgrc files in commit.
if not root.find( '.hg' ) >= 0 and not root.find( 'hgrc' ) >= 0:
@@ -109,78 +106,9 @@ class UploadController( BaseController ):
repo.dirstate.add( file_path )
files_to_commit.append( file_path )
else:
- # The repo already contains the file, so we need to make sure the file being
- # uploaded is different from the file in the repo. This is a temporary brute-
- # force method.
- # Make a clone of the repository in a temporary location
- tmp_dir = tempfile.mkdtemp()
- tmp_archive_dir = os.path.join( tmp_dir, 'tmp_archive_dir' )
- if not os.path.exists( tmp_archive_dir ):
- os.makedirs( tmp_archive_dir )
- cmd = "hg clone %s > /dev/null 2>&1" % os.path.abspath( repo_dir )
- os.chdir( tmp_archive_dir )
- os.system( cmd )
- os.chdir( current_working_dir )
- cloned_repo_dir = os.path.join( tmp_archive_dir, 'repo_%d' % repository.id )
- if upload_point is not None:
- full_path = os.path.abspath( os.path.join( cloned_repo_dir, upload_point, file_data.filename ) )
- else:
- full_path = os.path.abspath( os.path.join( cloned_repo_dir, file_data.filename ) )
- # Extract the uploaded tarball to the load_point within the cloned repository hierarchy
- tar.extractall( path=full_path )
tar.close()
- uploaded_file.close()
- # We want these change sets to be associated with the owner of the repository, so we'll
- # set the HGUSER environment variable accordingly.
- os.environ[ 'HGUSER' ] = trans.user.username
- # Add the file to the cloned repository. If it's already tracked, this should do nothing.
- os.chdir( cloned_repo_dir )
- os.system( 'hg add > /dev/null 2>&1' )
- os.chdir( current_working_dir )
- os.chdir( cloned_repo_dir )
- # Commit the change set to the cloned repository
- os.system( "hg commit -m '%s' > /dev/null 2>&1" % commit_message )
- os.chdir( current_working_dir )
- # Push the change set to the master repository
- cmd = "hg push %s > /dev/null 2>&1" % os.path.abspath( repo_dir )
- os.chdir( cloned_repo_dir )
- os.system( cmd )
- # Change the current working directory to the original
- os.chdir( current_working_dir )
- # Since we extracted the archive into repo_dir, a copy of the archive's
- # files remains there. The following will remove them. It would be
- # more ideal if we could use the mercurial api to do this, but I haven't
- # yet discovered a way to pass the -r null flag to repo.update().
- # TODO: our current support for browsing repo contents requires a copy
- # of the repository files in the repo root directory. To produce these
- # copies, we'll update without passing the -r null flag. When we figure
- # out how to browse the repository files, uncomment the -r flag below.
- os.chdir( repo_dir )
- os.system( 'hg update > /dev/null 2>&1' )
- os.chdir( current_working_dir )
- # Remove tmp directory
- shutil.rmtree( tmp_dir )
- message = "The file '%s' has been successfully uploaded to the repository." % file_data.filename
- trans.response.send_redirect( web.url_for( controller='repository',
- action='browse_repository',
- message=message,
- id=trans.security.encode_id( repository.id ) ) )
-
-
else:
- tar.close()
- else:
- """
- # TODO: This segment uses the mercurial api (and works), but we need the
- # api section below to be functional in order for this segment to be used.
- # In the meantime, we use the repository.is_new check below...
- repo_contains = file_path in [ i for i in ctx.manifest() ]
- if not repo_contains:
- repo.dirstate.add( file_path )
- files_to_commit.append( file_path )
- """
- if repository.is_new:
- # We're uploading a single file
+ # We have a single file
if upload_point is not None:
full_path = os.path.abspath( os.path.join( upload_point, file_data.filename ) )
file_path = os.path.join( upload_point, file_data.filename )
@@ -190,98 +118,18 @@ class UploadController( BaseController ):
shutil.move( uploaded_file.name, full_path )
repo.dirstate.add( file_path )
files_to_commit.append( file_path )
- else:
- """
- # TODO: This segment attempts to use the mercurial api, but is not functional.
- # Until we get it working, we're using the brute force method below it.
- fctx = None
- for changeset in repo.changelog:
- ctx = repo.changectx( changeset )
- if file_path not in ctx.files():
- continue
- fctx = ctx[ file_path ]
- break
- # We now have the parent version of the upload file.
- if fctx:
- data = fctx.data()
- # TODO: obviously very bad way of comparing files...
- file_path_data = open( full_path ).read()
- different = data != file_path_data
- if different:
- # TODO: how do you insert a new version of an existing file using the mercurial api???
- # the follwoin gis not correct!
- #repo.dirstate.normallookup( file_path )
- #files_to_commit.append( file_path )
- pass
- """
- # The repo already contains the file, so we need to make sure the file being
- # uploaded is different from the file in the repo. This is a temporary brute-
- # force method.
- # Make a clone of the repository in a temporary location
- tmp_dir = tempfile.mkdtemp()
- tmp_archive_dir = os.path.join( tmp_dir, 'tmp_archive_dir' )
- if not os.path.exists( tmp_archive_dir ):
- os.makedirs( tmp_archive_dir )
- cmd = "hg clone %s > /dev/null 2>&1" % os.path.abspath( repo_dir )
- os.chdir( tmp_archive_dir )
- os.system( cmd )
- os.chdir( current_working_dir )
- cloned_repo_dir = os.path.join( tmp_archive_dir, 'repo_%d' % repository.id )
- if upload_point is not None:
- full_path = os.path.abspath( os.path.join( cloned_repo_dir, upload_point, file_data.filename ) )
- else:
- full_path = os.path.abspath( os.path.join( cloned_repo_dir, file_data.filename ) )
- # Move the uploaded file to the load_point within the cloned repository hierarchy
- shutil.move( uploaded_file.name, full_path )
- # We want these change sets to be associated with the owner of the repository, so we'll
- # set the HGUSER environment variable accordingly.
- os.environ[ 'HGUSER' ] = trans.user.username
- # Add the file to the cloned repository. If it's already tracked, this should do nothing.
- os.chdir( cloned_repo_dir )
- os.system( 'hg add > /dev/null 2>&1' )
- os.chdir( current_working_dir )
- os.chdir( cloned_repo_dir )
- # Commit the change set to the cloned repository
- os.system( "hg commit -m '%s' > /dev/null 2>&1" % commit_message )
- os.chdir( current_working_dir )
- # Push the change set to the master repository
- cmd = "hg push %s > /dev/null 2>&1" % os.path.abspath( repo_dir )
- os.chdir( cloned_repo_dir )
- os.system( cmd )
- os.chdir( current_working_dir )
- # Since we extracted the archive into repo_dir, a copy of the archive's
- # files remains there. The following will remove them. It would be
- # more ideal if we could use the mercurial api to do this, but I haven't
- # yet discovered a way to pass the -r null flag to repo.update().
- # TODO: our current support for browsing repo contents requires a copy
- # of the repository files in the repo root directory. To produce these
- # copies, we'll update without passing the -r null flag. When we figure
- # out how to browse the repository files, uncomment the -r flag below.
- os.chdir( repo_dir )
- os.system( 'hg update > /dev/null 2>&1' )
- os.chdir( current_working_dir )
- # Remove tmp directory
- shutil.rmtree( tmp_dir )
- message = "The file '%s' has been successfully uploaded to the repository." % file_data.filename
- trans.response.send_redirect( web.url_for( controller='repository',
- action='browse_repository',
- message=message,
- id=trans.security.encode_id( repository.id ) ) )
+ else:
+ # We're uploading files to a repository with existing
+ # contents, so clone the repository to a temporary location.
+ tmp_dir, cloned_repo_dir = self.__handle_hg_clone( trans, repository, upload_point, uploaded_file, file_data, repo_dir, current_working_dir, istar, tar=tar )
+ # Commit and push the changes from the cloned repo to the master repo.
+ self.__handle_hg_push( trans, repository, file_data, commit_message, current_working_dir, cloned_repo_dir, repo_dir, tmp_dir )
if ok:
if files_to_commit:
repo.dirstate.write()
repo.commit( text=commit_message )
- # Since we extracted the archive into repo_dir, a copy of the archive's
- # files remains there. The following will remove them. It would be
- # more ideal if we could use the mercurial api to do this, but I haven't
- # yet discovered a way to pass the -r null flag to repo.update().
- # TODO: our current support for browsing repo contents requires a copy
- # of the repository files in the repo root directory. To produce these
- # copies, we'll update without passing the -r null flag. When we figure
- # out how to browse the repository files, uncomment the -r flag below.
os.chdir( repo_dir )
os.system( 'hg update > /dev/null 2>&1' )
- #os.system( 'hg update -r null' )
os.chdir( current_working_dir )
message = "The file '%s' has been successfully uploaded to the repository." % file_data.filename
trans.response.send_redirect( web.url_for( controller='repository',
@@ -290,17 +138,8 @@ class UploadController( BaseController ):
id=trans.security.encode_id( repository.id ) ) )
else:
status = 'error'
- # Since we extracted the archive into repo_dir, a copy of the archive's
- # files remains there. The following will remove them. It would be
- # more ideal if we could use the mercurial api to do this, but I haven't
- # yet discovered a way to pass the -r null flag to repo.update().
- # TODO: our current support for browsing repo contents requires a copy
- # of the repository files in the repo root directory. To produce these
- # copies, we'll update without passing the -r null flag. When we figure
- # out how to browse the repository files, uncomment the -r flag below.
os.chdir( repo_dir )
os.system( 'hg update > /dev/null 2>&1' )
- #os.system( 'hg update -r null' )
os.chdir( current_working_dir )
selected_categories = [ trans.security.decode_id( id ) for id in category_ids ]
return trans.fill_template( '/webapps/community/repository/upload.mako',
@@ -308,6 +147,57 @@ class UploadController( BaseController ):
commit_message=commit_message,
message=message,
status=status )
+ def __handle_hg_clone( self, trans, repository, upload_point, uploaded_file, file_data, repo_dir, current_working_dir, istar, tar=None ):
+ tmp_dir = tempfile.mkdtemp()
+ tmp_archive_dir = os.path.join( tmp_dir, 'tmp_archive_dir' )
+ if not os.path.exists( tmp_archive_dir ):
+ os.makedirs( tmp_archive_dir )
+ # Make a clone of the repository in a temporary location
+ cmd = "hg clone %s > /dev/null 2>&1" % os.path.abspath( repo_dir )
+ os.chdir( tmp_archive_dir )
+ os.system( cmd )
+ os.chdir( current_working_dir )
+ cloned_repo_dir = os.path.join( tmp_archive_dir, 'repo_%d' % repository.id )
+ if upload_point is not None:
+ full_path = os.path.abspath( os.path.join( cloned_repo_dir, upload_point, file_data.filename ) )
+ else:
+ full_path = os.path.abspath( os.path.join( cloned_repo_dir, file_data.filename ) )
+ if istar:
+ # Extract the uploaded tarball to the load_point within the cloned repository hierarchy
+ tar.extractall( path=full_path )
+ tar.close()
+ uploaded_file.close()
+ else:
+ # Move the uploaded file to the load_point within the cloned repository hierarchy
+ shutil.move( uploaded_file.name, full_path )
+ return tmp_dir, cloned_repo_dir
+ def __handle_hg_push( self, trans, repository, file_data, commit_message, current_working_dir, cloned_repo_dir, repo_dir, tmp_dir ):
+ # We want these change sets to be associated with the owner of the repository, so we'll
+ # set the HGUSER environment variable accordingly.
+ os.environ[ 'HGUSER' ] = trans.user.username
+ # Add the file to the cloned repository. If it's already tracked, this should do nothing.
+ os.chdir( cloned_repo_dir )
+ os.system( 'hg add > /dev/null 2>&1' )
+ os.chdir( current_working_dir )
+ os.chdir( cloned_repo_dir )
+ # Commit the change set to the cloned repository
+ os.system( "hg commit -m '%s' > /dev/null 2>&1" % commit_message )
+ os.chdir( current_working_dir )
+ # Push the change set to the master repository
+ cmd = "hg push %s > /dev/null 2>&1" % os.path.abspath( repo_dir )
+ os.chdir( cloned_repo_dir )
+ os.system( cmd )
+ os.chdir( current_working_dir )
+ # Make a copy of the updated repository files for browsing.
+ os.chdir( repo_dir )
+ os.system( 'hg update > /dev/null 2>&1' )
+ os.chdir( current_working_dir )
+ shutil.rmtree( tmp_dir )
+ message = "The file '%s' has been successfully uploaded to the repository." % file_data.filename
+ trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repository',
+ message=message,
+ id=trans.security.encode_id( repository.id ) ) )
def __check_archive( self, archive ):
for member in archive.getmembers():
# Allow regular files and directories only
diff --git a/templates/webapps/community/upload/upload.mako b/templates/webapps/community/upload/upload.mako
deleted file mode 100644
index b853d3cb237..00000000000
--- a/templates/webapps/community/upload/upload.mako
+++ /dev/null
@@ -1,242 +0,0 @@
-<%namespace file="/message.mako" import="render_msg" />
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/community/base_panels.mako'
- else:
- return '/base.mako'
-%>
-
-<%inherit file="${inherit(context)}"/>
-
-<%
- if selected_upload_type == 'tool':
- title = 'Upload a tool archive'
- type_label = 'tool'
- elif selected_upload_type == 'toolsuite':
- title = 'Upload a tool suite archive'
- type_label = 'tool suite'
-%>
-
-<%def name="title()">
- ${title}
-%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
-
-%def>
-
-${title}
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-Tool Suite Archive
- suite_config.xml which provides information about the id, name,
- version and description of the tool suite, as well as the id, name, version and description of each tool
- in the suite. Here is an example suite_config.xml file.
-
- <suite id="lastz_toolsuite" name="Suite of Lastz tools" version="1.0.0">
- <description>This suite contains all of my Lastz tools for Galaxy</description>
- <tool id="lastz_wrapper_2" name="Lastz" version="1.1.0">
- <description> map short reads against reference sequence</description>
- </tool>
- <tool id="lastz_paired_reads_wrapper" name="Lastz paired reads" version="1.0.0">
- <description> map short paired reads against reference sequence</description>
- </tool>
- </suite>
-
-
- New versions of the suite can be uploaded, replacing an older version of the suite, but the version attribute
- of the
- The id, name and version attributes of each suite_config.xml file must exactly match the same
- attributes in each associated tool config in the archive or you will not be allowed to upload the archive.
-
- In addition to the suite_config.xml file, the archive must include all
- tool config files,
- executables, functional test data (if your tool config includes functional tests) and other files needed for each
- of the tools in your suite to function within Galaxy. See the information about single tool archives below for
- additional hints to enable ease-of-use when others download your suite of tools.
-
- For example, to package the above Lastz suite of tools: -
- user@host:~% tar jcvf ~/Desktop/galaxy_lastz_toolsuite.tar.bz2 lastzsuite - lastzsuite/ - lastzsuite/README - lastzsuite/suite_config.xml - lastzsuite/lastz_paired_reads_wrapper.py - lastzsuite/lastz_paired_reads_wrapper.xml - lastzsuite/lastz_wrapper.py - lastzsuite/lastz_wrapper.xml - lastzsuite/lastz-distrib-1.02.00/ - lastzsuite/lastz-distrib-1.02.00/src/ - lastzsuite/lastz-distrib-1.02.00/src/Makefile - lastzsuite/lastz-distrib-1.02.00/src/version.mak - lastzsuite/lastz-distrib-1.02.00/src/lastz.c - lastzsuite/lastz-distrib-1.02.00/src/lastz.h - ... -- ~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded. - -%endif -
- A single tool archive must include a - tool config file - and will probably also include a tool script. If any steps are necessary to install your tool beyond the basic - instructions below, include a README file to provide details. If the tool (or parts of it) are written in C, - the source code can be included (or put links to the source in the README). Do not include pre-compiled binaries - without source since Galaxy is run on a wide variety of platforms. Also, if you are only wrapping or providing a - Galaxy config for a tool that is not your own, be sure the license allows for redistribution before including any - part of that tool in the archive. -
-- There are no requirements about the directory structure inside the archive, but for ease of use it's generally - a good idea to put everything inside a sub-directory, instead of directly at the top level. -
-- For example, to package the Lastz tool's config file, Galaxy wrapper, and the C source: -
- user@host:~% tar jcvf ~/Desktop/galaxy_lastz_tool.tar.bz2 lastz - lastz/ - lastz/README - lastz/lastz_wrapper.py - lastz/lastz_wrapper.xml - lastz/lastz-distrib-1.02.00/ - lastz/lastz-distrib-1.02.00/src/ - lastz/lastz-distrib-1.02.00/src/Makefile - lastz/lastz-distrib-1.02.00/src/version.mak - lastz/lastz-distrib-1.02.00/src/lastz.c - lastz/lastz-distrib-1.02.00/src/lastz.h - ... -- ~/Desktop/galaxy_lastz_tool.tar.bz2 is now ready to be uploaded. - -
- Simply uploading a tool to the Galaxy too shed will not allow other users to find and download your tool. It will - need to be approved by an administrator before it appears in the tool list. -
-- After your archive has successfully uploaded, you will be redirected to the Edit Tool page. Provide a detailed - description of what the tool does - this will be used by administrators to understand the tool before approving it - for display on the site. Once approved, this information will be displayed to users who view your tool. In addition, - the site administrators will have configured a number of categories with which you can associate your tool to make it - easy to find by users looking to solve specific problems. Associate as many categories as are relevant to your tool. - You may change the description and associated categories as often as you'd like until you click the "Submit for - approval" button. Once submitted, the tool will be approved or rejected by an administrator. If the tool is - rejected, you will see information about why it was rejected, and you can make appropriate changes to the archive and - re-submit it for approval. When it is approved, your archive will be visible to everyone. At that point, the description - and associated categories can only be changed by an administrator. -
-- When the tool has been approved or rejected, you may upload a new version by browsing to the tool's "View Tool" page, - clicking the "Tool actions" menu in the upper right corner of the page, and selecting "Upload a new version" from the - menu. -
-- A tool's download link will send you the tool archive. Once downloaded, unpack the tool on your local Galaxy instance's server: -
- user@host:~% tar xvf galaxy_lastz_tool.tar - ... - user@host:~% tar zxvf galaxy_lastz_tool.tar.gz - ... - user@host:~% tar jxvf galaxy_lastz_tool.tar.bz2 - ... -- If the archive includes a README file, consult it for installation instructions. If not, follow these basic steps: -
galaxy_dist/tools/ to house downloaded tool(s).$PATH. If the tool depends on
- C binaries but does not come with them (only source), you'll need to compile the source first.
- galaxy_dist/tool_conf.xml.
- In the near future, we plan to implement a more direct method to install tools via the Galaxy administrator user interface instead
- of placing files on the filesystem and manually managing the tool_conf.xml file.
-