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