##// END OF EJS Templates
mercurial: enable showfunc diff options to make it similar like git backend....
dan -
r849:f812d434 default
parent child Browse files
Show More
@@ -1,1009 +1,1009 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2019 RhodeCode GmbH
2 # Copyright (C) 2014-2019 RhodeCode GmbH
3 #
3 #
4 # This program is free software; you can redistribute it and/or modify
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import io
18 import io
19 import logging
19 import logging
20 import stat
20 import stat
21 import urllib
21 import urllib
22 import urllib2
22 import urllib2
23 import traceback
23 import traceback
24
24
25 from hgext import largefiles, rebase, purge
25 from hgext import largefiles, rebase, purge
26 from hgext.strip import strip as hgext_strip
26 from hgext.strip import strip as hgext_strip
27 from mercurial import commands
27 from mercurial import commands
28 from mercurial import unionrepo
28 from mercurial import unionrepo
29 from mercurial import verify
29 from mercurial import verify
30 from mercurial import repair
30 from mercurial import repair
31
31
32 import vcsserver
32 import vcsserver
33 from vcsserver import exceptions
33 from vcsserver import exceptions
34 from vcsserver.base import RepoFactory, obfuscate_qs, raise_from_original
34 from vcsserver.base import RepoFactory, obfuscate_qs, raise_from_original
35 from vcsserver.hgcompat import (
35 from vcsserver.hgcompat import (
36 archival, bin, clone, config as hgconfig, diffopts, hex, get_ctx,
36 archival, bin, clone, config as hgconfig, diffopts, hex, get_ctx,
37 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler,
37 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler,
38 makepeer, instance, match, memctx, exchange, memfilectx, nullrev, hg_merge,
38 makepeer, instance, match, memctx, exchange, memfilectx, nullrev, hg_merge,
39 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
39 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
40 RepoLookupError, InterventionRequired, RequirementError)
40 RepoLookupError, InterventionRequired, RequirementError)
41 from vcsserver.vcs_base import RemoteBase
41 from vcsserver.vcs_base import RemoteBase
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45
45
46 def make_ui_from_config(repo_config):
46 def make_ui_from_config(repo_config):
47
47
48 class LoggingUI(ui.ui):
48 class LoggingUI(ui.ui):
49 def status(self, *msg, **opts):
49 def status(self, *msg, **opts):
50 log.info(' '.join(msg).rstrip('\n'))
50 log.info(' '.join(msg).rstrip('\n'))
51 super(LoggingUI, self).status(*msg, **opts)
51 super(LoggingUI, self).status(*msg, **opts)
52
52
53 def warn(self, *msg, **opts):
53 def warn(self, *msg, **opts):
54 log.warn(' '.join(msg).rstrip('\n'))
54 log.warn(' '.join(msg).rstrip('\n'))
55 super(LoggingUI, self).warn(*msg, **opts)
55 super(LoggingUI, self).warn(*msg, **opts)
56
56
57 def error(self, *msg, **opts):
57 def error(self, *msg, **opts):
58 log.error(' '.join(msg).rstrip('\n'))
58 log.error(' '.join(msg).rstrip('\n'))
59 super(LoggingUI, self).error(*msg, **opts)
59 super(LoggingUI, self).error(*msg, **opts)
60
60
61 def note(self, *msg, **opts):
61 def note(self, *msg, **opts):
62 log.info(' '.join(msg).rstrip('\n'))
62 log.info(' '.join(msg).rstrip('\n'))
63 super(LoggingUI, self).note(*msg, **opts)
63 super(LoggingUI, self).note(*msg, **opts)
64
64
65 def debug(self, *msg, **opts):
65 def debug(self, *msg, **opts):
66 log.debug(' '.join(msg).rstrip('\n'))
66 log.debug(' '.join(msg).rstrip('\n'))
67 super(LoggingUI, self).debug(*msg, **opts)
67 super(LoggingUI, self).debug(*msg, **opts)
68
68
69 baseui = LoggingUI()
69 baseui = LoggingUI()
70
70
71 # clean the baseui object
71 # clean the baseui object
72 baseui._ocfg = hgconfig.config()
72 baseui._ocfg = hgconfig.config()
73 baseui._ucfg = hgconfig.config()
73 baseui._ucfg = hgconfig.config()
74 baseui._tcfg = hgconfig.config()
74 baseui._tcfg = hgconfig.config()
75
75
76 for section, option, value in repo_config:
76 for section, option, value in repo_config:
77 baseui.setconfig(section, option, value)
77 baseui.setconfig(section, option, value)
78
78
79 # make our hgweb quiet so it doesn't print output
79 # make our hgweb quiet so it doesn't print output
80 baseui.setconfig('ui', 'quiet', 'true')
80 baseui.setconfig('ui', 'quiet', 'true')
81
81
82 baseui.setconfig('ui', 'paginate', 'never')
82 baseui.setconfig('ui', 'paginate', 'never')
83 # for better Error reporting of Mercurial
83 # for better Error reporting of Mercurial
84 baseui.setconfig('ui', 'message-output', 'stderr')
84 baseui.setconfig('ui', 'message-output', 'stderr')
85
85
86 # force mercurial to only use 1 thread, otherwise it may try to set a
86 # force mercurial to only use 1 thread, otherwise it may try to set a
87 # signal in a non-main thread, thus generating a ValueError.
87 # signal in a non-main thread, thus generating a ValueError.
88 baseui.setconfig('worker', 'numcpus', 1)
88 baseui.setconfig('worker', 'numcpus', 1)
89
89
90 # If there is no config for the largefiles extension, we explicitly disable
90 # If there is no config for the largefiles extension, we explicitly disable
91 # it here. This overrides settings from repositories hgrc file. Recent
91 # it here. This overrides settings from repositories hgrc file. Recent
92 # mercurial versions enable largefiles in hgrc on clone from largefile
92 # mercurial versions enable largefiles in hgrc on clone from largefile
93 # repo.
93 # repo.
94 if not baseui.hasconfig('extensions', 'largefiles'):
94 if not baseui.hasconfig('extensions', 'largefiles'):
95 log.debug('Explicitly disable largefiles extension for repo.')
95 log.debug('Explicitly disable largefiles extension for repo.')
96 baseui.setconfig('extensions', 'largefiles', '!')
96 baseui.setconfig('extensions', 'largefiles', '!')
97
97
98 return baseui
98 return baseui
99
99
100
100
101 def reraise_safe_exceptions(func):
101 def reraise_safe_exceptions(func):
102 """Decorator for converting mercurial exceptions to something neutral."""
102 """Decorator for converting mercurial exceptions to something neutral."""
103
103
104 def wrapper(*args, **kwargs):
104 def wrapper(*args, **kwargs):
105 try:
105 try:
106 return func(*args, **kwargs)
106 return func(*args, **kwargs)
107 except (Abort, InterventionRequired) as e:
107 except (Abort, InterventionRequired) as e:
108 raise_from_original(exceptions.AbortException(e))
108 raise_from_original(exceptions.AbortException(e))
109 except RepoLookupError as e:
109 except RepoLookupError as e:
110 raise_from_original(exceptions.LookupException(e))
110 raise_from_original(exceptions.LookupException(e))
111 except RequirementError as e:
111 except RequirementError as e:
112 raise_from_original(exceptions.RequirementException(e))
112 raise_from_original(exceptions.RequirementException(e))
113 except RepoError as e:
113 except RepoError as e:
114 raise_from_original(exceptions.VcsException(e))
114 raise_from_original(exceptions.VcsException(e))
115 except LookupError as e:
115 except LookupError as e:
116 raise_from_original(exceptions.LookupException(e))
116 raise_from_original(exceptions.LookupException(e))
117 except Exception as e:
117 except Exception as e:
118 if not hasattr(e, '_vcs_kind'):
118 if not hasattr(e, '_vcs_kind'):
119 log.exception("Unhandled exception in hg remote call")
119 log.exception("Unhandled exception in hg remote call")
120 raise_from_original(exceptions.UnhandledException(e))
120 raise_from_original(exceptions.UnhandledException(e))
121
121
122 raise
122 raise
123 return wrapper
123 return wrapper
124
124
125
125
126 class MercurialFactory(RepoFactory):
126 class MercurialFactory(RepoFactory):
127 repo_type = 'hg'
127 repo_type = 'hg'
128
128
129 def _create_config(self, config, hooks=True):
129 def _create_config(self, config, hooks=True):
130 if not hooks:
130 if not hooks:
131 hooks_to_clean = frozenset((
131 hooks_to_clean = frozenset((
132 'changegroup.repo_size', 'preoutgoing.pre_pull',
132 'changegroup.repo_size', 'preoutgoing.pre_pull',
133 'outgoing.pull_logger', 'prechangegroup.pre_push'))
133 'outgoing.pull_logger', 'prechangegroup.pre_push'))
134 new_config = []
134 new_config = []
135 for section, option, value in config:
135 for section, option, value in config:
136 if section == 'hooks' and option in hooks_to_clean:
136 if section == 'hooks' and option in hooks_to_clean:
137 continue
137 continue
138 new_config.append((section, option, value))
138 new_config.append((section, option, value))
139 config = new_config
139 config = new_config
140
140
141 baseui = make_ui_from_config(config)
141 baseui = make_ui_from_config(config)
142 return baseui
142 return baseui
143
143
144 def _create_repo(self, wire, create):
144 def _create_repo(self, wire, create):
145 baseui = self._create_config(wire["config"])
145 baseui = self._create_config(wire["config"])
146 return instance(baseui, wire["path"], create)
146 return instance(baseui, wire["path"], create)
147
147
148 def repo(self, wire, create=False):
148 def repo(self, wire, create=False):
149 """
149 """
150 Get a repository instance for the given path.
150 Get a repository instance for the given path.
151 """
151 """
152 return self._create_repo(wire, create)
152 return self._create_repo(wire, create)
153
153
154
154
155 def patch_ui_message_output(baseui):
155 def patch_ui_message_output(baseui):
156 baseui.setconfig('ui', 'quiet', 'false')
156 baseui.setconfig('ui', 'quiet', 'false')
157 output = io.BytesIO()
157 output = io.BytesIO()
158
158
159 def write(data, **unused_kwargs):
159 def write(data, **unused_kwargs):
160 output.write(data)
160 output.write(data)
161
161
162 baseui.status = write
162 baseui.status = write
163 baseui.write = write
163 baseui.write = write
164 baseui.warn = write
164 baseui.warn = write
165 baseui.debug = write
165 baseui.debug = write
166
166
167 return baseui, output
167 return baseui, output
168
168
169
169
170 class HgRemote(RemoteBase):
170 class HgRemote(RemoteBase):
171
171
172 def __init__(self, factory):
172 def __init__(self, factory):
173 self._factory = factory
173 self._factory = factory
174 self._bulk_methods = {
174 self._bulk_methods = {
175 "affected_files": self.ctx_files,
175 "affected_files": self.ctx_files,
176 "author": self.ctx_user,
176 "author": self.ctx_user,
177 "branch": self.ctx_branch,
177 "branch": self.ctx_branch,
178 "children": self.ctx_children,
178 "children": self.ctx_children,
179 "date": self.ctx_date,
179 "date": self.ctx_date,
180 "message": self.ctx_description,
180 "message": self.ctx_description,
181 "parents": self.ctx_parents,
181 "parents": self.ctx_parents,
182 "status": self.ctx_status,
182 "status": self.ctx_status,
183 "obsolete": self.ctx_obsolete,
183 "obsolete": self.ctx_obsolete,
184 "phase": self.ctx_phase,
184 "phase": self.ctx_phase,
185 "hidden": self.ctx_hidden,
185 "hidden": self.ctx_hidden,
186 "_file_paths": self.ctx_list,
186 "_file_paths": self.ctx_list,
187 }
187 }
188
188
189 def _get_ctx(self, repo, ref):
189 def _get_ctx(self, repo, ref):
190 return get_ctx(repo, ref)
190 return get_ctx(repo, ref)
191
191
192 @reraise_safe_exceptions
192 @reraise_safe_exceptions
193 def discover_hg_version(self):
193 def discover_hg_version(self):
194 from mercurial import util
194 from mercurial import util
195 return util.version()
195 return util.version()
196
196
197 @reraise_safe_exceptions
197 @reraise_safe_exceptions
198 def is_empty(self, wire):
198 def is_empty(self, wire):
199 repo = self._factory.repo(wire)
199 repo = self._factory.repo(wire)
200
200
201 try:
201 try:
202 return len(repo) == 0
202 return len(repo) == 0
203 except Exception:
203 except Exception:
204 log.exception("failed to read object_store")
204 log.exception("failed to read object_store")
205 return False
205 return False
206
206
207 @reraise_safe_exceptions
207 @reraise_safe_exceptions
208 def archive_repo(self, archive_path, mtime, file_info, kind):
208 def archive_repo(self, archive_path, mtime, file_info, kind):
209 if kind == "tgz":
209 if kind == "tgz":
210 archiver = archival.tarit(archive_path, mtime, "gz")
210 archiver = archival.tarit(archive_path, mtime, "gz")
211 elif kind == "tbz2":
211 elif kind == "tbz2":
212 archiver = archival.tarit(archive_path, mtime, "bz2")
212 archiver = archival.tarit(archive_path, mtime, "bz2")
213 elif kind == 'zip':
213 elif kind == 'zip':
214 archiver = archival.zipit(archive_path, mtime)
214 archiver = archival.zipit(archive_path, mtime)
215 else:
215 else:
216 raise exceptions.ArchiveException()(
216 raise exceptions.ArchiveException()(
217 'Remote does not support: "%s".' % kind)
217 'Remote does not support: "%s".' % kind)
218
218
219 for f_path, f_mode, f_is_link, f_content in file_info:
219 for f_path, f_mode, f_is_link, f_content in file_info:
220 archiver.addfile(f_path, f_mode, f_is_link, f_content)
220 archiver.addfile(f_path, f_mode, f_is_link, f_content)
221 archiver.done()
221 archiver.done()
222
222
223 @reraise_safe_exceptions
223 @reraise_safe_exceptions
224 def bookmarks(self, wire):
224 def bookmarks(self, wire):
225 cache_on, context_uid, repo_id = self._cache_on(wire)
225 cache_on, context_uid, repo_id = self._cache_on(wire)
226 @self.region.conditional_cache_on_arguments(condition=cache_on)
226 @self.region.conditional_cache_on_arguments(condition=cache_on)
227 def _bookmarks(_context_uid, _repo_id):
227 def _bookmarks(_context_uid, _repo_id):
228 repo = self._factory.repo(wire)
228 repo = self._factory.repo(wire)
229 return dict(repo._bookmarks)
229 return dict(repo._bookmarks)
230
230
231 return _bookmarks(context_uid, repo_id)
231 return _bookmarks(context_uid, repo_id)
232
232
233 @reraise_safe_exceptions
233 @reraise_safe_exceptions
234 def branches(self, wire, normal, closed):
234 def branches(self, wire, normal, closed):
235 cache_on, context_uid, repo_id = self._cache_on(wire)
235 cache_on, context_uid, repo_id = self._cache_on(wire)
236 @self.region.conditional_cache_on_arguments(condition=cache_on)
236 @self.region.conditional_cache_on_arguments(condition=cache_on)
237 def _branches(_context_uid, _repo_id, _normal, _closed):
237 def _branches(_context_uid, _repo_id, _normal, _closed):
238 repo = self._factory.repo(wire)
238 repo = self._factory.repo(wire)
239 iter_branches = repo.branchmap().iterbranches()
239 iter_branches = repo.branchmap().iterbranches()
240 bt = {}
240 bt = {}
241 for branch_name, _heads, tip, is_closed in iter_branches:
241 for branch_name, _heads, tip, is_closed in iter_branches:
242 if normal and not is_closed:
242 if normal and not is_closed:
243 bt[branch_name] = tip
243 bt[branch_name] = tip
244 if closed and is_closed:
244 if closed and is_closed:
245 bt[branch_name] = tip
245 bt[branch_name] = tip
246
246
247 return bt
247 return bt
248
248
249 return _branches(context_uid, repo_id, normal, closed)
249 return _branches(context_uid, repo_id, normal, closed)
250
250
251 @reraise_safe_exceptions
251 @reraise_safe_exceptions
252 def bulk_request(self, wire, commit_id, pre_load):
252 def bulk_request(self, wire, commit_id, pre_load):
253 cache_on, context_uid, repo_id = self._cache_on(wire)
253 cache_on, context_uid, repo_id = self._cache_on(wire)
254 @self.region.conditional_cache_on_arguments(condition=cache_on)
254 @self.region.conditional_cache_on_arguments(condition=cache_on)
255 def _bulk_request(_repo_id, _commit_id, _pre_load):
255 def _bulk_request(_repo_id, _commit_id, _pre_load):
256 result = {}
256 result = {}
257 for attr in pre_load:
257 for attr in pre_load:
258 try:
258 try:
259 method = self._bulk_methods[attr]
259 method = self._bulk_methods[attr]
260 result[attr] = method(wire, commit_id)
260 result[attr] = method(wire, commit_id)
261 except KeyError as e:
261 except KeyError as e:
262 raise exceptions.VcsException(e)(
262 raise exceptions.VcsException(e)(
263 'Unknown bulk attribute: "%s"' % attr)
263 'Unknown bulk attribute: "%s"' % attr)
264 return result
264 return result
265
265
266 return _bulk_request(repo_id, commit_id, sorted(pre_load))
266 return _bulk_request(repo_id, commit_id, sorted(pre_load))
267
267
268 @reraise_safe_exceptions
268 @reraise_safe_exceptions
269 def ctx_branch(self, wire, commit_id):
269 def ctx_branch(self, wire, commit_id):
270 cache_on, context_uid, repo_id = self._cache_on(wire)
270 cache_on, context_uid, repo_id = self._cache_on(wire)
271 @self.region.conditional_cache_on_arguments(condition=cache_on)
271 @self.region.conditional_cache_on_arguments(condition=cache_on)
272 def _ctx_branch(_repo_id, _commit_id):
272 def _ctx_branch(_repo_id, _commit_id):
273 repo = self._factory.repo(wire)
273 repo = self._factory.repo(wire)
274 ctx = self._get_ctx(repo, commit_id)
274 ctx = self._get_ctx(repo, commit_id)
275 return ctx.branch()
275 return ctx.branch()
276 return _ctx_branch(repo_id, commit_id)
276 return _ctx_branch(repo_id, commit_id)
277
277
278 @reraise_safe_exceptions
278 @reraise_safe_exceptions
279 def ctx_date(self, wire, commit_id):
279 def ctx_date(self, wire, commit_id):
280 cache_on, context_uid, repo_id = self._cache_on(wire)
280 cache_on, context_uid, repo_id = self._cache_on(wire)
281 @self.region.conditional_cache_on_arguments(condition=cache_on)
281 @self.region.conditional_cache_on_arguments(condition=cache_on)
282 def _ctx_date(_repo_id, _commit_id):
282 def _ctx_date(_repo_id, _commit_id):
283 repo = self._factory.repo(wire)
283 repo = self._factory.repo(wire)
284 ctx = self._get_ctx(repo, commit_id)
284 ctx = self._get_ctx(repo, commit_id)
285 return ctx.date()
285 return ctx.date()
286 return _ctx_date(repo_id, commit_id)
286 return _ctx_date(repo_id, commit_id)
287
287
288 @reraise_safe_exceptions
288 @reraise_safe_exceptions
289 def ctx_description(self, wire, revision):
289 def ctx_description(self, wire, revision):
290 repo = self._factory.repo(wire)
290 repo = self._factory.repo(wire)
291 ctx = self._get_ctx(repo, revision)
291 ctx = self._get_ctx(repo, revision)
292 return ctx.description()
292 return ctx.description()
293
293
294 @reraise_safe_exceptions
294 @reraise_safe_exceptions
295 def ctx_files(self, wire, commit_id):
295 def ctx_files(self, wire, commit_id):
296 cache_on, context_uid, repo_id = self._cache_on(wire)
296 cache_on, context_uid, repo_id = self._cache_on(wire)
297 @self.region.conditional_cache_on_arguments(condition=cache_on)
297 @self.region.conditional_cache_on_arguments(condition=cache_on)
298 def _ctx_files(_repo_id, _commit_id):
298 def _ctx_files(_repo_id, _commit_id):
299 repo = self._factory.repo(wire)
299 repo = self._factory.repo(wire)
300 ctx = self._get_ctx(repo, commit_id)
300 ctx = self._get_ctx(repo, commit_id)
301 return ctx.files()
301 return ctx.files()
302
302
303 return _ctx_files(repo_id, commit_id)
303 return _ctx_files(repo_id, commit_id)
304
304
305 @reraise_safe_exceptions
305 @reraise_safe_exceptions
306 def ctx_list(self, path, revision):
306 def ctx_list(self, path, revision):
307 repo = self._factory.repo(path)
307 repo = self._factory.repo(path)
308 ctx = self._get_ctx(repo, revision)
308 ctx = self._get_ctx(repo, revision)
309 return list(ctx)
309 return list(ctx)
310
310
311 @reraise_safe_exceptions
311 @reraise_safe_exceptions
312 def ctx_parents(self, wire, commit_id):
312 def ctx_parents(self, wire, commit_id):
313 cache_on, context_uid, repo_id = self._cache_on(wire)
313 cache_on, context_uid, repo_id = self._cache_on(wire)
314 @self.region.conditional_cache_on_arguments(condition=cache_on)
314 @self.region.conditional_cache_on_arguments(condition=cache_on)
315 def _ctx_parents(_repo_id, _commit_id):
315 def _ctx_parents(_repo_id, _commit_id):
316 repo = self._factory.repo(wire)
316 repo = self._factory.repo(wire)
317 ctx = self._get_ctx(repo, commit_id)
317 ctx = self._get_ctx(repo, commit_id)
318 return [parent.hex() for parent in ctx.parents()
318 return [parent.hex() for parent in ctx.parents()
319 if not (parent.hidden() or parent.obsolete())]
319 if not (parent.hidden() or parent.obsolete())]
320
320
321 return _ctx_parents(repo_id, commit_id)
321 return _ctx_parents(repo_id, commit_id)
322
322
323 @reraise_safe_exceptions
323 @reraise_safe_exceptions
324 def ctx_children(self, wire, commit_id):
324 def ctx_children(self, wire, commit_id):
325 cache_on, context_uid, repo_id = self._cache_on(wire)
325 cache_on, context_uid, repo_id = self._cache_on(wire)
326 @self.region.conditional_cache_on_arguments(condition=cache_on)
326 @self.region.conditional_cache_on_arguments(condition=cache_on)
327 def _ctx_children(_repo_id, _commit_id):
327 def _ctx_children(_repo_id, _commit_id):
328 repo = self._factory.repo(wire)
328 repo = self._factory.repo(wire)
329 ctx = self._get_ctx(repo, commit_id)
329 ctx = self._get_ctx(repo, commit_id)
330 return [child.hex() for child in ctx.children()
330 return [child.hex() for child in ctx.children()
331 if not (child.hidden() or child.obsolete())]
331 if not (child.hidden() or child.obsolete())]
332
332
333 return _ctx_children(repo_id, commit_id)
333 return _ctx_children(repo_id, commit_id)
334
334
335 @reraise_safe_exceptions
335 @reraise_safe_exceptions
336 def ctx_phase(self, wire, commit_id):
336 def ctx_phase(self, wire, commit_id):
337 cache_on, context_uid, repo_id = self._cache_on(wire)
337 cache_on, context_uid, repo_id = self._cache_on(wire)
338 @self.region.conditional_cache_on_arguments(condition=cache_on)
338 @self.region.conditional_cache_on_arguments(condition=cache_on)
339 def _ctx_phase(_context_uid, _repo_id, _commit_id):
339 def _ctx_phase(_context_uid, _repo_id, _commit_id):
340 repo = self._factory.repo(wire)
340 repo = self._factory.repo(wire)
341 ctx = self._get_ctx(repo, commit_id)
341 ctx = self._get_ctx(repo, commit_id)
342 # public=0, draft=1, secret=3
342 # public=0, draft=1, secret=3
343 return ctx.phase()
343 return ctx.phase()
344 return _ctx_phase(context_uid, repo_id, commit_id)
344 return _ctx_phase(context_uid, repo_id, commit_id)
345
345
346 @reraise_safe_exceptions
346 @reraise_safe_exceptions
347 def ctx_obsolete(self, wire, commit_id):
347 def ctx_obsolete(self, wire, commit_id):
348 cache_on, context_uid, repo_id = self._cache_on(wire)
348 cache_on, context_uid, repo_id = self._cache_on(wire)
349 @self.region.conditional_cache_on_arguments(condition=cache_on)
349 @self.region.conditional_cache_on_arguments(condition=cache_on)
350 def _ctx_obsolete(_context_uid, _repo_id, _commit_id):
350 def _ctx_obsolete(_context_uid, _repo_id, _commit_id):
351 repo = self._factory.repo(wire)
351 repo = self._factory.repo(wire)
352 ctx = self._get_ctx(repo, commit_id)
352 ctx = self._get_ctx(repo, commit_id)
353 return ctx.obsolete()
353 return ctx.obsolete()
354 return _ctx_obsolete(context_uid, repo_id, commit_id)
354 return _ctx_obsolete(context_uid, repo_id, commit_id)
355
355
356 @reraise_safe_exceptions
356 @reraise_safe_exceptions
357 def ctx_hidden(self, wire, commit_id):
357 def ctx_hidden(self, wire, commit_id):
358 cache_on, context_uid, repo_id = self._cache_on(wire)
358 cache_on, context_uid, repo_id = self._cache_on(wire)
359 @self.region.conditional_cache_on_arguments(condition=cache_on)
359 @self.region.conditional_cache_on_arguments(condition=cache_on)
360 def _ctx_hidden(_context_uid, _repo_id, _commit_id):
360 def _ctx_hidden(_context_uid, _repo_id, _commit_id):
361 repo = self._factory.repo(wire)
361 repo = self._factory.repo(wire)
362 ctx = self._get_ctx(repo, commit_id)
362 ctx = self._get_ctx(repo, commit_id)
363 return ctx.hidden()
363 return ctx.hidden()
364 return _ctx_hidden(context_uid, repo_id, commit_id)
364 return _ctx_hidden(context_uid, repo_id, commit_id)
365
365
366 @reraise_safe_exceptions
366 @reraise_safe_exceptions
367 def ctx_substate(self, wire, revision):
367 def ctx_substate(self, wire, revision):
368 repo = self._factory.repo(wire)
368 repo = self._factory.repo(wire)
369 ctx = self._get_ctx(repo, revision)
369 ctx = self._get_ctx(repo, revision)
370 return ctx.substate
370 return ctx.substate
371
371
372 @reraise_safe_exceptions
372 @reraise_safe_exceptions
373 def ctx_status(self, wire, revision):
373 def ctx_status(self, wire, revision):
374 repo = self._factory.repo(wire)
374 repo = self._factory.repo(wire)
375 ctx = self._get_ctx(repo, revision)
375 ctx = self._get_ctx(repo, revision)
376 status = repo[ctx.p1().node()].status(other=ctx.node())
376 status = repo[ctx.p1().node()].status(other=ctx.node())
377 # object of status (odd, custom named tuple in mercurial) is not
377 # object of status (odd, custom named tuple in mercurial) is not
378 # correctly serializable, we make it a list, as the underling
378 # correctly serializable, we make it a list, as the underling
379 # API expects this to be a list
379 # API expects this to be a list
380 return list(status)
380 return list(status)
381
381
382 @reraise_safe_exceptions
382 @reraise_safe_exceptions
383 def ctx_user(self, wire, revision):
383 def ctx_user(self, wire, revision):
384 repo = self._factory.repo(wire)
384 repo = self._factory.repo(wire)
385 ctx = self._get_ctx(repo, revision)
385 ctx = self._get_ctx(repo, revision)
386 return ctx.user()
386 return ctx.user()
387
387
388 @reraise_safe_exceptions
388 @reraise_safe_exceptions
389 def check_url(self, url, config):
389 def check_url(self, url, config):
390 _proto = None
390 _proto = None
391 if '+' in url[:url.find('://')]:
391 if '+' in url[:url.find('://')]:
392 _proto = url[0:url.find('+')]
392 _proto = url[0:url.find('+')]
393 url = url[url.find('+') + 1:]
393 url = url[url.find('+') + 1:]
394 handlers = []
394 handlers = []
395 url_obj = url_parser(url)
395 url_obj = url_parser(url)
396 test_uri, authinfo = url_obj.authinfo()
396 test_uri, authinfo = url_obj.authinfo()
397 url_obj.passwd = '*****' if url_obj.passwd else url_obj.passwd
397 url_obj.passwd = '*****' if url_obj.passwd else url_obj.passwd
398 url_obj.query = obfuscate_qs(url_obj.query)
398 url_obj.query = obfuscate_qs(url_obj.query)
399
399
400 cleaned_uri = str(url_obj)
400 cleaned_uri = str(url_obj)
401 log.info("Checking URL for remote cloning/import: %s", cleaned_uri)
401 log.info("Checking URL for remote cloning/import: %s", cleaned_uri)
402
402
403 if authinfo:
403 if authinfo:
404 # create a password manager
404 # create a password manager
405 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
405 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
406 passmgr.add_password(*authinfo)
406 passmgr.add_password(*authinfo)
407
407
408 handlers.extend((httpbasicauthhandler(passmgr),
408 handlers.extend((httpbasicauthhandler(passmgr),
409 httpdigestauthhandler(passmgr)))
409 httpdigestauthhandler(passmgr)))
410
410
411 o = urllib2.build_opener(*handlers)
411 o = urllib2.build_opener(*handlers)
412 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
412 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
413 ('Accept', 'application/mercurial-0.1')]
413 ('Accept', 'application/mercurial-0.1')]
414
414
415 q = {"cmd": 'between'}
415 q = {"cmd": 'between'}
416 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
416 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
417 qs = '?%s' % urllib.urlencode(q)
417 qs = '?%s' % urllib.urlencode(q)
418 cu = "%s%s" % (test_uri, qs)
418 cu = "%s%s" % (test_uri, qs)
419 req = urllib2.Request(cu, None, {})
419 req = urllib2.Request(cu, None, {})
420
420
421 try:
421 try:
422 log.debug("Trying to open URL %s", cleaned_uri)
422 log.debug("Trying to open URL %s", cleaned_uri)
423 resp = o.open(req)
423 resp = o.open(req)
424 if resp.code != 200:
424 if resp.code != 200:
425 raise exceptions.URLError()('Return Code is not 200')
425 raise exceptions.URLError()('Return Code is not 200')
426 except Exception as e:
426 except Exception as e:
427 log.warning("URL cannot be opened: %s", cleaned_uri, exc_info=True)
427 log.warning("URL cannot be opened: %s", cleaned_uri, exc_info=True)
428 # means it cannot be cloned
428 # means it cannot be cloned
429 raise exceptions.URLError(e)("[%s] org_exc: %s" % (cleaned_uri, e))
429 raise exceptions.URLError(e)("[%s] org_exc: %s" % (cleaned_uri, e))
430
430
431 # now check if it's a proper hg repo, but don't do it for svn
431 # now check if it's a proper hg repo, but don't do it for svn
432 try:
432 try:
433 if _proto == 'svn':
433 if _proto == 'svn':
434 pass
434 pass
435 else:
435 else:
436 # check for pure hg repos
436 # check for pure hg repos
437 log.debug(
437 log.debug(
438 "Verifying if URL is a Mercurial repository: %s",
438 "Verifying if URL is a Mercurial repository: %s",
439 cleaned_uri)
439 cleaned_uri)
440 ui = make_ui_from_config(config)
440 ui = make_ui_from_config(config)
441 peer_checker = makepeer(ui, url)
441 peer_checker = makepeer(ui, url)
442 peer_checker.lookup('tip')
442 peer_checker.lookup('tip')
443 except Exception as e:
443 except Exception as e:
444 log.warning("URL is not a valid Mercurial repository: %s",
444 log.warning("URL is not a valid Mercurial repository: %s",
445 cleaned_uri)
445 cleaned_uri)
446 raise exceptions.URLError(e)(
446 raise exceptions.URLError(e)(
447 "url [%s] does not look like an hg repo org_exc: %s"
447 "url [%s] does not look like an hg repo org_exc: %s"
448 % (cleaned_uri, e))
448 % (cleaned_uri, e))
449
449
450 log.info("URL is a valid Mercurial repository: %s", cleaned_uri)
450 log.info("URL is a valid Mercurial repository: %s", cleaned_uri)
451 return True
451 return True
452
452
453 @reraise_safe_exceptions
453 @reraise_safe_exceptions
454 def diff(self, wire, commit_id_1, commit_id_2, file_filter, opt_git, opt_ignorews, context):
454 def diff(self, wire, commit_id_1, commit_id_2, file_filter, opt_git, opt_ignorews, context):
455 repo = self._factory.repo(wire)
455 repo = self._factory.repo(wire)
456
456
457 if file_filter:
457 if file_filter:
458 match_filter = match(file_filter[0], '', [file_filter[1]])
458 match_filter = match(file_filter[0], '', [file_filter[1]])
459 else:
459 else:
460 match_filter = file_filter
460 match_filter = file_filter
461 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context)
461 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context, showfunc=1)
462
462
463 try:
463 try:
464 return "".join(patch.diff(
464 return "".join(patch.diff(
465 repo, node1=commit_id_1, node2=commit_id_2, match=match_filter, opts=opts))
465 repo, node1=commit_id_1, node2=commit_id_2, match=match_filter, opts=opts))
466 except RepoLookupError as e:
466 except RepoLookupError as e:
467 raise exceptions.LookupException(e)()
467 raise exceptions.LookupException(e)()
468
468
469 @reraise_safe_exceptions
469 @reraise_safe_exceptions
470 def node_history(self, wire, revision, path, limit):
470 def node_history(self, wire, revision, path, limit):
471 cache_on, context_uid, repo_id = self._cache_on(wire)
471 cache_on, context_uid, repo_id = self._cache_on(wire)
472 @self.region.conditional_cache_on_arguments(condition=cache_on)
472 @self.region.conditional_cache_on_arguments(condition=cache_on)
473 def _node_history(_context_uid, _repo_id, _revision, _path, _limit):
473 def _node_history(_context_uid, _repo_id, _revision, _path, _limit):
474 repo = self._factory.repo(wire)
474 repo = self._factory.repo(wire)
475
475
476 ctx = self._get_ctx(repo, revision)
476 ctx = self._get_ctx(repo, revision)
477 fctx = ctx.filectx(path)
477 fctx = ctx.filectx(path)
478
478
479 def history_iter():
479 def history_iter():
480 limit_rev = fctx.rev()
480 limit_rev = fctx.rev()
481 for obj in reversed(list(fctx.filelog())):
481 for obj in reversed(list(fctx.filelog())):
482 obj = fctx.filectx(obj)
482 obj = fctx.filectx(obj)
483 ctx = obj.changectx()
483 ctx = obj.changectx()
484 if ctx.hidden() or ctx.obsolete():
484 if ctx.hidden() or ctx.obsolete():
485 continue
485 continue
486
486
487 if limit_rev >= obj.rev():
487 if limit_rev >= obj.rev():
488 yield obj
488 yield obj
489
489
490 history = []
490 history = []
491 for cnt, obj in enumerate(history_iter()):
491 for cnt, obj in enumerate(history_iter()):
492 if limit and cnt >= limit:
492 if limit and cnt >= limit:
493 break
493 break
494 history.append(hex(obj.node()))
494 history.append(hex(obj.node()))
495
495
496 return [x for x in history]
496 return [x for x in history]
497 return _node_history(context_uid, repo_id, revision, path, limit)
497 return _node_history(context_uid, repo_id, revision, path, limit)
498
498
499 @reraise_safe_exceptions
499 @reraise_safe_exceptions
500 def node_history_untill(self, wire, revision, path, limit):
500 def node_history_untill(self, wire, revision, path, limit):
501 cache_on, context_uid, repo_id = self._cache_on(wire)
501 cache_on, context_uid, repo_id = self._cache_on(wire)
502 @self.region.conditional_cache_on_arguments(condition=cache_on)
502 @self.region.conditional_cache_on_arguments(condition=cache_on)
503 def _node_history_until(_context_uid, _repo_id):
503 def _node_history_until(_context_uid, _repo_id):
504 repo = self._factory.repo(wire)
504 repo = self._factory.repo(wire)
505 ctx = self._get_ctx(repo, revision)
505 ctx = self._get_ctx(repo, revision)
506 fctx = ctx.filectx(path)
506 fctx = ctx.filectx(path)
507
507
508 file_log = list(fctx.filelog())
508 file_log = list(fctx.filelog())
509 if limit:
509 if limit:
510 # Limit to the last n items
510 # Limit to the last n items
511 file_log = file_log[-limit:]
511 file_log = file_log[-limit:]
512
512
513 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
513 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
514 return _node_history_until(context_uid, repo_id, revision, path, limit)
514 return _node_history_until(context_uid, repo_id, revision, path, limit)
515
515
516 @reraise_safe_exceptions
516 @reraise_safe_exceptions
517 def fctx_annotate(self, wire, revision, path):
517 def fctx_annotate(self, wire, revision, path):
518 repo = self._factory.repo(wire)
518 repo = self._factory.repo(wire)
519 ctx = self._get_ctx(repo, revision)
519 ctx = self._get_ctx(repo, revision)
520 fctx = ctx.filectx(path)
520 fctx = ctx.filectx(path)
521
521
522 result = []
522 result = []
523 for i, annotate_obj in enumerate(fctx.annotate(), 1):
523 for i, annotate_obj in enumerate(fctx.annotate(), 1):
524 ln_no = i
524 ln_no = i
525 sha = hex(annotate_obj.fctx.node())
525 sha = hex(annotate_obj.fctx.node())
526 content = annotate_obj.text
526 content = annotate_obj.text
527 result.append((ln_no, sha, content))
527 result.append((ln_no, sha, content))
528 return result
528 return result
529
529
530 @reraise_safe_exceptions
530 @reraise_safe_exceptions
531 def fctx_node_data(self, wire, revision, path):
531 def fctx_node_data(self, wire, revision, path):
532 repo = self._factory.repo(wire)
532 repo = self._factory.repo(wire)
533 ctx = self._get_ctx(repo, revision)
533 ctx = self._get_ctx(repo, revision)
534 fctx = ctx.filectx(path)
534 fctx = ctx.filectx(path)
535 return fctx.data()
535 return fctx.data()
536
536
537 @reraise_safe_exceptions
537 @reraise_safe_exceptions
538 def fctx_flags(self, wire, commit_id, path):
538 def fctx_flags(self, wire, commit_id, path):
539 cache_on, context_uid, repo_id = self._cache_on(wire)
539 cache_on, context_uid, repo_id = self._cache_on(wire)
540 @self.region.conditional_cache_on_arguments(condition=cache_on)
540 @self.region.conditional_cache_on_arguments(condition=cache_on)
541 def _fctx_flags(_repo_id, _commit_id, _path):
541 def _fctx_flags(_repo_id, _commit_id, _path):
542 repo = self._factory.repo(wire)
542 repo = self._factory.repo(wire)
543 ctx = self._get_ctx(repo, commit_id)
543 ctx = self._get_ctx(repo, commit_id)
544 fctx = ctx.filectx(path)
544 fctx = ctx.filectx(path)
545 return fctx.flags()
545 return fctx.flags()
546
546
547 return _fctx_flags(repo_id, commit_id, path)
547 return _fctx_flags(repo_id, commit_id, path)
548
548
549 @reraise_safe_exceptions
549 @reraise_safe_exceptions
550 def fctx_size(self, wire, commit_id, path):
550 def fctx_size(self, wire, commit_id, path):
551 cache_on, context_uid, repo_id = self._cache_on(wire)
551 cache_on, context_uid, repo_id = self._cache_on(wire)
552 @self.region.conditional_cache_on_arguments(condition=cache_on)
552 @self.region.conditional_cache_on_arguments(condition=cache_on)
553 def _fctx_size(_repo_id, _revision, _path):
553 def _fctx_size(_repo_id, _revision, _path):
554 repo = self._factory.repo(wire)
554 repo = self._factory.repo(wire)
555 ctx = self._get_ctx(repo, commit_id)
555 ctx = self._get_ctx(repo, commit_id)
556 fctx = ctx.filectx(path)
556 fctx = ctx.filectx(path)
557 return fctx.size()
557 return fctx.size()
558 return _fctx_size(repo_id, commit_id, path)
558 return _fctx_size(repo_id, commit_id, path)
559
559
560 @reraise_safe_exceptions
560 @reraise_safe_exceptions
561 def get_all_commit_ids(self, wire, name):
561 def get_all_commit_ids(self, wire, name):
562 cache_on, context_uid, repo_id = self._cache_on(wire)
562 cache_on, context_uid, repo_id = self._cache_on(wire)
563 @self.region.conditional_cache_on_arguments(condition=cache_on)
563 @self.region.conditional_cache_on_arguments(condition=cache_on)
564 def _get_all_commit_ids(_context_uid, _repo_id, _name):
564 def _get_all_commit_ids(_context_uid, _repo_id, _name):
565 repo = self._factory.repo(wire)
565 repo = self._factory.repo(wire)
566 repo = repo.filtered(name)
566 repo = repo.filtered(name)
567 revs = map(lambda x: hex(x[7]), repo.changelog.index)
567 revs = map(lambda x: hex(x[7]), repo.changelog.index)
568 return revs
568 return revs
569 return _get_all_commit_ids(context_uid, repo_id, name)
569 return _get_all_commit_ids(context_uid, repo_id, name)
570
570
571 @reraise_safe_exceptions
571 @reraise_safe_exceptions
572 def get_config_value(self, wire, section, name, untrusted=False):
572 def get_config_value(self, wire, section, name, untrusted=False):
573 repo = self._factory.repo(wire)
573 repo = self._factory.repo(wire)
574 return repo.ui.config(section, name, untrusted=untrusted)
574 return repo.ui.config(section, name, untrusted=untrusted)
575
575
576 @reraise_safe_exceptions
576 @reraise_safe_exceptions
577 def is_large_file(self, wire, commit_id, path):
577 def is_large_file(self, wire, commit_id, path):
578 cache_on, context_uid, repo_id = self._cache_on(wire)
578 cache_on, context_uid, repo_id = self._cache_on(wire)
579 @self.region.conditional_cache_on_arguments(condition=cache_on)
579 @self.region.conditional_cache_on_arguments(condition=cache_on)
580 def _is_large_file(_context_uid, _repo_id, _commit_id, _path):
580 def _is_large_file(_context_uid, _repo_id, _commit_id, _path):
581 return largefiles.lfutil.isstandin(path)
581 return largefiles.lfutil.isstandin(path)
582
582
583 return _is_large_file(context_uid, repo_id, commit_id, path)
583 return _is_large_file(context_uid, repo_id, commit_id, path)
584
584
585 @reraise_safe_exceptions
585 @reraise_safe_exceptions
586 def is_binary(self, wire, revision, path):
586 def is_binary(self, wire, revision, path):
587 cache_on, context_uid, repo_id = self._cache_on(wire)
587 cache_on, context_uid, repo_id = self._cache_on(wire)
588
588
589 @self.region.conditional_cache_on_arguments(condition=cache_on)
589 @self.region.conditional_cache_on_arguments(condition=cache_on)
590 def _is_binary(_repo_id, _sha, _path):
590 def _is_binary(_repo_id, _sha, _path):
591 repo = self._factory.repo(wire)
591 repo = self._factory.repo(wire)
592 ctx = self._get_ctx(repo, revision)
592 ctx = self._get_ctx(repo, revision)
593 fctx = ctx.filectx(path)
593 fctx = ctx.filectx(path)
594 return fctx.isbinary()
594 return fctx.isbinary()
595
595
596 return _is_binary(repo_id, revision, path)
596 return _is_binary(repo_id, revision, path)
597
597
598 @reraise_safe_exceptions
598 @reraise_safe_exceptions
599 def in_largefiles_store(self, wire, sha):
599 def in_largefiles_store(self, wire, sha):
600 repo = self._factory.repo(wire)
600 repo = self._factory.repo(wire)
601 return largefiles.lfutil.instore(repo, sha)
601 return largefiles.lfutil.instore(repo, sha)
602
602
603 @reraise_safe_exceptions
603 @reraise_safe_exceptions
604 def in_user_cache(self, wire, sha):
604 def in_user_cache(self, wire, sha):
605 repo = self._factory.repo(wire)
605 repo = self._factory.repo(wire)
606 return largefiles.lfutil.inusercache(repo.ui, sha)
606 return largefiles.lfutil.inusercache(repo.ui, sha)
607
607
608 @reraise_safe_exceptions
608 @reraise_safe_exceptions
609 def store_path(self, wire, sha):
609 def store_path(self, wire, sha):
610 repo = self._factory.repo(wire)
610 repo = self._factory.repo(wire)
611 return largefiles.lfutil.storepath(repo, sha)
611 return largefiles.lfutil.storepath(repo, sha)
612
612
613 @reraise_safe_exceptions
613 @reraise_safe_exceptions
614 def link(self, wire, sha, path):
614 def link(self, wire, sha, path):
615 repo = self._factory.repo(wire)
615 repo = self._factory.repo(wire)
616 largefiles.lfutil.link(
616 largefiles.lfutil.link(
617 largefiles.lfutil.usercachepath(repo.ui, sha), path)
617 largefiles.lfutil.usercachepath(repo.ui, sha), path)
618
618
619 @reraise_safe_exceptions
619 @reraise_safe_exceptions
620 def localrepository(self, wire, create=False):
620 def localrepository(self, wire, create=False):
621 self._factory.repo(wire, create=create)
621 self._factory.repo(wire, create=create)
622
622
623 @reraise_safe_exceptions
623 @reraise_safe_exceptions
624 def lookup(self, wire, revision, both):
624 def lookup(self, wire, revision, both):
625 cache_on, context_uid, repo_id = self._cache_on(wire)
625 cache_on, context_uid, repo_id = self._cache_on(wire)
626 @self.region.conditional_cache_on_arguments(condition=cache_on)
626 @self.region.conditional_cache_on_arguments(condition=cache_on)
627 def _lookup(_context_uid, _repo_id, _revision, _both):
627 def _lookup(_context_uid, _repo_id, _revision, _both):
628
628
629 repo = self._factory.repo(wire)
629 repo = self._factory.repo(wire)
630 rev = _revision
630 rev = _revision
631 if isinstance(rev, int):
631 if isinstance(rev, int):
632 # NOTE(marcink):
632 # NOTE(marcink):
633 # since Mercurial doesn't support negative indexes properly
633 # since Mercurial doesn't support negative indexes properly
634 # we need to shift accordingly by one to get proper index, e.g
634 # we need to shift accordingly by one to get proper index, e.g
635 # repo[-1] => repo[-2]
635 # repo[-1] => repo[-2]
636 # repo[0] => repo[-1]
636 # repo[0] => repo[-1]
637 if rev <= 0:
637 if rev <= 0:
638 rev = rev + -1
638 rev = rev + -1
639 try:
639 try:
640 ctx = self._get_ctx(repo, rev)
640 ctx = self._get_ctx(repo, rev)
641 except (TypeError, RepoLookupError) as e:
641 except (TypeError, RepoLookupError) as e:
642 e._org_exc_tb = traceback.format_exc()
642 e._org_exc_tb = traceback.format_exc()
643 raise exceptions.LookupException(e)(rev)
643 raise exceptions.LookupException(e)(rev)
644 except LookupError as e:
644 except LookupError as e:
645 e._org_exc_tb = traceback.format_exc()
645 e._org_exc_tb = traceback.format_exc()
646 raise exceptions.LookupException(e)(e.name)
646 raise exceptions.LookupException(e)(e.name)
647
647
648 if not both:
648 if not both:
649 return ctx.hex()
649 return ctx.hex()
650
650
651 ctx = repo[ctx.hex()]
651 ctx = repo[ctx.hex()]
652 return ctx.hex(), ctx.rev()
652 return ctx.hex(), ctx.rev()
653
653
654 return _lookup(context_uid, repo_id, revision, both)
654 return _lookup(context_uid, repo_id, revision, both)
655
655
656 @reraise_safe_exceptions
656 @reraise_safe_exceptions
657 def sync_push(self, wire, url):
657 def sync_push(self, wire, url):
658 if not self.check_url(url, wire['config']):
658 if not self.check_url(url, wire['config']):
659 return
659 return
660
660
661 repo = self._factory.repo(wire)
661 repo = self._factory.repo(wire)
662
662
663 # Disable any prompts for this repo
663 # Disable any prompts for this repo
664 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
664 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
665
665
666 bookmarks = dict(repo._bookmarks).keys()
666 bookmarks = dict(repo._bookmarks).keys()
667 remote = peer(repo, {}, url)
667 remote = peer(repo, {}, url)
668 # Disable any prompts for this remote
668 # Disable any prompts for this remote
669 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
669 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
670
670
671 return exchange.push(
671 return exchange.push(
672 repo, remote, newbranch=True, bookmarks=bookmarks).cgresult
672 repo, remote, newbranch=True, bookmarks=bookmarks).cgresult
673
673
674 @reraise_safe_exceptions
674 @reraise_safe_exceptions
675 def revision(self, wire, rev):
675 def revision(self, wire, rev):
676 repo = self._factory.repo(wire)
676 repo = self._factory.repo(wire)
677 ctx = self._get_ctx(repo, rev)
677 ctx = self._get_ctx(repo, rev)
678 return ctx.rev()
678 return ctx.rev()
679
679
680 @reraise_safe_exceptions
680 @reraise_safe_exceptions
681 def rev_range(self, wire, commit_filter):
681 def rev_range(self, wire, commit_filter):
682 cache_on, context_uid, repo_id = self._cache_on(wire)
682 cache_on, context_uid, repo_id = self._cache_on(wire)
683
683
684 @self.region.conditional_cache_on_arguments(condition=cache_on)
684 @self.region.conditional_cache_on_arguments(condition=cache_on)
685 def _rev_range(_context_uid, _repo_id, _filter):
685 def _rev_range(_context_uid, _repo_id, _filter):
686 repo = self._factory.repo(wire)
686 repo = self._factory.repo(wire)
687 revisions = [rev for rev in revrange(repo, commit_filter)]
687 revisions = [rev for rev in revrange(repo, commit_filter)]
688 return revisions
688 return revisions
689
689
690 return _rev_range(context_uid, repo_id, sorted(commit_filter))
690 return _rev_range(context_uid, repo_id, sorted(commit_filter))
691
691
692 @reraise_safe_exceptions
692 @reraise_safe_exceptions
693 def rev_range_hash(self, wire, node):
693 def rev_range_hash(self, wire, node):
694 repo = self._factory.repo(wire)
694 repo = self._factory.repo(wire)
695
695
696 def get_revs(repo, rev_opt):
696 def get_revs(repo, rev_opt):
697 if rev_opt:
697 if rev_opt:
698 revs = revrange(repo, rev_opt)
698 revs = revrange(repo, rev_opt)
699 if len(revs) == 0:
699 if len(revs) == 0:
700 return (nullrev, nullrev)
700 return (nullrev, nullrev)
701 return max(revs), min(revs)
701 return max(revs), min(revs)
702 else:
702 else:
703 return len(repo) - 1, 0
703 return len(repo) - 1, 0
704
704
705 stop, start = get_revs(repo, [node + ':'])
705 stop, start = get_revs(repo, [node + ':'])
706 revs = [hex(repo[r].node()) for r in xrange(start, stop + 1)]
706 revs = [hex(repo[r].node()) for r in xrange(start, stop + 1)]
707 return revs
707 return revs
708
708
709 @reraise_safe_exceptions
709 @reraise_safe_exceptions
710 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
710 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
711 other_path = kwargs.pop('other_path', None)
711 other_path = kwargs.pop('other_path', None)
712
712
713 # case when we want to compare two independent repositories
713 # case when we want to compare two independent repositories
714 if other_path and other_path != wire["path"]:
714 if other_path and other_path != wire["path"]:
715 baseui = self._factory._create_config(wire["config"])
715 baseui = self._factory._create_config(wire["config"])
716 repo = unionrepo.makeunionrepository(baseui, other_path, wire["path"])
716 repo = unionrepo.makeunionrepository(baseui, other_path, wire["path"])
717 else:
717 else:
718 repo = self._factory.repo(wire)
718 repo = self._factory.repo(wire)
719 return list(repo.revs(rev_spec, *args))
719 return list(repo.revs(rev_spec, *args))
720
720
721 @reraise_safe_exceptions
721 @reraise_safe_exceptions
722 def verify(self, wire,):
722 def verify(self, wire,):
723 repo = self._factory.repo(wire)
723 repo = self._factory.repo(wire)
724 baseui = self._factory._create_config(wire['config'])
724 baseui = self._factory._create_config(wire['config'])
725
725
726 baseui, output = patch_ui_message_output(baseui)
726 baseui, output = patch_ui_message_output(baseui)
727
727
728 repo.ui = baseui
728 repo.ui = baseui
729 verify.verify(repo)
729 verify.verify(repo)
730 return output.getvalue()
730 return output.getvalue()
731
731
732 @reraise_safe_exceptions
732 @reraise_safe_exceptions
733 def hg_update_cache(self, wire,):
733 def hg_update_cache(self, wire,):
734 repo = self._factory.repo(wire)
734 repo = self._factory.repo(wire)
735 baseui = self._factory._create_config(wire['config'])
735 baseui = self._factory._create_config(wire['config'])
736 baseui, output = patch_ui_message_output(baseui)
736 baseui, output = patch_ui_message_output(baseui)
737
737
738 repo.ui = baseui
738 repo.ui = baseui
739 with repo.wlock(), repo.lock():
739 with repo.wlock(), repo.lock():
740 repo.updatecaches(full=True)
740 repo.updatecaches(full=True)
741
741
742 return output.getvalue()
742 return output.getvalue()
743
743
744 @reraise_safe_exceptions
744 @reraise_safe_exceptions
745 def hg_rebuild_fn_cache(self, wire,):
745 def hg_rebuild_fn_cache(self, wire,):
746 repo = self._factory.repo(wire)
746 repo = self._factory.repo(wire)
747 baseui = self._factory._create_config(wire['config'])
747 baseui = self._factory._create_config(wire['config'])
748 baseui, output = patch_ui_message_output(baseui)
748 baseui, output = patch_ui_message_output(baseui)
749
749
750 repo.ui = baseui
750 repo.ui = baseui
751
751
752 repair.rebuildfncache(baseui, repo)
752 repair.rebuildfncache(baseui, repo)
753
753
754 return output.getvalue()
754 return output.getvalue()
755
755
756 @reraise_safe_exceptions
756 @reraise_safe_exceptions
757 def tags(self, wire):
757 def tags(self, wire):
758 cache_on, context_uid, repo_id = self._cache_on(wire)
758 cache_on, context_uid, repo_id = self._cache_on(wire)
759 @self.region.conditional_cache_on_arguments(condition=cache_on)
759 @self.region.conditional_cache_on_arguments(condition=cache_on)
760 def _tags(_context_uid, _repo_id):
760 def _tags(_context_uid, _repo_id):
761 repo = self._factory.repo(wire)
761 repo = self._factory.repo(wire)
762 return repo.tags()
762 return repo.tags()
763
763
764 return _tags(context_uid, repo_id)
764 return _tags(context_uid, repo_id)
765
765
766 @reraise_safe_exceptions
766 @reraise_safe_exceptions
767 def update(self, wire, node=None, clean=False):
767 def update(self, wire, node=None, clean=False):
768 repo = self._factory.repo(wire)
768 repo = self._factory.repo(wire)
769 baseui = self._factory._create_config(wire['config'])
769 baseui = self._factory._create_config(wire['config'])
770 commands.update(baseui, repo, node=node, clean=clean)
770 commands.update(baseui, repo, node=node, clean=clean)
771
771
772 @reraise_safe_exceptions
772 @reraise_safe_exceptions
773 def identify(self, wire):
773 def identify(self, wire):
774 repo = self._factory.repo(wire)
774 repo = self._factory.repo(wire)
775 baseui = self._factory._create_config(wire['config'])
775 baseui = self._factory._create_config(wire['config'])
776 output = io.BytesIO()
776 output = io.BytesIO()
777 baseui.write = output.write
777 baseui.write = output.write
778 # This is required to get a full node id
778 # This is required to get a full node id
779 baseui.debugflag = True
779 baseui.debugflag = True
780 commands.identify(baseui, repo, id=True)
780 commands.identify(baseui, repo, id=True)
781
781
782 return output.getvalue()
782 return output.getvalue()
783
783
784 @reraise_safe_exceptions
784 @reraise_safe_exceptions
785 def heads(self, wire, branch=None):
785 def heads(self, wire, branch=None):
786 repo = self._factory.repo(wire)
786 repo = self._factory.repo(wire)
787 baseui = self._factory._create_config(wire['config'])
787 baseui = self._factory._create_config(wire['config'])
788 output = io.BytesIO()
788 output = io.BytesIO()
789
789
790 def write(data, **unused_kwargs):
790 def write(data, **unused_kwargs):
791 output.write(data)
791 output.write(data)
792
792
793 baseui.write = write
793 baseui.write = write
794 if branch:
794 if branch:
795 args = [branch]
795 args = [branch]
796 else:
796 else:
797 args = []
797 args = []
798 commands.heads(baseui, repo, template='{node} ', *args)
798 commands.heads(baseui, repo, template='{node} ', *args)
799
799
800 return output.getvalue()
800 return output.getvalue()
801
801
802 @reraise_safe_exceptions
802 @reraise_safe_exceptions
803 def ancestor(self, wire, revision1, revision2):
803 def ancestor(self, wire, revision1, revision2):
804 repo = self._factory.repo(wire)
804 repo = self._factory.repo(wire)
805 changelog = repo.changelog
805 changelog = repo.changelog
806 lookup = repo.lookup
806 lookup = repo.lookup
807 a = changelog.ancestor(lookup(revision1), lookup(revision2))
807 a = changelog.ancestor(lookup(revision1), lookup(revision2))
808 return hex(a)
808 return hex(a)
809
809
810 @reraise_safe_exceptions
810 @reraise_safe_exceptions
811 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
811 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
812 baseui = self._factory._create_config(wire["config"], hooks=hooks)
812 baseui = self._factory._create_config(wire["config"], hooks=hooks)
813 clone(baseui, source, dest, noupdate=not update_after_clone)
813 clone(baseui, source, dest, noupdate=not update_after_clone)
814
814
815 @reraise_safe_exceptions
815 @reraise_safe_exceptions
816 def commitctx(self, wire, message, parents, commit_time, commit_timezone, user, files, extra, removed, updated):
816 def commitctx(self, wire, message, parents, commit_time, commit_timezone, user, files, extra, removed, updated):
817
817
818 repo = self._factory.repo(wire)
818 repo = self._factory.repo(wire)
819 baseui = self._factory._create_config(wire['config'])
819 baseui = self._factory._create_config(wire['config'])
820 publishing = baseui.configbool('phases', 'publish')
820 publishing = baseui.configbool('phases', 'publish')
821 if publishing:
821 if publishing:
822 new_commit = 'public'
822 new_commit = 'public'
823 else:
823 else:
824 new_commit = 'draft'
824 new_commit = 'draft'
825
825
826 def _filectxfn(_repo, ctx, path):
826 def _filectxfn(_repo, ctx, path):
827 """
827 """
828 Marks given path as added/changed/removed in a given _repo. This is
828 Marks given path as added/changed/removed in a given _repo. This is
829 for internal mercurial commit function.
829 for internal mercurial commit function.
830 """
830 """
831
831
832 # check if this path is removed
832 # check if this path is removed
833 if path in removed:
833 if path in removed:
834 # returning None is a way to mark node for removal
834 # returning None is a way to mark node for removal
835 return None
835 return None
836
836
837 # check if this path is added
837 # check if this path is added
838 for node in updated:
838 for node in updated:
839 if node['path'] == path:
839 if node['path'] == path:
840 return memfilectx(
840 return memfilectx(
841 _repo,
841 _repo,
842 changectx=ctx,
842 changectx=ctx,
843 path=node['path'],
843 path=node['path'],
844 data=node['content'],
844 data=node['content'],
845 islink=False,
845 islink=False,
846 isexec=bool(node['mode'] & stat.S_IXUSR),
846 isexec=bool(node['mode'] & stat.S_IXUSR),
847 copysource=False)
847 copysource=False)
848
848
849 raise exceptions.AbortException()(
849 raise exceptions.AbortException()(
850 "Given path haven't been marked as added, "
850 "Given path haven't been marked as added, "
851 "changed or removed (%s)" % path)
851 "changed or removed (%s)" % path)
852
852
853 with repo.ui.configoverride({('phases', 'new-commit'): new_commit}):
853 with repo.ui.configoverride({('phases', 'new-commit'): new_commit}):
854
854
855 commit_ctx = memctx(
855 commit_ctx = memctx(
856 repo=repo,
856 repo=repo,
857 parents=parents,
857 parents=parents,
858 text=message,
858 text=message,
859 files=files,
859 files=files,
860 filectxfn=_filectxfn,
860 filectxfn=_filectxfn,
861 user=user,
861 user=user,
862 date=(commit_time, commit_timezone),
862 date=(commit_time, commit_timezone),
863 extra=extra)
863 extra=extra)
864
864
865 n = repo.commitctx(commit_ctx)
865 n = repo.commitctx(commit_ctx)
866 new_id = hex(n)
866 new_id = hex(n)
867
867
868 return new_id
868 return new_id
869
869
870 @reraise_safe_exceptions
870 @reraise_safe_exceptions
871 def pull(self, wire, url, commit_ids=None):
871 def pull(self, wire, url, commit_ids=None):
872 repo = self._factory.repo(wire)
872 repo = self._factory.repo(wire)
873 # Disable any prompts for this repo
873 # Disable any prompts for this repo
874 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
874 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
875
875
876 remote = peer(repo, {}, url)
876 remote = peer(repo, {}, url)
877 # Disable any prompts for this remote
877 # Disable any prompts for this remote
878 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
878 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
879
879
880 if commit_ids:
880 if commit_ids:
881 commit_ids = [bin(commit_id) for commit_id in commit_ids]
881 commit_ids = [bin(commit_id) for commit_id in commit_ids]
882
882
883 return exchange.pull(
883 return exchange.pull(
884 repo, remote, heads=commit_ids, force=None).cgresult
884 repo, remote, heads=commit_ids, force=None).cgresult
885
885
886 @reraise_safe_exceptions
886 @reraise_safe_exceptions
887 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None, hooks=True):
887 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None, hooks=True):
888 repo = self._factory.repo(wire)
888 repo = self._factory.repo(wire)
889 baseui = self._factory._create_config(wire['config'], hooks=hooks)
889 baseui = self._factory._create_config(wire['config'], hooks=hooks)
890
890
891 # Mercurial internally has a lot of logic that checks ONLY if
891 # Mercurial internally has a lot of logic that checks ONLY if
892 # option is defined, we just pass those if they are defined then
892 # option is defined, we just pass those if they are defined then
893 opts = {}
893 opts = {}
894 if bookmark:
894 if bookmark:
895 opts['bookmark'] = bookmark
895 opts['bookmark'] = bookmark
896 if branch:
896 if branch:
897 opts['branch'] = branch
897 opts['branch'] = branch
898 if revision:
898 if revision:
899 opts['rev'] = revision
899 opts['rev'] = revision
900
900
901 commands.pull(baseui, repo, source, **opts)
901 commands.pull(baseui, repo, source, **opts)
902
902
903 @reraise_safe_exceptions
903 @reraise_safe_exceptions
904 def push(self, wire, revisions, dest_path, hooks=True, push_branches=False):
904 def push(self, wire, revisions, dest_path, hooks=True, push_branches=False):
905 repo = self._factory.repo(wire)
905 repo = self._factory.repo(wire)
906 baseui = self._factory._create_config(wire['config'], hooks=hooks)
906 baseui = self._factory._create_config(wire['config'], hooks=hooks)
907 commands.push(baseui, repo, dest=dest_path, rev=revisions,
907 commands.push(baseui, repo, dest=dest_path, rev=revisions,
908 new_branch=push_branches)
908 new_branch=push_branches)
909
909
910 @reraise_safe_exceptions
910 @reraise_safe_exceptions
911 def strip(self, wire, revision, update, backup):
911 def strip(self, wire, revision, update, backup):
912 repo = self._factory.repo(wire)
912 repo = self._factory.repo(wire)
913 ctx = self._get_ctx(repo, revision)
913 ctx = self._get_ctx(repo, revision)
914 hgext_strip(
914 hgext_strip(
915 repo.baseui, repo, ctx.node(), update=update, backup=backup)
915 repo.baseui, repo, ctx.node(), update=update, backup=backup)
916
916
917 @reraise_safe_exceptions
917 @reraise_safe_exceptions
918 def get_unresolved_files(self, wire):
918 def get_unresolved_files(self, wire):
919 repo = self._factory.repo(wire)
919 repo = self._factory.repo(wire)
920
920
921 log.debug('Calculating unresolved files for repo: %s', repo)
921 log.debug('Calculating unresolved files for repo: %s', repo)
922 output = io.BytesIO()
922 output = io.BytesIO()
923
923
924 def write(data, **unused_kwargs):
924 def write(data, **unused_kwargs):
925 output.write(data)
925 output.write(data)
926
926
927 baseui = self._factory._create_config(wire['config'])
927 baseui = self._factory._create_config(wire['config'])
928 baseui.write = write
928 baseui.write = write
929
929
930 commands.resolve(baseui, repo, list=True)
930 commands.resolve(baseui, repo, list=True)
931 unresolved = output.getvalue().splitlines(0)
931 unresolved = output.getvalue().splitlines(0)
932 return unresolved
932 return unresolved
933
933
934 @reraise_safe_exceptions
934 @reraise_safe_exceptions
935 def merge(self, wire, revision):
935 def merge(self, wire, revision):
936 repo = self._factory.repo(wire)
936 repo = self._factory.repo(wire)
937 baseui = self._factory._create_config(wire['config'])
937 baseui = self._factory._create_config(wire['config'])
938 repo.ui.setconfig('ui', 'merge', 'internal:dump')
938 repo.ui.setconfig('ui', 'merge', 'internal:dump')
939
939
940 # In case of sub repositories are used mercurial prompts the user in
940 # In case of sub repositories are used mercurial prompts the user in
941 # case of merge conflicts or different sub repository sources. By
941 # case of merge conflicts or different sub repository sources. By
942 # setting the interactive flag to `False` mercurial doesn't prompt the
942 # setting the interactive flag to `False` mercurial doesn't prompt the
943 # used but instead uses a default value.
943 # used but instead uses a default value.
944 repo.ui.setconfig('ui', 'interactive', False)
944 repo.ui.setconfig('ui', 'interactive', False)
945 commands.merge(baseui, repo, rev=revision)
945 commands.merge(baseui, repo, rev=revision)
946
946
947 @reraise_safe_exceptions
947 @reraise_safe_exceptions
948 def merge_state(self, wire):
948 def merge_state(self, wire):
949 repo = self._factory.repo(wire)
949 repo = self._factory.repo(wire)
950 repo.ui.setconfig('ui', 'merge', 'internal:dump')
950 repo.ui.setconfig('ui', 'merge', 'internal:dump')
951
951
952 # In case of sub repositories are used mercurial prompts the user in
952 # In case of sub repositories are used mercurial prompts the user in
953 # case of merge conflicts or different sub repository sources. By
953 # case of merge conflicts or different sub repository sources. By
954 # setting the interactive flag to `False` mercurial doesn't prompt the
954 # setting the interactive flag to `False` mercurial doesn't prompt the
955 # used but instead uses a default value.
955 # used but instead uses a default value.
956 repo.ui.setconfig('ui', 'interactive', False)
956 repo.ui.setconfig('ui', 'interactive', False)
957 ms = hg_merge.mergestate(repo)
957 ms = hg_merge.mergestate(repo)
958 return [x for x in ms.unresolved()]
958 return [x for x in ms.unresolved()]
959
959
960 @reraise_safe_exceptions
960 @reraise_safe_exceptions
961 def commit(self, wire, message, username, close_branch=False):
961 def commit(self, wire, message, username, close_branch=False):
962 repo = self._factory.repo(wire)
962 repo = self._factory.repo(wire)
963 baseui = self._factory._create_config(wire['config'])
963 baseui = self._factory._create_config(wire['config'])
964 repo.ui.setconfig('ui', 'username', username)
964 repo.ui.setconfig('ui', 'username', username)
965 commands.commit(baseui, repo, message=message, close_branch=close_branch)
965 commands.commit(baseui, repo, message=message, close_branch=close_branch)
966
966
967 @reraise_safe_exceptions
967 @reraise_safe_exceptions
968 def rebase(self, wire, source=None, dest=None, abort=False):
968 def rebase(self, wire, source=None, dest=None, abort=False):
969 repo = self._factory.repo(wire)
969 repo = self._factory.repo(wire)
970 baseui = self._factory._create_config(wire['config'])
970 baseui = self._factory._create_config(wire['config'])
971 repo.ui.setconfig('ui', 'merge', 'internal:dump')
971 repo.ui.setconfig('ui', 'merge', 'internal:dump')
972 # In case of sub repositories are used mercurial prompts the user in
972 # In case of sub repositories are used mercurial prompts the user in
973 # case of merge conflicts or different sub repository sources. By
973 # case of merge conflicts or different sub repository sources. By
974 # setting the interactive flag to `False` mercurial doesn't prompt the
974 # setting the interactive flag to `False` mercurial doesn't prompt the
975 # used but instead uses a default value.
975 # used but instead uses a default value.
976 repo.ui.setconfig('ui', 'interactive', False)
976 repo.ui.setconfig('ui', 'interactive', False)
977 rebase.rebase(baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
977 rebase.rebase(baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
978
978
979 @reraise_safe_exceptions
979 @reraise_safe_exceptions
980 def tag(self, wire, name, revision, message, local, user, tag_time, tag_timezone):
980 def tag(self, wire, name, revision, message, local, user, tag_time, tag_timezone):
981 repo = self._factory.repo(wire)
981 repo = self._factory.repo(wire)
982 ctx = self._get_ctx(repo, revision)
982 ctx = self._get_ctx(repo, revision)
983 node = ctx.node()
983 node = ctx.node()
984
984
985 date = (tag_time, tag_timezone)
985 date = (tag_time, tag_timezone)
986 try:
986 try:
987 hg_tag.tag(repo, name, node, message, local, user, date)
987 hg_tag.tag(repo, name, node, message, local, user, date)
988 except Abort as e:
988 except Abort as e:
989 log.exception("Tag operation aborted")
989 log.exception("Tag operation aborted")
990 # Exception can contain unicode which we convert
990 # Exception can contain unicode which we convert
991 raise exceptions.AbortException(e)(repr(e))
991 raise exceptions.AbortException(e)(repr(e))
992
992
993 @reraise_safe_exceptions
993 @reraise_safe_exceptions
994 def bookmark(self, wire, bookmark, revision=None):
994 def bookmark(self, wire, bookmark, revision=None):
995 repo = self._factory.repo(wire)
995 repo = self._factory.repo(wire)
996 baseui = self._factory._create_config(wire['config'])
996 baseui = self._factory._create_config(wire['config'])
997 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
997 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
998
998
999 @reraise_safe_exceptions
999 @reraise_safe_exceptions
1000 def install_hooks(self, wire, force=False):
1000 def install_hooks(self, wire, force=False):
1001 # we don't need any special hooks for Mercurial
1001 # we don't need any special hooks for Mercurial
1002 pass
1002 pass
1003
1003
1004 @reraise_safe_exceptions
1004 @reraise_safe_exceptions
1005 def get_hooks_info(self, wire):
1005 def get_hooks_info(self, wire):
1006 return {
1006 return {
1007 'pre_version': vcsserver.__version__,
1007 'pre_version': vcsserver.__version__,
1008 'post_version': vcsserver.__version__,
1008 'post_version': vcsserver.__version__,
1009 }
1009 }
General Comments 0
You need to be logged in to leave comments. Login now