From 1e3aff12b89a3dcacf59dbac6e4e350f9ff6300a Mon Sep 17 00:00:00 2001 From: Greg Von Kuster Date: Tue, 7 Aug 2012 13:43:36 -0400 Subject: [PATCH] Fix mercurial command line handling for pushes from the command line that were broken in change set d19fbfefb676 for versions of mercurial older than 2.2.3. Pushes should now function correctly for those running mercurial older than version 2.2.3. --- .../webapps/community/controllers/hg.py | 26 ++++++++++++++++--- .../community/framework/middleware/hg.py | 4 ++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/galaxy/webapps/community/controllers/hg.py b/lib/galaxy/webapps/community/controllers/hg.py index 9fb48d505c7..a4626941f95 100644 --- a/lib/galaxy/webapps/community/controllers/hg.py +++ b/lib/galaxy/webapps/community/controllers/hg.py @@ -1,9 +1,12 @@ import os, logging from galaxy.web.base.controller import * from galaxy.webapps.community.controllers.common import * +from galaxy.util.shed_util import update_repository from galaxy import eggs eggs.require('mercurial') +import mercurial.__version__ +from mercurial import hg, ui, commands from mercurial.hgweb.hgwebdir_mod import hgwebdir from mercurial.hgweb.request import wsgiapplication @@ -14,17 +17,32 @@ class HgController( BaseUIController ): def handle_request( self, trans, **kwd ): # The os command that results in this method being called will look something like # hg clone http://test@127.0.0.1:9009/repos/test/convert_characters1 + hg_version = mercurial.__version__.version cmd = kwd.get( 'cmd', None ) wsgi_app = wsgiapplication( make_web_app ) - if cmd == 'pushkey': - # This results from an "hg push" from the command line. When doing this, the following 6 commands, in order, - # will be retrieved from environ: capabilities -> batch -> branchmap -> unbundle -> listkeys -> pushkey + # In mercurial version 2.2.3, section 15.2. Command changes includes a new feature: pushkey: add hooks for pushkey/listkeys (see + # http://mercurial.selenic.com/wiki/WhatsNew#Mercurial_2.2.3_.282012-07-01.29). Older versions require checking for 'listkeys'. + push_from_command_line = ( hg_version < '2.2.3' and cmd == 'listkeys' ) or ( hg_version >= '2.2.3' and cmd == 'pushkey' ) + if push_from_command_line: + # When doing an "hg push" from the command line, the following commands, in order, will be retrieved from environ, depending + # upon the mercurial version being used. There is a weakness if the mercurial version < '2.2.3' because several commands include + # listkeys, so repository metadata will be set, but only for the files currently on disk, so doing so is not too expensive. + # If mercurial version < '2.2.3: + # capabilities -> batch -> branchmap -> unbundle -> listkeys + # If mercurial version >= '2.2.3': + # capabilities -> batch -> branchmap -> unbundle -> listkeys -> pushkey path_info = kwd.get( 'path_info', None ) if path_info: owner, name = path_info.split( '/' ) repository = get_repository_by_name_and_owner( trans, name, owner ) if repository: - error_message, status = reset_all_metadata_on_repository( trans, trans.security.encode_id( repository.id ) ) + if hg_version < '2.2.3': + # We're forced to update the repository so the disk files include the changes in the push. This is handled in the + # pushkey hook in mercurial version 2.2.3 and newer. + repo = hg.repository( ui.ui(), repository.repo_path ) + update_repository( repo ) + # Set metadata using the repository files on disk. + error_message, status = set_repository_metadata( trans, repository ) if status not in [ 'ok' ] and error_message: log.debug( "Error resetting metadata on repository '%s': %s" % ( str( repository.name ), str( error_message ) ) ) elif status in [ 'ok' ] and error_message: diff --git a/lib/galaxy/webapps/community/framework/middleware/hg.py b/lib/galaxy/webapps/community/framework/middleware/hg.py index d5cfe160d01..49a46c78dc0 100644 --- a/lib/galaxy/webapps/community/framework/middleware/hg.py +++ b/lib/galaxy/webapps/community/framework/middleware/hg.py @@ -8,11 +8,13 @@ from paste.httpheaders import REMOTE_USER, AUTH_TYPE from galaxy.webapps.community import model from galaxy.util.hash_util import new_secure_hash +import mercurial.__version__ log = logging.getLogger(__name__) class Hg( object ): def __init__( self, app, config ): + print "mercurial version is:", mercurial.__version__.version self.app = app self.config = config # Authenticate this mercurial request using basic authentication @@ -56,7 +58,7 @@ class Hg( object ): connection.close() if cmd == 'unbundle': # This is an hg push from the command line. When doing this, the following 7 commands, in order, - # will be retrieved from environ: + # will be retrieved from environ (see the docs at http://mercurial.selenic.com/wiki/WireProtocol): # between -> capabilities -> heads -> branchmap -> unbundle -> unbundle -> listkeys # # The mercurial API unbundle() ( i.e., hg push ) method ultimately requires authorization.