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