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