plugin mr mercurial, tools(common/utils): moved command protocol to a new module

This commit is contained in:
Goffi 2019-01-25 09:06:29 +01:00
commit 8a59034935

View file

@ -17,13 +17,13 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from twisted.python.procutils import which
from sat.tools.common import async_process
from sat.tools import utils
from sat.core.i18n import _, D_
from sat.core.constants import Const as C
from sat.core import exceptions
from twisted.internet import reactor, defer, protocol
from twisted.python.failure import Failure
from twisted.python.procutils import which
import re
from sat.core.log import getLogger
log = getLogger(__name__)
@ -42,66 +42,25 @@ SHORT_DESC = D_(u"handle Mercurial repository")
CLEAN_RE = re.compile(ur'[^\w -._]', flags=re.UNICODE)
class MercurialProtocol(protocol.ProcessProtocol):
class MercurialProtocol(async_process.CommandProtocol):
"""handle hg commands"""
hg = None
def __init__(self, deferred, stdin=None):
"""
@param deferred(defer.Deferred): will be called when command is completed
@param stdin(str, None): if not None, will be push to standard input
"""
self._stdin = stdin
self._deferred = deferred
self.data = []
def connectionMade(self):
if self._stdin is not None:
self.transport.write(self._stdin)
self.transport.closeStdin()
def outReceived(self, data):
self.data.append(data)
def errReceived(self, data):
self.data.append(data)
def processEnded(self, reason):
data = u''.join([d.decode('utf-8') for d in self.data])
if (reason.value.exitCode == 0):
log.debug(_('Mercurial command succeed'))
self._deferred.callback(data)
else:
msg = (_(u"Can't complete Mercurial command (error code: {code}): {message}")
.format(code = reason.value.exitCode, message = data))
log.warning(msg)
self._deferred.errback(Failure(RuntimeError(msg)))
name = u"Mercurial"
command = None
@classmethod
def run(cls, path, command, *args, **kwargs):
"""Create a new MercurialRegisterProtocol and execute the given mercurial command.
@param path(unicode): path to the repository
@param command(unicode): command to run
@param *args(unicode): command arguments
@param **kwargs: used because Python2 doesn't handle normal kw args after *args
can only be:
- stdin(unicode, None): data to push to standard input
@return ((D)):
@param command(unicode): hg command to run
"""
stdin = kwargs.pop('stdin', None)
if kwargs:
raise exceptions.InternalError(u'only stdin is allowed as keyword argument')
if stdin is not None:
stdin = stdin.encode('utf-8')
d = defer.Deferred()
mercurial_prot = MercurialProtocol(d, stdin=stdin)
cmd_args = [cls.hg, command.encode('utf-8')]
cmd_args.extend([a.encode('utf-8') for a in args])
reactor.spawnProcess(mercurial_prot,
cls.hg,
cmd_args,
path=path.encode('utf-8'))
assert u"path" not in kwargs
kwargs["path"] = path
# FIXME: we have to use this workaround because Twisted's protocol.ProcessProtocol
# is not using new style classes. This can be removed once moved to
# Python 3 (super can be used normally then).
d = async_process.CommandProtocol.run.__func__(cls, command, *args, **kwargs)
d.addErrback(utils.logError)
return d
@ -111,7 +70,7 @@ class MercurialHandler(object):
def __init__(self, host):
log.info(_(u"Mercurial merge request handler initialization"))
try:
MercurialProtocol.hg = which('hg')[0]
MercurialProtocol.command = which('hg')[0]
except IndexError:
raise exceptions.NotFound(_(u"Mercurial executable (hg) not found, "
u"can't use Mercurial handler"))
@ -119,6 +78,7 @@ class MercurialHandler(object):
self._m = host.plugins['MERGE_REQUESTS']
self._m.register('mercurial', self, self.data_types, SHORT_DESC)
def check(self, repository):
d = MercurialProtocol.run(repository, 'identify')
d.addCallback(lambda __: True)