Mercurial > libervia-backend
comparison sat/plugins/plugin_merge_req_mercurial.py @ 3028:ab2696e34d29
Python 3 port:
/!\ this is a huge commit
/!\ starting from this commit, SàT is needs Python 3.6+
/!\ SàT maybe be instable or some feature may not work anymore, this will improve with time
This patch port backend, bridge and frontends to Python 3.
Roughly this has been done this way:
- 2to3 tools has been applied (with python 3.7)
- all references to python2 have been replaced with python3 (notably shebangs)
- fixed files not handled by 2to3 (notably the shell script)
- several manual fixes
- fixed issues reported by Python 3 that where not handled in Python 2
- replaced "async" with "async_" when needed (it's a reserved word from Python 3.7)
- replaced zope's "implements" with @implementer decorator
- temporary hack to handle data pickled in database, as str or bytes may be returned,
to be checked later
- fixed hash comparison for password
- removed some code which is not needed anymore with Python 3
- deactivated some code which needs to be checked (notably certificate validation)
- tested with jp, fixed reported issues until some basic commands worked
- ported Primitivus (after porting dependencies like urwid satext)
- more manual fixes
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 13 Aug 2019 19:08:41 +0200 |
parents | 181735d1b062 |
children | fee60f17ebac |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SàT plugin for import external blogs | 4 # SàT plugin for import external blogs |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 6 |
33 C.PI_IMPORT_NAME: "MERGE_REQUEST_MERCURIAL", | 33 C.PI_IMPORT_NAME: "MERGE_REQUEST_MERCURIAL", |
34 C.PI_TYPE: C.PLUG_TYPE_MISC, | 34 C.PI_TYPE: C.PLUG_TYPE_MISC, |
35 C.PI_DEPENDENCIES: ["MERGE_REQUESTS"], | 35 C.PI_DEPENDENCIES: ["MERGE_REQUESTS"], |
36 C.PI_MAIN: "MercurialHandler", | 36 C.PI_MAIN: "MercurialHandler", |
37 C.PI_HANDLER: "no", | 37 C.PI_HANDLER: "no", |
38 C.PI_DESCRIPTION: _(u"""Merge request handler for Mercurial""") | 38 C.PI_DESCRIPTION: _("""Merge request handler for Mercurial""") |
39 } | 39 } |
40 | 40 |
41 SHORT_DESC = D_(u"handle Mercurial repository") | 41 SHORT_DESC = D_("handle Mercurial repository") |
42 CLEAN_RE = re.compile(ur'[^\w -._]', flags=re.UNICODE) | 42 CLEAN_RE = re.compile(r'[^\w -._]', flags=re.UNICODE) |
43 | 43 |
44 | 44 |
45 class MercurialProtocol(async_process.CommandProtocol): | 45 class MercurialProtocol(async_process.CommandProtocol): |
46 """handle hg commands""" | 46 """handle hg commands""" |
47 name = u"Mercurial" | 47 name = "Mercurial" |
48 command = None | 48 command = None |
49 | 49 |
50 @classmethod | 50 @classmethod |
51 def run(cls, path, command, *args, **kwargs): | 51 def run(cls, path, command, *args, **kwargs): |
52 """Create a new MercurialRegisterProtocol and execute the given mercurial command. | 52 """Create a new MercurialRegisterProtocol and execute the given mercurial command. |
53 | 53 |
54 @param path(unicode): path to the repository | 54 @param path(unicode): path to the repository |
55 @param command(unicode): hg command to run | 55 @param command(unicode): hg command to run |
56 """ | 56 """ |
57 assert u"path" not in kwargs | 57 assert "path" not in kwargs |
58 kwargs["path"] = path | 58 kwargs["path"] = path |
59 # FIXME: we have to use this workaround because Twisted's protocol.ProcessProtocol | 59 # FIXME: we have to use this workaround because Twisted's protocol.ProcessProtocol |
60 # is not using new style classes. This can be removed once moved to | 60 # is not using new style classes. This can be removed once moved to |
61 # Python 3 (super can be used normally then). | 61 # Python 3 (super can be used normally then). |
62 d = async_process.CommandProtocol.run.__func__(cls, command, *args, **kwargs) | 62 d = async_process.CommandProtocol.run.__func__(cls, command, *args, **kwargs) |
63 d.addErrback(utils.logError) | 63 d.addErrback(utils.logError) |
64 return d | 64 return d |
65 | 65 |
66 | 66 |
67 class MercurialHandler(object): | 67 class MercurialHandler(object): |
68 data_types = (u'mercurial_changeset',) | 68 data_types = ('mercurial_changeset',) |
69 | 69 |
70 def __init__(self, host): | 70 def __init__(self, host): |
71 log.info(_(u"Mercurial merge request handler initialization")) | 71 log.info(_("Mercurial merge request handler initialization")) |
72 try: | 72 try: |
73 MercurialProtocol.command = which('hg')[0] | 73 MercurialProtocol.command = which('hg')[0] |
74 except IndexError: | 74 except IndexError: |
75 raise exceptions.NotFound(_(u"Mercurial executable (hg) not found, " | 75 raise exceptions.NotFound(_("Mercurial executable (hg) not found, " |
76 u"can't use Mercurial handler")) | 76 "can't use Mercurial handler")) |
77 self.host = host | 77 self.host = host |
78 self._m = host.plugins['MERGE_REQUESTS'] | 78 self._m = host.plugins['MERGE_REQUESTS'] |
79 self._m.register('mercurial', self, self.data_types, SHORT_DESC) | 79 self._m.register('mercurial', self, self.data_types, SHORT_DESC) |
80 | 80 |
81 | 81 |
90 '--encoding=utf-8') | 90 '--encoding=utf-8') |
91 | 91 |
92 def import_(self, repository, data, data_type, item_id, service, node, extra): | 92 def import_(self, repository, data, data_type, item_id, service, node, extra): |
93 parsed_data = self.parse(data) | 93 parsed_data = self.parse(data) |
94 try: | 94 try: |
95 parsed_name = parsed_data[0][u'commit_msg'].split(u'\n')[0] | 95 parsed_name = parsed_data[0]['commit_msg'].split('\n')[0] |
96 parsed_name = CLEAN_RE.sub(u'', parsed_name)[:40] | 96 parsed_name = CLEAN_RE.sub('', parsed_name)[:40] |
97 except Exception: | 97 except Exception: |
98 parsed_name = u'' | 98 parsed_name = '' |
99 name = u'mr_{item_id}_{parsed_name}'.format(item_id=CLEAN_RE.sub(u'', item_id), | 99 name = 'mr_{item_id}_{parsed_name}'.format(item_id=CLEAN_RE.sub('', item_id), |
100 parsed_name=parsed_name) | 100 parsed_name=parsed_name) |
101 return MercurialProtocol.run(repository, 'qimport', '-g', '--name', name, | 101 return MercurialProtocol.run(repository, 'qimport', '-g', '--name', name, |
102 '--encoding=utf-8', '-', stdin=data) | 102 '--encoding=utf-8', '-', stdin=data) |
103 | 103 |
104 def parse(self, data, data_type=None): | 104 def parse(self, data, data_type=None): |
109 patch = {} | 109 patch = {} |
110 commit_msg = [] | 110 commit_msg = [] |
111 diff = [] | 111 diff = [] |
112 state = 'init' | 112 state = 'init' |
113 if lines[0] != '# HG changeset patch': | 113 if lines[0] != '# HG changeset patch': |
114 raise exceptions.DataError(_(u'invalid changeset signature')) | 114 raise exceptions.DataError(_('invalid changeset signature')) |
115 # line index of this patch in the whole data | 115 # line index of this patch in the whole data |
116 patch_idx = total_lines - len(lines) | 116 patch_idx = total_lines - len(lines) |
117 del lines[0] | 117 del lines[0] |
118 | 118 |
119 for idx, line in enumerate(lines): | 119 for idx, line in enumerate(lines): |
120 if state == 'init': | 120 if state == 'init': |
121 if line.startswith(u'# '): | 121 if line.startswith('# '): |
122 if line.startswith(u'# User '): | 122 if line.startswith('# User '): |
123 elems = line[7:].split() | 123 elems = line[7:].split() |
124 if not elems: | 124 if not elems: |
125 continue | 125 continue |
126 last = elems[-1] | 126 last = elems[-1] |
127 if (last.startswith(u'<') and last.endswith(u'>') | 127 if (last.startswith('<') and last.endswith('>') |
128 and u'@' in last): | 128 and '@' in last): |
129 patch[self._m.META_EMAIL] = elems.pop()[1:-1] | 129 patch[self._m.META_EMAIL] = elems.pop()[1:-1] |
130 patch[self._m.META_AUTHOR] = u' '.join(elems) | 130 patch[self._m.META_AUTHOR] = ' '.join(elems) |
131 elif line.startswith(u'# Date '): | 131 elif line.startswith('# Date '): |
132 time_data = line[7:].split() | 132 time_data = line[7:].split() |
133 if len(time_data) != 2: | 133 if len(time_data) != 2: |
134 log.warning(_(u'unexpected time data: {data}') | 134 log.warning(_('unexpected time data: {data}') |
135 .format(data=line[7:])) | 135 .format(data=line[7:])) |
136 continue | 136 continue |
137 patch[self._m.META_TIMESTAMP] = (int(time_data[0]) | 137 patch[self._m.META_TIMESTAMP] = (int(time_data[0]) |
138 + int(time_data[1])) | 138 + int(time_data[1])) |
139 elif line.startswith(u'# Node ID '): | 139 elif line.startswith('# Node ID '): |
140 patch[self._m.META_HASH] = line[10:] | 140 patch[self._m.META_HASH] = line[10:] |
141 elif line.startswith(u'# Parent '): | 141 elif line.startswith('# Parent '): |
142 patch[self._m.META_PARENT_HASH] = line[10:] | 142 patch[self._m.META_PARENT_HASH] = line[10:] |
143 else: | 143 else: |
144 state = 'commit_msg' | 144 state = 'commit_msg' |
145 if state == 'commit_msg': | 145 if state == 'commit_msg': |
146 if line.startswith(u'diff --git a/'): | 146 if line.startswith('diff --git a/'): |
147 state = 'diff' | 147 state = 'diff' |
148 patch[self._m.META_DIFF_IDX] = patch_idx + idx + 1 | 148 patch[self._m.META_DIFF_IDX] = patch_idx + idx + 1 |
149 else: | 149 else: |
150 commit_msg.append(line) | 150 commit_msg.append(line) |
151 if state == 'diff': | 151 if state == 'diff': |
152 if line.startswith(u'# ') or idx == len(lines)-1: | 152 if line.startswith('# ') or idx == len(lines)-1: |
153 # a new patch is starting or we have reached end of patches | 153 # a new patch is starting or we have reached end of patches |
154 if idx == len(lines)-1: | 154 if idx == len(lines)-1: |
155 # end of patches, we need to keep the line | 155 # end of patches, we need to keep the line |
156 diff.append(line) | 156 diff.append(line) |
157 patch[self._m.META_COMMIT_MSG] = u'\n'.join(commit_msg) | 157 patch[self._m.META_COMMIT_MSG] = '\n'.join(commit_msg) |
158 patch[self._m.META_DIFF] = u'\n'.join(diff) | 158 patch[self._m.META_DIFF] = '\n'.join(diff) |
159 patches.append(patch) | 159 patches.append(patch) |
160 if idx == len(lines)-1: | 160 if idx == len(lines)-1: |
161 del lines[:] | 161 del lines[:] |
162 else: | 162 else: |
163 del lines[:idx] | 163 del lines[:idx] |