##// END OF EJS Templates
py3: fixed few mercurial cases
super-admin -
r1050:bf6aa61b python3
parent child Browse files
Show More
@@ -1,84 +1,87 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-2020 RhodeCode GmbH
2 # Copyright (C) 2014-2020 RhodeCode GmbH
3 #
3 #
4 # This program is free software; you can redistribute it and/or modify
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 """
18 """
19 Mercurial libs compatibility
19 Mercurial libs compatibility
20 """
20 """
21
21
22 import mercurial
22 import mercurial
23 from mercurial import demandimport
23 from mercurial import demandimport
24
24
25 # patch demandimport, due to bug in mercurial when it always triggers
25 # patch demandimport, due to bug in mercurial when it always triggers
26 # demandimport.enable()
26 # demandimport.enable()
27 from vcsserver.utils import safe_bytes
28
27 demandimport.enable = lambda *args, **kwargs: 1
29 demandimport.enable = lambda *args, **kwargs: 1
28
30
29 from mercurial import ui
31 from mercurial import ui
30 from mercurial import patch
32 from mercurial import patch
31 from mercurial import config
33 from mercurial import config
32 from mercurial import extensions
34 from mercurial import extensions
33 from mercurial import scmutil
35 from mercurial import scmutil
34 from mercurial import archival
36 from mercurial import archival
35 from mercurial import discovery
37 from mercurial import discovery
36 from mercurial import unionrepo
38 from mercurial import unionrepo
37 from mercurial import localrepo
39 from mercurial import localrepo
38 from mercurial import merge as hg_merge
40 from mercurial import merge as hg_merge
39 from mercurial import subrepo
41 from mercurial import subrepo
40 from mercurial import subrepoutil
42 from mercurial import subrepoutil
41 from mercurial import tags as hg_tag
43 from mercurial import tags as hg_tag
42 from mercurial import util as hgutil
44 from mercurial import util as hgutil
43 from mercurial.commands import clone, pull
45 from mercurial.commands import clone, pull
44 from mercurial.node import nullid
46 from mercurial.node import nullid
45 from mercurial.context import memctx, memfilectx
47 from mercurial.context import memctx, memfilectx
46 from mercurial.error import (
48 from mercurial.error import (
47 LookupError, RepoError, RepoLookupError, Abort, InterventionRequired,
49 LookupError, RepoError, RepoLookupError, Abort, InterventionRequired,
48 RequirementError, ProgrammingError)
50 RequirementError, ProgrammingError)
49 from mercurial.hgweb import hgweb_mod
51 from mercurial.hgweb import hgweb_mod
50 from mercurial.localrepo import instance
52 from mercurial.localrepo import instance
51 from mercurial.match import match, alwaysmatcher, patternmatcher
53 from mercurial.match import match, alwaysmatcher, patternmatcher
52 from mercurial.mdiff import diffopts
54 from mercurial.mdiff import diffopts
53 from mercurial.node import bin, hex
55 from mercurial.node import bin, hex
54 from mercurial.encoding import tolocal
56 from mercurial.encoding import tolocal
55 from mercurial.discovery import findcommonoutgoing
57 from mercurial.discovery import findcommonoutgoing
56 from mercurial.hg import peer
58 from mercurial.hg import peer
57 from mercurial.httppeer import makepeer
59 from mercurial.httppeer import makepeer
58 from mercurial.utils.urlutil import url as hg_url
60 from mercurial.utils.urlutil import url as hg_url
59 from mercurial.scmutil import revrange, revsymbol
61 from mercurial.scmutil import revrange, revsymbol
60 from mercurial.node import nullrev
62 from mercurial.node import nullrev
61 from mercurial import exchange
63 from mercurial import exchange
62 from hgext import largefiles
64 from hgext import largefiles
63
65
64 # those authnadlers are patched for python 2.6.5 bug an
66 # those authnadlers are patched for python 2.6.5 bug an
65 # infinit looping when given invalid resources
67 # infinit looping when given invalid resources
66 from mercurial.url import httpbasicauthhandler, httpdigestauthhandler
68 from mercurial.url import httpbasicauthhandler, httpdigestauthhandler
67
69
68 # hg strip is in core now
70 # hg strip is in core now
69 from mercurial import strip as hgext_strip
71 from mercurial import strip as hgext_strip
70
72
71
73
72 def get_ctx(repo, ref):
74 def get_ctx(repo, ref):
75 ref = safe_bytes(ref)
73 try:
76 try:
74 ctx = repo[ref]
77 ctx = repo[ref]
75 except (ProgrammingError, TypeError):
78 except (ProgrammingError, TypeError):
76 # we're unable to find the rev using a regular lookup, we fallback
79 # we're unable to find the rev using a regular lookup, we fallback
77 # to slower, but backward compat revsymbol usage
80 # to slower, but backward compat revsymbol usage
78 ctx = revsymbol(repo, ref)
81 ctx = revsymbol(repo, ref)
79 except (LookupError, RepoLookupError):
82 except (LookupError, RepoLookupError):
80 # Similar case as above but only for refs that are not numeric
83 # Similar case as above but only for refs that are not numeric
81 if isinstance(ref, int):
84 if isinstance(ref, int):
82 raise
85 raise
83 ctx = revsymbol(repo, ref)
86 ctx = revsymbol(repo, ref)
84 return ctx
87 return ctx
@@ -1,1057 +1,1062 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-2020 RhodeCode GmbH
2 # Copyright (C) 2014-2020 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.request, urllib.parse, urllib.error
21 import urllib.request, urllib.parse, urllib.error
22 import urllib.request, urllib.error, urllib.parse
22 import urllib.request, urllib.error, urllib.parse
23 import traceback
23 import traceback
24
24
25 from hgext import largefiles, rebase, purge
25 from hgext import largefiles, rebase, purge
26
26
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 from mercurial import repair
30 from mercurial import repair
31
31
32 import vcsserver
32 import vcsserver
33 from vcsserver import exceptions
33 from vcsserver import exceptions
34 from vcsserver.base import RepoFactory, obfuscate_qs, raise_from_original, archive_repo, ArchiveNode
34 from vcsserver.base import RepoFactory, obfuscate_qs, raise_from_original, archive_repo, ArchiveNode
35 from vcsserver.hgcompat import (
35 from vcsserver.hgcompat import (
36 archival, bin, clone, config as hgconfig, diffopts, hex, get_ctx,
36 archival, bin, clone, config as hgconfig, diffopts, hex, get_ctx,
37 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler,
37 hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler,
38 makepeer, instance, match, memctx, exchange, memfilectx, nullrev, hg_merge,
38 makepeer, instance, match, memctx, exchange, memfilectx, nullrev, hg_merge,
39 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
39 patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
40 RepoLookupError, InterventionRequired, RequirementError,
40 RepoLookupError, InterventionRequired, RequirementError,
41 alwaysmatcher, patternmatcher, hgutil, hgext_strip)
41 alwaysmatcher, patternmatcher, hgutil, hgext_strip)
42 from vcsserver.utils import ascii_bytes, ascii_str, safe_str
42 from vcsserver.utils import ascii_bytes, ascii_str, safe_str, safe_bytes
43 from vcsserver.vcs_base import RemoteBase
43 from vcsserver.vcs_base import RemoteBase
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47
47
48 def make_ui_from_config(repo_config):
48 def make_ui_from_config(repo_config):
49
49
50 class LoggingUI(ui.ui):
50 class LoggingUI(ui.ui):
51
51
52 def status(self, *msg, **opts):
52 def status(self, *msg, **opts):
53 str_msg = map(safe_str, msg)
53 str_msg = map(safe_str, msg)
54 log.info(' '.join(str_msg).rstrip('\n'))
54 log.info(' '.join(str_msg).rstrip('\n'))
55 #super(LoggingUI, self).status(*msg, **opts)
55 #super(LoggingUI, self).status(*msg, **opts)
56
56
57 def warn(self, *msg, **opts):
57 def warn(self, *msg, **opts):
58 str_msg = map(safe_str, msg)
58 str_msg = map(safe_str, msg)
59 log.warning('ui_logger:'+' '.join(str_msg).rstrip('\n'))
59 log.warning('ui_logger:'+' '.join(str_msg).rstrip('\n'))
60 #super(LoggingUI, self).warn(*msg, **opts)
60 #super(LoggingUI, self).warn(*msg, **opts)
61
61
62 def error(self, *msg, **opts):
62 def error(self, *msg, **opts):
63 str_msg = map(safe_str, msg)
63 str_msg = map(safe_str, msg)
64 log.error('ui_logger:'+' '.join(str_msg).rstrip('\n'))
64 log.error('ui_logger:'+' '.join(str_msg).rstrip('\n'))
65 #super(LoggingUI, self).error(*msg, **opts)
65 #super(LoggingUI, self).error(*msg, **opts)
66
66
67 def note(self, *msg, **opts):
67 def note(self, *msg, **opts):
68 str_msg = map(safe_str, msg)
68 str_msg = map(safe_str, msg)
69 log.info('ui_logger:'+' '.join(str_msg).rstrip('\n'))
69 log.info('ui_logger:'+' '.join(str_msg).rstrip('\n'))
70 #super(LoggingUI, self).note(*msg, **opts)
70 #super(LoggingUI, self).note(*msg, **opts)
71
71
72 def debug(self, *msg, **opts):
72 def debug(self, *msg, **opts):
73 str_msg = map(safe_str, msg)
73 str_msg = map(safe_str, msg)
74 log.debug('ui_logger:'+' '.join(str_msg).rstrip('\n'))
74 log.debug('ui_logger:'+' '.join(str_msg).rstrip('\n'))
75 #super(LoggingUI, self).debug(*msg, **opts)
75 #super(LoggingUI, self).debug(*msg, **opts)
76
76
77 baseui = LoggingUI()
77 baseui = LoggingUI()
78
78
79 # clean the baseui object
79 # clean the baseui object
80 baseui._ocfg = hgconfig.config()
80 baseui._ocfg = hgconfig.config()
81 baseui._ucfg = hgconfig.config()
81 baseui._ucfg = hgconfig.config()
82 baseui._tcfg = hgconfig.config()
82 baseui._tcfg = hgconfig.config()
83
83
84 for section, option, value in repo_config:
84 for section, option, value in repo_config:
85 baseui.setconfig(ascii_bytes(section), ascii_bytes(option), ascii_bytes(value))
85 baseui.setconfig(ascii_bytes(section), ascii_bytes(option), ascii_bytes(value))
86
86
87 # make our hgweb quiet so it doesn't print output
87 # make our hgweb quiet so it doesn't print output
88 baseui.setconfig(b'ui', b'quiet', b'true')
88 baseui.setconfig(b'ui', b'quiet', b'true')
89
89
90 baseui.setconfig(b'ui', b'paginate', b'never')
90 baseui.setconfig(b'ui', b'paginate', b'never')
91 # for better Error reporting of Mercurial
91 # for better Error reporting of Mercurial
92 baseui.setconfig(b'ui', b'message-output', b'stderr')
92 baseui.setconfig(b'ui', b'message-output', b'stderr')
93
93
94 # force mercurial to only use 1 thread, otherwise it may try to set a
94 # force mercurial to only use 1 thread, otherwise it may try to set a
95 # signal in a non-main thread, thus generating a ValueError.
95 # signal in a non-main thread, thus generating a ValueError.
96 baseui.setconfig(b'worker', b'numcpus', 1)
96 baseui.setconfig(b'worker', b'numcpus', 1)
97
97
98 # If there is no config for the largefiles extension, we explicitly disable
98 # If there is no config for the largefiles extension, we explicitly disable
99 # it here. This overrides settings from repositories hgrc file. Recent
99 # it here. This overrides settings from repositories hgrc file. Recent
100 # mercurial versions enable largefiles in hgrc on clone from largefile
100 # mercurial versions enable largefiles in hgrc on clone from largefile
101 # repo.
101 # repo.
102 if not baseui.hasconfig(b'extensions', b'largefiles'):
102 if not baseui.hasconfig(b'extensions', b'largefiles'):
103 log.debug('Explicitly disable largefiles extension for repo.')
103 log.debug('Explicitly disable largefiles extension for repo.')
104 baseui.setconfig(b'extensions', b'largefiles', b'!')
104 baseui.setconfig(b'extensions', b'largefiles', b'!')
105
105
106 return baseui
106 return baseui
107
107
108
108
109 def reraise_safe_exceptions(func):
109 def reraise_safe_exceptions(func):
110 """Decorator for converting mercurial exceptions to something neutral."""
110 """Decorator for converting mercurial exceptions to something neutral."""
111
111
112 def wrapper(*args, **kwargs):
112 def wrapper(*args, **kwargs):
113 try:
113 try:
114 return func(*args, **kwargs)
114 return func(*args, **kwargs)
115 except (Abort, InterventionRequired) as e:
115 except (Abort, InterventionRequired) as e:
116 raise_from_original(exceptions.AbortException(e), e)
116 raise_from_original(exceptions.AbortException(e), e)
117 except RepoLookupError as e:
117 except RepoLookupError as e:
118 raise_from_original(exceptions.LookupException(e), e)
118 raise_from_original(exceptions.LookupException(e), e)
119 except RequirementError as e:
119 except RequirementError as e:
120 raise_from_original(exceptions.RequirementException(e), e)
120 raise_from_original(exceptions.RequirementException(e), e)
121 except RepoError as e:
121 except RepoError as e:
122 raise_from_original(exceptions.VcsException(e), e)
122 raise_from_original(exceptions.VcsException(e), e)
123 except LookupError as e:
123 except LookupError as e:
124 raise_from_original(exceptions.LookupException(e), e)
124 raise_from_original(exceptions.LookupException(e), e)
125 except Exception as e:
125 except Exception as e:
126 if not hasattr(e, '_vcs_kind'):
126 if not hasattr(e, '_vcs_kind'):
127 log.exception("Unhandled exception in hg remote call")
127 log.exception("Unhandled exception in hg remote call")
128 raise_from_original(exceptions.UnhandledException(e), e)
128 raise_from_original(exceptions.UnhandledException(e), e)
129
129
130 raise
130 raise
131 return wrapper
131 return wrapper
132
132
133
133
134 class MercurialFactory(RepoFactory):
134 class MercurialFactory(RepoFactory):
135 repo_type = 'hg'
135 repo_type = 'hg'
136
136
137 def _create_config(self, config, hooks=True):
137 def _create_config(self, config, hooks=True):
138 if not hooks:
138 if not hooks:
139 hooks_to_clean = frozenset((
139 hooks_to_clean = frozenset((
140 'changegroup.repo_size', 'preoutgoing.pre_pull',
140 'changegroup.repo_size', 'preoutgoing.pre_pull',
141 'outgoing.pull_logger', 'prechangegroup.pre_push'))
141 'outgoing.pull_logger', 'prechangegroup.pre_push'))
142 new_config = []
142 new_config = []
143 for section, option, value in config:
143 for section, option, value in config:
144 if section == 'hooks' and option in hooks_to_clean:
144 if section == 'hooks' and option in hooks_to_clean:
145 continue
145 continue
146 new_config.append((section, option, value))
146 new_config.append((section, option, value))
147 config = new_config
147 config = new_config
148
148
149 baseui = make_ui_from_config(config)
149 baseui = make_ui_from_config(config)
150 return baseui
150 return baseui
151
151
152 def _create_repo(self, wire, create):
152 def _create_repo(self, wire, create):
153 baseui = self._create_config(wire["config"])
153 baseui = self._create_config(wire["config"])
154 return instance(baseui, ascii_bytes(wire["path"]), create)
154 return instance(baseui, ascii_bytes(wire["path"]), create)
155
155
156 def repo(self, wire, create=False):
156 def repo(self, wire, create=False):
157 """
157 """
158 Get a repository instance for the given path.
158 Get a repository instance for the given path.
159 """
159 """
160 return self._create_repo(wire, create)
160 return self._create_repo(wire, create)
161
161
162
162
163 def patch_ui_message_output(baseui):
163 def patch_ui_message_output(baseui):
164 baseui.setconfig(b'ui', b'quiet', b'false')
164 baseui.setconfig(b'ui', b'quiet', b'false')
165 output = io.BytesIO()
165 output = io.BytesIO()
166
166
167 def write(data, **unused_kwargs):
167 def write(data, **unused_kwargs):
168 output.write(data)
168 output.write(data)
169
169
170 baseui.status = write
170 baseui.status = write
171 baseui.write = write
171 baseui.write = write
172 baseui.warn = write
172 baseui.warn = write
173 baseui.debug = write
173 baseui.debug = write
174
174
175 return baseui, output
175 return baseui, output
176
176
177
177
178 class HgRemote(RemoteBase):
178 class HgRemote(RemoteBase):
179
179
180 def __init__(self, factory):
180 def __init__(self, factory):
181 self._factory = factory
181 self._factory = factory
182 self._bulk_methods = {
182 self._bulk_methods = {
183 "affected_files": self.ctx_files,
183 "affected_files": self.ctx_files,
184 "author": self.ctx_user,
184 "author": self.ctx_user,
185 "branch": self.ctx_branch,
185 "branch": self.ctx_branch,
186 "children": self.ctx_children,
186 "children": self.ctx_children,
187 "date": self.ctx_date,
187 "date": self.ctx_date,
188 "message": self.ctx_description,
188 "message": self.ctx_description,
189 "parents": self.ctx_parents,
189 "parents": self.ctx_parents,
190 "status": self.ctx_status,
190 "status": self.ctx_status,
191 "obsolete": self.ctx_obsolete,
191 "obsolete": self.ctx_obsolete,
192 "phase": self.ctx_phase,
192 "phase": self.ctx_phase,
193 "hidden": self.ctx_hidden,
193 "hidden": self.ctx_hidden,
194 "_file_paths": self.ctx_list,
194 "_file_paths": self.ctx_list,
195 }
195 }
196
196
197 def _get_ctx(self, repo, ref):
197 def _get_ctx(self, repo, ref):
198 return get_ctx(repo, ref)
198 return get_ctx(repo, ref)
199
199
200 @reraise_safe_exceptions
200 @reraise_safe_exceptions
201 def discover_hg_version(self):
201 def discover_hg_version(self):
202 from mercurial import util
202 from mercurial import util
203 return util.version()
203 return util.version()
204
204
205 @reraise_safe_exceptions
205 @reraise_safe_exceptions
206 def is_empty(self, wire):
206 def is_empty(self, wire):
207 repo = self._factory.repo(wire)
207 repo = self._factory.repo(wire)
208
208
209 try:
209 try:
210 return len(repo) == 0
210 return len(repo) == 0
211 except Exception:
211 except Exception:
212 log.exception("failed to read object_store")
212 log.exception("failed to read object_store")
213 return False
213 return False
214
214
215 @reraise_safe_exceptions
215 @reraise_safe_exceptions
216 def bookmarks(self, wire):
216 def bookmarks(self, wire):
217 cache_on, context_uid, repo_id = self._cache_on(wire)
217 cache_on, context_uid, repo_id = self._cache_on(wire)
218 region = self._region(wire)
218 region = self._region(wire)
219 @region.conditional_cache_on_arguments(condition=cache_on)
219 @region.conditional_cache_on_arguments(condition=cache_on)
220 def _bookmarks(_context_uid, _repo_id):
220 def _bookmarks(_context_uid, _repo_id):
221 repo = self._factory.repo(wire)
221 repo = self._factory.repo(wire)
222 return dict(repo._bookmarks)
222 return dict(repo._bookmarks)
223
223
224 return _bookmarks(context_uid, repo_id)
224 return _bookmarks(context_uid, repo_id)
225
225
226 @reraise_safe_exceptions
226 @reraise_safe_exceptions
227 def branches(self, wire, normal, closed):
227 def branches(self, wire, normal, closed):
228 cache_on, context_uid, repo_id = self._cache_on(wire)
228 cache_on, context_uid, repo_id = self._cache_on(wire)
229 region = self._region(wire)
229 region = self._region(wire)
230 @region.conditional_cache_on_arguments(condition=cache_on)
230 @region.conditional_cache_on_arguments(condition=cache_on)
231 def _branches(_context_uid, _repo_id, _normal, _closed):
231 def _branches(_context_uid, _repo_id, _normal, _closed):
232 repo = self._factory.repo(wire)
232 repo = self._factory.repo(wire)
233 iter_branches = repo.branchmap().iterbranches()
233 iter_branches = repo.branchmap().iterbranches()
234 bt = {}
234 bt = {}
235 for branch_name, _heads, tip, is_closed in iter_branches:
235 for branch_name, _heads, tip, is_closed in iter_branches:
236 if normal and not is_closed:
236 if normal and not is_closed:
237 bt[branch_name] = tip
237 bt[branch_name] = tip
238 if closed and is_closed:
238 if closed and is_closed:
239 bt[branch_name] = tip
239 bt[branch_name] = tip
240
240
241 return bt
241 return bt
242
242
243 return _branches(context_uid, repo_id, normal, closed)
243 return _branches(context_uid, repo_id, normal, closed)
244
244
245 @reraise_safe_exceptions
245 @reraise_safe_exceptions
246 def bulk_request(self, wire, commit_id, pre_load):
246 def bulk_request(self, wire, commit_id, pre_load):
247 cache_on, context_uid, repo_id = self._cache_on(wire)
247 cache_on, context_uid, repo_id = self._cache_on(wire)
248 region = self._region(wire)
248 region = self._region(wire)
249 @region.conditional_cache_on_arguments(condition=cache_on)
249 @region.conditional_cache_on_arguments(condition=cache_on)
250 def _bulk_request(_repo_id, _commit_id, _pre_load):
250 def _bulk_request(_repo_id, _commit_id, _pre_load):
251 result = {}
251 result = {}
252 for attr in pre_load:
252 for attr in pre_load:
253 try:
253 try:
254 method = self._bulk_methods[attr]
254 method = self._bulk_methods[attr]
255 result[attr] = method(wire, commit_id)
255 result[attr] = method(wire, commit_id)
256 except KeyError as e:
256 except KeyError as e:
257 raise exceptions.VcsException(e)(
257 raise exceptions.VcsException(e)(
258 'Unknown bulk attribute: "%s"' % attr)
258 'Unknown bulk attribute: "%s"' % attr)
259 return result
259 return result
260
260
261 return _bulk_request(repo_id, commit_id, sorted(pre_load))
261 return _bulk_request(repo_id, commit_id, sorted(pre_load))
262
262
263 @reraise_safe_exceptions
263 @reraise_safe_exceptions
264 def ctx_branch(self, wire, commit_id):
264 def ctx_branch(self, wire, commit_id):
265 cache_on, context_uid, repo_id = self._cache_on(wire)
265 cache_on, context_uid, repo_id = self._cache_on(wire)
266 region = self._region(wire)
266 region = self._region(wire)
267 @region.conditional_cache_on_arguments(condition=cache_on)
267 @region.conditional_cache_on_arguments(condition=cache_on)
268 def _ctx_branch(_repo_id, _commit_id):
268 def _ctx_branch(_repo_id, _commit_id):
269 repo = self._factory.repo(wire)
269 repo = self._factory.repo(wire)
270 ctx = self._get_ctx(repo, commit_id)
270 ctx = self._get_ctx(repo, commit_id)
271 return ctx.branch()
271 return ctx.branch()
272 return _ctx_branch(repo_id, commit_id)
272 return _ctx_branch(repo_id, commit_id)
273
273
274 @reraise_safe_exceptions
274 @reraise_safe_exceptions
275 def ctx_date(self, wire, commit_id):
275 def ctx_date(self, wire, commit_id):
276 cache_on, context_uid, repo_id = self._cache_on(wire)
276 cache_on, context_uid, repo_id = self._cache_on(wire)
277 region = self._region(wire)
277 region = self._region(wire)
278 @region.conditional_cache_on_arguments(condition=cache_on)
278 @region.conditional_cache_on_arguments(condition=cache_on)
279 def _ctx_date(_repo_id, _commit_id):
279 def _ctx_date(_repo_id, _commit_id):
280 repo = self._factory.repo(wire)
280 repo = self._factory.repo(wire)
281 ctx = self._get_ctx(repo, commit_id)
281 ctx = self._get_ctx(repo, commit_id)
282 return ctx.date()
282 return ctx.date()
283 return _ctx_date(repo_id, commit_id)
283 return _ctx_date(repo_id, commit_id)
284
284
285 @reraise_safe_exceptions
285 @reraise_safe_exceptions
286 def ctx_description(self, wire, revision):
286 def ctx_description(self, wire, revision):
287 repo = self._factory.repo(wire)
287 repo = self._factory.repo(wire)
288 ctx = self._get_ctx(repo, revision)
288 ctx = self._get_ctx(repo, revision)
289 return ctx.description()
289 return ctx.description()
290
290
291 @reraise_safe_exceptions
291 @reraise_safe_exceptions
292 def ctx_files(self, wire, commit_id):
292 def ctx_files(self, wire, commit_id):
293 cache_on, context_uid, repo_id = self._cache_on(wire)
293 cache_on, context_uid, repo_id = self._cache_on(wire)
294 region = self._region(wire)
294 region = self._region(wire)
295 @region.conditional_cache_on_arguments(condition=cache_on)
295 @region.conditional_cache_on_arguments(condition=cache_on)
296 def _ctx_files(_repo_id, _commit_id):
296 def _ctx_files(_repo_id, _commit_id):
297 repo = self._factory.repo(wire)
297 repo = self._factory.repo(wire)
298 ctx = self._get_ctx(repo, commit_id)
298 ctx = self._get_ctx(repo, commit_id)
299 return ctx.files()
299 return ctx.files()
300
300
301 return _ctx_files(repo_id, commit_id)
301 return _ctx_files(repo_id, commit_id)
302
302
303 @reraise_safe_exceptions
303 @reraise_safe_exceptions
304 def ctx_list(self, path, revision):
304 def ctx_list(self, path, revision):
305 repo = self._factory.repo(path)
305 repo = self._factory.repo(path)
306 ctx = self._get_ctx(repo, revision)
306 ctx = self._get_ctx(repo, revision)
307 return list(ctx)
307 return list(ctx)
308
308
309 @reraise_safe_exceptions
309 @reraise_safe_exceptions
310 def ctx_parents(self, wire, commit_id):
310 def ctx_parents(self, wire, commit_id):
311 cache_on, context_uid, repo_id = self._cache_on(wire)
311 cache_on, context_uid, repo_id = self._cache_on(wire)
312 region = self._region(wire)
312 region = self._region(wire)
313 @region.conditional_cache_on_arguments(condition=cache_on)
313 @region.conditional_cache_on_arguments(condition=cache_on)
314 def _ctx_parents(_repo_id, _commit_id):
314 def _ctx_parents(_repo_id, _commit_id):
315 repo = self._factory.repo(wire)
315 repo = self._factory.repo(wire)
316 ctx = self._get_ctx(repo, commit_id)
316 ctx = self._get_ctx(repo, commit_id)
317 return [parent.hex() for parent in ctx.parents()
317 return [parent.hex() for parent in ctx.parents()
318 if not (parent.hidden() or parent.obsolete())]
318 if not (parent.hidden() or parent.obsolete())]
319
319
320 return _ctx_parents(repo_id, commit_id)
320 return _ctx_parents(repo_id, commit_id)
321
321
322 @reraise_safe_exceptions
322 @reraise_safe_exceptions
323 def ctx_children(self, wire, commit_id):
323 def ctx_children(self, wire, commit_id):
324 cache_on, context_uid, repo_id = self._cache_on(wire)
324 cache_on, context_uid, repo_id = self._cache_on(wire)
325 region = self._region(wire)
325 region = self._region(wire)
326 @region.conditional_cache_on_arguments(condition=cache_on)
326 @region.conditional_cache_on_arguments(condition=cache_on)
327 def _ctx_children(_repo_id, _commit_id):
327 def _ctx_children(_repo_id, _commit_id):
328 repo = self._factory.repo(wire)
328 repo = self._factory.repo(wire)
329 ctx = self._get_ctx(repo, commit_id)
329 ctx = self._get_ctx(repo, commit_id)
330 return [child.hex() for child in ctx.children()
330 return [child.hex() for child in ctx.children()
331 if not (child.hidden() or child.obsolete())]
331 if not (child.hidden() or child.obsolete())]
332
332
333 return _ctx_children(repo_id, commit_id)
333 return _ctx_children(repo_id, commit_id)
334
334
335 @reraise_safe_exceptions
335 @reraise_safe_exceptions
336 def ctx_phase(self, wire, commit_id):
336 def ctx_phase(self, wire, commit_id):
337 cache_on, context_uid, repo_id = self._cache_on(wire)
337 cache_on, context_uid, repo_id = self._cache_on(wire)
338 region = self._region(wire)
338 region = self._region(wire)
339 @region.conditional_cache_on_arguments(condition=cache_on)
339 @region.conditional_cache_on_arguments(condition=cache_on)
340 def _ctx_phase(_context_uid, _repo_id, _commit_id):
340 def _ctx_phase(_context_uid, _repo_id, _commit_id):
341 repo = self._factory.repo(wire)
341 repo = self._factory.repo(wire)
342 ctx = self._get_ctx(repo, commit_id)
342 ctx = self._get_ctx(repo, commit_id)
343 # public=0, draft=1, secret=3
343 # public=0, draft=1, secret=3
344 return ctx.phase()
344 return ctx.phase()
345 return _ctx_phase(context_uid, repo_id, commit_id)
345 return _ctx_phase(context_uid, repo_id, commit_id)
346
346
347 @reraise_safe_exceptions
347 @reraise_safe_exceptions
348 def ctx_obsolete(self, wire, commit_id):
348 def ctx_obsolete(self, wire, commit_id):
349 cache_on, context_uid, repo_id = self._cache_on(wire)
349 cache_on, context_uid, repo_id = self._cache_on(wire)
350 region = self._region(wire)
350 region = self._region(wire)
351 @region.conditional_cache_on_arguments(condition=cache_on)
351 @region.conditional_cache_on_arguments(condition=cache_on)
352 def _ctx_obsolete(_context_uid, _repo_id, _commit_id):
352 def _ctx_obsolete(_context_uid, _repo_id, _commit_id):
353 repo = self._factory.repo(wire)
353 repo = self._factory.repo(wire)
354 ctx = self._get_ctx(repo, commit_id)
354 ctx = self._get_ctx(repo, commit_id)
355 return ctx.obsolete()
355 return ctx.obsolete()
356 return _ctx_obsolete(context_uid, repo_id, commit_id)
356 return _ctx_obsolete(context_uid, repo_id, commit_id)
357
357
358 @reraise_safe_exceptions
358 @reraise_safe_exceptions
359 def ctx_hidden(self, wire, commit_id):
359 def ctx_hidden(self, wire, commit_id):
360 cache_on, context_uid, repo_id = self._cache_on(wire)
360 cache_on, context_uid, repo_id = self._cache_on(wire)
361 region = self._region(wire)
361 region = self._region(wire)
362 @region.conditional_cache_on_arguments(condition=cache_on)
362 @region.conditional_cache_on_arguments(condition=cache_on)
363 def _ctx_hidden(_context_uid, _repo_id, _commit_id):
363 def _ctx_hidden(_context_uid, _repo_id, _commit_id):
364 repo = self._factory.repo(wire)
364 repo = self._factory.repo(wire)
365 ctx = self._get_ctx(repo, commit_id)
365 ctx = self._get_ctx(repo, commit_id)
366 return ctx.hidden()
366 return ctx.hidden()
367 return _ctx_hidden(context_uid, repo_id, commit_id)
367 return _ctx_hidden(context_uid, repo_id, commit_id)
368
368
369 @reraise_safe_exceptions
369 @reraise_safe_exceptions
370 def ctx_substate(self, wire, revision):
370 def ctx_substate(self, wire, revision):
371 repo = self._factory.repo(wire)
371 repo = self._factory.repo(wire)
372 ctx = self._get_ctx(repo, revision)
372 ctx = self._get_ctx(repo, revision)
373 return ctx.substate
373 return ctx.substate
374
374
375 @reraise_safe_exceptions
375 @reraise_safe_exceptions
376 def ctx_status(self, wire, revision):
376 def ctx_status(self, wire, revision):
377 repo = self._factory.repo(wire)
377 repo = self._factory.repo(wire)
378 ctx = self._get_ctx(repo, revision)
378 ctx = self._get_ctx(repo, revision)
379 status = repo[ctx.p1().node()].status(other=ctx.node())
379 status = repo[ctx.p1().node()].status(other=ctx.node())
380 # object of status (odd, custom named tuple in mercurial) is not
380 # object of status (odd, custom named tuple in mercurial) is not
381 # correctly serializable, we make it a list, as the underling
381 # correctly serializable, we make it a list, as the underling
382 # API expects this to be a list
382 # API expects this to be a list
383 return list(status)
383 return list(status)
384
384
385 @reraise_safe_exceptions
385 @reraise_safe_exceptions
386 def ctx_user(self, wire, revision):
386 def ctx_user(self, wire, revision):
387 repo = self._factory.repo(wire)
387 repo = self._factory.repo(wire)
388 ctx = self._get_ctx(repo, revision)
388 ctx = self._get_ctx(repo, revision)
389 return ctx.user()
389 return ctx.user()
390
390
391 @reraise_safe_exceptions
391 @reraise_safe_exceptions
392 def check_url(self, url, config):
392 def check_url(self, url, config):
393 _proto = None
393 _proto = None
394 if '+' in url[:url.find('://')]:
394 if '+' in url[:url.find('://')]:
395 _proto = url[0:url.find('+')]
395 _proto = url[0:url.find('+')]
396 url = url[url.find('+') + 1:]
396 url = url[url.find('+') + 1:]
397 handlers = []
397 handlers = []
398 url_obj = url_parser(url)
398 url_obj = url_parser(url)
399 test_uri, authinfo = url_obj.authinfo()
399 test_uri, authinfo = url_obj.authinfo()
400 url_obj.passwd = '*****' if url_obj.passwd else url_obj.passwd
400 url_obj.passwd = '*****' if url_obj.passwd else url_obj.passwd
401 url_obj.query = obfuscate_qs(url_obj.query)
401 url_obj.query = obfuscate_qs(url_obj.query)
402
402
403 cleaned_uri = str(url_obj)
403 cleaned_uri = str(url_obj)
404 log.info("Checking URL for remote cloning/import: %s", cleaned_uri)
404 log.info("Checking URL for remote cloning/import: %s", cleaned_uri)
405
405
406 if authinfo:
406 if authinfo:
407 # create a password manager
407 # create a password manager
408 passmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
408 passmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
409 passmgr.add_password(*authinfo)
409 passmgr.add_password(*authinfo)
410
410
411 handlers.extend((httpbasicauthhandler(passmgr),
411 handlers.extend((httpbasicauthhandler(passmgr),
412 httpdigestauthhandler(passmgr)))
412 httpdigestauthhandler(passmgr)))
413
413
414 o = urllib.request.build_opener(*handlers)
414 o = urllib.request.build_opener(*handlers)
415 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
415 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
416 ('Accept', 'application/mercurial-0.1')]
416 ('Accept', 'application/mercurial-0.1')]
417
417
418 q = {"cmd": 'between'}
418 q = {"cmd": 'between'}
419 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
419 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
420 qs = '?%s' % urllib.parse.urlencode(q)
420 qs = '?%s' % urllib.parse.urlencode(q)
421 cu = "%s%s" % (test_uri, qs)
421 cu = "%s%s" % (test_uri, qs)
422 req = urllib.request.Request(cu, None, {})
422 req = urllib.request.Request(cu, None, {})
423
423
424 try:
424 try:
425 log.debug("Trying to open URL %s", cleaned_uri)
425 log.debug("Trying to open URL %s", cleaned_uri)
426 resp = o.open(req)
426 resp = o.open(req)
427 if resp.code != 200:
427 if resp.code != 200:
428 raise exceptions.URLError()('Return Code is not 200')
428 raise exceptions.URLError()('Return Code is not 200')
429 except Exception as e:
429 except Exception as e:
430 log.warning("URL cannot be opened: %s", cleaned_uri, exc_info=True)
430 log.warning("URL cannot be opened: %s", cleaned_uri, exc_info=True)
431 # means it cannot be cloned
431 # means it cannot be cloned
432 raise exceptions.URLError(e)("[%s] org_exc: %s" % (cleaned_uri, e))
432 raise exceptions.URLError(e)("[%s] org_exc: %s" % (cleaned_uri, e))
433
433
434 # now check if it's a proper hg repo, but don't do it for svn
434 # now check if it's a proper hg repo, but don't do it for svn
435 try:
435 try:
436 if _proto == 'svn':
436 if _proto == 'svn':
437 pass
437 pass
438 else:
438 else:
439 # check for pure hg repos
439 # check for pure hg repos
440 log.debug(
440 log.debug(
441 "Verifying if URL is a Mercurial repository: %s",
441 "Verifying if URL is a Mercurial repository: %s",
442 cleaned_uri)
442 cleaned_uri)
443 ui = make_ui_from_config(config)
443 ui = make_ui_from_config(config)
444 peer_checker = makepeer(ui, url)
444 peer_checker = makepeer(ui, url)
445 peer_checker.lookup('tip')
445 peer_checker.lookup('tip')
446 except Exception as e:
446 except Exception as e:
447 log.warning("URL is not a valid Mercurial repository: %s",
447 log.warning("URL is not a valid Mercurial repository: %s",
448 cleaned_uri)
448 cleaned_uri)
449 raise exceptions.URLError(e)(
449 raise exceptions.URLError(e)(
450 "url [%s] does not look like an hg repo org_exc: %s"
450 "url [%s] does not look like an hg repo org_exc: %s"
451 % (cleaned_uri, e))
451 % (cleaned_uri, e))
452
452
453 log.info("URL is a valid Mercurial repository: %s", cleaned_uri)
453 log.info("URL is a valid Mercurial repository: %s", cleaned_uri)
454 return True
454 return True
455
455
456 @reraise_safe_exceptions
456 @reraise_safe_exceptions
457 def diff(self, wire, commit_id_1, commit_id_2, file_filter, opt_git, opt_ignorews, context):
457 def diff(self, wire, commit_id_1, commit_id_2, file_filter, opt_git, opt_ignorews, context):
458 repo = self._factory.repo(wire)
458 repo = self._factory.repo(wire)
459
459
460 if file_filter:
460 if file_filter:
461 match_filter = match(file_filter[0], '', [file_filter[1]])
461 match_filter = match(file_filter[0], '', [file_filter[1]])
462 else:
462 else:
463 match_filter = file_filter
463 match_filter = file_filter
464 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context, showfunc=1)
464 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context, showfunc=1)
465
465
466 try:
466 try:
467 return "".join(patch.diff(
467 return "".join(patch.diff(
468 repo, node1=commit_id_1, node2=commit_id_2, match=match_filter, opts=opts))
468 repo, node1=commit_id_1, node2=commit_id_2, match=match_filter, opts=opts))
469 except RepoLookupError as e:
469 except RepoLookupError as e:
470 raise exceptions.LookupException(e)()
470 raise exceptions.LookupException(e)()
471
471
472 @reraise_safe_exceptions
472 @reraise_safe_exceptions
473 def node_history(self, wire, revision, path, limit):
473 def node_history(self, wire, revision, path, limit):
474 cache_on, context_uid, repo_id = self._cache_on(wire)
474 cache_on, context_uid, repo_id = self._cache_on(wire)
475 region = self._region(wire)
475 region = self._region(wire)
476
476
477 @region.conditional_cache_on_arguments(condition=cache_on)
477 @region.conditional_cache_on_arguments(condition=cache_on)
478 def _node_history(_context_uid, _repo_id, _revision, _path, _limit):
478 def _node_history(_context_uid, _repo_id, _revision, _path, _limit):
479 repo = self._factory.repo(wire)
479 repo = self._factory.repo(wire)
480
480
481 ctx = self._get_ctx(repo, revision)
481 ctx = self._get_ctx(repo, revision)
482 fctx = ctx.filectx(path)
482 fctx = ctx.filectx(safe_bytes(path))
483
483
484 def history_iter():
484 def history_iter():
485 limit_rev = fctx.rev()
485 limit_rev = fctx.rev()
486 for obj in reversed(list(fctx.filelog())):
486 for obj in reversed(list(fctx.filelog())):
487 obj = fctx.filectx(obj)
487 obj = fctx.filectx(obj)
488 ctx = obj.changectx()
488 ctx = obj.changectx()
489 if ctx.hidden() or ctx.obsolete():
489 if ctx.hidden() or ctx.obsolete():
490 continue
490 continue
491
491
492 if limit_rev >= obj.rev():
492 if limit_rev >= obj.rev():
493 yield obj
493 yield obj
494
494
495 history = []
495 history = []
496 for cnt, obj in enumerate(history_iter()):
496 for cnt, obj in enumerate(history_iter()):
497 if limit and cnt >= limit:
497 if limit and cnt >= limit:
498 break
498 break
499 history.append(hex(obj.node()))
499 history.append(hex(obj.node()))
500
500
501 return [x for x in history]
501 return [x for x in history]
502 return _node_history(context_uid, repo_id, revision, path, limit)
502 return _node_history(context_uid, repo_id, revision, path, limit)
503
503
504 @reraise_safe_exceptions
504 @reraise_safe_exceptions
505 def node_history_untill(self, wire, revision, path, limit):
505 def node_history_untill(self, wire, revision, path, limit):
506 cache_on, context_uid, repo_id = self._cache_on(wire)
506 cache_on, context_uid, repo_id = self._cache_on(wire)
507 region = self._region(wire)
507 region = self._region(wire)
508
508
509 @region.conditional_cache_on_arguments(condition=cache_on)
509 @region.conditional_cache_on_arguments(condition=cache_on)
510 def _node_history_until(_context_uid, _repo_id):
510 def _node_history_until(_context_uid, _repo_id):
511 repo = self._factory.repo(wire)
511 repo = self._factory.repo(wire)
512 ctx = self._get_ctx(repo, revision)
512 ctx = self._get_ctx(repo, revision)
513 fctx = ctx.filectx(path)
513 fctx = ctx.filectx(safe_bytes(path))
514
514
515 file_log = list(fctx.filelog())
515 file_log = list(fctx.filelog())
516 if limit:
516 if limit:
517 # Limit to the last n items
517 # Limit to the last n items
518 file_log = file_log[-limit:]
518 file_log = file_log[-limit:]
519
519
520 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
520 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
521 return _node_history_until(context_uid, repo_id, revision, path, limit)
521 return _node_history_until(context_uid, repo_id, revision, path, limit)
522
522
523 @reraise_safe_exceptions
523 @reraise_safe_exceptions
524 def fctx_annotate(self, wire, revision, path):
524 def fctx_annotate(self, wire, revision, path):
525 repo = self._factory.repo(wire)
525 repo = self._factory.repo(wire)
526 ctx = self._get_ctx(repo, revision)
526 ctx = self._get_ctx(repo, revision)
527 fctx = ctx.filectx(path)
527 fctx = ctx.filectx(safe_bytes(path))
528
528
529 result = []
529 result = []
530 for i, annotate_obj in enumerate(fctx.annotate(), 1):
530 for i, annotate_obj in enumerate(fctx.annotate(), 1):
531 ln_no = i
531 ln_no = i
532 sha = hex(annotate_obj.fctx.node())
532 sha = hex(annotate_obj.fctx.node())
533 content = annotate_obj.text
533 content = annotate_obj.text
534 result.append((ln_no, sha, content))
534 result.append((ln_no, sha, content))
535 return result
535 return result
536
536
537 @reraise_safe_exceptions
537 @reraise_safe_exceptions
538 def fctx_node_data(self, wire, revision, path):
538 def fctx_node_data(self, wire, revision, path):
539 repo = self._factory.repo(wire)
539 repo = self._factory.repo(wire)
540 ctx = self._get_ctx(repo, revision)
540 ctx = self._get_ctx(repo, revision)
541 fctx = ctx.filectx(path)
541 fctx = ctx.filectx(safe_bytes(path))
542 return fctx.data_queue()
542 return fctx.data()
543
543
544 @reraise_safe_exceptions
544 @reraise_safe_exceptions
545 def fctx_flags(self, wire, commit_id, path):
545 def fctx_flags(self, wire, commit_id, path):
546 cache_on, context_uid, repo_id = self._cache_on(wire)
546 cache_on, context_uid, repo_id = self._cache_on(wire)
547 region = self._region(wire)
547 region = self._region(wire)
548
548 @region.conditional_cache_on_arguments(condition=cache_on)
549 @region.conditional_cache_on_arguments(condition=cache_on)
549 def _fctx_flags(_repo_id, _commit_id, _path):
550 def _fctx_flags(_repo_id, _commit_id, _path):
550 repo = self._factory.repo(wire)
551 repo = self._factory.repo(wire)
551 ctx = self._get_ctx(repo, commit_id)
552 ctx = self._get_ctx(repo, commit_id)
552 fctx = ctx.filectx(path)
553 fctx = ctx.filectx(safe_bytes(path))
553 return fctx.flags()
554 return fctx.flags()
554
555
555 return _fctx_flags(repo_id, commit_id, path)
556 return _fctx_flags(repo_id, commit_id, path)
556
557
557 @reraise_safe_exceptions
558 @reraise_safe_exceptions
558 def fctx_size(self, wire, commit_id, path):
559 def fctx_size(self, wire, commit_id, path):
559 cache_on, context_uid, repo_id = self._cache_on(wire)
560 cache_on, context_uid, repo_id = self._cache_on(wire)
560 region = self._region(wire)
561 region = self._region(wire)
562
561 @region.conditional_cache_on_arguments(condition=cache_on)
563 @region.conditional_cache_on_arguments(condition=cache_on)
562 def _fctx_size(_repo_id, _revision, _path):
564 def _fctx_size(_repo_id, _revision, _path):
563 repo = self._factory.repo(wire)
565 repo = self._factory.repo(wire)
564 ctx = self._get_ctx(repo, commit_id)
566 ctx = self._get_ctx(repo, commit_id)
565 fctx = ctx.filectx(path)
567 fctx = ctx.filectx(safe_bytes(path))
566 return fctx.size()
568 return fctx.size()
567 return _fctx_size(repo_id, commit_id, path)
569 return _fctx_size(repo_id, commit_id, path)
568
570
569 @reraise_safe_exceptions
571 @reraise_safe_exceptions
570 def get_all_commit_ids(self, wire, name):
572 def get_all_commit_ids(self, wire, name):
571 cache_on, context_uid, repo_id = self._cache_on(wire)
573 cache_on, context_uid, repo_id = self._cache_on(wire)
572 region = self._region(wire)
574 region = self._region(wire)
573
575
574 @region.conditional_cache_on_arguments(condition=cache_on)
576 @region.conditional_cache_on_arguments(condition=cache_on)
575 def _get_all_commit_ids(_context_uid, _repo_id, _name):
577 def _get_all_commit_ids(_context_uid, _repo_id, _name):
576 repo = self._factory.repo(wire)
578 repo = self._factory.repo(wire)
577 repo = repo.filtered(name)
578 revs = [ascii_str(repo[x].hex()) for x in repo.filtered(b'visible').changelog.revs()]
579 revs = [ascii_str(repo[x].hex()) for x in repo.filtered(b'visible').changelog.revs()]
579 return revs
580 return revs
580 return _get_all_commit_ids(context_uid, repo_id, name)
581 return _get_all_commit_ids(context_uid, repo_id, name)
581
582
582 @reraise_safe_exceptions
583 @reraise_safe_exceptions
583 def get_config_value(self, wire, section, name, untrusted=False):
584 def get_config_value(self, wire, section, name, untrusted=False):
584 repo = self._factory.repo(wire)
585 repo = self._factory.repo(wire)
585 return repo.ui.config(section, name, untrusted=untrusted)
586 return repo.ui.config(section, name, untrusted=untrusted)
586
587
587 @reraise_safe_exceptions
588 @reraise_safe_exceptions
588 def is_large_file(self, wire, commit_id, path):
589 def is_large_file(self, wire, commit_id, path):
589 cache_on, context_uid, repo_id = self._cache_on(wire)
590 cache_on, context_uid, repo_id = self._cache_on(wire)
590 region = self._region(wire)
591 region = self._region(wire)
591
592
592 @region.conditional_cache_on_arguments(condition=cache_on)
593 @region.conditional_cache_on_arguments(condition=cache_on)
593 def _is_large_file(_context_uid, _repo_id, _commit_id, _path):
594 def _is_large_file(_context_uid, _repo_id, _commit_id, _path):
594 return largefiles.lfutil.isstandin(path)
595 return largefiles.lfutil.isstandin(safe_bytes(path))
595
596
596 return _is_large_file(context_uid, repo_id, commit_id, path)
597 return _is_large_file(context_uid, repo_id, commit_id, path)
597
598
598 @reraise_safe_exceptions
599 @reraise_safe_exceptions
599 def is_binary(self, wire, revision, path):
600 def is_binary(self, wire, revision, path):
600 cache_on, context_uid, repo_id = self._cache_on(wire)
601 cache_on, context_uid, repo_id = self._cache_on(wire)
601 region = self._region(wire)
602 region = self._region(wire)
602
603
603 @region.conditional_cache_on_arguments(condition=cache_on)
604 @region.conditional_cache_on_arguments(condition=cache_on)
604 def _is_binary(_repo_id, _sha, _path):
605 def _is_binary(_repo_id, _sha, _path):
605 repo = self._factory.repo(wire)
606 repo = self._factory.repo(wire)
606 ctx = self._get_ctx(repo, revision)
607 ctx = self._get_ctx(repo, revision)
607 fctx = ctx.filectx(path)
608 fctx = ctx.filectx(safe_bytes(path))
608 return fctx.isbinary()
609 return fctx.isbinary()
609
610
610 return _is_binary(repo_id, revision, path)
611 return _is_binary(repo_id, revision, path)
611
612
612 @reraise_safe_exceptions
613 @reraise_safe_exceptions
613 def in_largefiles_store(self, wire, sha):
614 def in_largefiles_store(self, wire, sha):
614 repo = self._factory.repo(wire)
615 repo = self._factory.repo(wire)
615 return largefiles.lfutil.instore(repo, sha)
616 return largefiles.lfutil.instore(repo, sha)
616
617
617 @reraise_safe_exceptions
618 @reraise_safe_exceptions
618 def in_user_cache(self, wire, sha):
619 def in_user_cache(self, wire, sha):
619 repo = self._factory.repo(wire)
620 repo = self._factory.repo(wire)
620 return largefiles.lfutil.inusercache(repo.ui, sha)
621 return largefiles.lfutil.inusercache(repo.ui, sha)
621
622
622 @reraise_safe_exceptions
623 @reraise_safe_exceptions
623 def store_path(self, wire, sha):
624 def store_path(self, wire, sha):
624 repo = self._factory.repo(wire)
625 repo = self._factory.repo(wire)
625 return largefiles.lfutil.storepath(repo, sha)
626 return largefiles.lfutil.storepath(repo, sha)
626
627
627 @reraise_safe_exceptions
628 @reraise_safe_exceptions
628 def link(self, wire, sha, path):
629 def link(self, wire, sha, path):
629 repo = self._factory.repo(wire)
630 repo = self._factory.repo(wire)
630 largefiles.lfutil.link(
631 largefiles.lfutil.link(
631 largefiles.lfutil.usercachepath(repo.ui, sha), path)
632 largefiles.lfutil.usercachepath(repo.ui, sha), path)
632
633
633 @reraise_safe_exceptions
634 @reraise_safe_exceptions
634 def localrepository(self, wire, create=False):
635 def localrepository(self, wire, create=False):
635 self._factory.repo(wire, create=create)
636 self._factory.repo(wire, create=create)
636
637
637 @reraise_safe_exceptions
638 @reraise_safe_exceptions
638 def lookup(self, wire, revision, both):
639 def lookup(self, wire, revision, both):
639 cache_on, context_uid, repo_id = self._cache_on(wire)
640 cache_on, context_uid, repo_id = self._cache_on(wire)
641 region = self._region(wire)
640
642
641 region = self._region(wire)
642 @region.conditional_cache_on_arguments(condition=cache_on)
643 @region.conditional_cache_on_arguments(condition=cache_on)
643 def _lookup(_context_uid, _repo_id, _revision, _both):
644 def _lookup(_context_uid, _repo_id, _revision, _both):
644
645
645 repo = self._factory.repo(wire)
646 repo = self._factory.repo(wire)
646 rev = _revision
647 rev = _revision
647 if isinstance(rev, int):
648 if isinstance(rev, int):
648 # NOTE(marcink):
649 # NOTE(marcink):
649 # since Mercurial doesn't support negative indexes properly
650 # since Mercurial doesn't support negative indexes properly
650 # we need to shift accordingly by one to get proper index, e.g
651 # we need to shift accordingly by one to get proper index, e.g
651 # repo[-1] => repo[-2]
652 # repo[-1] => repo[-2]
652 # repo[0] => repo[-1]
653 # repo[0] => repo[-1]
653 if rev <= 0:
654 if rev <= 0:
654 rev = rev + -1
655 rev = rev + -1
655 try:
656 try:
656 ctx = self._get_ctx(repo, rev)
657 ctx = self._get_ctx(repo, rev)
657 except (TypeError, RepoLookupError) as e:
658 except (TypeError, RepoLookupError) as e:
658 e._org_exc_tb = traceback.format_exc()
659 e._org_exc_tb = traceback.format_exc()
659 raise exceptions.LookupException(e)(rev)
660 raise exceptions.LookupException(e)(rev)
660 except LookupError as e:
661 except LookupError as e:
661 e._org_exc_tb = traceback.format_exc()
662 e._org_exc_tb = traceback.format_exc()
662 raise exceptions.LookupException(e)(e.name)
663 raise exceptions.LookupException(e)(e.name)
663
664
664 if not both:
665 if not both:
665 return ctx.hex()
666 return ctx.hex()
666
667
667 ctx = repo[ctx.hex()]
668 ctx = repo[ctx.hex()]
668 return ctx.hex(), ctx.rev()
669 return ctx.hex(), ctx.rev()
669
670
670 return _lookup(context_uid, repo_id, revision, both)
671 return _lookup(context_uid, repo_id, revision, both)
671
672
672 @reraise_safe_exceptions
673 @reraise_safe_exceptions
673 def sync_push(self, wire, url):
674 def sync_push(self, wire, url):
674 if not self.check_url(url, wire['config']):
675 if not self.check_url(url, wire['config']):
675 return
676 return
676
677
677 repo = self._factory.repo(wire)
678 repo = self._factory.repo(wire)
678
679
679 # Disable any prompts for this repo
680 # Disable any prompts for this repo
680 repo.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
681 repo.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
681
682
682 bookmarks = list(dict(repo._bookmarks).keys())
683 bookmarks = list(dict(repo._bookmarks).keys())
683 remote = peer(repo, {}, url)
684 remote = peer(repo, {}, url)
684 # Disable any prompts for this remote
685 # Disable any prompts for this remote
685 remote.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
686 remote.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
686
687
687 return exchange.push(
688 return exchange.push(
688 repo, remote, newbranch=True, bookmarks=bookmarks).cgresult
689 repo, remote, newbranch=True, bookmarks=bookmarks).cgresult
689
690
690 @reraise_safe_exceptions
691 @reraise_safe_exceptions
691 def revision(self, wire, rev):
692 def revision(self, wire, rev):
692 repo = self._factory.repo(wire)
693 repo = self._factory.repo(wire)
693 ctx = self._get_ctx(repo, rev)
694 ctx = self._get_ctx(repo, rev)
694 return ctx.rev()
695 return ctx.rev()
695
696
696 @reraise_safe_exceptions
697 @reraise_safe_exceptions
697 def rev_range(self, wire, commit_filter):
698 def rev_range(self, wire, commit_filter):
698 cache_on, context_uid, repo_id = self._cache_on(wire)
699 cache_on, context_uid, repo_id = self._cache_on(wire)
700 region = self._region(wire)
699
701
700 region = self._region(wire)
701 @region.conditional_cache_on_arguments(condition=cache_on)
702 @region.conditional_cache_on_arguments(condition=cache_on)
702 def _rev_range(_context_uid, _repo_id, _filter):
703 def _rev_range(_context_uid, _repo_id, _filter):
703 repo = self._factory.repo(wire)
704 repo = self._factory.repo(wire)
704 revisions = [rev for rev in revrange(repo, commit_filter)]
705 revisions = [
706 ascii_str(repo[rev].hex())
707 for rev in revrange(repo, list(map(ascii_bytes, commit_filter)))
708 ]
705 return revisions
709 return revisions
706
710
707 return _rev_range(context_uid, repo_id, sorted(commit_filter))
711 return _rev_range(context_uid, repo_id, sorted(commit_filter))
708
712
709 @reraise_safe_exceptions
713 @reraise_safe_exceptions
710 def rev_range_hash(self, wire, node):
714 def rev_range_hash(self, wire, node):
711 repo = self._factory.repo(wire)
715 repo = self._factory.repo(wire)
712
716
713 def get_revs(repo, rev_opt):
717 def get_revs(repo, rev_opt):
714 if rev_opt:
718 if rev_opt:
715 revs = revrange(repo, rev_opt)
719 revs = revrange(repo, rev_opt)
716 if len(revs) == 0:
720 if len(revs) == 0:
717 return (nullrev, nullrev)
721 return (nullrev, nullrev)
718 return max(revs), min(revs)
722 return max(revs), min(revs)
719 else:
723 else:
720 return len(repo) - 1, 0
724 return len(repo) - 1, 0
721
725
722 stop, start = get_revs(repo, [node + ':'])
726 stop, start = get_revs(repo, [node + ':'])
723 revs = [hex(repo[r].node()) for r in range(start, stop + 1)]
727 revs = [ascii_str(repo[r].hex()) for r in range(start, stop + 1)]
724 return revs
728 return revs
725
729
726 @reraise_safe_exceptions
730 @reraise_safe_exceptions
727 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
731 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
728 other_path = kwargs.pop('other_path', None)
732 other_path = kwargs.pop('other_path', None)
729
733
730 # case when we want to compare two independent repositories
734 # case when we want to compare two independent repositories
731 if other_path and other_path != wire["path"]:
735 if other_path and other_path != wire["path"]:
732 baseui = self._factory._create_config(wire["config"])
736 baseui = self._factory._create_config(wire["config"])
733 repo = unionrepo.makeunionrepository(baseui, other_path, wire["path"])
737 repo = unionrepo.makeunionrepository(baseui, other_path, wire["path"])
734 else:
738 else:
735 repo = self._factory.repo(wire)
739 repo = self._factory.repo(wire)
736 return list(repo.revs(rev_spec, *args))
740 return list(repo.revs(rev_spec, *args))
737
741
738 @reraise_safe_exceptions
742 @reraise_safe_exceptions
739 def verify(self, wire,):
743 def verify(self, wire,):
740 repo = self._factory.repo(wire)
744 repo = self._factory.repo(wire)
741 baseui = self._factory._create_config(wire['config'])
745 baseui = self._factory._create_config(wire['config'])
742
746
743 baseui, output = patch_ui_message_output(baseui)
747 baseui, output = patch_ui_message_output(baseui)
744
748
745 repo.ui = baseui
749 repo.ui = baseui
746 verify.verify(repo)
750 verify.verify(repo)
747 return output.getvalue()
751 return output.getvalue()
748
752
749 @reraise_safe_exceptions
753 @reraise_safe_exceptions
750 def hg_update_cache(self, wire,):
754 def hg_update_cache(self, wire,):
751 repo = self._factory.repo(wire)
755 repo = self._factory.repo(wire)
752 baseui = self._factory._create_config(wire['config'])
756 baseui = self._factory._create_config(wire['config'])
753 baseui, output = patch_ui_message_output(baseui)
757 baseui, output = patch_ui_message_output(baseui)
754
758
755 repo.ui = baseui
759 repo.ui = baseui
756 with repo.wlock(), repo.lock():
760 with repo.wlock(), repo.lock():
757 repo.updatecaches(full=True)
761 repo.updatecaches(full=True)
758
762
759 return output.getvalue()
763 return output.getvalue()
760
764
761 @reraise_safe_exceptions
765 @reraise_safe_exceptions
762 def hg_rebuild_fn_cache(self, wire,):
766 def hg_rebuild_fn_cache(self, wire,):
763 repo = self._factory.repo(wire)
767 repo = self._factory.repo(wire)
764 baseui = self._factory._create_config(wire['config'])
768 baseui = self._factory._create_config(wire['config'])
765 baseui, output = patch_ui_message_output(baseui)
769 baseui, output = patch_ui_message_output(baseui)
766
770
767 repo.ui = baseui
771 repo.ui = baseui
768
772
769 repair.rebuildfncache(baseui, repo)
773 repair.rebuildfncache(baseui, repo)
770
774
771 return output.getvalue()
775 return output.getvalue()
772
776
773 @reraise_safe_exceptions
777 @reraise_safe_exceptions
774 def tags(self, wire):
778 def tags(self, wire):
775 cache_on, context_uid, repo_id = self._cache_on(wire)
779 cache_on, context_uid, repo_id = self._cache_on(wire)
776 region = self._region(wire)
780 region = self._region(wire)
781
777 @region.conditional_cache_on_arguments(condition=cache_on)
782 @region.conditional_cache_on_arguments(condition=cache_on)
778 def _tags(_context_uid, _repo_id):
783 def _tags(_context_uid, _repo_id):
779 repo = self._factory.repo(wire)
784 repo = self._factory.repo(wire)
780 return repo.tags()
785 return repo.tags()
781
786
782 return _tags(context_uid, repo_id)
787 return _tags(context_uid, repo_id)
783
788
784 @reraise_safe_exceptions
789 @reraise_safe_exceptions
785 def update(self, wire, node=None, clean=False):
790 def update(self, wire, node=None, clean=False):
786 repo = self._factory.repo(wire)
791 repo = self._factory.repo(wire)
787 baseui = self._factory._create_config(wire['config'])
792 baseui = self._factory._create_config(wire['config'])
788 commands.update(baseui, repo, node=node, clean=clean)
793 commands.update(baseui, repo, node=node, clean=clean)
789
794
790 @reraise_safe_exceptions
795 @reraise_safe_exceptions
791 def identify(self, wire):
796 def identify(self, wire):
792 repo = self._factory.repo(wire)
797 repo = self._factory.repo(wire)
793 baseui = self._factory._create_config(wire['config'])
798 baseui = self._factory._create_config(wire['config'])
794 output = io.BytesIO()
799 output = io.BytesIO()
795 baseui.write = output.write
800 baseui.write = output.write
796 # This is required to get a full node id
801 # This is required to get a full node id
797 baseui.debugflag = True
802 baseui.debugflag = True
798 commands.identify(baseui, repo, id=True)
803 commands.identify(baseui, repo, id=True)
799
804
800 return output.getvalue()
805 return output.getvalue()
801
806
802 @reraise_safe_exceptions
807 @reraise_safe_exceptions
803 def heads(self, wire, branch=None):
808 def heads(self, wire, branch=None):
804 repo = self._factory.repo(wire)
809 repo = self._factory.repo(wire)
805 baseui = self._factory._create_config(wire['config'])
810 baseui = self._factory._create_config(wire['config'])
806 output = io.BytesIO()
811 output = io.BytesIO()
807
812
808 def write(data, **unused_kwargs):
813 def write(data, **unused_kwargs):
809 output.write(data)
814 output.write(data)
810
815
811 baseui.write = write
816 baseui.write = write
812 if branch:
817 if branch:
813 args = [branch]
818 args = [branch]
814 else:
819 else:
815 args = []
820 args = []
816 commands.heads(baseui, repo, template='{node} ', *args)
821 commands.heads(baseui, repo, template='{node} ', *args)
817
822
818 return output.getvalue()
823 return output.getvalue()
819
824
820 @reraise_safe_exceptions
825 @reraise_safe_exceptions
821 def ancestor(self, wire, revision1, revision2):
826 def ancestor(self, wire, revision1, revision2):
822 repo = self._factory.repo(wire)
827 repo = self._factory.repo(wire)
823 changelog = repo.changelog
828 changelog = repo.changelog
824 lookup = repo.lookup
829 lookup = repo.lookup
825 a = changelog.ancestor(lookup(revision1), lookup(revision2))
830 a = changelog.ancestor(lookup(revision1), lookup(revision2))
826 return hex(a)
831 return hex(a)
827
832
828 @reraise_safe_exceptions
833 @reraise_safe_exceptions
829 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
834 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
830 baseui = self._factory._create_config(wire["config"], hooks=hooks)
835 baseui = self._factory._create_config(wire["config"], hooks=hooks)
831 clone(baseui, source, dest, noupdate=not update_after_clone)
836 clone(baseui, source, dest, noupdate=not update_after_clone)
832
837
833 @reraise_safe_exceptions
838 @reraise_safe_exceptions
834 def commitctx(self, wire, message, parents, commit_time, commit_timezone, user, files, extra, removed, updated):
839 def commitctx(self, wire, message, parents, commit_time, commit_timezone, user, files, extra, removed, updated):
835
840
836 repo = self._factory.repo(wire)
841 repo = self._factory.repo(wire)
837 baseui = self._factory._create_config(wire['config'])
842 baseui = self._factory._create_config(wire['config'])
838 publishing = baseui.configbool('phases', 'publish')
843 publishing = baseui.configbool('phases', 'publish')
839 if publishing:
844 if publishing:
840 new_commit = 'public'
845 new_commit = 'public'
841 else:
846 else:
842 new_commit = 'draft'
847 new_commit = 'draft'
843
848
844 def _filectxfn(_repo, ctx, path):
849 def _filectxfn(_repo, ctx, path):
845 """
850 """
846 Marks given path as added/changed/removed in a given _repo. This is
851 Marks given path as added/changed/removed in a given _repo. This is
847 for internal mercurial commit function.
852 for internal mercurial commit function.
848 """
853 """
849
854
850 # check if this path is removed
855 # check if this path is removed
851 if path in removed:
856 if path in removed:
852 # returning None is a way to mark node for removal
857 # returning None is a way to mark node for removal
853 return None
858 return None
854
859
855 # check if this path is added
860 # check if this path is added
856 for node in updated:
861 for node in updated:
857 if node['path'] == path:
862 if node['path'] == path:
858 return memfilectx(
863 return memfilectx(
859 _repo,
864 _repo,
860 changectx=ctx,
865 changectx=ctx,
861 path=node['path'],
866 path=node['path'],
862 data=node['content'],
867 data=node['content'],
863 islink=False,
868 islink=False,
864 isexec=bool(node['mode'] & stat.S_IXUSR),
869 isexec=bool(node['mode'] & stat.S_IXUSR),
865 copysource=False)
870 copysource=False)
866
871
867 raise exceptions.AbortException()(
872 raise exceptions.AbortException()(
868 "Given path haven't been marked as added, "
873 "Given path haven't been marked as added, "
869 "changed or removed (%s)" % path)
874 "changed or removed (%s)" % path)
870
875
871 with repo.ui.configoverride({('phases', 'new-commit'): new_commit}):
876 with repo.ui.configoverride({('phases', 'new-commit'): new_commit}):
872
877
873 commit_ctx = memctx(
878 commit_ctx = memctx(
874 repo=repo,
879 repo=repo,
875 parents=parents,
880 parents=parents,
876 text=message,
881 text=message,
877 files=files,
882 files=files,
878 filectxfn=_filectxfn,
883 filectxfn=_filectxfn,
879 user=user,
884 user=user,
880 date=(commit_time, commit_timezone),
885 date=(commit_time, commit_timezone),
881 extra=extra)
886 extra=extra)
882
887
883 n = repo.commitctx(commit_ctx)
888 n = repo.commitctx(commit_ctx)
884 new_id = hex(n)
889 new_id = hex(n)
885
890
886 return new_id
891 return new_id
887
892
888 @reraise_safe_exceptions
893 @reraise_safe_exceptions
889 def pull(self, wire, url, commit_ids=None):
894 def pull(self, wire, url, commit_ids=None):
890 repo = self._factory.repo(wire)
895 repo = self._factory.repo(wire)
891 # Disable any prompts for this repo
896 # Disable any prompts for this repo
892 repo.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
897 repo.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
893
898
894 remote = peer(repo, {}, url)
899 remote = peer(repo, {}, url)
895 # Disable any prompts for this remote
900 # Disable any prompts for this remote
896 remote.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
901 remote.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
897
902
898 if commit_ids:
903 if commit_ids:
899 commit_ids = [bin(commit_id) for commit_id in commit_ids]
904 commit_ids = [bin(commit_id) for commit_id in commit_ids]
900
905
901 return exchange.pull(
906 return exchange.pull(
902 repo, remote, heads=commit_ids, force=None).cgresult
907 repo, remote, heads=commit_ids, force=None).cgresult
903
908
904 @reraise_safe_exceptions
909 @reraise_safe_exceptions
905 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None, hooks=True):
910 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None, hooks=True):
906 repo = self._factory.repo(wire)
911 repo = self._factory.repo(wire)
907 baseui = self._factory._create_config(wire['config'], hooks=hooks)
912 baseui = self._factory._create_config(wire['config'], hooks=hooks)
908
913
909 # Mercurial internally has a lot of logic that checks ONLY if
914 # Mercurial internally has a lot of logic that checks ONLY if
910 # option is defined, we just pass those if they are defined then
915 # option is defined, we just pass those if they are defined then
911 opts = {}
916 opts = {}
912 if bookmark:
917 if bookmark:
913 opts['bookmark'] = bookmark
918 opts['bookmark'] = bookmark
914 if branch:
919 if branch:
915 opts['branch'] = branch
920 opts['branch'] = branch
916 if revision:
921 if revision:
917 opts['rev'] = revision
922 opts['rev'] = revision
918
923
919 commands.pull(baseui, repo, source, **opts)
924 commands.pull(baseui, repo, source, **opts)
920
925
921 @reraise_safe_exceptions
926 @reraise_safe_exceptions
922 def push(self, wire, revisions, dest_path, hooks=True, push_branches=False):
927 def push(self, wire, revisions, dest_path, hooks=True, push_branches=False):
923 repo = self._factory.repo(wire)
928 repo = self._factory.repo(wire)
924 baseui = self._factory._create_config(wire['config'], hooks=hooks)
929 baseui = self._factory._create_config(wire['config'], hooks=hooks)
925 commands.push(baseui, repo, dest=dest_path, rev=revisions,
930 commands.push(baseui, repo, dest=dest_path, rev=revisions,
926 new_branch=push_branches)
931 new_branch=push_branches)
927
932
928 @reraise_safe_exceptions
933 @reraise_safe_exceptions
929 def strip(self, wire, revision, update, backup):
934 def strip(self, wire, revision, update, backup):
930 repo = self._factory.repo(wire)
935 repo = self._factory.repo(wire)
931 ctx = self._get_ctx(repo, revision)
936 ctx = self._get_ctx(repo, revision)
932 hgext_strip(
937 hgext_strip(
933 repo.baseui, repo, ctx.node(), update=update, backup=backup)
938 repo.baseui, repo, ctx.node(), update=update, backup=backup)
934
939
935 @reraise_safe_exceptions
940 @reraise_safe_exceptions
936 def get_unresolved_files(self, wire):
941 def get_unresolved_files(self, wire):
937 repo = self._factory.repo(wire)
942 repo = self._factory.repo(wire)
938
943
939 log.debug('Calculating unresolved files for repo: %s', repo)
944 log.debug('Calculating unresolved files for repo: %s', repo)
940 output = io.BytesIO()
945 output = io.BytesIO()
941
946
942 def write(data, **unused_kwargs):
947 def write(data, **unused_kwargs):
943 output.write(data)
948 output.write(data)
944
949
945 baseui = self._factory._create_config(wire['config'])
950 baseui = self._factory._create_config(wire['config'])
946 baseui.write = write
951 baseui.write = write
947
952
948 commands.resolve(baseui, repo, list=True)
953 commands.resolve(baseui, repo, list=True)
949 unresolved = output.getvalue().splitlines(0)
954 unresolved = output.getvalue().splitlines(0)
950 return unresolved
955 return unresolved
951
956
952 @reraise_safe_exceptions
957 @reraise_safe_exceptions
953 def merge(self, wire, revision):
958 def merge(self, wire, revision):
954 repo = self._factory.repo(wire)
959 repo = self._factory.repo(wire)
955 baseui = self._factory._create_config(wire['config'])
960 baseui = self._factory._create_config(wire['config'])
956 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
961 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
957
962
958 # In case of sub repositories are used mercurial prompts the user in
963 # In case of sub repositories are used mercurial prompts the user in
959 # case of merge conflicts or different sub repository sources. By
964 # case of merge conflicts or different sub repository sources. By
960 # setting the interactive flag to `False` mercurial doesn't prompt the
965 # setting the interactive flag to `False` mercurial doesn't prompt the
961 # used but instead uses a default value.
966 # used but instead uses a default value.
962 repo.ui.setconfig(b'ui', b'interactive', False)
967 repo.ui.setconfig(b'ui', b'interactive', False)
963 commands.merge(baseui, repo, rev=revision)
968 commands.merge(baseui, repo, rev=revision)
964
969
965 @reraise_safe_exceptions
970 @reraise_safe_exceptions
966 def merge_state(self, wire):
971 def merge_state(self, wire):
967 repo = self._factory.repo(wire)
972 repo = self._factory.repo(wire)
968 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
973 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
969
974
970 # In case of sub repositories are used mercurial prompts the user in
975 # In case of sub repositories are used mercurial prompts the user in
971 # case of merge conflicts or different sub repository sources. By
976 # case of merge conflicts or different sub repository sources. By
972 # setting the interactive flag to `False` mercurial doesn't prompt the
977 # setting the interactive flag to `False` mercurial doesn't prompt the
973 # used but instead uses a default value.
978 # used but instead uses a default value.
974 repo.ui.setconfig(b'ui', b'interactive', False)
979 repo.ui.setconfig(b'ui', b'interactive', False)
975 ms = hg_merge.mergestate(repo)
980 ms = hg_merge.mergestate(repo)
976 return [x for x in ms.unresolved()]
981 return [x for x in ms.unresolved()]
977
982
978 @reraise_safe_exceptions
983 @reraise_safe_exceptions
979 def commit(self, wire, message, username, close_branch=False):
984 def commit(self, wire, message, username, close_branch=False):
980 repo = self._factory.repo(wire)
985 repo = self._factory.repo(wire)
981 baseui = self._factory._create_config(wire['config'])
986 baseui = self._factory._create_config(wire['config'])
982 repo.ui.setconfig(b'ui', b'username', username)
987 repo.ui.setconfig(b'ui', b'username', username)
983 commands.commit(baseui, repo, message=message, close_branch=close_branch)
988 commands.commit(baseui, repo, message=message, close_branch=close_branch)
984
989
985 @reraise_safe_exceptions
990 @reraise_safe_exceptions
986 def rebase(self, wire, source=None, dest=None, abort=False):
991 def rebase(self, wire, source=None, dest=None, abort=False):
987 repo = self._factory.repo(wire)
992 repo = self._factory.repo(wire)
988 baseui = self._factory._create_config(wire['config'])
993 baseui = self._factory._create_config(wire['config'])
989 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
994 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
990 # In case of sub repositories are used mercurial prompts the user in
995 # In case of sub repositories are used mercurial prompts the user in
991 # case of merge conflicts or different sub repository sources. By
996 # case of merge conflicts or different sub repository sources. By
992 # setting the interactive flag to `False` mercurial doesn't prompt the
997 # setting the interactive flag to `False` mercurial doesn't prompt the
993 # used but instead uses a default value.
998 # used but instead uses a default value.
994 repo.ui.setconfig(b'ui', b'interactive', False)
999 repo.ui.setconfig(b'ui', b'interactive', False)
995 rebase.rebase(baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
1000 rebase.rebase(baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
996
1001
997 @reraise_safe_exceptions
1002 @reraise_safe_exceptions
998 def tag(self, wire, name, revision, message, local, user, tag_time, tag_timezone):
1003 def tag(self, wire, name, revision, message, local, user, tag_time, tag_timezone):
999 repo = self._factory.repo(wire)
1004 repo = self._factory.repo(wire)
1000 ctx = self._get_ctx(repo, revision)
1005 ctx = self._get_ctx(repo, revision)
1001 node = ctx.node()
1006 node = ctx.node()
1002
1007
1003 date = (tag_time, tag_timezone)
1008 date = (tag_time, tag_timezone)
1004 try:
1009 try:
1005 hg_tag.tag(repo, name, node, message, local, user, date)
1010 hg_tag.tag(repo, name, node, message, local, user, date)
1006 except Abort as e:
1011 except Abort as e:
1007 log.exception("Tag operation aborted")
1012 log.exception("Tag operation aborted")
1008 # Exception can contain unicode which we convert
1013 # Exception can contain unicode which we convert
1009 raise exceptions.AbortException(e)(repr(e))
1014 raise exceptions.AbortException(e)(repr(e))
1010
1015
1011 @reraise_safe_exceptions
1016 @reraise_safe_exceptions
1012 def bookmark(self, wire, bookmark, revision=None):
1017 def bookmark(self, wire, bookmark, revision=None):
1013 repo = self._factory.repo(wire)
1018 repo = self._factory.repo(wire)
1014 baseui = self._factory._create_config(wire['config'])
1019 baseui = self._factory._create_config(wire['config'])
1015 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
1020 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
1016
1021
1017 @reraise_safe_exceptions
1022 @reraise_safe_exceptions
1018 def install_hooks(self, wire, force=False):
1023 def install_hooks(self, wire, force=False):
1019 # we don't need any special hooks for Mercurial
1024 # we don't need any special hooks for Mercurial
1020 pass
1025 pass
1021
1026
1022 @reraise_safe_exceptions
1027 @reraise_safe_exceptions
1023 def get_hooks_info(self, wire):
1028 def get_hooks_info(self, wire):
1024 return {
1029 return {
1025 'pre_version': vcsserver.__version__,
1030 'pre_version': vcsserver.__version__,
1026 'post_version': vcsserver.__version__,
1031 'post_version': vcsserver.__version__,
1027 }
1032 }
1028
1033
1029 @reraise_safe_exceptions
1034 @reraise_safe_exceptions
1030 def set_head_ref(self, wire, head_name):
1035 def set_head_ref(self, wire, head_name):
1031 pass
1036 pass
1032
1037
1033 @reraise_safe_exceptions
1038 @reraise_safe_exceptions
1034 def archive_repo(self, wire, archive_dest_path, kind, mtime, archive_at_path,
1039 def archive_repo(self, wire, archive_dest_path, kind, mtime, archive_at_path,
1035 archive_dir_name, commit_id):
1040 archive_dir_name, commit_id):
1036
1041
1037 def file_walker(_commit_id, path):
1042 def file_walker(_commit_id, path):
1038 repo = self._factory.repo(wire)
1043 repo = self._factory.repo(wire)
1039 ctx = repo[_commit_id]
1044 ctx = repo[_commit_id]
1040 is_root = path in ['', '/']
1045 is_root = path in ['', '/']
1041 if is_root:
1046 if is_root:
1042 matcher = alwaysmatcher(badfn=None)
1047 matcher = alwaysmatcher(badfn=None)
1043 else:
1048 else:
1044 matcher = patternmatcher('', [(b'glob', path+'/**', b'')], badfn=None)
1049 matcher = patternmatcher('', [(b'glob', path+'/**', b'')], badfn=None)
1045 file_iter = ctx.manifest().walk(matcher)
1050 file_iter = ctx.manifest().walk(matcher)
1046
1051
1047 for fn in file_iter:
1052 for fn in file_iter:
1048 file_path = fn
1053 file_path = fn
1049 flags = ctx.flags(fn)
1054 flags = ctx.flags(fn)
1050 mode = b'x' in flags and 0o755 or 0o644
1055 mode = b'x' in flags and 0o755 or 0o644
1051 is_link = b'l' in flags
1056 is_link = b'l' in flags
1052
1057
1053 yield ArchiveNode(file_path, mode, is_link, ctx[fn].data_queue)
1058 yield ArchiveNode(file_path, mode, is_link, ctx[fn].data)
1054
1059
1055 return archive_repo(file_walker, archive_dest_path, kind, mtime, archive_at_path,
1060 return archive_repo(file_walker, archive_dest_path, kind, mtime, archive_at_path,
1056 archive_dir_name, commit_id)
1061 archive_dir_name, commit_id)
1057
1062
General Comments 0
You need to be logged in to leave comments. Login now