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