diff --git a/.bumpversion.cfg b/.bumpversion.cfg --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 4.26.0 +current_version = 4.27.0 message = release: Bump version {current_version} to {new_version} [bumpversion:file:rhodecode/VERSION] diff --git a/.release.cfg b/.release.cfg --- a/.release.cfg +++ b/.release.cfg @@ -5,26 +5,20 @@ done = false done = true [task:rc_tools_pinned] -done = true [task:fixes_on_stable] -done = true [task:pip2nix_generated] -done = true [task:changelog_updated] -done = true [task:generate_api_docs] -done = true [task:updated_translation] -done = true [release] -state = prepared -version = 4.26.0 +state = in_progress +version = 4.27.0 [task:generate_js_routes] diff --git a/docs/admin/system-overview.rst b/docs/admin/system-overview.rst --- a/docs/admin/system-overview.rst +++ b/docs/admin/system-overview.rst @@ -169,4 +169,4 @@ Deprecated Support - Internet Explorer 9 support deprecated since version 3.8.0. .. _here: https://rhodecode.com/licenses/ -.. _Transifex: https://www.transifex.com/projects/p/RhodeCode/ +.. _Transifex: https://explore.transifex.com/rhodecode/RhodeCode/ diff --git a/docs/release-notes/release-notes-4.27.0.rst b/docs/release-notes/release-notes-4.27.0.rst new file mode 100644 --- /dev/null +++ b/docs/release-notes/release-notes-4.27.0.rst @@ -0,0 +1,58 @@ +|RCE| 4.27.0 |RNS| +------------------ + +Release Date +^^^^^^^^^^^^ + +- 2022-09-01 + + +New Features +^^^^^^^^^^^^ + + +- Git: allow overriding default master branch with an env variable. +- VCS settings: when setting landing ref from UI switch default GIT branch too. + This allows having non-default branches set as default. +- Users: enable full edit mode for super admins. + Super-Admins now are allowed to edit even LDAP/OAuth user attributes. + We'll enable the users to change their names via external auth for rename cases. + + +General +^^^^^^^ + +- Commits/summary: unify fetching remote attribute in summary and commits page to properly and in the same way show the data. +- Caches: updated logging and some timings +- Caches: allow regional per repo caches, and invalidate caches via a remote call. +- Caches: invalidate cache on remote side from repo settings alongside local cache. +- Git: allow setting symbolic ref for repos without master branch. +- Sys-info: added helpers for faster loading of sys-info data +- Debugging: debug = true flag now prints associated exception and logs right into the error page + + +Security +^^^^^^^^ + +- Healthcheck: Added authentication because we expose DB information +- Security: fixed self-xss on archive download page. + + +Performance +^^^^^^^^^^^ + + + +Fixes +^^^^^ + +- Drafts: show TODO drafts properly in edge cases. +- Files: fixed unicode problems in specially encoded paths handler. +- Caches: fixed issue with exception on handling non-ascii cache keys. +- Git: handle archive generation crash case when submodules are present. + + +Upgrade notes +^^^^^^^^^^^^^ + +- Scheduled release 4.27.0. diff --git a/docs/release-notes/release-notes.rst b/docs/release-notes/release-notes.rst --- a/docs/release-notes/release-notes.rst +++ b/docs/release-notes/release-notes.rst @@ -9,6 +9,7 @@ Release Notes .. toctree:: :maxdepth: 1 + release-notes-4.27.0.rst release-notes-4.26.0.rst release-notes-4.25.2.rst release-notes-4.25.1.rst diff --git a/pkgs/patches/rhodecode_tools/setuptools.patch b/pkgs/patches/rhodecode_tools/setuptools.patch --- a/pkgs/patches/rhodecode_tools/setuptools.patch +++ b/pkgs/patches/rhodecode_tools/setuptools.patch @@ -1,6 +1,6 @@ -diff -rup rhodecode-tools-1.4.0-orig/setup.py rhodecode-tools-1.4.0/setup.py ---- rhodecode-tools-1.4.0/setup-orig.py 2021-03-11 12:34:45.000000000 +0100 -+++ rhodecode-tools-1.4.0/setup.py 2021-03-11 12:34:56.000000000 +0100 +diff -rup rhodecode-tools-1.4.1-orig/setup.py rhodecode-tools-1.4.1/setup.py +--- rhodecode-tools-1.4.1/setup-orig.py 2021-03-11 12:34:45.000000000 +0100 ++++ rhodecode-tools-1.4.1/setup.py 2021-03-11 12:34:56.000000000 +0100 @@ -69,7 +69,7 @@ def _get_requirements(req_filename, excl diff --git a/pkgs/python-packages.nix b/pkgs/python-packages.nix --- a/pkgs/python-packages.nix +++ b/pkgs/python-packages.nix @@ -1883,7 +1883,7 @@ self: super: { }; }; "rhodecode-enterprise-ce" = super.buildPythonPackage { - name = "rhodecode-enterprise-ce-4.26.0"; + name = "rhodecode-enterprise-ce-4.27.0"; buildInputs = [ self."pytest" self."py" @@ -2020,7 +2020,7 @@ self: super: { }; }; "rhodecode-tools" = super.buildPythonPackage { - name = "rhodecode-tools-1.4.0"; + name = "rhodecode-tools-1.4.1"; doCheck = false; propagatedBuildInputs = [ self."click" @@ -2037,8 +2037,8 @@ self: super: { self."elasticsearch1-dsl" ]; src = fetchurl { - url = "https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-ed54e749-2ef5-4bc7-ae7f-7900e3c2aa15.tar.gz?sha256=76f024bad3a1e55fdb3d64f13f5b77ff21a12fee699918de2110fe21effd5a3a"; - sha256 = "0fjszppj3zhh47g1i6b9xqps28gzfxdkzwb47pdmzrd1sfx29w3n"; + url = "https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-d9ea7914-e475-44af-a80a-7e32edc17e2f.tar.gz?sha256=6e5aaac455b4a0b2dee013a1241b367e2991e345fda6ed0f4a8c66c941a19184"; + sha256 = "6e5aaac455b4a0b2dee013a1241b367e2991e345fda6ed0f4a8c66c941a19184"; }; meta = { license = [ { fullName = "Apache 2.0 and Proprietary"; } ]; diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -111,7 +111,7 @@ ipdb==0.13.2 ipython==5.1.0 ## rhodecode-tools, special case, use file://PATH.tar.gz#egg=rhodecode-tools==X.Y.Z, to test local version -https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-ed54e749-2ef5-4bc7-ae7f-7900e3c2aa15.tar.gz?sha256=76f024bad3a1e55fdb3d64f13f5b77ff21a12fee699918de2110fe21effd5a3a#egg=rhodecode-tools==1.4.0 +https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-d9ea7914-e475-44af-a80a-7e32edc17e2f.tar.gz?sha256=6e5aaac455b4a0b2dee013a1241b367e2991e345fda6ed0f4a8c66c941a19184#egg=rhodecode-tools==1.4.1 ## appenlight diff --git a/rhodecode/VERSION b/rhodecode/VERSION --- a/rhodecode/VERSION +++ b/rhodecode/VERSION @@ -1,1 +1,1 @@ -4.26.0 \ No newline at end of file +4.27.0 \ No newline at end of file diff --git a/rhodecode/apps/_base/__init__.py b/rhodecode/apps/_base/__init__.py --- a/rhodecode/apps/_base/__init__.py +++ b/rhodecode/apps/_base/__init__.py @@ -389,6 +389,11 @@ class RepoAppView(BaseAppView): return True return False + def get_commit_preload_attrs(cls): + pre_load = ['author', 'branch', 'date', 'message', 'parents', + 'obsolete', 'phase', 'hidden'] + return pre_load + class PathFilter(object): diff --git a/rhodecode/apps/admin/views/system_info.py b/rhodecode/apps/admin/views/system_info.py --- a/rhodecode/apps/admin/views/system_info.py +++ b/rhodecode/apps/admin/views/system_info.py @@ -20,8 +20,7 @@ import logging import urllib2 - - +import os import rhodecode from rhodecode.apps._base import BaseAppView @@ -40,6 +39,40 @@ class AdminSystemInfoSettingsView(BaseAp c = self._get_local_tmpl_context() return c + def get_env_data(self): + black_list = [ + 'NIX_LDFLAGS', + 'NIX_CFLAGS_COMPILE', + 'propagatedBuildInputs', + 'propagatedNativeBuildInputs', + 'postInstall', + 'buildInputs', + 'buildPhase', + 'preShellHook', + 'preShellHook', + 'preCheck', + 'preBuild', + 'postShellHook', + 'postFixup', + 'postCheck', + 'nativeBuildInputs', + 'installPhase', + 'installCheckPhase', + 'checkPhase', + 'configurePhase', + 'shellHook' + ] + secret_list = [ + 'RHODECODE_USER_PASS' + ] + + for k, v in sorted(os.environ.items()): + if k in black_list: + continue + if k in secret_list: + v = '*****' + yield k, v + @LoginRequired() @HasPermissionAllDecorator('hg.admin') def settings_system_info(self): @@ -55,6 +88,7 @@ class AdminSystemInfoSettingsView(BaseAp snapshot = str2bool(self.request.params.get('snapshot')) c.rhodecode_update_url = UpdateModel().get_update_url() + c.env_data = self.get_env_data() server_info = system_info.get_system_info(self.request.environ) for key, val in server_info.items(): diff --git a/rhodecode/apps/admin/views/users.py b/rhodecode/apps/admin/views/users.py --- a/rhodecode/apps/admin/views/users.py +++ b/rhodecode/apps/admin/views/users.py @@ -311,13 +311,16 @@ class UsersView(UserAppView): available_languages=available_languages, old_data={'user_id': user_id, 'email': c.user.email})() + + c.edit_mode = self.request.POST.get('edit') == '1' form_result = {} old_values = c.user.get_api_data() try: form_result = _form.to_python(dict(self.request.POST)) skip_attrs = ['extern_name'] # TODO: plugin should define if username can be updated - if c.extern_type != "rhodecode": + + if c.extern_type != "rhodecode" and not c.edit_mode: # forbid updating username for external accounts skip_attrs.append('username') @@ -485,6 +488,7 @@ class UsersView(UserAppView): c.extern_type = c.user.extern_type c.extern_name = c.user.extern_name c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr) + c.edit_mode = self.request.GET.get('edit') == '1' defaults = c.user.get_dict() defaults.update({'language': c.user.user_data.get('language')}) diff --git a/rhodecode/apps/repository/views/repo_caches.py b/rhodecode/apps/repository/views/repo_caches.py --- a/rhodecode/apps/repository/views/repo_caches.py +++ b/rhodecode/apps/repository/views/repo_caches.py @@ -66,18 +66,28 @@ class RepoCachesView(RepoAppView): _ = self.request.translate c = self.load_default_context() c.active = 'caches' + invalidated = 0 try: ScmModel().mark_for_invalidation(self.db_repo_name, delete=True) - Session().commit() - - h.flash(_('Cache invalidation successful'), - category='success') + invalidated +=1 except Exception: log.exception("Exception during cache invalidation") h.flash(_('An error occurred during cache invalidation'), category='error') + try: + invalidated += 1 + self.rhodecode_vcs_repo.vcsserver_invalidate_cache(delete=True) + except Exception: + log.exception("Exception during vcsserver cache invalidation") + h.flash(_('An error occurred during vcsserver cache invalidation'), + category='error') + + if invalidated: + h.flash(_('Cache invalidation successful. Stages {}/2').format(invalidated), + category='success') + raise HTTPFound(h.route_path( 'edit_repo_caches', repo_name=self.db_repo_name)) \ No newline at end of file diff --git a/rhodecode/apps/repository/views/repo_changelog.py b/rhodecode/apps/repository/views/repo_changelog.py --- a/rhodecode/apps/repository/views/repo_changelog.py +++ b/rhodecode/apps/repository/views/repo_changelog.py @@ -168,11 +168,6 @@ class RepoChangelogView(RepoAppView): return c - def _get_preload_attrs(self): - pre_load = ['author', 'branch', 'date', 'message', 'parents', - 'obsolete', 'phase', 'hidden'] - return pre_load - @LoginRequired() @HasRepoPermissionAnyDecorator( 'repository.read', 'repository.write', 'repository.admin') @@ -200,7 +195,7 @@ class RepoChangelogView(RepoAppView): self._check_if_valid_branch(branch_name, self.db_repo_name, f_path) c.changelog_for_path = f_path - pre_load = self._get_preload_attrs() + pre_load = self.get_commit_preload_attrs() partial_xhr = self.request.environ.get('HTTP_X_PARTIAL_XHR') @@ -256,6 +251,8 @@ class RepoChangelogView(RepoAppView): raise HTTPFound( h.route_path('repo_summary', repo_name=self.db_repo_name)) + + if partial_xhr or self.request.environ.get('HTTP_X_PJAX'): # case when loading dynamic file history in file view # loading from ajax, we don't want the first result, it's popped @@ -304,7 +301,7 @@ class RepoChangelogView(RepoAppView): return wrap_for_error( safe_str('Branch: {} is not valid'.format(branch_name))) - pre_load = self._get_preload_attrs() + pre_load = self.get_commit_preload_attrs() if f_path: try: diff --git a/rhodecode/apps/repository/views/repo_files.py b/rhodecode/apps/repository/views/repo_files.py --- a/rhodecode/apps/repository/views/repo_files.py +++ b/rhodecode/apps/repository/views/repo_files.py @@ -381,7 +381,7 @@ class RepoFilesView(RepoAppView): try: at_path = commit.get_node(at_path).path or default_at_path except Exception: - return Response(_('No node at path {} for this repository').format(at_path)) + return Response(_('No node at path {} for this repository').format(h.escape(at_path))) # path sha is part of subdir path_sha = '' diff --git a/rhodecode/apps/repository/views/repo_summary.py b/rhodecode/apps/repository/views/repo_summary.py --- a/rhodecode/apps/repository/views/repo_summary.py +++ b/rhodecode/apps/repository/views/repo_summary.py @@ -65,7 +65,8 @@ class RepoSummaryView(RepoAppView): 'repo_summary_commits', repo_name=c.rhodecode_db_repo.repo_name, _query=query_params) - pre_load = ['author', 'branch', 'date', 'message'] + pre_load = self.get_commit_preload_attrs() + try: collection = self.rhodecode_vcs_repo.get_commits( pre_load=pre_load, translate_tags=False) diff --git a/rhodecode/config/middleware.py b/rhodecode/config/middleware.py --- a/rhodecode/config/middleware.py +++ b/rhodecode/config/middleware.py @@ -154,6 +154,7 @@ def not_found_view(request): def error_handler(exception, request): import rhodecode from rhodecode.lib import helpers + from rhodecode.lib.utils2 import str2bool rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode' @@ -205,6 +206,8 @@ def error_handler(exception, request): if c.show_exception_id: store_exception(c.exception_id, exc_info) + c.exception_debug = str2bool(rhodecode.CONFIG.get('debug')) + c.exception_config_ini = rhodecode.CONFIG.get('__file__') response = render_to_response( '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request, diff --git a/rhodecode/config/routing_links.py b/rhodecode/config/routing_links.py --- a/rhodecode/config/routing_links.py +++ b/rhodecode/config/routing_links.py @@ -95,7 +95,7 @@ link_config = [ { "name": "rhodecode_translations", "target": "https://rhodecode.com/translate/enterprise", - "external_target": "https://www.transifex.com/rhodecode/RhodeCode/", + "external_target": "https://explore.transifex.com/rhodecode/RhodeCode/", }, ] diff --git a/rhodecode/i18n/how_to.rst b/rhodecode/i18n/how_to.rst --- a/rhodecode/i18n/how_to.rst +++ b/rhodecode/i18n/how_to.rst @@ -4,7 +4,7 @@ To create a new language Translations are available on transifex under:: - https://www.transifex.com/projects/p/RhodeCode/ + https://explore.transifex.com/rhodecode/RhodeCode/ Log into transifex and request new language translation. diff --git a/rhodecode/lib/_vendor/redis_lock/__init__.py b/rhodecode/lib/_vendor/redis_lock/__init__.py --- a/rhodecode/lib/_vendor/redis_lock/__init__.py +++ b/rhodecode/lib/_vendor/redis_lock/__init__.py @@ -221,7 +221,7 @@ class Lock(object): """ logger = loggers["acquire"] - logger.debug("Getting acquire on %r ...", self._name) + logger.debug("Getting blocking: %s acquire on %r ...", blocking, self._name) if self._held: owner_id = self.get_owner_id() diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -337,11 +337,13 @@ def files_breadcrumbs(repo_name, repo_ty def files_url_data(request): + import urllib matchdict = request.matchdict if 'f_path' not in matchdict: matchdict['f_path'] = '' - + else: + matchdict['f_path'] = urllib.quote(safe_str(matchdict['f_path'])) if 'commit_id' not in matchdict: matchdict['commit_id'] = 'tip' @@ -1679,9 +1681,8 @@ def process_patterns(text_string, repo_n errors = [] new_text = text_string - log.debug('Got %s entries to process', len(active_entries)) + log.debug('Got %s pattern entries to process', len(active_entries)) for uid, entry in active_entries.items(): - log.debug('found issue tracker entry with uid %s', uid) if not (entry['pat'] and entry['url']): log.debug('skipping due to missing data') diff --git a/rhodecode/lib/logging_formatter.py b/rhodecode/lib/logging_formatter.py --- a/rhodecode/lib/logging_formatter.py +++ b/rhodecode/lib/logging_formatter.py @@ -125,20 +125,34 @@ class ColorFormatter(ExceptionAwareForma def _inject_req_id(record): from pyramid.threadlocal import get_current_request + dummy = '00000000-0000-0000-0000-000000000000' + req_id = None + req = get_current_request() - dummy = '00000000-0000-0000-0000-000000000000' - req_id = 'req_id:%-36s' % (getattr(req, 'req_id', dummy)) + if req: + req_id = getattr(req, 'req_id', None) + + req_id = 'req_id:%-36s' % (req_id or dummy) record.req_id = req_id +def _add_log_to_debug_bucket(formatted_record): + from pyramid.threadlocal import get_current_request + req = get_current_request() + if req: + req.req_id_bucket.append(formatted_record) + + class RequestTrackingFormatter(ExceptionAwareFormatter): def format(self, record): _inject_req_id(record) def_record = logging.Formatter.format(self, record) + _add_log_to_debug_bucket(def_record) return def_record class ColorRequestTrackingFormatter(ColorFormatter): + def format(self, record): """ Changes record's levelname to use with COLORS enum @@ -150,6 +164,7 @@ class ColorRequestTrackingFormatter(Colo end = RESET_SEQ colored_record = ''.join([start, def_record, end]) + _add_log_to_debug_bucket(def_record) return colored_record diff --git a/rhodecode/lib/rc_cache/backends.py b/rhodecode/lib/rc_cache/backends.py --- a/rhodecode/lib/rc_cache/backends.py +++ b/rhodecode/lib/rc_cache/backends.py @@ -36,6 +36,7 @@ from dogpile.cache.util import memoized_ from pyramid.settings import asbool from rhodecode.lib.memory_lru_dict import LRUDict, LRUDictDebug +from rhodecode.lib.utils import safe_str _default_max_size = 1024 @@ -167,7 +168,7 @@ class FileNamespaceBackend(PickleSeriali try: super(FileNamespaceBackend, self).__init__(arguments) except Exception: - log.error('Failed to initialize db at: %s', db_file) + log.exception('Failed to initialize db at: %s', db_file) raise def __repr__(self): @@ -299,7 +300,7 @@ class BaseRedisBackend(redis_backend.Red def get_mutex(self, key): if self.distributed_lock: - lock_key = redis_backend.u('_lock_{0}').format(key) + lock_key = redis_backend.u('_lock_{0}').format(safe_str(key)) return get_mutex_lock(self.client, lock_key, self._lock_timeout, auto_renewal=self._lock_auto_renewal) else: diff --git a/rhodecode/lib/request.py b/rhodecode/lib/request.py --- a/rhodecode/lib/request.py +++ b/rhodecode/lib/request.py @@ -24,6 +24,15 @@ from pyramid.request import Request as _ class Request(_Request): + _req_id_bucket = list() + @reify def req_id(self): return str(uuid4()) + + @property + def req_id_bucket(self): + return self._req_id_bucket + + def req_id_records_init(self): + self._req_id_bucket = list() diff --git a/rhodecode/lib/vcs/backends/base.py b/rhodecode/lib/vcs/backends/base.py --- a/rhodecode/lib/vcs/backends/base.py +++ b/rhodecode/lib/vcs/backends/base.py @@ -875,6 +875,9 @@ class BaseRepository(object): def get_hooks_info(self): return self._remote.get_hooks_info() + def vcsserver_invalidate_cache(self, delete=False): + return self._remote.vcsserver_invalidate_cache(delete) + class BaseCommit(object): """ diff --git a/rhodecode/lib/vcs/backends/git/repository.py b/rhodecode/lib/vcs/backends/git/repository.py --- a/rhodecode/lib/vcs/backends/git/repository.py +++ b/rhodecode/lib/vcs/backends/git/repository.py @@ -54,7 +54,7 @@ class GitRepository(BaseRepository): """ Git repository backend. """ - DEFAULT_BRANCH_NAME = 'master' + DEFAULT_BRANCH_NAME = os.environ.get('GIT_DEFAULT_BRANCH_NAME') or 'master' contact = BaseRepository.DEFAULT_CONTACT diff --git a/rhodecode/lib/vcs/client_http.py b/rhodecode/lib/vcs/client_http.py --- a/rhodecode/lib/vcs/client_http.py +++ b/rhodecode/lib/vcs/client_http.py @@ -37,6 +37,8 @@ import requests from requests.packages.urllib3.util.retry import Retry import rhodecode +from rhodecode.lib import rc_cache +from rhodecode.lib.rc_cache.utils import compute_key_from_params from rhodecode.lib.system_info import get_cert_path from rhodecode.lib.vcs import exceptions, CurlSession @@ -127,7 +129,6 @@ class ServiceConnection(object): def __getattr__(self, name): def f(*args, **kwargs): return self._call(name, *args, **kwargs) - return f @exceptions.map_vcs_exceptions @@ -150,6 +151,12 @@ class RemoteVCSMaker(object): self._session_factory = session_factory self.backend_type = backend_type + @classmethod + def init_cache_region(cls, repo_id): + cache_namespace_uid = 'cache_repo.{}'.format(repo_id) + region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid) + return region, cache_namespace_uid + def __call__(self, path, repo_id, config, with_wire=None): log.debug('%s RepoMaker call on %s', self.backend_type.upper(), path) return RemoteRepo(path, repo_id, config, self, with_wire=with_wire) @@ -178,6 +185,8 @@ class RemoteRepo(object): self.url = remote_maker.url self.stream_url = remote_maker.stream_url self._session = remote_maker._session_factory() + self._cache_region, self._cache_namespace = \ + remote_maker.init_cache_region(self._repo_id_sanitizer(repo_id)) with_wire = with_wire or {} @@ -200,6 +209,9 @@ class RemoteRepo(object): self.cert_dir = get_cert_path(rhodecode.CONFIG.get('__file__')) + def _repo_id_sanitizer(self, repo_id): + return repo_id.replace('/', '__') + def __getattr__(self, name): if name.startswith('stream:'): @@ -233,11 +245,34 @@ class RemoteRepo(object): url = self.url start = time.time() - if self._call_with_logging: - log.debug('Calling %s@%s with args:%.10240r. wire_context: %s', - url, name, args, context_uid) + + cache_on = False + cache_key = '' + local_cache_on = rhodecode.CONFIG.get('vcs.methods.cache') + + cache_methods = [ + 'branches', 'tags', 'bookmarks', + 'is_large_file', 'is_binary', 'fctx_size', 'node_history', 'blob_raw_length', + 'revision', 'tree_items', + 'ctx_list', + 'bulk_request', + ] - result = _remote_call(url, payload, EXCEPTIONS_MAP, self._session) + if local_cache_on and name in cache_methods: + cache_on = True + repo_state_uid = self._wire['repo_state_uid'] + call_args = [a for a in args] + cache_key = compute_key_from_params(repo_state_uid, name, *call_args) + + @self._cache_region.conditional_cache_on_arguments( + namespace=self._cache_namespace, condition=cache_on and cache_key) + def remote_call(_cache_key): + if self._call_with_logging: + log.debug('Calling %s@%s with args:%.10240r. wire_context: %s cache_on: %s', + url, name, args, context_uid, cache_on) + return _remote_call(url, payload, EXCEPTIONS_MAP, self._session) + + result = remote_call(cache_key) if self._call_with_logging: log.debug('Call %s@%s took: %.4fs. wire_context: %s', url, name, time.time()-start, context_uid) diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py --- a/rhodecode/model/repo.py +++ b/rhodecode/model/repo.py @@ -467,6 +467,9 @@ class RepoModel(BaseModel): RepoModel().grant_user_permission( repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM ) + if kwargs.get('repo_landing_rev'): + landing_rev_val = kwargs['repo_landing_rev'] + RepoModel().set_landing_rev(cur_repo, landing_rev_val) # handle extra fields for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs): @@ -933,6 +936,13 @@ class RepoModel(BaseModel): if field: self.sa.delete(field) + def set_landing_rev(self, repo, landing_rev_name): + if landing_rev_name.startswith('branch:'): + landing_rev_name = landing_rev_name.split('branch:')[-1] + scm_instance = repo.scm_instance() + if scm_instance: + return scm_instance._remote.set_head_ref(landing_rev_name) + def _create_filesystem_repo(self, repo_name, repo_type, repo_group, clone_uri=None, repo_store_location=None, use_global_config=False, install_hooks=True): diff --git a/rhodecode/model/validation_schema/validators.py b/rhodecode/model/validation_schema/validators.py --- a/rhodecode/model/validation_schema/validators.py +++ b/rhodecode/model/validation_schema/validators.py @@ -139,7 +139,7 @@ class CloneUriValidator(object): raise colander.Invalid(node, e.message) except Exception: log.exception('Url validation failed') - msg = _(u'invalid clone url for {repo_type} repository').format( + msg = _(u'invalid clone url or credentials for {repo_type} repository').format( repo_type=self.repo_type) raise colander.Invalid(node, msg) diff --git a/rhodecode/model/validators.py b/rhodecode/model/validators.py --- a/rhodecode/model/validators.py +++ b/rhodecode/model/validators.py @@ -624,7 +624,7 @@ def ValidCloneUri(localizer): class _validator(formencode.validators.FancyValidator): messages = { - 'clone_uri': _(u'invalid clone url for %(rtype)s repository'), + 'clone_uri': _(u'invalid clone url or credentials for %(rtype)s repository'), 'invalid_clone_uri': _( u'Invalid clone url, provide a valid clone ' u'url starting with one of %(allowed_prefixes)s') diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js --- a/rhodecode/public/js/rhodecode/routes.js +++ b/rhodecode/public/js/rhodecode/routes.js @@ -244,6 +244,7 @@ function registerRCRoutes() { pyroutes.register('notifications_show_all', '/_admin/notifications', []); pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']); pyroutes.register('ops_error_test', '/_admin/ops/error', []); + pyroutes.register('ops_healthcheck', '/_admin/ops/status', []); pyroutes.register('ops_ping', '/_admin/ops/ping', []); pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []); pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']); diff --git a/rhodecode/subscribers.py b/rhodecode/subscribers.py --- a/rhodecode/subscribers.py +++ b/rhodecode/subscribers.py @@ -106,6 +106,14 @@ def add_request_user_context(event): request.environ['rc_req_id'] = req_id +def reset_log_bucket(event): + """ + reset the log bucket on new request + """ + request = event.request + request.req_id_records_init() + + def scan_repositories_if_enabled(event): """ This is subscribed to the `pyramid.events.ApplicationCreated` event. It diff --git a/rhodecode/templates/admin/settings/settings_system.mako b/rhodecode/templates/admin/settings/settings_system.mako --- a/rhodecode/templates/admin/settings/settings_system.mako +++ b/rhodecode/templates/admin/settings/settings_system.mako @@ -62,6 +62,25 @@ +
+
+

${_('Env Variables')}

+
+
+ + + + % for env_key, env_val in c.env_data: + + + + + % endfor +
${env_key}${env_val}
+ +
+
+