##// END OF EJS Templates
mercurial: fix problems with latest httppeer changes in mercurial 4.6 series.
marcink -
r457:62954e5c default
parent child Browse files
Show More
@@ -1,789 +1,791 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-2018 RhodeCode GmbH
2 # Copyright (C) 2014-2018 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
23
24 from hgext import largefiles, rebase
24 from hgext import largefiles, rebase
25 from hgext.strip import strip as hgext_strip
25 from hgext.strip import strip as hgext_strip
26 from mercurial import commands
26 from mercurial import commands
27 from mercurial import unionrepo
27 from mercurial import unionrepo
28 from mercurial import verify
28 from mercurial import verify
29
29
30 from vcsserver import exceptions
30 from vcsserver import exceptions
31 from vcsserver.base import RepoFactory, obfuscate_qs, raise_from_original
31 from vcsserver.base import RepoFactory, obfuscate_qs, raise_from_original
32 from vcsserver.hgcompat import (
32 from vcsserver.hgcompat import (
33 archival, bin, clone, config as hgconfig, diffopts, hex,
33 archival, bin, clone, config as hgconfig, diffopts, hex,
34 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler,
34 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler,
35 httppeer, localrepository, match, memctx, exchange, memfilectx, nullrev,
35 makepeer, localrepository, match, memctx, exchange, memfilectx, nullrev,
36 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
36 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
37 RepoLookupError, InterventionRequired, RequirementError)
37 RepoLookupError, InterventionRequired, RequirementError)
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41
41
42 def make_ui_from_config(repo_config):
42 def make_ui_from_config(repo_config):
43 baseui = ui.ui()
43 baseui = ui.ui()
44
44
45 # clean the baseui object
45 # clean the baseui object
46 baseui._ocfg = hgconfig.config()
46 baseui._ocfg = hgconfig.config()
47 baseui._ucfg = hgconfig.config()
47 baseui._ucfg = hgconfig.config()
48 baseui._tcfg = hgconfig.config()
48 baseui._tcfg = hgconfig.config()
49
49
50 for section, option, value in repo_config:
50 for section, option, value in repo_config:
51 baseui.setconfig(section, option, value)
51 baseui.setconfig(section, option, value)
52
52
53 # make our hgweb quiet so it doesn't print output
53 # make our hgweb quiet so it doesn't print output
54 baseui.setconfig('ui', 'quiet', 'true')
54 baseui.setconfig('ui', 'quiet', 'true')
55
55
56 baseui.setconfig('ui', 'paginate', 'never')
56 baseui.setconfig('ui', 'paginate', 'never')
57 # force mercurial to only use 1 thread, otherwise it may try to set a
57 # force mercurial to only use 1 thread, otherwise it may try to set a
58 # signal in a non-main thread, thus generating a ValueError.
58 # signal in a non-main thread, thus generating a ValueError.
59 baseui.setconfig('worker', 'numcpus', 1)
59 baseui.setconfig('worker', 'numcpus', 1)
60
60
61 # If there is no config for the largefiles extension, we explicitly disable
61 # If there is no config for the largefiles extension, we explicitly disable
62 # it here. This overrides settings from repositories hgrc file. Recent
62 # it here. This overrides settings from repositories hgrc file. Recent
63 # mercurial versions enable largefiles in hgrc on clone from largefile
63 # mercurial versions enable largefiles in hgrc on clone from largefile
64 # repo.
64 # repo.
65 if not baseui.hasconfig('extensions', 'largefiles'):
65 if not baseui.hasconfig('extensions', 'largefiles'):
66 log.debug('Explicitly disable largefiles extension for repo.')
66 log.debug('Explicitly disable largefiles extension for repo.')
67 baseui.setconfig('extensions', 'largefiles', '!')
67 baseui.setconfig('extensions', 'largefiles', '!')
68
68
69 return baseui
69 return baseui
70
70
71
71
72 def reraise_safe_exceptions(func):
72 def reraise_safe_exceptions(func):
73 """Decorator for converting mercurial exceptions to something neutral."""
73 """Decorator for converting mercurial exceptions to something neutral."""
74 def wrapper(*args, **kwargs):
74 def wrapper(*args, **kwargs):
75 try:
75 try:
76 return func(*args, **kwargs)
76 return func(*args, **kwargs)
77 except (Abort, InterventionRequired):
77 except (Abort, InterventionRequired):
78 raise_from_original(exceptions.AbortException)
78 raise_from_original(exceptions.AbortException)
79 except RepoLookupError:
79 except RepoLookupError:
80 raise_from_original(exceptions.LookupException)
80 raise_from_original(exceptions.LookupException)
81 except RequirementError:
81 except RequirementError:
82 raise_from_original(exceptions.RequirementException)
82 raise_from_original(exceptions.RequirementException)
83 except RepoError:
83 except RepoError:
84 raise_from_original(exceptions.VcsException)
84 raise_from_original(exceptions.VcsException)
85 except LookupError:
85 except LookupError:
86 raise_from_original(exceptions.LookupException)
86 raise_from_original(exceptions.LookupException)
87 except Exception as e:
87 except Exception as e:
88 if not hasattr(e, '_vcs_kind'):
88 if not hasattr(e, '_vcs_kind'):
89 log.exception("Unhandled exception in hg remote call")
89 log.exception("Unhandled exception in hg remote call")
90 raise_from_original(exceptions.UnhandledException)
90 raise_from_original(exceptions.UnhandledException)
91 raise
91 raise
92 return wrapper
92 return wrapper
93
93
94
94
95 class MercurialFactory(RepoFactory):
95 class MercurialFactory(RepoFactory):
96
96
97 def _create_config(self, config, hooks=True):
97 def _create_config(self, config, hooks=True):
98 if not hooks:
98 if not hooks:
99 hooks_to_clean = frozenset((
99 hooks_to_clean = frozenset((
100 'changegroup.repo_size', 'preoutgoing.pre_pull',
100 'changegroup.repo_size', 'preoutgoing.pre_pull',
101 'outgoing.pull_logger', 'prechangegroup.pre_push'))
101 'outgoing.pull_logger', 'prechangegroup.pre_push'))
102 new_config = []
102 new_config = []
103 for section, option, value in config:
103 for section, option, value in config:
104 if section == 'hooks' and option in hooks_to_clean:
104 if section == 'hooks' and option in hooks_to_clean:
105 continue
105 continue
106 new_config.append((section, option, value))
106 new_config.append((section, option, value))
107 config = new_config
107 config = new_config
108
108
109 baseui = make_ui_from_config(config)
109 baseui = make_ui_from_config(config)
110 return baseui
110 return baseui
111
111
112 def _create_repo(self, wire, create):
112 def _create_repo(self, wire, create):
113 baseui = self._create_config(wire["config"])
113 baseui = self._create_config(wire["config"])
114 return localrepository(baseui, wire["path"], create)
114 return localrepository(baseui, wire["path"], create)
115
115
116
116
117 class HgRemote(object):
117 class HgRemote(object):
118
118
119 def __init__(self, factory):
119 def __init__(self, factory):
120 self._factory = factory
120 self._factory = factory
121
121
122 self._bulk_methods = {
122 self._bulk_methods = {
123 "affected_files": self.ctx_files,
123 "affected_files": self.ctx_files,
124 "author": self.ctx_user,
124 "author": self.ctx_user,
125 "branch": self.ctx_branch,
125 "branch": self.ctx_branch,
126 "children": self.ctx_children,
126 "children": self.ctx_children,
127 "date": self.ctx_date,
127 "date": self.ctx_date,
128 "message": self.ctx_description,
128 "message": self.ctx_description,
129 "parents": self.ctx_parents,
129 "parents": self.ctx_parents,
130 "status": self.ctx_status,
130 "status": self.ctx_status,
131 "obsolete": self.ctx_obsolete,
131 "obsolete": self.ctx_obsolete,
132 "phase": self.ctx_phase,
132 "phase": self.ctx_phase,
133 "hidden": self.ctx_hidden,
133 "hidden": self.ctx_hidden,
134 "_file_paths": self.ctx_list,
134 "_file_paths": self.ctx_list,
135 }
135 }
136
136
137 @reraise_safe_exceptions
137 @reraise_safe_exceptions
138 def discover_hg_version(self):
138 def discover_hg_version(self):
139 from mercurial import util
139 from mercurial import util
140 return util.version()
140 return util.version()
141
141
142 @reraise_safe_exceptions
142 @reraise_safe_exceptions
143 def archive_repo(self, archive_path, mtime, file_info, kind):
143 def archive_repo(self, archive_path, mtime, file_info, kind):
144 if kind == "tgz":
144 if kind == "tgz":
145 archiver = archival.tarit(archive_path, mtime, "gz")
145 archiver = archival.tarit(archive_path, mtime, "gz")
146 elif kind == "tbz2":
146 elif kind == "tbz2":
147 archiver = archival.tarit(archive_path, mtime, "bz2")
147 archiver = archival.tarit(archive_path, mtime, "bz2")
148 elif kind == 'zip':
148 elif kind == 'zip':
149 archiver = archival.zipit(archive_path, mtime)
149 archiver = archival.zipit(archive_path, mtime)
150 else:
150 else:
151 raise exceptions.ArchiveException(
151 raise exceptions.ArchiveException(
152 'Remote does not support: "%s".' % kind)
152 'Remote does not support: "%s".' % kind)
153
153
154 for f_path, f_mode, f_is_link, f_content in file_info:
154 for f_path, f_mode, f_is_link, f_content in file_info:
155 archiver.addfile(f_path, f_mode, f_is_link, f_content)
155 archiver.addfile(f_path, f_mode, f_is_link, f_content)
156 archiver.done()
156 archiver.done()
157
157
158 @reraise_safe_exceptions
158 @reraise_safe_exceptions
159 def bookmarks(self, wire):
159 def bookmarks(self, wire):
160 repo = self._factory.repo(wire)
160 repo = self._factory.repo(wire)
161 return dict(repo._bookmarks)
161 return dict(repo._bookmarks)
162
162
163 @reraise_safe_exceptions
163 @reraise_safe_exceptions
164 def branches(self, wire, normal, closed):
164 def branches(self, wire, normal, closed):
165 repo = self._factory.repo(wire)
165 repo = self._factory.repo(wire)
166 iter_branches = repo.branchmap().iterbranches()
166 iter_branches = repo.branchmap().iterbranches()
167 bt = {}
167 bt = {}
168 for branch_name, _heads, tip, is_closed in iter_branches:
168 for branch_name, _heads, tip, is_closed in iter_branches:
169 if normal and not is_closed:
169 if normal and not is_closed:
170 bt[branch_name] = tip
170 bt[branch_name] = tip
171 if closed and is_closed:
171 if closed and is_closed:
172 bt[branch_name] = tip
172 bt[branch_name] = tip
173
173
174 return bt
174 return bt
175
175
176 @reraise_safe_exceptions
176 @reraise_safe_exceptions
177 def bulk_request(self, wire, rev, pre_load):
177 def bulk_request(self, wire, rev, pre_load):
178 result = {}
178 result = {}
179 for attr in pre_load:
179 for attr in pre_load:
180 try:
180 try:
181 method = self._bulk_methods[attr]
181 method = self._bulk_methods[attr]
182 result[attr] = method(wire, rev)
182 result[attr] = method(wire, rev)
183 except KeyError:
183 except KeyError:
184 raise exceptions.VcsException(
184 raise exceptions.VcsException(
185 'Unknown bulk attribute: "%s"' % attr)
185 'Unknown bulk attribute: "%s"' % attr)
186 return result
186 return result
187
187
188 @reraise_safe_exceptions
188 @reraise_safe_exceptions
189 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
189 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
190 baseui = self._factory._create_config(wire["config"], hooks=hooks)
190 baseui = self._factory._create_config(wire["config"], hooks=hooks)
191 clone(baseui, source, dest, noupdate=not update_after_clone)
191 clone(baseui, source, dest, noupdate=not update_after_clone)
192
192
193 @reraise_safe_exceptions
193 @reraise_safe_exceptions
194 def commitctx(
194 def commitctx(
195 self, wire, message, parents, commit_time, commit_timezone,
195 self, wire, message, parents, commit_time, commit_timezone,
196 user, files, extra, removed, updated):
196 user, files, extra, removed, updated):
197
197
198 def _filectxfn(_repo, memctx, path):
198 def _filectxfn(_repo, memctx, path):
199 """
199 """
200 Marks given path as added/changed/removed in a given _repo. This is
200 Marks given path as added/changed/removed in a given _repo. This is
201 for internal mercurial commit function.
201 for internal mercurial commit function.
202 """
202 """
203
203
204 # check if this path is removed
204 # check if this path is removed
205 if path in removed:
205 if path in removed:
206 # returning None is a way to mark node for removal
206 # returning None is a way to mark node for removal
207 return None
207 return None
208
208
209 # check if this path is added
209 # check if this path is added
210 for node in updated:
210 for node in updated:
211 if node['path'] == path:
211 if node['path'] == path:
212 return memfilectx(
212 return memfilectx(
213 _repo,
213 _repo,
214 changectx=memctx,
214 changectx=memctx,
215 path=node['path'],
215 path=node['path'],
216 data=node['content'],
216 data=node['content'],
217 islink=False,
217 islink=False,
218 isexec=bool(node['mode'] & stat.S_IXUSR),
218 isexec=bool(node['mode'] & stat.S_IXUSR),
219 copied=False)
219 copied=False)
220
220
221 raise exceptions.AbortException(
221 raise exceptions.AbortException(
222 "Given path haven't been marked as added, "
222 "Given path haven't been marked as added, "
223 "changed or removed (%s)" % path)
223 "changed or removed (%s)" % path)
224
224
225 repo = self._factory.repo(wire)
225 repo = self._factory.repo(wire)
226
226
227 commit_ctx = memctx(
227 commit_ctx = memctx(
228 repo=repo,
228 repo=repo,
229 parents=parents,
229 parents=parents,
230 text=message,
230 text=message,
231 files=files,
231 files=files,
232 filectxfn=_filectxfn,
232 filectxfn=_filectxfn,
233 user=user,
233 user=user,
234 date=(commit_time, commit_timezone),
234 date=(commit_time, commit_timezone),
235 extra=extra)
235 extra=extra)
236
236
237 n = repo.commitctx(commit_ctx)
237 n = repo.commitctx(commit_ctx)
238 new_id = hex(n)
238 new_id = hex(n)
239
239
240 return new_id
240 return new_id
241
241
242 @reraise_safe_exceptions
242 @reraise_safe_exceptions
243 def ctx_branch(self, wire, revision):
243 def ctx_branch(self, wire, revision):
244 repo = self._factory.repo(wire)
244 repo = self._factory.repo(wire)
245 ctx = repo[revision]
245 ctx = repo[revision]
246 return ctx.branch()
246 return ctx.branch()
247
247
248 @reraise_safe_exceptions
248 @reraise_safe_exceptions
249 def ctx_children(self, wire, revision):
249 def ctx_children(self, wire, revision):
250 repo = self._factory.repo(wire)
250 repo = self._factory.repo(wire)
251 ctx = repo[revision]
251 ctx = repo[revision]
252 return [child.rev() for child in ctx.children()]
252 return [child.rev() for child in ctx.children()]
253
253
254 @reraise_safe_exceptions
254 @reraise_safe_exceptions
255 def ctx_date(self, wire, revision):
255 def ctx_date(self, wire, revision):
256 repo = self._factory.repo(wire)
256 repo = self._factory.repo(wire)
257 ctx = repo[revision]
257 ctx = repo[revision]
258 return ctx.date()
258 return ctx.date()
259
259
260 @reraise_safe_exceptions
260 @reraise_safe_exceptions
261 def ctx_description(self, wire, revision):
261 def ctx_description(self, wire, revision):
262 repo = self._factory.repo(wire)
262 repo = self._factory.repo(wire)
263 ctx = repo[revision]
263 ctx = repo[revision]
264 return ctx.description()
264 return ctx.description()
265
265
266 @reraise_safe_exceptions
266 @reraise_safe_exceptions
267 def ctx_diff(
267 def ctx_diff(
268 self, wire, revision, git=True, ignore_whitespace=True, context=3):
268 self, wire, revision, git=True, ignore_whitespace=True, context=3):
269 repo = self._factory.repo(wire)
269 repo = self._factory.repo(wire)
270 ctx = repo[revision]
270 ctx = repo[revision]
271 result = ctx.diff(
271 result = ctx.diff(
272 git=git, ignore_whitespace=ignore_whitespace, context=context)
272 git=git, ignore_whitespace=ignore_whitespace, context=context)
273 return list(result)
273 return list(result)
274
274
275 @reraise_safe_exceptions
275 @reraise_safe_exceptions
276 def ctx_files(self, wire, revision):
276 def ctx_files(self, wire, revision):
277 repo = self._factory.repo(wire)
277 repo = self._factory.repo(wire)
278 ctx = repo[revision]
278 ctx = repo[revision]
279 return ctx.files()
279 return ctx.files()
280
280
281 @reraise_safe_exceptions
281 @reraise_safe_exceptions
282 def ctx_list(self, path, revision):
282 def ctx_list(self, path, revision):
283 repo = self._factory.repo(path)
283 repo = self._factory.repo(path)
284 ctx = repo[revision]
284 ctx = repo[revision]
285 return list(ctx)
285 return list(ctx)
286
286
287 @reraise_safe_exceptions
287 @reraise_safe_exceptions
288 def ctx_parents(self, wire, revision):
288 def ctx_parents(self, wire, revision):
289 repo = self._factory.repo(wire)
289 repo = self._factory.repo(wire)
290 ctx = repo[revision]
290 ctx = repo[revision]
291 return [parent.rev() for parent in ctx.parents()]
291 return [parent.rev() for parent in ctx.parents()]
292
292
293 @reraise_safe_exceptions
293 @reraise_safe_exceptions
294 def ctx_phase(self, wire, revision):
294 def ctx_phase(self, wire, revision):
295 repo = self._factory.repo(wire)
295 repo = self._factory.repo(wire)
296 ctx = repo[revision]
296 ctx = repo[revision]
297 # public=0, draft=1, secret=3
297 # public=0, draft=1, secret=3
298 return ctx.phase()
298 return ctx.phase()
299
299
300 @reraise_safe_exceptions
300 @reraise_safe_exceptions
301 def ctx_obsolete(self, wire, revision):
301 def ctx_obsolete(self, wire, revision):
302 repo = self._factory.repo(wire)
302 repo = self._factory.repo(wire)
303 ctx = repo[revision]
303 ctx = repo[revision]
304 return ctx.obsolete()
304 return ctx.obsolete()
305
305
306 @reraise_safe_exceptions
306 @reraise_safe_exceptions
307 def ctx_hidden(self, wire, revision):
307 def ctx_hidden(self, wire, revision):
308 repo = self._factory.repo(wire)
308 repo = self._factory.repo(wire)
309 ctx = repo[revision]
309 ctx = repo[revision]
310 return ctx.hidden()
310 return ctx.hidden()
311
311
312 @reraise_safe_exceptions
312 @reraise_safe_exceptions
313 def ctx_substate(self, wire, revision):
313 def ctx_substate(self, wire, revision):
314 repo = self._factory.repo(wire)
314 repo = self._factory.repo(wire)
315 ctx = repo[revision]
315 ctx = repo[revision]
316 return ctx.substate
316 return ctx.substate
317
317
318 @reraise_safe_exceptions
318 @reraise_safe_exceptions
319 def ctx_status(self, wire, revision):
319 def ctx_status(self, wire, revision):
320 repo = self._factory.repo(wire)
320 repo = self._factory.repo(wire)
321 ctx = repo[revision]
321 ctx = repo[revision]
322 status = repo[ctx.p1().node()].status(other=ctx.node())
322 status = repo[ctx.p1().node()].status(other=ctx.node())
323 # object of status (odd, custom named tuple in mercurial) is not
323 # object of status (odd, custom named tuple in mercurial) is not
324 # correctly serializable, we make it a list, as the underling
324 # correctly serializable, we make it a list, as the underling
325 # API expects this to be a list
325 # API expects this to be a list
326 return list(status)
326 return list(status)
327
327
328 @reraise_safe_exceptions
328 @reraise_safe_exceptions
329 def ctx_user(self, wire, revision):
329 def ctx_user(self, wire, revision):
330 repo = self._factory.repo(wire)
330 repo = self._factory.repo(wire)
331 ctx = repo[revision]
331 ctx = repo[revision]
332 return ctx.user()
332 return ctx.user()
333
333
334 @reraise_safe_exceptions
334 @reraise_safe_exceptions
335 def check_url(self, url, config):
335 def check_url(self, url, config):
336 _proto = None
336 _proto = None
337 if '+' in url[:url.find('://')]:
337 if '+' in url[:url.find('://')]:
338 _proto = url[0:url.find('+')]
338 _proto = url[0:url.find('+')]
339 url = url[url.find('+') + 1:]
339 url = url[url.find('+') + 1:]
340 handlers = []
340 handlers = []
341 url_obj = url_parser(url)
341 url_obj = url_parser(url)
342 test_uri, authinfo = url_obj.authinfo()
342 test_uri, authinfo = url_obj.authinfo()
343 url_obj.passwd = '*****' if url_obj.passwd else url_obj.passwd
343 url_obj.passwd = '*****' if url_obj.passwd else url_obj.passwd
344 url_obj.query = obfuscate_qs(url_obj.query)
344 url_obj.query = obfuscate_qs(url_obj.query)
345
345
346 cleaned_uri = str(url_obj)
346 cleaned_uri = str(url_obj)
347 log.info("Checking URL for remote cloning/import: %s", cleaned_uri)
347 log.info("Checking URL for remote cloning/import: %s", cleaned_uri)
348
348
349 if authinfo:
349 if authinfo:
350 # create a password manager
350 # create a password manager
351 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
351 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
352 passmgr.add_password(*authinfo)
352 passmgr.add_password(*authinfo)
353
353
354 handlers.extend((httpbasicauthhandler(passmgr),
354 handlers.extend((httpbasicauthhandler(passmgr),
355 httpdigestauthhandler(passmgr)))
355 httpdigestauthhandler(passmgr)))
356
356
357 o = urllib2.build_opener(*handlers)
357 o = urllib2.build_opener(*handlers)
358 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
358 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
359 ('Accept', 'application/mercurial-0.1')]
359 ('Accept', 'application/mercurial-0.1')]
360
360
361 q = {"cmd": 'between'}
361 q = {"cmd": 'between'}
362 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
362 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
363 qs = '?%s' % urllib.urlencode(q)
363 qs = '?%s' % urllib.urlencode(q)
364 cu = "%s%s" % (test_uri, qs)
364 cu = "%s%s" % (test_uri, qs)
365 req = urllib2.Request(cu, None, {})
365 req = urllib2.Request(cu, None, {})
366
366
367 try:
367 try:
368 log.debug("Trying to open URL %s", cleaned_uri)
368 log.debug("Trying to open URL %s", cleaned_uri)
369 resp = o.open(req)
369 resp = o.open(req)
370 if resp.code != 200:
370 if resp.code != 200:
371 raise exceptions.URLError('Return Code is not 200')
371 raise exceptions.URLError('Return Code is not 200')
372 except Exception as e:
372 except Exception as e:
373 log.warning("URL cannot be opened: %s", cleaned_uri, exc_info=True)
373 log.warning("URL cannot be opened: %s", cleaned_uri, exc_info=True)
374 # means it cannot be cloned
374 # means it cannot be cloned
375 raise exceptions.URLError("[%s] org_exc: %s" % (cleaned_uri, e))
375 raise exceptions.URLError("[%s] org_exc: %s" % (cleaned_uri, e))
376
376
377 # now check if it's a proper hg repo, but don't do it for svn
377 # now check if it's a proper hg repo, but don't do it for svn
378 try:
378 try:
379 if _proto == 'svn':
379 if _proto == 'svn':
380 pass
380 pass
381 else:
381 else:
382 # check for pure hg repos
382 # check for pure hg repos
383 log.debug(
383 log.debug(
384 "Verifying if URL is a Mercurial repository: %s",
384 "Verifying if URL is a Mercurial repository: %s",
385 cleaned_uri)
385 cleaned_uri)
386 httppeer(make_ui_from_config(config), url).lookup('tip')
386 ui = make_ui_from_config(config)
387 peer_checker = makepeer(ui, url)
388 peer_checker.lookup('tip')
387 except Exception as e:
389 except Exception as e:
388 log.warning("URL is not a valid Mercurial repository: %s",
390 log.warning("URL is not a valid Mercurial repository: %s",
389 cleaned_uri)
391 cleaned_uri)
390 raise exceptions.URLError(
392 raise exceptions.URLError(
391 "url [%s] does not look like an hg repo org_exc: %s"
393 "url [%s] does not look like an hg repo org_exc: %s"
392 % (cleaned_uri, e))
394 % (cleaned_uri, e))
393
395
394 log.info("URL is a valid Mercurial repository: %s", cleaned_uri)
396 log.info("URL is a valid Mercurial repository: %s", cleaned_uri)
395 return True
397 return True
396
398
397 @reraise_safe_exceptions
399 @reraise_safe_exceptions
398 def diff(
400 def diff(
399 self, wire, rev1, rev2, file_filter, opt_git, opt_ignorews,
401 self, wire, rev1, rev2, file_filter, opt_git, opt_ignorews,
400 context):
402 context):
401 repo = self._factory.repo(wire)
403 repo = self._factory.repo(wire)
402
404
403 if file_filter:
405 if file_filter:
404 match_filter = match(file_filter[0], '', [file_filter[1]])
406 match_filter = match(file_filter[0], '', [file_filter[1]])
405 else:
407 else:
406 match_filter = file_filter
408 match_filter = file_filter
407 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context)
409 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context)
408
410
409 try:
411 try:
410 return "".join(patch.diff(
412 return "".join(patch.diff(
411 repo, node1=rev1, node2=rev2, match=match_filter, opts=opts))
413 repo, node1=rev1, node2=rev2, match=match_filter, opts=opts))
412 except RepoLookupError:
414 except RepoLookupError:
413 raise exceptions.LookupException()
415 raise exceptions.LookupException()
414
416
415 @reraise_safe_exceptions
417 @reraise_safe_exceptions
416 def file_history(self, wire, revision, path, limit):
418 def file_history(self, wire, revision, path, limit):
417 repo = self._factory.repo(wire)
419 repo = self._factory.repo(wire)
418
420
419 ctx = repo[revision]
421 ctx = repo[revision]
420 fctx = ctx.filectx(path)
422 fctx = ctx.filectx(path)
421
423
422 def history_iter():
424 def history_iter():
423 limit_rev = fctx.rev()
425 limit_rev = fctx.rev()
424 for obj in reversed(list(fctx.filelog())):
426 for obj in reversed(list(fctx.filelog())):
425 obj = fctx.filectx(obj)
427 obj = fctx.filectx(obj)
426 if limit_rev >= obj.rev():
428 if limit_rev >= obj.rev():
427 yield obj
429 yield obj
428
430
429 history = []
431 history = []
430 for cnt, obj in enumerate(history_iter()):
432 for cnt, obj in enumerate(history_iter()):
431 if limit and cnt >= limit:
433 if limit and cnt >= limit:
432 break
434 break
433 history.append(hex(obj.node()))
435 history.append(hex(obj.node()))
434
436
435 return [x for x in history]
437 return [x for x in history]
436
438
437 @reraise_safe_exceptions
439 @reraise_safe_exceptions
438 def file_history_untill(self, wire, revision, path, limit):
440 def file_history_untill(self, wire, revision, path, limit):
439 repo = self._factory.repo(wire)
441 repo = self._factory.repo(wire)
440 ctx = repo[revision]
442 ctx = repo[revision]
441 fctx = ctx.filectx(path)
443 fctx = ctx.filectx(path)
442
444
443 file_log = list(fctx.filelog())
445 file_log = list(fctx.filelog())
444 if limit:
446 if limit:
445 # Limit to the last n items
447 # Limit to the last n items
446 file_log = file_log[-limit:]
448 file_log = file_log[-limit:]
447
449
448 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
450 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
449
451
450 @reraise_safe_exceptions
452 @reraise_safe_exceptions
451 def fctx_annotate(self, wire, revision, path):
453 def fctx_annotate(self, wire, revision, path):
452 repo = self._factory.repo(wire)
454 repo = self._factory.repo(wire)
453 ctx = repo[revision]
455 ctx = repo[revision]
454 fctx = ctx.filectx(path)
456 fctx = ctx.filectx(path)
455
457
456 result = []
458 result = []
457 for i, annotate_obj in enumerate(fctx.annotate(), 1):
459 for i, annotate_obj in enumerate(fctx.annotate(), 1):
458 ln_no = i
460 ln_no = i
459 sha = hex(annotate_obj.fctx.node())
461 sha = hex(annotate_obj.fctx.node())
460 content = annotate_obj.text
462 content = annotate_obj.text
461 result.append((ln_no, sha, content))
463 result.append((ln_no, sha, content))
462 return result
464 return result
463
465
464 @reraise_safe_exceptions
466 @reraise_safe_exceptions
465 def fctx_data(self, wire, revision, path):
467 def fctx_data(self, wire, revision, path):
466 repo = self._factory.repo(wire)
468 repo = self._factory.repo(wire)
467 ctx = repo[revision]
469 ctx = repo[revision]
468 fctx = ctx.filectx(path)
470 fctx = ctx.filectx(path)
469 return fctx.data()
471 return fctx.data()
470
472
471 @reraise_safe_exceptions
473 @reraise_safe_exceptions
472 def fctx_flags(self, wire, revision, path):
474 def fctx_flags(self, wire, revision, path):
473 repo = self._factory.repo(wire)
475 repo = self._factory.repo(wire)
474 ctx = repo[revision]
476 ctx = repo[revision]
475 fctx = ctx.filectx(path)
477 fctx = ctx.filectx(path)
476 return fctx.flags()
478 return fctx.flags()
477
479
478 @reraise_safe_exceptions
480 @reraise_safe_exceptions
479 def fctx_size(self, wire, revision, path):
481 def fctx_size(self, wire, revision, path):
480 repo = self._factory.repo(wire)
482 repo = self._factory.repo(wire)
481 ctx = repo[revision]
483 ctx = repo[revision]
482 fctx = ctx.filectx(path)
484 fctx = ctx.filectx(path)
483 return fctx.size()
485 return fctx.size()
484
486
485 @reraise_safe_exceptions
487 @reraise_safe_exceptions
486 def get_all_commit_ids(self, wire, name):
488 def get_all_commit_ids(self, wire, name):
487 repo = self._factory.repo(wire)
489 repo = self._factory.repo(wire)
488 revs = repo.filtered(name).changelog.index
490 revs = repo.filtered(name).changelog.index
489 return map(lambda x: hex(x[7]), revs)[:-1]
491 return map(lambda x: hex(x[7]), revs)[:-1]
490
492
491 @reraise_safe_exceptions
493 @reraise_safe_exceptions
492 def get_config_value(self, wire, section, name, untrusted=False):
494 def get_config_value(self, wire, section, name, untrusted=False):
493 repo = self._factory.repo(wire)
495 repo = self._factory.repo(wire)
494 return repo.ui.config(section, name, untrusted=untrusted)
496 return repo.ui.config(section, name, untrusted=untrusted)
495
497
496 @reraise_safe_exceptions
498 @reraise_safe_exceptions
497 def get_config_bool(self, wire, section, name, untrusted=False):
499 def get_config_bool(self, wire, section, name, untrusted=False):
498 repo = self._factory.repo(wire)
500 repo = self._factory.repo(wire)
499 return repo.ui.configbool(section, name, untrusted=untrusted)
501 return repo.ui.configbool(section, name, untrusted=untrusted)
500
502
501 @reraise_safe_exceptions
503 @reraise_safe_exceptions
502 def get_config_list(self, wire, section, name, untrusted=False):
504 def get_config_list(self, wire, section, name, untrusted=False):
503 repo = self._factory.repo(wire)
505 repo = self._factory.repo(wire)
504 return repo.ui.configlist(section, name, untrusted=untrusted)
506 return repo.ui.configlist(section, name, untrusted=untrusted)
505
507
506 @reraise_safe_exceptions
508 @reraise_safe_exceptions
507 def is_large_file(self, wire, path):
509 def is_large_file(self, wire, path):
508 return largefiles.lfutil.isstandin(path)
510 return largefiles.lfutil.isstandin(path)
509
511
510 @reraise_safe_exceptions
512 @reraise_safe_exceptions
511 def in_largefiles_store(self, wire, sha):
513 def in_largefiles_store(self, wire, sha):
512 repo = self._factory.repo(wire)
514 repo = self._factory.repo(wire)
513 return largefiles.lfutil.instore(repo, sha)
515 return largefiles.lfutil.instore(repo, sha)
514
516
515 @reraise_safe_exceptions
517 @reraise_safe_exceptions
516 def in_user_cache(self, wire, sha):
518 def in_user_cache(self, wire, sha):
517 repo = self._factory.repo(wire)
519 repo = self._factory.repo(wire)
518 return largefiles.lfutil.inusercache(repo.ui, sha)
520 return largefiles.lfutil.inusercache(repo.ui, sha)
519
521
520 @reraise_safe_exceptions
522 @reraise_safe_exceptions
521 def store_path(self, wire, sha):
523 def store_path(self, wire, sha):
522 repo = self._factory.repo(wire)
524 repo = self._factory.repo(wire)
523 return largefiles.lfutil.storepath(repo, sha)
525 return largefiles.lfutil.storepath(repo, sha)
524
526
525 @reraise_safe_exceptions
527 @reraise_safe_exceptions
526 def link(self, wire, sha, path):
528 def link(self, wire, sha, path):
527 repo = self._factory.repo(wire)
529 repo = self._factory.repo(wire)
528 largefiles.lfutil.link(
530 largefiles.lfutil.link(
529 largefiles.lfutil.usercachepath(repo.ui, sha), path)
531 largefiles.lfutil.usercachepath(repo.ui, sha), path)
530
532
531 @reraise_safe_exceptions
533 @reraise_safe_exceptions
532 def localrepository(self, wire, create=False):
534 def localrepository(self, wire, create=False):
533 self._factory.repo(wire, create=create)
535 self._factory.repo(wire, create=create)
534
536
535 @reraise_safe_exceptions
537 @reraise_safe_exceptions
536 def lookup(self, wire, revision, both):
538 def lookup(self, wire, revision, both):
537
539
538 repo = self._factory.repo(wire)
540 repo = self._factory.repo(wire)
539
541
540 if isinstance(revision, int):
542 if isinstance(revision, int):
541 # NOTE(marcink):
543 # NOTE(marcink):
542 # since Mercurial doesn't support indexes properly
544 # since Mercurial doesn't support indexes properly
543 # we need to shift accordingly by one to get proper index, e.g
545 # we need to shift accordingly by one to get proper index, e.g
544 # repo[-1] => repo[-2]
546 # repo[-1] => repo[-2]
545 # repo[0] => repo[-1]
547 # repo[0] => repo[-1]
546 # repo[1] => repo[2] we also never call repo[0] because
548 # repo[1] => repo[2] we also never call repo[0] because
547 # it's actually second commit
549 # it's actually second commit
548 if revision <= 0:
550 if revision <= 0:
549 revision = revision + -1
551 revision = revision + -1
550 else:
552 else:
551 revision = revision + 1
553 revision = revision + 1
552
554
553 try:
555 try:
554 ctx = repo[revision]
556 ctx = repo[revision]
555 except RepoLookupError:
557 except RepoLookupError:
556 raise exceptions.LookupException(revision)
558 raise exceptions.LookupException(revision)
557 except LookupError as e:
559 except LookupError as e:
558 raise exceptions.LookupException(e.name)
560 raise exceptions.LookupException(e.name)
559
561
560 if not both:
562 if not both:
561 return ctx.hex()
563 return ctx.hex()
562
564
563 ctx = repo[ctx.hex()]
565 ctx = repo[ctx.hex()]
564 return ctx.hex(), ctx.rev()
566 return ctx.hex(), ctx.rev()
565
567
566 @reraise_safe_exceptions
568 @reraise_safe_exceptions
567 def pull(self, wire, url, commit_ids=None):
569 def pull(self, wire, url, commit_ids=None):
568 repo = self._factory.repo(wire)
570 repo = self._factory.repo(wire)
569 # Disable any prompts for this repo
571 # Disable any prompts for this repo
570 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
572 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
571
573
572 remote = peer(repo, {}, url)
574 remote = peer(repo, {}, url)
573 # Disable any prompts for this remote
575 # Disable any prompts for this remote
574 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
576 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
575
577
576 if commit_ids:
578 if commit_ids:
577 commit_ids = [bin(commit_id) for commit_id in commit_ids]
579 commit_ids = [bin(commit_id) for commit_id in commit_ids]
578
580
579 return exchange.pull(
581 return exchange.pull(
580 repo, remote, heads=commit_ids, force=None).cgresult
582 repo, remote, heads=commit_ids, force=None).cgresult
581
583
582 @reraise_safe_exceptions
584 @reraise_safe_exceptions
583 def sync_push(self, wire, url):
585 def sync_push(self, wire, url):
584 if self.check_url(url, wire['config']):
586 if self.check_url(url, wire['config']):
585 repo = self._factory.repo(wire)
587 repo = self._factory.repo(wire)
586
588
587 # Disable any prompts for this repo
589 # Disable any prompts for this repo
588 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
590 repo.ui.setconfig('ui', 'interactive', 'off', '-y')
589
591
590 bookmarks = dict(repo._bookmarks).keys()
592 bookmarks = dict(repo._bookmarks).keys()
591 remote = peer(repo, {}, url)
593 remote = peer(repo, {}, url)
592 # Disable any prompts for this remote
594 # Disable any prompts for this remote
593 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
595 remote.ui.setconfig('ui', 'interactive', 'off', '-y')
594
596
595 return exchange.push(
597 return exchange.push(
596 repo, remote, newbranch=True, bookmarks=bookmarks).cgresult
598 repo, remote, newbranch=True, bookmarks=bookmarks).cgresult
597
599
598 @reraise_safe_exceptions
600 @reraise_safe_exceptions
599 def revision(self, wire, rev):
601 def revision(self, wire, rev):
600 repo = self._factory.repo(wire)
602 repo = self._factory.repo(wire)
601 ctx = repo[rev]
603 ctx = repo[rev]
602 return ctx.rev()
604 return ctx.rev()
603
605
604 @reraise_safe_exceptions
606 @reraise_safe_exceptions
605 def rev_range(self, wire, filter):
607 def rev_range(self, wire, filter):
606 repo = self._factory.repo(wire)
608 repo = self._factory.repo(wire)
607 revisions = [rev for rev in revrange(repo, filter)]
609 revisions = [rev for rev in revrange(repo, filter)]
608 return revisions
610 return revisions
609
611
610 @reraise_safe_exceptions
612 @reraise_safe_exceptions
611 def rev_range_hash(self, wire, node):
613 def rev_range_hash(self, wire, node):
612 repo = self._factory.repo(wire)
614 repo = self._factory.repo(wire)
613
615
614 def get_revs(repo, rev_opt):
616 def get_revs(repo, rev_opt):
615 if rev_opt:
617 if rev_opt:
616 revs = revrange(repo, rev_opt)
618 revs = revrange(repo, rev_opt)
617 if len(revs) == 0:
619 if len(revs) == 0:
618 return (nullrev, nullrev)
620 return (nullrev, nullrev)
619 return max(revs), min(revs)
621 return max(revs), min(revs)
620 else:
622 else:
621 return len(repo) - 1, 0
623 return len(repo) - 1, 0
622
624
623 stop, start = get_revs(repo, [node + ':'])
625 stop, start = get_revs(repo, [node + ':'])
624 revs = [hex(repo[r].node()) for r in xrange(start, stop + 1)]
626 revs = [hex(repo[r].node()) for r in xrange(start, stop + 1)]
625 return revs
627 return revs
626
628
627 @reraise_safe_exceptions
629 @reraise_safe_exceptions
628 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
630 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
629 other_path = kwargs.pop('other_path', None)
631 other_path = kwargs.pop('other_path', None)
630
632
631 # case when we want to compare two independent repositories
633 # case when we want to compare two independent repositories
632 if other_path and other_path != wire["path"]:
634 if other_path and other_path != wire["path"]:
633 baseui = self._factory._create_config(wire["config"])
635 baseui = self._factory._create_config(wire["config"])
634 repo = unionrepo.unionrepository(baseui, other_path, wire["path"])
636 repo = unionrepo.unionrepository(baseui, other_path, wire["path"])
635 else:
637 else:
636 repo = self._factory.repo(wire)
638 repo = self._factory.repo(wire)
637 return list(repo.revs(rev_spec, *args))
639 return list(repo.revs(rev_spec, *args))
638
640
639 @reraise_safe_exceptions
641 @reraise_safe_exceptions
640 def strip(self, wire, revision, update, backup):
642 def strip(self, wire, revision, update, backup):
641 repo = self._factory.repo(wire)
643 repo = self._factory.repo(wire)
642 ctx = repo[revision]
644 ctx = repo[revision]
643 hgext_strip(
645 hgext_strip(
644 repo.baseui, repo, ctx.node(), update=update, backup=backup)
646 repo.baseui, repo, ctx.node(), update=update, backup=backup)
645
647
646 @reraise_safe_exceptions
648 @reraise_safe_exceptions
647 def verify(self, wire,):
649 def verify(self, wire,):
648 repo = self._factory.repo(wire)
650 repo = self._factory.repo(wire)
649 baseui = self._factory._create_config(wire['config'])
651 baseui = self._factory._create_config(wire['config'])
650 baseui.setconfig('ui', 'quiet', 'false')
652 baseui.setconfig('ui', 'quiet', 'false')
651 output = io.BytesIO()
653 output = io.BytesIO()
652
654
653 def write(data, **unused_kwargs):
655 def write(data, **unused_kwargs):
654 output.write(data)
656 output.write(data)
655 baseui.write = write
657 baseui.write = write
656
658
657 repo.ui = baseui
659 repo.ui = baseui
658 verify.verify(repo)
660 verify.verify(repo)
659 return output.getvalue()
661 return output.getvalue()
660
662
661 @reraise_safe_exceptions
663 @reraise_safe_exceptions
662 def tag(self, wire, name, revision, message, local, user,
664 def tag(self, wire, name, revision, message, local, user,
663 tag_time, tag_timezone):
665 tag_time, tag_timezone):
664 repo = self._factory.repo(wire)
666 repo = self._factory.repo(wire)
665 ctx = repo[revision]
667 ctx = repo[revision]
666 node = ctx.node()
668 node = ctx.node()
667
669
668 date = (tag_time, tag_timezone)
670 date = (tag_time, tag_timezone)
669 try:
671 try:
670 hg_tag.tag(repo, name, node, message, local, user, date)
672 hg_tag.tag(repo, name, node, message, local, user, date)
671 except Abort as e:
673 except Abort as e:
672 log.exception("Tag operation aborted")
674 log.exception("Tag operation aborted")
673 # Exception can contain unicode which we convert
675 # Exception can contain unicode which we convert
674 raise exceptions.AbortException(repr(e))
676 raise exceptions.AbortException(repr(e))
675
677
676 @reraise_safe_exceptions
678 @reraise_safe_exceptions
677 def tags(self, wire):
679 def tags(self, wire):
678 repo = self._factory.repo(wire)
680 repo = self._factory.repo(wire)
679 return repo.tags()
681 return repo.tags()
680
682
681 @reraise_safe_exceptions
683 @reraise_safe_exceptions
682 def update(self, wire, node=None, clean=False):
684 def update(self, wire, node=None, clean=False):
683 repo = self._factory.repo(wire)
685 repo = self._factory.repo(wire)
684 baseui = self._factory._create_config(wire['config'])
686 baseui = self._factory._create_config(wire['config'])
685 commands.update(baseui, repo, node=node, clean=clean)
687 commands.update(baseui, repo, node=node, clean=clean)
686
688
687 @reraise_safe_exceptions
689 @reraise_safe_exceptions
688 def identify(self, wire):
690 def identify(self, wire):
689 repo = self._factory.repo(wire)
691 repo = self._factory.repo(wire)
690 baseui = self._factory._create_config(wire['config'])
692 baseui = self._factory._create_config(wire['config'])
691 output = io.BytesIO()
693 output = io.BytesIO()
692 baseui.write = output.write
694 baseui.write = output.write
693 # This is required to get a full node id
695 # This is required to get a full node id
694 baseui.debugflag = True
696 baseui.debugflag = True
695 commands.identify(baseui, repo, id=True)
697 commands.identify(baseui, repo, id=True)
696
698
697 return output.getvalue()
699 return output.getvalue()
698
700
699 @reraise_safe_exceptions
701 @reraise_safe_exceptions
700 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None,
702 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None,
701 hooks=True):
703 hooks=True):
702 repo = self._factory.repo(wire)
704 repo = self._factory.repo(wire)
703 baseui = self._factory._create_config(wire['config'], hooks=hooks)
705 baseui = self._factory._create_config(wire['config'], hooks=hooks)
704
706
705 # Mercurial internally has a lot of logic that checks ONLY if
707 # Mercurial internally has a lot of logic that checks ONLY if
706 # option is defined, we just pass those if they are defined then
708 # option is defined, we just pass those if they are defined then
707 opts = {}
709 opts = {}
708 if bookmark:
710 if bookmark:
709 opts['bookmark'] = bookmark
711 opts['bookmark'] = bookmark
710 if branch:
712 if branch:
711 opts['branch'] = branch
713 opts['branch'] = branch
712 if revision:
714 if revision:
713 opts['rev'] = revision
715 opts['rev'] = revision
714
716
715 commands.pull(baseui, repo, source, **opts)
717 commands.pull(baseui, repo, source, **opts)
716
718
717 @reraise_safe_exceptions
719 @reraise_safe_exceptions
718 def heads(self, wire, branch=None):
720 def heads(self, wire, branch=None):
719 repo = self._factory.repo(wire)
721 repo = self._factory.repo(wire)
720 baseui = self._factory._create_config(wire['config'])
722 baseui = self._factory._create_config(wire['config'])
721 output = io.BytesIO()
723 output = io.BytesIO()
722
724
723 def write(data, **unused_kwargs):
725 def write(data, **unused_kwargs):
724 output.write(data)
726 output.write(data)
725
727
726 baseui.write = write
728 baseui.write = write
727 if branch:
729 if branch:
728 args = [branch]
730 args = [branch]
729 else:
731 else:
730 args = []
732 args = []
731 commands.heads(baseui, repo, template='{node} ', *args)
733 commands.heads(baseui, repo, template='{node} ', *args)
732
734
733 return output.getvalue()
735 return output.getvalue()
734
736
735 @reraise_safe_exceptions
737 @reraise_safe_exceptions
736 def ancestor(self, wire, revision1, revision2):
738 def ancestor(self, wire, revision1, revision2):
737 repo = self._factory.repo(wire)
739 repo = self._factory.repo(wire)
738 changelog = repo.changelog
740 changelog = repo.changelog
739 lookup = repo.lookup
741 lookup = repo.lookup
740 a = changelog.ancestor(lookup(revision1), lookup(revision2))
742 a = changelog.ancestor(lookup(revision1), lookup(revision2))
741 return hex(a)
743 return hex(a)
742
744
743 @reraise_safe_exceptions
745 @reraise_safe_exceptions
744 def push(self, wire, revisions, dest_path, hooks=True,
746 def push(self, wire, revisions, dest_path, hooks=True,
745 push_branches=False):
747 push_branches=False):
746 repo = self._factory.repo(wire)
748 repo = self._factory.repo(wire)
747 baseui = self._factory._create_config(wire['config'], hooks=hooks)
749 baseui = self._factory._create_config(wire['config'], hooks=hooks)
748 commands.push(baseui, repo, dest=dest_path, rev=revisions,
750 commands.push(baseui, repo, dest=dest_path, rev=revisions,
749 new_branch=push_branches)
751 new_branch=push_branches)
750
752
751 @reraise_safe_exceptions
753 @reraise_safe_exceptions
752 def merge(self, wire, revision):
754 def merge(self, wire, revision):
753 repo = self._factory.repo(wire)
755 repo = self._factory.repo(wire)
754 baseui = self._factory._create_config(wire['config'])
756 baseui = self._factory._create_config(wire['config'])
755 repo.ui.setconfig('ui', 'merge', 'internal:dump')
757 repo.ui.setconfig('ui', 'merge', 'internal:dump')
756
758
757 # In case of sub repositories are used mercurial prompts the user in
759 # In case of sub repositories are used mercurial prompts the user in
758 # case of merge conflicts or different sub repository sources. By
760 # case of merge conflicts or different sub repository sources. By
759 # setting the interactive flag to `False` mercurial doesn't prompt the
761 # setting the interactive flag to `False` mercurial doesn't prompt the
760 # used but instead uses a default value.
762 # used but instead uses a default value.
761 repo.ui.setconfig('ui', 'interactive', False)
763 repo.ui.setconfig('ui', 'interactive', False)
762
764
763 commands.merge(baseui, repo, rev=revision)
765 commands.merge(baseui, repo, rev=revision)
764
766
765 @reraise_safe_exceptions
767 @reraise_safe_exceptions
766 def commit(self, wire, message, username, close_branch=False):
768 def commit(self, wire, message, username, close_branch=False):
767 repo = self._factory.repo(wire)
769 repo = self._factory.repo(wire)
768 baseui = self._factory._create_config(wire['config'])
770 baseui = self._factory._create_config(wire['config'])
769 repo.ui.setconfig('ui', 'username', username)
771 repo.ui.setconfig('ui', 'username', username)
770 commands.commit(baseui, repo, message=message, close_branch=close_branch)
772 commands.commit(baseui, repo, message=message, close_branch=close_branch)
771
773
772 @reraise_safe_exceptions
774 @reraise_safe_exceptions
773 def rebase(self, wire, source=None, dest=None, abort=False):
775 def rebase(self, wire, source=None, dest=None, abort=False):
774 repo = self._factory.repo(wire)
776 repo = self._factory.repo(wire)
775 baseui = self._factory._create_config(wire['config'])
777 baseui = self._factory._create_config(wire['config'])
776 repo.ui.setconfig('ui', 'merge', 'internal:dump')
778 repo.ui.setconfig('ui', 'merge', 'internal:dump')
777 rebase.rebase(
779 rebase.rebase(
778 baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
780 baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
779
781
780 @reraise_safe_exceptions
782 @reraise_safe_exceptions
781 def bookmark(self, wire, bookmark, revision=None):
783 def bookmark(self, wire, bookmark, revision=None):
782 repo = self._factory.repo(wire)
784 repo = self._factory.repo(wire)
783 baseui = self._factory._create_config(wire['config'])
785 baseui = self._factory._create_config(wire['config'])
784 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
786 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
785
787
786 @reraise_safe_exceptions
788 @reraise_safe_exceptions
787 def install_hooks(self, wire, force=False):
789 def install_hooks(self, wire, force=False):
788 # we don't need any special hooks for Mercurial
790 # we don't need any special hooks for Mercurial
789 pass
791 pass
@@ -1,63 +1,63 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-2018 RhodeCode GmbH
2 # Copyright (C) 2014-2018 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 tags as hg_tag
39 from mercurial import tags as hg_tag
40
40
41 from mercurial.commands import clone, nullid, pull
41 from mercurial.commands import clone, nullid, pull
42 from mercurial.context import memctx, memfilectx
42 from mercurial.context import memctx, memfilectx
43 from mercurial.error import (
43 from mercurial.error import (
44 LookupError, RepoError, RepoLookupError, Abort, InterventionRequired,
44 LookupError, RepoError, RepoLookupError, Abort, InterventionRequired,
45 RequirementError)
45 RequirementError)
46 from mercurial.hgweb import hgweb_mod
46 from mercurial.hgweb import hgweb_mod
47 from mercurial.localrepo import localrepository
47 from mercurial.localrepo import localrepository
48 from mercurial.match import match
48 from mercurial.match import match
49 from mercurial.mdiff import diffopts
49 from mercurial.mdiff import diffopts
50 from mercurial.node import bin, hex
50 from mercurial.node import bin, hex
51 from mercurial.encoding import tolocal
51 from mercurial.encoding import tolocal
52 from mercurial.discovery import findcommonoutgoing
52 from mercurial.discovery import findcommonoutgoing
53 from mercurial.hg import peer
53 from mercurial.hg import peer
54 from mercurial.httppeer import httppeer
54 from mercurial.httppeer import makepeer
55 from mercurial.util import url as hg_url
55 from mercurial.util import url as hg_url
56 from mercurial.scmutil import revrange
56 from mercurial.scmutil import revrange
57 from mercurial.node import nullrev
57 from mercurial.node import nullrev
58 from mercurial import exchange
58 from mercurial import exchange
59 from hgext import largefiles
59 from hgext import largefiles
60
60
61 # those authnadlers are patched for python 2.6.5 bug an
61 # those authnadlers are patched for python 2.6.5 bug an
62 # infinit looping when given invalid resources
62 # infinit looping when given invalid resources
63 from mercurial.url import httpbasicauthhandler, httpdigestauthhandler
63 from mercurial.url import httpbasicauthhandler, httpdigestauthhandler
General Comments 0
You need to be logged in to leave comments. Login now