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