Mercurial > libervia-backend
comparison sat/plugins/plugin_merge_req_mercurial.py @ 2793:181735d1b062
plugin mr mercurial, tools(common/utils): moved command protocol to a new module
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 25 Jan 2019 09:06:29 +0100 |
parents | 003b8b4b56a7 |
children | ab2696e34d29 |
comparison
equal
deleted
inserted
replaced
2792:441b536e28ed | 2793:181735d1b062 |
---|---|
15 # GNU Affero General Public License for more details. | 15 # GNU Affero General Public License for more details. |
16 | 16 |
17 # You should have received a copy of the GNU Affero General Public License | 17 # You should have received a copy of the GNU Affero General Public License |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 import re | |
21 from twisted.python.procutils import which | |
22 from sat.tools.common import async_process | |
23 from sat.tools import utils | |
20 from sat.core.i18n import _, D_ | 24 from sat.core.i18n import _, D_ |
21 from sat.core.constants import Const as C | 25 from sat.core.constants import Const as C |
22 from sat.core import exceptions | 26 from sat.core import exceptions |
23 from twisted.internet import reactor, defer, protocol | |
24 from twisted.python.failure import Failure | |
25 from twisted.python.procutils import which | |
26 import re | |
27 from sat.core.log import getLogger | 27 from sat.core.log import getLogger |
28 log = getLogger(__name__) | 28 log = getLogger(__name__) |
29 | 29 |
30 | 30 |
31 PLUGIN_INFO = { | 31 PLUGIN_INFO = { |
40 | 40 |
41 SHORT_DESC = D_(u"handle Mercurial repository") | 41 SHORT_DESC = D_(u"handle Mercurial repository") |
42 CLEAN_RE = re.compile(ur'[^\w -._]', flags=re.UNICODE) | 42 CLEAN_RE = re.compile(ur'[^\w -._]', flags=re.UNICODE) |
43 | 43 |
44 | 44 |
45 class MercurialProtocol(protocol.ProcessProtocol): | 45 class MercurialProtocol(async_process.CommandProtocol): |
46 """handle hg commands""" | 46 """handle hg commands""" |
47 hg = None | 47 name = u"Mercurial" |
48 | 48 command = None |
49 def __init__(self, deferred, stdin=None): | |
50 """ | |
51 @param deferred(defer.Deferred): will be called when command is completed | |
52 @param stdin(str, None): if not None, will be push to standard input | |
53 """ | |
54 self._stdin = stdin | |
55 self._deferred = deferred | |
56 self.data = [] | |
57 | |
58 def connectionMade(self): | |
59 if self._stdin is not None: | |
60 self.transport.write(self._stdin) | |
61 self.transport.closeStdin() | |
62 | |
63 def outReceived(self, data): | |
64 self.data.append(data) | |
65 | |
66 def errReceived(self, data): | |
67 self.data.append(data) | |
68 | |
69 def processEnded(self, reason): | |
70 data = u''.join([d.decode('utf-8') for d in self.data]) | |
71 if (reason.value.exitCode == 0): | |
72 log.debug(_('Mercurial command succeed')) | |
73 self._deferred.callback(data) | |
74 else: | |
75 msg = (_(u"Can't complete Mercurial command (error code: {code}): {message}") | |
76 .format(code = reason.value.exitCode, message = data)) | |
77 log.warning(msg) | |
78 self._deferred.errback(Failure(RuntimeError(msg))) | |
79 | 49 |
80 @classmethod | 50 @classmethod |
81 def run(cls, path, command, *args, **kwargs): | 51 def run(cls, path, command, *args, **kwargs): |
82 """Create a new MercurialRegisterProtocol and execute the given mercurial command. | 52 """Create a new MercurialRegisterProtocol and execute the given mercurial command. |
83 | 53 |
84 @param path(unicode): path to the repository | 54 @param path(unicode): path to the repository |
85 @param command(unicode): command to run | 55 @param command(unicode): hg command to run |
86 @param *args(unicode): command arguments | |
87 @param **kwargs: used because Python2 doesn't handle normal kw args after *args | |
88 can only be: | |
89 - stdin(unicode, None): data to push to standard input | |
90 @return ((D)): | |
91 """ | 56 """ |
92 stdin = kwargs.pop('stdin', None) | 57 assert u"path" not in kwargs |
93 if kwargs: | 58 kwargs["path"] = path |
94 raise exceptions.InternalError(u'only stdin is allowed as keyword argument') | 59 # FIXME: we have to use this workaround because Twisted's protocol.ProcessProtocol |
95 if stdin is not None: | 60 # is not using new style classes. This can be removed once moved to |
96 stdin = stdin.encode('utf-8') | 61 # Python 3 (super can be used normally then). |
97 d = defer.Deferred() | 62 d = async_process.CommandProtocol.run.__func__(cls, command, *args, **kwargs) |
98 mercurial_prot = MercurialProtocol(d, stdin=stdin) | 63 d.addErrback(utils.logError) |
99 cmd_args = [cls.hg, command.encode('utf-8')] | |
100 cmd_args.extend([a.encode('utf-8') for a in args]) | |
101 reactor.spawnProcess(mercurial_prot, | |
102 cls.hg, | |
103 cmd_args, | |
104 path=path.encode('utf-8')) | |
105 return d | 64 return d |
106 | 65 |
107 | 66 |
108 class MercurialHandler(object): | 67 class MercurialHandler(object): |
109 data_types = (u'mercurial_changeset',) | 68 data_types = (u'mercurial_changeset',) |
110 | 69 |
111 def __init__(self, host): | 70 def __init__(self, host): |
112 log.info(_(u"Mercurial merge request handler initialization")) | 71 log.info(_(u"Mercurial merge request handler initialization")) |
113 try: | 72 try: |
114 MercurialProtocol.hg = which('hg')[0] | 73 MercurialProtocol.command = which('hg')[0] |
115 except IndexError: | 74 except IndexError: |
116 raise exceptions.NotFound(_(u"Mercurial executable (hg) not found, " | 75 raise exceptions.NotFound(_(u"Mercurial executable (hg) not found, " |
117 u"can't use Mercurial handler")) | 76 u"can't use Mercurial handler")) |
118 self.host = host | 77 self.host = host |
119 self._m = host.plugins['MERGE_REQUESTS'] | 78 self._m = host.plugins['MERGE_REQUESTS'] |
120 self._m.register('mercurial', self, self.data_types, SHORT_DESC) | 79 self._m.register('mercurial', self, self.data_types, SHORT_DESC) |
80 | |
121 | 81 |
122 def check(self, repository): | 82 def check(self, repository): |
123 d = MercurialProtocol.run(repository, 'identify') | 83 d = MercurialProtocol.run(repository, 'identify') |
124 d.addCallback(lambda __: True) | 84 d.addCallback(lambda __: True) |
125 d.addErrback(lambda __: False) | 85 d.addErrback(lambda __: False) |