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