release: Merge default into stable for release preparation
This commit is contained in:
commit
a507d3e7f6
39 changed files with 306 additions and 60 deletions
|
|
@ -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]
|
||||
|
|
|
|||
10
.release.cfg
10
.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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
58
docs/release-notes/release-notes-4.27.0.rst
Normal file
58
docs/release-notes/release-notes-4.27.0.rst
Normal file
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"; } ];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
4.26.0
|
||||
4.27.0
|
||||
|
|
@ -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):
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@
|
|||
|
||||
import logging
|
||||
import urllib2
|
||||
|
||||
|
||||
import os
|
||||
|
||||
import rhodecode
|
||||
from rhodecode.apps._base import BaseAppView
|
||||
|
|
@ -40,6 +39,40 @@ class AdminSystemInfoSettingsView(BaseAppView):
|
|||
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(BaseAppView):
|
|||
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():
|
||||
|
|
|
|||
|
|
@ -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')})
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 = ''
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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/",
|
||||
},
|
||||
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -337,11 +337,13 @@ def files_breadcrumbs(repo_name, repo_type, commit_id, file_path, landing_ref_na
|
|||
|
||||
|
||||
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_name, link_format='html', active_entries=
|
|||
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')
|
||||
|
|
|
|||
|
|
@ -125,20 +125,34 @@ class ColorFormatter(ExceptionAwareFormatter):
|
|||
|
||||
def _inject_req_id(record):
|
||||
from pyramid.threadlocal import get_current_request
|
||||
req = get_current_request()
|
||||
dummy = '00000000-0000-0000-0000-000000000000'
|
||||
req_id = 'req_id:%-36s' % (getattr(req, 'req_id', dummy))
|
||||
req_id = None
|
||||
|
||||
req = get_current_request()
|
||||
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(ColorFormatter):
|
|||
end = RESET_SEQ
|
||||
|
||||
colored_record = ''.join([start, def_record, end])
|
||||
_add_log_to_debug_bucket(def_record)
|
||||
return colored_record
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ from dogpile.cache.util import memoized_property
|
|||
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(PickleSerializer, file_backend.DBMBackend):
|
|||
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.RedisBackend):
|
|||
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@ from pyramid.request import Request as _Request
|
|||
|
||||
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
result = _remote_call(url, payload, EXCEPTIONS_MAP, self._session)
|
||||
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',
|
||||
]
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -62,6 +62,25 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">${_('Env Variables')}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table>
|
||||
<th></th>
|
||||
<th></th>
|
||||
% for env_key, env_val in c.env_data:
|
||||
<tr>
|
||||
<td style="vertical-align: top">${env_key}</td>
|
||||
<td>${env_val}</td>
|
||||
</tr>
|
||||
% endfor
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$('#check_for_update').click(function(e){
|
||||
$('#update_notice').show();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@
|
|||
${h.secure_form(h.route_path('user_update', user_id=c.user.user_id), class_='form', request=request)}
|
||||
<% readonly = None %>
|
||||
<% disabled = "" %>
|
||||
%if c.extern_type != 'rhodecode':
|
||||
% if c.edit_mode:
|
||||
${h.hidden('edit', '1')}
|
||||
% endif
|
||||
%if c.extern_type != 'rhodecode' and not c.edit_mode:
|
||||
<% readonly = "readonly" %>
|
||||
<% disabled = " disabled" %>
|
||||
<div class="alert-warning" style="margin:0px 0px 20px 0px; padding: 10px">
|
||||
|
|
@ -40,6 +43,12 @@
|
|||
</div>
|
||||
<div class="input">
|
||||
${h.text('username', class_='%s medium' % disabled, readonly=readonly)}
|
||||
<br/>
|
||||
% if c.extern_type != 'rhodecode' and c.is_super_admin:
|
||||
<p class="help-block">
|
||||
${_('Super-admin can edit this field by entering ')} <a href="${h.current_route_path(request, edit=1)}">edit mode</a>
|
||||
</p>
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
% endif
|
||||
% else:
|
||||
## SKIP TODOs we display them in other area
|
||||
% if comment_obj.is_todo:
|
||||
% if comment_obj.is_todo and not comment_obj.draft:
|
||||
<% display = 'none' %>
|
||||
% endif
|
||||
## Skip outdated comments
|
||||
|
|
@ -122,12 +122,21 @@
|
|||
'review_status': (comment_obj.review_status or '')
|
||||
})
|
||||
|
||||
icon = ''
|
||||
|
||||
if comment_obj.outdated:
|
||||
icon = 'icon-comment-toggle'
|
||||
icon += ' icon-comment-toggle'
|
||||
elif comment_obj.is_inline:
|
||||
icon = 'icon-code'
|
||||
icon += ' icon-code'
|
||||
else:
|
||||
icon = 'icon-comment'
|
||||
icon += ' icon-comment'
|
||||
|
||||
if comment_obj.draft:
|
||||
if comment_obj.is_todo:
|
||||
icon = 'icon-flag-filled icon-draft'
|
||||
else:
|
||||
icon = 'icon-comment icon-draft'
|
||||
|
||||
%>
|
||||
|
||||
<i id="commentHovercard${comment_obj.comment_id}"
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ if (show_disabled) {
|
|||
<time class="timeago" title="<%= created_on %>" datetime="<%= datetime %>"><%= $.timeago(datetime) %></time>
|
||||
|
||||
<% if (is_todo) { %>
|
||||
<div style="text-align: center; padding-top: 5px">
|
||||
<div style="text-align: left; padding-top: 5px">
|
||||
<a class="btn btn-sm" href="#resolveTodo<%- comment_id -%>" onclick="Rhodecode.comments.resolveTodo(this, '<%- comment_id -%>'); return false">
|
||||
<strong>Resolve TODO</strong>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -84,6 +84,24 @@
|
|||
|
||||
Super-admins can see details of the above error in the exception tracker found under
|
||||
<a href="${h.route_url('admin_settings_exception_tracker')}">admin > settings > exception tracker</a>.
|
||||
|
||||
% if c.exception_debug:
|
||||
<pre>
|
||||
<strong>DEBUG MODE ON FOR EXCEPTION: ${c.exception_id}</strong>
|
||||
<strong>REQUEST_ID: ${getattr(request, 'req_id', None)}</strong>
|
||||
----------------
|
||||
debug mode is controlled by
|
||||
${c.exception_config_ini}
|
||||
file settings:
|
||||
|
||||
debug = true
|
||||
----------------
|
||||
|
||||
% for rec in getattr(request, 'req_id_bucket', []):
|
||||
${rec}
|
||||
% endfor
|
||||
</pre>
|
||||
% endif
|
||||
</p>
|
||||
</div>
|
||||
% endif
|
||||
|
|
|
|||
|
|
@ -564,7 +564,6 @@
|
|||
<input name="select_all_drafts" type="checkbox" onclick="selectDraftComments(event)">
|
||||
</span>
|
||||
<span class="sidebar-heading noselect" onclick="refreshDraftComments(); return false">
|
||||
<i class="icon-comment icon-draft"></i>
|
||||
${_('Drafts')}
|
||||
</span>
|
||||
<span class="block-right action_button last-item" onclick="submitDrafts(event)">${_('Submit')}</span>
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ def includeme(config):
|
|||
'pyramid.events.NewRequest')
|
||||
config.add_subscriber('rhodecode.subscribers.add_localizer',
|
||||
'pyramid.events.NewRequest')
|
||||
config.add_subscriber('rhodecode.subscribers.reset_log_bucket',
|
||||
'pyramid.events.NewRequest')
|
||||
config.add_subscriber('rhodecode.subscribers.add_request_user_context',
|
||||
'pyramid.events.ContextFound')
|
||||
config.add_tween('rhodecode.tweens.vcs_detection_tween_factory')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue