diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -57,3 +57,7 @@ 5e0c2990e095bba1dc903cf0e6ef6ac035e0ccf9 8a824544d95037d76d99b104b5d2363858101d53 v4.17.2 ccd806a2d9482f61bd7e8956a02a28eb24a1d46a v4.17.3 e533ca02ccc205189b7bad9f227a312212772022 v4.17.4 +ba6a6dc9ecd7fd8b1dcd6eb0c4ee0210e897c426 v4.18.0 +17bc818b41bcf6883b9ff0da31f01d8c2a5d0781 v4.18.1 +1e9f12aa01f82c335abc9017efe94ce1c30b52ba v4.18.2 +f4cc6b3c5680bdf4541d7d442fbb7086640fb547 v4.18.3 diff --git a/vcsserver/git.py b/vcsserver/git.py --- a/vcsserver/git.py +++ b/vcsserver/git.py @@ -39,7 +39,7 @@ from dulwich.repo import Repo as Dulwich from dulwich.server import update_server_info from vcsserver import exceptions, settings, subprocessio -from vcsserver.utils import safe_str, safe_int +from vcsserver.utils import safe_str, safe_int, safe_unicode from vcsserver.base import RepoFactory, obfuscate_qs from vcsserver.hgcompat import ( hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler) @@ -840,7 +840,11 @@ class GitRemote(RemoteBase): if author.email: return u"{} <{}>".format(author.name, author.email) - return u"{}".format(author.raw_name) + try: + return u"{}".format(author.name) + except Exception: + return u"{}".format(safe_unicode(author.raw_name)) + return _author(repo_id, commit_id) @reraise_safe_exceptions diff --git a/vcsserver/hg.py b/vcsserver/hg.py --- a/vcsserver/hg.py +++ b/vcsserver/hg.py @@ -27,6 +27,7 @@ from hgext.strip import strip as hgext_s from mercurial import commands from mercurial import unionrepo from mercurial import verify +from mercurial import repair import vcsserver from vcsserver import exceptions @@ -151,6 +152,21 @@ class MercurialFactory(RepoFactory): return self._create_repo(wire, create) +def patch_ui_message_output(baseui): + baseui.setconfig('ui', 'quiet', 'false') + 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): @@ -706,12 +722,8 @@ class HgRemote(RemoteBase): def verify(self, wire,): repo = self._factory.repo(wire) baseui = self._factory._create_config(wire['config']) - baseui.setconfig('ui', 'quiet', 'false') - output = io.BytesIO() - def write(data, **unused_kwargs): - output.write(data) - baseui.write = write + baseui, output = patch_ui_message_output(baseui) repo.ui = baseui verify.verify(repo) @@ -721,12 +733,7 @@ class HgRemote(RemoteBase): def hg_update_cache(self, wire,): repo = self._factory.repo(wire) baseui = self._factory._create_config(wire['config']) - baseui.setconfig('ui', 'quiet', 'false') - output = io.BytesIO() - - def write(data, **unused_kwargs): - output.write(data) - baseui.write = write + baseui, output = patch_ui_message_output(baseui) repo.ui = baseui with repo.wlock(), repo.lock(): @@ -735,6 +742,18 @@ class HgRemote(RemoteBase): 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) @self.region.conditional_cache_on_arguments(condition=cache_on) diff --git a/vcsserver/hgcompat.py b/vcsserver/hgcompat.py --- a/vcsserver/hgcompat.py +++ b/vcsserver/hgcompat.py @@ -71,5 +71,9 @@ def get_ctx(repo, ref): # we're unable to find the rev using a regular lookup, we fallback # to slower, but backward compat revsymbol usage ctx = revsymbol(repo, ref) - + except (LookupError, RepoLookupError): + # Similar case as above but only for refs that are not numeric + if isinstance(ref, (int, long)): + raise + ctx = revsymbol(repo, ref) return ctx diff --git a/vcsserver/hooks.py b/vcsserver/hooks.py --- a/vcsserver/hooks.py +++ b/vcsserver/hooks.py @@ -691,7 +691,14 @@ def svn_post_commit(repo_path, commit_da """ commit_data is path, rev, txn_id """ - path, commit_id, txn_id = commit_data + if len(commit_data) == 3: + path, commit_id, txn_id = commit_data + elif len(commit_data) == 2: + log.error('Failed to extract txn_id from commit_data using legacy method. ' + 'Some functionality might be limited') + path, commit_id = commit_data + txn_id = None + branches = [] tags = [] diff --git a/vcsserver/utils.py b/vcsserver/utils.py --- a/vcsserver/utils.py +++ b/vcsserver/utils.py @@ -37,18 +37,16 @@ def safe_int(val, default=None): return val -def safe_str(unicode_, to_encoding=['utf8']): +def safe_str(unicode_, to_encoding=None): """ safe str function. Does few trick to turn unicode_ into string - In case of UnicodeEncodeError, we try to return it with encoding detected - by chardet library if it fails fallback to string with errors replaced - :param unicode_: unicode to encode + :param to_encoding: encode to this type UTF8 default :rtype: str :returns: str object """ - + to_encoding = to_encoding or ['utf8'] # if it's not basestr cast to str if not isinstance(unicode_, basestring): return str(unicode_) @@ -65,15 +63,38 @@ def safe_str(unicode_, to_encoding=['utf except UnicodeEncodeError: pass + return unicode_.encode(to_encoding[0], 'replace') + + +def safe_unicode(str_, from_encoding=None): + """ + safe unicode function. Does few trick to turn str_ into unicode + + :param str_: string to decode + :param from_encoding: encode from this type UTF8 default + :rtype: unicode + :returns: unicode object + """ + from_encoding = from_encoding or ['utf8'] + + if isinstance(str_, unicode): + return str_ + + if not isinstance(from_encoding, (list, tuple)): + from_encoding = [from_encoding] + try: - import chardet - encoding = chardet.detect(unicode_)['encoding'] - if encoding is None: - raise UnicodeEncodeError() + return unicode(str_) + except UnicodeDecodeError: + pass - return unicode_.encode(encoding) - except (ImportError, UnicodeEncodeError): - return unicode_.encode(to_encoding[0], 'replace') + for enc in from_encoding: + try: + return unicode(str_, enc) + except UnicodeDecodeError: + pass + + return unicode(str_, from_encoding[0], 'replace') class AttributeDict(dict):