##// END OF EJS Templates
git/hg: skip double caching with bulk requests calls....
git/hg: skip double caching with bulk requests calls. - calling builk request which can be cached itself, would call other cached methods and that is much slower

File last commit:

r1075:8fc1778b python3
r1075:8fc1778b python3
Show More
hg.py
1087 lines | 39.7 KiB | text/x-python | PythonLexer
core: move git/svn/hg into submodule
r1043 # RhodeCode VCSServer provides access to different vcs backends via network.
# Copyright (C) 2014-2020 RhodeCode GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import io
import logging
import stat
import urllib.request, urllib.parse, urllib.error
import urllib.request, urllib.error, urllib.parse
import traceback
from hgext import largefiles, rebase, purge
from mercurial import commands
from mercurial import unionrepo
from mercurial import verify
from mercurial import repair
import vcsserver
from vcsserver import exceptions
from vcsserver.base import RepoFactory, obfuscate_qs, raise_from_original, archive_repo, ArchiveNode
from vcsserver.hgcompat import (
archival, bin, clone, config as hgconfig, diffopts, hex, get_ctx,
hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler,
makepeer, instance, match, memctx, exchange, memfilectx, nullrev, hg_merge,
patch, peer, revrange, ui, hg_tag, Abort, LookupError, RepoError,
RepoLookupError, InterventionRequired, RequirementError,
alwaysmatcher, patternmatcher, hgutil, hgext_strip)
packages: move the str utils to it's own module
r1060 from vcsserver.str_utils import ascii_bytes, ascii_str, safe_str, safe_bytes
core: move git/svn/hg into submodule
r1043 from vcsserver.vcs_base import RemoteBase
log = logging.getLogger(__name__)
def make_ui_from_config(repo_config):
class LoggingUI(ui.ui):
python3: code change for py3 support...
r1048
core: move git/svn/hg into submodule
r1043 def status(self, *msg, **opts):
python3: code change for py3 support...
r1048 str_msg = map(safe_str, msg)
log.info(' '.join(str_msg).rstrip('\n'))
#super(LoggingUI, self).status(*msg, **opts)
core: move git/svn/hg into submodule
r1043
def warn(self, *msg, **opts):
python3: code change for py3 support...
r1048 str_msg = map(safe_str, msg)
log.warning('ui_logger:'+' '.join(str_msg).rstrip('\n'))
#super(LoggingUI, self).warn(*msg, **opts)
core: move git/svn/hg into submodule
r1043
def error(self, *msg, **opts):
python3: code change for py3 support...
r1048 str_msg = map(safe_str, msg)
log.error('ui_logger:'+' '.join(str_msg).rstrip('\n'))
#super(LoggingUI, self).error(*msg, **opts)
core: move git/svn/hg into submodule
r1043
def note(self, *msg, **opts):
python3: code change for py3 support...
r1048 str_msg = map(safe_str, msg)
log.info('ui_logger:'+' '.join(str_msg).rstrip('\n'))
#super(LoggingUI, self).note(*msg, **opts)
core: move git/svn/hg into submodule
r1043
def debug(self, *msg, **opts):
python3: code change for py3 support...
r1048 str_msg = map(safe_str, msg)
log.debug('ui_logger:'+' '.join(str_msg).rstrip('\n'))
#super(LoggingUI, self).debug(*msg, **opts)
core: move git/svn/hg into submodule
r1043
baseui = LoggingUI()
# clean the baseui object
baseui._ocfg = hgconfig.config()
baseui._ucfg = hgconfig.config()
baseui._tcfg = hgconfig.config()
for section, option, value in repo_config:
python3: code change for py3 support...
r1048 baseui.setconfig(ascii_bytes(section), ascii_bytes(option), ascii_bytes(value))
core: move git/svn/hg into submodule
r1043
# make our hgweb quiet so it doesn't print output
python3: code change for py3 support...
r1048 baseui.setconfig(b'ui', b'quiet', b'true')
core: move git/svn/hg into submodule
r1043
python3: code change for py3 support...
r1048 baseui.setconfig(b'ui', b'paginate', b'never')
core: move git/svn/hg into submodule
r1043 # for better Error reporting of Mercurial
python3: code change for py3 support...
r1048 baseui.setconfig(b'ui', b'message-output', b'stderr')
core: move git/svn/hg into submodule
r1043
# force mercurial to only use 1 thread, otherwise it may try to set a
# signal in a non-main thread, thus generating a ValueError.
python3: code change for py3 support...
r1048 baseui.setconfig(b'worker', b'numcpus', 1)
core: move git/svn/hg into submodule
r1043
# If there is no config for the largefiles extension, we explicitly disable
# it here. This overrides settings from repositories hgrc file. Recent
# mercurial versions enable largefiles in hgrc on clone from largefile
# repo.
python3: code change for py3 support...
r1048 if not baseui.hasconfig(b'extensions', b'largefiles'):
core: move git/svn/hg into submodule
r1043 log.debug('Explicitly disable largefiles extension for repo.')
python3: code change for py3 support...
r1048 baseui.setconfig(b'extensions', b'largefiles', b'!')
core: move git/svn/hg into submodule
r1043
return baseui
def reraise_safe_exceptions(func):
"""Decorator for converting mercurial exceptions to something neutral."""
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except (Abort, InterventionRequired) as e:
python3: code change for py3 support...
r1048 raise_from_original(exceptions.AbortException(e), e)
core: move git/svn/hg into submodule
r1043 except RepoLookupError as e:
python3: code change for py3 support...
r1048 raise_from_original(exceptions.LookupException(e), e)
core: move git/svn/hg into submodule
r1043 except RequirementError as e:
python3: code change for py3 support...
r1048 raise_from_original(exceptions.RequirementException(e), e)
core: move git/svn/hg into submodule
r1043 except RepoError as e:
python3: code change for py3 support...
r1048 raise_from_original(exceptions.VcsException(e), e)
core: move git/svn/hg into submodule
r1043 except LookupError as e:
python3: code change for py3 support...
r1048 raise_from_original(exceptions.LookupException(e), e)
core: move git/svn/hg into submodule
r1043 except Exception as e:
if not hasattr(e, '_vcs_kind'):
log.exception("Unhandled exception in hg remote call")
python3: code change for py3 support...
r1048 raise_from_original(exceptions.UnhandledException(e), e)
core: move git/svn/hg into submodule
r1043
raise
return wrapper
class MercurialFactory(RepoFactory):
repo_type = 'hg'
def _create_config(self, config, hooks=True):
if not hooks:
hooks_to_clean = frozenset((
'changegroup.repo_size', 'preoutgoing.pre_pull',
'outgoing.pull_logger', 'prechangegroup.pre_push'))
new_config = []
for section, option, value in config:
if section == 'hooks' and option in hooks_to_clean:
continue
new_config.append((section, option, value))
config = new_config
baseui = make_ui_from_config(config)
return baseui
def _create_repo(self, wire, create):
baseui = self._create_config(wire["config"])
python3: code change for py3 support...
r1048 return instance(baseui, ascii_bytes(wire["path"]), create)
core: move git/svn/hg into submodule
r1043
def repo(self, wire, create=False):
"""
Get a repository instance for the given path.
"""
return self._create_repo(wire, create)
def patch_ui_message_output(baseui):
python3: code change for py3 support...
r1048 baseui.setconfig(b'ui', b'quiet', b'false')
core: move git/svn/hg into submodule
r1043 output = io.BytesIO()
def write(data, **unused_kwargs):
output.write(data)
baseui.status = write
baseui.write = write
baseui.warn = write
baseui.debug = write
return baseui, output
class HgRemote(RemoteBase):
def __init__(self, factory):
self._factory = factory
self._bulk_methods = {
"affected_files": self.ctx_files,
"author": self.ctx_user,
"branch": self.ctx_branch,
"children": self.ctx_children,
"date": self.ctx_date,
"message": self.ctx_description,
"parents": self.ctx_parents,
"status": self.ctx_status,
"obsolete": self.ctx_obsolete,
"phase": self.ctx_phase,
"hidden": self.ctx_hidden,
"_file_paths": self.ctx_list,
}
def _get_ctx(self, repo, ref):
return get_ctx(repo, ref)
@reraise_safe_exceptions
def discover_hg_version(self):
from mercurial import util
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 return safe_str(util.version())
core: move git/svn/hg into submodule
r1043
@reraise_safe_exceptions
def is_empty(self, wire):
repo = self._factory.repo(wire)
try:
return len(repo) == 0
except Exception:
log.exception("failed to read object_store")
return False
@reraise_safe_exceptions
def bookmarks(self, wire):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _bookmarks(_context_uid, _repo_id):
repo = self._factory.repo(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 return {safe_str(name): ascii_str(hex(sha)) for name, sha in repo._bookmarks.items()}
core: move git/svn/hg into submodule
r1043
return _bookmarks(context_uid, repo_id)
@reraise_safe_exceptions
def branches(self, wire, normal, closed):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _branches(_context_uid, _repo_id, _normal, _closed):
repo = self._factory.repo(wire)
iter_branches = repo.branchmap().iterbranches()
bt = {}
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 for branch_name, _heads, tip_node, is_closed in iter_branches:
core: move git/svn/hg into submodule
r1043 if normal and not is_closed:
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 bt[safe_str(branch_name)] = ascii_str(hex(tip_node))
core: move git/svn/hg into submodule
r1043 if closed and is_closed:
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 bt[safe_str(branch_name)] = ascii_str(hex(tip_node))
core: move git/svn/hg into submodule
r1043
return bt
return _branches(context_uid, repo_id, normal, closed)
@reraise_safe_exceptions
def bulk_request(self, wire, commit_id, pre_load):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _bulk_request(_repo_id, _commit_id, _pre_load):
result = {}
for attr in pre_load:
try:
method = self._bulk_methods[attr]
git/hg: skip double caching with bulk requests calls....
r1075 wire.update({'cache': False}) # disable cache for bulk calls so we don't double cache
core: move git/svn/hg into submodule
r1043 result[attr] = method(wire, commit_id)
except KeyError as e:
raise exceptions.VcsException(e)(
'Unknown bulk attribute: "%s"' % attr)
return result
return _bulk_request(repo_id, commit_id, sorted(pre_load))
@reraise_safe_exceptions
def ctx_branch(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_branch(_repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
return ctx.branch()
return _ctx_branch(repo_id, commit_id)
@reraise_safe_exceptions
def ctx_date(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_date(_repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
return ctx.date()
return _ctx_date(repo_id, commit_id)
@reraise_safe_exceptions
def ctx_description(self, wire, revision):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
return ctx.description()
@reraise_safe_exceptions
def ctx_files(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_files(_repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
return ctx.files()
return _ctx_files(repo_id, commit_id)
@reraise_safe_exceptions
def ctx_list(self, path, revision):
repo = self._factory.repo(path)
ctx = self._get_ctx(repo, revision)
return list(ctx)
@reraise_safe_exceptions
def ctx_parents(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_parents(_repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
return [parent.hex() for parent in ctx.parents()
if not (parent.hidden() or parent.obsolete())]
return _ctx_parents(repo_id, commit_id)
@reraise_safe_exceptions
def ctx_children(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_children(_repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
return [child.hex() for child in ctx.children()
if not (child.hidden() or child.obsolete())]
return _ctx_children(repo_id, commit_id)
@reraise_safe_exceptions
def ctx_phase(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_phase(_context_uid, _repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
# public=0, draft=1, secret=3
return ctx.phase()
return _ctx_phase(context_uid, repo_id, commit_id)
@reraise_safe_exceptions
def ctx_obsolete(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_obsolete(_context_uid, _repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
return ctx.obsolete()
return _ctx_obsolete(context_uid, repo_id, commit_id)
@reraise_safe_exceptions
def ctx_hidden(self, wire, commit_id):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _ctx_hidden(_context_uid, _repo_id, _commit_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
return ctx.hidden()
return _ctx_hidden(context_uid, repo_id, commit_id)
@reraise_safe_exceptions
def ctx_substate(self, wire, revision):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
return ctx.substate
@reraise_safe_exceptions
def ctx_status(self, wire, revision):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
status = repo[ctx.p1().node()].status(other=ctx.node())
# object of status (odd, custom named tuple in mercurial) is not
# correctly serializable, we make it a list, as the underling
# API expects this to be a list
return list(status)
@reraise_safe_exceptions
def ctx_user(self, wire, revision):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
return ctx.user()
@reraise_safe_exceptions
def check_url(self, url, config):
_proto = None
if '+' in url[:url.find('://')]:
_proto = url[0:url.find('+')]
url = url[url.find('+') + 1:]
handlers = []
url_obj = url_parser(url)
test_uri, authinfo = url_obj.authinfo()
url_obj.passwd = '*****' if url_obj.passwd else url_obj.passwd
url_obj.query = obfuscate_qs(url_obj.query)
cleaned_uri = str(url_obj)
log.info("Checking URL for remote cloning/import: %s", cleaned_uri)
if authinfo:
# create a password manager
passmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
passmgr.add_password(*authinfo)
handlers.extend((httpbasicauthhandler(passmgr),
httpdigestauthhandler(passmgr)))
o = urllib.request.build_opener(*handlers)
o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
('Accept', 'application/mercurial-0.1')]
q = {"cmd": 'between'}
q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
qs = '?%s' % urllib.parse.urlencode(q)
cu = "%s%s" % (test_uri, qs)
req = urllib.request.Request(cu, None, {})
try:
log.debug("Trying to open URL %s", cleaned_uri)
resp = o.open(req)
if resp.code != 200:
raise exceptions.URLError()('Return Code is not 200')
except Exception as e:
log.warning("URL cannot be opened: %s", cleaned_uri, exc_info=True)
# means it cannot be cloned
raise exceptions.URLError(e)("[%s] org_exc: %s" % (cleaned_uri, e))
# now check if it's a proper hg repo, but don't do it for svn
try:
if _proto == 'svn':
pass
else:
# check for pure hg repos
log.debug(
"Verifying if URL is a Mercurial repository: %s",
cleaned_uri)
ui = make_ui_from_config(config)
peer_checker = makepeer(ui, url)
peer_checker.lookup('tip')
except Exception as e:
log.warning("URL is not a valid Mercurial repository: %s",
cleaned_uri)
raise exceptions.URLError(e)(
"url [%s] does not look like an hg repo org_exc: %s"
% (cleaned_uri, e))
log.info("URL is a valid Mercurial repository: %s", cleaned_uri)
return True
@reraise_safe_exceptions
def diff(self, wire, commit_id_1, commit_id_2, file_filter, opt_git, opt_ignorews, context):
repo = self._factory.repo(wire)
if file_filter:
match_filter = match(file_filter[0], '', [file_filter[1]])
else:
match_filter = file_filter
opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context, showfunc=1)
try:
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 diff_iter = patch.diff(
repo, node1=commit_id_1, node2=commit_id_2, match=match_filter, opts=opts)
return b"".join(diff_iter)
core: move git/svn/hg into submodule
r1043 except RepoLookupError as e:
raise exceptions.LookupException(e)()
@reraise_safe_exceptions
def node_history(self, wire, revision, path, limit):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
python3: code change for py3 support...
r1048
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _node_history(_context_uid, _repo_id, _revision, _path, _limit):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
py3: fixed few mercurial cases
r1050 fctx = ctx.filectx(safe_bytes(path))
core: move git/svn/hg into submodule
r1043
def history_iter():
limit_rev = fctx.rev()
for obj in reversed(list(fctx.filelog())):
obj = fctx.filectx(obj)
ctx = obj.changectx()
if ctx.hidden() or ctx.obsolete():
continue
if limit_rev >= obj.rev():
yield obj
history = []
for cnt, obj in enumerate(history_iter()):
if limit and cnt >= limit:
break
history.append(hex(obj.node()))
return [x for x in history]
return _node_history(context_uid, repo_id, revision, path, limit)
@reraise_safe_exceptions
def node_history_untill(self, wire, revision, path, limit):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
python3: code change for py3 support...
r1048
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _node_history_until(_context_uid, _repo_id):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
py3: fixed few mercurial cases
r1050 fctx = ctx.filectx(safe_bytes(path))
core: move git/svn/hg into submodule
r1043
file_log = list(fctx.filelog())
if limit:
# Limit to the last n items
file_log = file_log[-limit:]
return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
return _node_history_until(context_uid, repo_id, revision, path, limit)
@reraise_safe_exceptions
def fctx_annotate(self, wire, revision, path):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
py3: fixed few mercurial cases
r1050 fctx = ctx.filectx(safe_bytes(path))
core: move git/svn/hg into submodule
r1043
result = []
for i, annotate_obj in enumerate(fctx.annotate(), 1):
ln_no = i
sha = hex(annotate_obj.fctx.node())
content = annotate_obj.text
result.append((ln_no, sha, content))
return result
@reraise_safe_exceptions
def fctx_node_data(self, wire, revision, path):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
py3: fixed few mercurial cases
r1050 fctx = ctx.filectx(safe_bytes(path))
return fctx.data()
core: move git/svn/hg into submodule
r1043
@reraise_safe_exceptions
def fctx_flags(self, wire, commit_id, path):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
py3: fixed few mercurial cases
r1050
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _fctx_flags(_repo_id, _commit_id, _path):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
py3: fixed few mercurial cases
r1050 fctx = ctx.filectx(safe_bytes(path))
core: move git/svn/hg into submodule
r1043 return fctx.flags()
return _fctx_flags(repo_id, commit_id, path)
@reraise_safe_exceptions
def fctx_size(self, wire, commit_id, path):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
py3: fixed few mercurial cases
r1050
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _fctx_size(_repo_id, _revision, _path):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, commit_id)
py3: fixed few mercurial cases
r1050 fctx = ctx.filectx(safe_bytes(path))
core: move git/svn/hg into submodule
r1043 return fctx.size()
return _fctx_size(repo_id, commit_id, path)
@reraise_safe_exceptions
def get_all_commit_ids(self, wire, name):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
python3: code change for py3 support...
r1048
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _get_all_commit_ids(_context_uid, _repo_id, _name):
repo = self._factory.repo(wire)
python3: code change for py3 support...
r1048 revs = [ascii_str(repo[x].hex()) for x in repo.filtered(b'visible').changelog.revs()]
core: move git/svn/hg into submodule
r1043 return revs
return _get_all_commit_ids(context_uid, repo_id, name)
@reraise_safe_exceptions
def get_config_value(self, wire, section, name, untrusted=False):
repo = self._factory.repo(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 return repo.ui.config(ascii_bytes(section), ascii_bytes(name), untrusted=untrusted)
core: move git/svn/hg into submodule
r1043
@reraise_safe_exceptions
def is_large_file(self, wire, commit_id, path):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
python3: code change for py3 support...
r1048
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _is_large_file(_context_uid, _repo_id, _commit_id, _path):
py3: fixed few mercurial cases
r1050 return largefiles.lfutil.isstandin(safe_bytes(path))
core: move git/svn/hg into submodule
r1043
return _is_large_file(context_uid, repo_id, commit_id, path)
@reraise_safe_exceptions
def is_binary(self, wire, revision, path):
cache_on, context_uid, repo_id = self._cache_on(wire)
python3: code change for py3 support...
r1048 region = self._region(wire)
core: move git/svn/hg into submodule
r1043
@region.conditional_cache_on_arguments(condition=cache_on)
def _is_binary(_repo_id, _sha, _path):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
py3: fixed few mercurial cases
r1050 fctx = ctx.filectx(safe_bytes(path))
core: move git/svn/hg into submodule
r1043 return fctx.isbinary()
return _is_binary(repo_id, revision, path)
@reraise_safe_exceptions
scm: added md5 methods to be calculated on vcsserver instead of RhodeCode side
r1074 def md5_hash(self, wire, revision, path):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
@region.conditional_cache_on_arguments(condition=cache_on)
def _md5_hash(_repo_id, _sha, _path):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
fctx = ctx.filectx(safe_bytes(path))
return hashlib.md5(fctx.data()).hexdigest()
return _md5_hash(repo_id, revision, path)
@reraise_safe_exceptions
core: move git/svn/hg into submodule
r1043 def in_largefiles_store(self, wire, sha):
repo = self._factory.repo(wire)
return largefiles.lfutil.instore(repo, sha)
@reraise_safe_exceptions
def in_user_cache(self, wire, sha):
repo = self._factory.repo(wire)
return largefiles.lfutil.inusercache(repo.ui, sha)
@reraise_safe_exceptions
def store_path(self, wire, sha):
repo = self._factory.repo(wire)
return largefiles.lfutil.storepath(repo, sha)
@reraise_safe_exceptions
def link(self, wire, sha, path):
repo = self._factory.repo(wire)
largefiles.lfutil.link(
largefiles.lfutil.usercachepath(repo.ui, sha), path)
@reraise_safe_exceptions
def localrepository(self, wire, create=False):
self._factory.repo(wire, create=create)
@reraise_safe_exceptions
def lookup(self, wire, revision, both):
cache_on, context_uid, repo_id = self._cache_on(wire)
py3: fixed few mercurial cases
r1050 region = self._region(wire)
core: move git/svn/hg into submodule
r1043
@region.conditional_cache_on_arguments(condition=cache_on)
def _lookup(_context_uid, _repo_id, _revision, _both):
repo = self._factory.repo(wire)
rev = _revision
if isinstance(rev, int):
# NOTE(marcink):
# since Mercurial doesn't support negative indexes properly
# we need to shift accordingly by one to get proper index, e.g
# repo[-1] => repo[-2]
# repo[0] => repo[-1]
if rev <= 0:
rev = rev + -1
try:
ctx = self._get_ctx(repo, rev)
except (TypeError, RepoLookupError) as e:
e._org_exc_tb = traceback.format_exc()
raise exceptions.LookupException(e)(rev)
except LookupError as e:
e._org_exc_tb = traceback.format_exc()
raise exceptions.LookupException(e)(e.name)
if not both:
return ctx.hex()
ctx = repo[ctx.hex()]
return ctx.hex(), ctx.rev()
return _lookup(context_uid, repo_id, revision, both)
@reraise_safe_exceptions
def sync_push(self, wire, url):
if not self.check_url(url, wire['config']):
return
repo = self._factory.repo(wire)
# Disable any prompts for this repo
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
core: move git/svn/hg into submodule
r1043
bookmarks = list(dict(repo._bookmarks).keys())
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 remote = peer(repo, {}, safe_bytes(url))
core: move git/svn/hg into submodule
r1043 # Disable any prompts for this remote
python3: code change for py3 support...
r1048 remote.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
core: move git/svn/hg into submodule
r1043
return exchange.push(
repo, remote, newbranch=True, bookmarks=bookmarks).cgresult
@reraise_safe_exceptions
def revision(self, wire, rev):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, rev)
return ctx.rev()
@reraise_safe_exceptions
def rev_range(self, wire, commit_filter):
cache_on, context_uid, repo_id = self._cache_on(wire)
py3: fixed few mercurial cases
r1050 region = self._region(wire)
core: move git/svn/hg into submodule
r1043
@region.conditional_cache_on_arguments(condition=cache_on)
def _rev_range(_context_uid, _repo_id, _filter):
repo = self._factory.repo(wire)
py3: fixed few mercurial cases
r1050 revisions = [
ascii_str(repo[rev].hex())
for rev in revrange(repo, list(map(ascii_bytes, commit_filter)))
]
core: move git/svn/hg into submodule
r1043 return revisions
return _rev_range(context_uid, repo_id, sorted(commit_filter))
@reraise_safe_exceptions
def rev_range_hash(self, wire, node):
repo = self._factory.repo(wire)
def get_revs(repo, rev_opt):
if rev_opt:
revs = revrange(repo, rev_opt)
if len(revs) == 0:
return (nullrev, nullrev)
return max(revs), min(revs)
else:
return len(repo) - 1, 0
stop, start = get_revs(repo, [node + ':'])
py3: fixed few mercurial cases
r1050 revs = [ascii_str(repo[r].hex()) for r in range(start, stop + 1)]
core: move git/svn/hg into submodule
r1043 return revs
@reraise_safe_exceptions
def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
other_path = kwargs.pop('other_path', None)
# case when we want to compare two independent repositories
if other_path and other_path != wire["path"]:
baseui = self._factory._create_config(wire["config"])
repo = unionrepo.makeunionrepository(baseui, other_path, wire["path"])
else:
repo = self._factory.repo(wire)
return list(repo.revs(rev_spec, *args))
@reraise_safe_exceptions
def verify(self, wire,):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
baseui, output = patch_ui_message_output(baseui)
repo.ui = baseui
verify.verify(repo)
return output.getvalue()
@reraise_safe_exceptions
def hg_update_cache(self, wire,):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
baseui, output = patch_ui_message_output(baseui)
repo.ui = baseui
with repo.wlock(), repo.lock():
repo.updatecaches(full=True)
return output.getvalue()
@reraise_safe_exceptions
def hg_rebuild_fn_cache(self, wire,):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
baseui, output = patch_ui_message_output(baseui)
repo.ui = baseui
repair.rebuildfncache(baseui, repo)
return output.getvalue()
@reraise_safe_exceptions
def tags(self, wire):
cache_on, context_uid, repo_id = self._cache_on(wire)
region = self._region(wire)
py3: fixed few mercurial cases
r1050
core: move git/svn/hg into submodule
r1043 @region.conditional_cache_on_arguments(condition=cache_on)
def _tags(_context_uid, _repo_id):
repo = self._factory.repo(wire)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 return {safe_str(name): ascii_str(hex(sha)) for name, sha in repo.tags().items()}
core: move git/svn/hg into submodule
r1043
return _tags(context_uid, repo_id)
@reraise_safe_exceptions
def update(self, wire, node=None, clean=False):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
commands.update(baseui, repo, node=node, clean=clean)
@reraise_safe_exceptions
def identify(self, wire):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
output = io.BytesIO()
baseui.write = output.write
# This is required to get a full node id
baseui.debugflag = True
commands.identify(baseui, repo, id=True)
return output.getvalue()
@reraise_safe_exceptions
def heads(self, wire, branch=None):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
output = io.BytesIO()
def write(data, **unused_kwargs):
output.write(data)
baseui.write = write
if branch:
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 args = [safe_bytes(branch)]
core: move git/svn/hg into submodule
r1043 else:
args = []
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 commands.heads(baseui, repo, template=b'{node} ', *args)
core: move git/svn/hg into submodule
r1043
return output.getvalue()
@reraise_safe_exceptions
def ancestor(self, wire, revision1, revision2):
repo = self._factory.repo(wire)
changelog = repo.changelog
lookup = repo.lookup
a = changelog.ancestor(lookup(revision1), lookup(revision2))
return hex(a)
@reraise_safe_exceptions
def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
baseui = self._factory._create_config(wire["config"], hooks=hooks)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 clone(baseui, safe_bytes(source), safe_bytes(dest), noupdate=not update_after_clone)
core: move git/svn/hg into submodule
r1043
@reraise_safe_exceptions
def commitctx(self, wire, message, parents, commit_time, commit_timezone, user, files, extra, removed, updated):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 publishing = baseui.configbool(b'phases', b'publish')
core: move git/svn/hg into submodule
r1043
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 def _filectxfn(_repo, ctx, path: bytes):
core: move git/svn/hg into submodule
r1043 """
Marks given path as added/changed/removed in a given _repo. This is
for internal mercurial commit function.
"""
# check if this path is removed
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 if safe_str(path) in removed:
core: move git/svn/hg into submodule
r1043 # returning None is a way to mark node for removal
return None
# check if this path is added
for node in updated:
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 if safe_bytes(node['path']) == path:
core: move git/svn/hg into submodule
r1043 return memfilectx(
_repo,
changectx=ctx,
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 path=safe_bytes(node['path']),
data=safe_bytes(node['content']),
core: move git/svn/hg into submodule
r1043 islink=False,
isexec=bool(node['mode'] & stat.S_IXUSR),
copysource=False)
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 abort_exc = exceptions.AbortException()
raise abort_exc(f"Given path haven't been marked as added, changed or removed ({path})")
core: move git/svn/hg into submodule
r1043
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 if publishing:
new_commit_phase = b'public'
else:
new_commit_phase = b'draft'
with repo.ui.configoverride({(b'phases', b'new-commit'): new_commit_phase}):
kwargs = {safe_bytes(k): safe_bytes(v) for k, v in extra.items()}
core: move git/svn/hg into submodule
r1043 commit_ctx = memctx(
repo=repo,
parents=parents,
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 text=safe_bytes(message),
files=[safe_bytes(x) for x in files],
core: move git/svn/hg into submodule
r1043 filectxfn=_filectxfn,
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 user=safe_bytes(user),
core: move git/svn/hg into submodule
r1043 date=(commit_time, commit_timezone),
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 extra=kwargs)
core: move git/svn/hg into submodule
r1043
n = repo.commitctx(commit_ctx)
new_id = hex(n)
return new_id
@reraise_safe_exceptions
def pull(self, wire, url, commit_ids=None):
repo = self._factory.repo(wire)
# Disable any prompts for this repo
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
core: move git/svn/hg into submodule
r1043
core: various fixes of bytes vs str usage based on rhodecode-ce tests outputs
r1070 remote = peer(repo, {}, safe_bytes(url))
core: move git/svn/hg into submodule
r1043 # Disable any prompts for this remote
python3: code change for py3 support...
r1048 remote.ui.setconfig(b'ui', b'interactive', b'off', b'-y')
core: move git/svn/hg into submodule
r1043
if commit_ids:
commit_ids = [bin(commit_id) for commit_id in commit_ids]
return exchange.pull(
repo, remote, heads=commit_ids, force=None).cgresult
@reraise_safe_exceptions
def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None, hooks=True):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'], hooks=hooks)
# Mercurial internally has a lot of logic that checks ONLY if
# option is defined, we just pass those if they are defined then
opts = {}
if bookmark:
opts['bookmark'] = bookmark
if branch:
opts['branch'] = branch
if revision:
opts['rev'] = revision
commands.pull(baseui, repo, source, **opts)
@reraise_safe_exceptions
def push(self, wire, revisions, dest_path, hooks=True, push_branches=False):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'], hooks=hooks)
commands.push(baseui, repo, dest=dest_path, rev=revisions,
new_branch=push_branches)
@reraise_safe_exceptions
def strip(self, wire, revision, update, backup):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
hgext_strip(
repo.baseui, repo, ctx.node(), update=update, backup=backup)
@reraise_safe_exceptions
def get_unresolved_files(self, wire):
repo = self._factory.repo(wire)
log.debug('Calculating unresolved files for repo: %s', repo)
output = io.BytesIO()
def write(data, **unused_kwargs):
output.write(data)
baseui = self._factory._create_config(wire['config'])
baseui.write = write
commands.resolve(baseui, repo, list=True)
unresolved = output.getvalue().splitlines(0)
return unresolved
@reraise_safe_exceptions
def merge(self, wire, revision):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
core: move git/svn/hg into submodule
r1043
# In case of sub repositories are used mercurial prompts the user in
# case of merge conflicts or different sub repository sources. By
# setting the interactive flag to `False` mercurial doesn't prompt the
# used but instead uses a default value.
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'interactive', False)
core: move git/svn/hg into submodule
r1043 commands.merge(baseui, repo, rev=revision)
@reraise_safe_exceptions
def merge_state(self, wire):
repo = self._factory.repo(wire)
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
core: move git/svn/hg into submodule
r1043
# In case of sub repositories are used mercurial prompts the user in
# case of merge conflicts or different sub repository sources. By
# setting the interactive flag to `False` mercurial doesn't prompt the
# used but instead uses a default value.
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'interactive', False)
core: move git/svn/hg into submodule
r1043 ms = hg_merge.mergestate(repo)
return [x for x in ms.unresolved()]
@reraise_safe_exceptions
def commit(self, wire, message, username, close_branch=False):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'username', username)
core: move git/svn/hg into submodule
r1043 commands.commit(baseui, repo, message=message, close_branch=close_branch)
@reraise_safe_exceptions
def rebase(self, wire, source=None, dest=None, abort=False):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'merge', b'internal:dump')
core: move git/svn/hg into submodule
r1043 # In case of sub repositories are used mercurial prompts the user in
# case of merge conflicts or different sub repository sources. By
# setting the interactive flag to `False` mercurial doesn't prompt the
# used but instead uses a default value.
python3: code change for py3 support...
r1048 repo.ui.setconfig(b'ui', b'interactive', False)
core: move git/svn/hg into submodule
r1043 rebase.rebase(baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
@reraise_safe_exceptions
def tag(self, wire, name, revision, message, local, user, tag_time, tag_timezone):
repo = self._factory.repo(wire)
ctx = self._get_ctx(repo, revision)
node = ctx.node()
date = (tag_time, tag_timezone)
try:
hg_tag.tag(repo, name, node, message, local, user, date)
except Abort as e:
log.exception("Tag operation aborted")
# Exception can contain unicode which we convert
raise exceptions.AbortException(e)(repr(e))
@reraise_safe_exceptions
def bookmark(self, wire, bookmark, revision=None):
repo = self._factory.repo(wire)
baseui = self._factory._create_config(wire['config'])
commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
@reraise_safe_exceptions
def install_hooks(self, wire, force=False):
# we don't need any special hooks for Mercurial
pass
@reraise_safe_exceptions
def get_hooks_info(self, wire):
return {
'pre_version': vcsserver.__version__,
'post_version': vcsserver.__version__,
}
@reraise_safe_exceptions
def set_head_ref(self, wire, head_name):
pass
@reraise_safe_exceptions
def archive_repo(self, wire, archive_dest_path, kind, mtime, archive_at_path,
archive_dir_name, commit_id):
def file_walker(_commit_id, path):
repo = self._factory.repo(wire)
ctx = repo[_commit_id]
is_root = path in ['', '/']
if is_root:
matcher = alwaysmatcher(badfn=None)
else:
matcher = patternmatcher('', [(b'glob', path+'/**', b'')], badfn=None)
file_iter = ctx.manifest().walk(matcher)
for fn in file_iter:
file_path = fn
flags = ctx.flags(fn)
mode = b'x' in flags and 0o755 or 0o644
is_link = b'l' in flags
py3: fixed few mercurial cases
r1050 yield ArchiveNode(file_path, mode, is_link, ctx[fn].data)
core: move git/svn/hg into submodule
r1043
return archive_repo(file_walker, archive_dest_path, kind, mtime, archive_at_path,
archive_dir_name, commit_id)