fix(apps): fixed readme generator from async to sync runner.

This caused some issues with threadlocals, this isn't safe to use at this moment and was a regression
This commit is contained in:
RhodeCode Admin 2023-11-16 08:10:20 +01:00
parent 30953604b1
commit 95a81d966d

View file

@ -26,7 +26,11 @@ from rhodecode.lib import helpers as h, diffs, rc_cache
from rhodecode.lib.str_utils import safe_str
from rhodecode.lib.utils import repo_name_slug
from rhodecode.lib.utils2 import (
StrictAttributeDict, str2bool, safe_int, datetime_to_time)
StrictAttributeDict,
str2bool,
safe_int,
datetime_to_time,
)
from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
from rhodecode.lib.vcs.backends.base import EmptyCommit
from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
@ -42,27 +46,27 @@ from rhodecode.model.repo import ReadmeFinder
log = logging.getLogger(__name__)
ADMIN_PREFIX: str = '/_admin'
STATIC_FILE_PREFIX: str = '/_static'
ADMIN_PREFIX: str = "/_admin"
STATIC_FILE_PREFIX: str = "/_static"
URL_NAME_REQUIREMENTS = {
# group name can have a slash in them, but they must not end with a slash
'group_name': r'.*?[^/]',
'repo_group_name': r'.*?[^/]',
"group_name": r".*?[^/]",
"repo_group_name": r".*?[^/]",
# repo names can have a slash in them, but they must not end with a slash
'repo_name': r'.*?[^/]',
"repo_name": r".*?[^/]",
# file path eats up everything at the end
'f_path': r'.*',
"f_path": r".*",
# reference types
'source_ref_type': r'(branch|book|tag|rev|\%\(source_ref_type\)s)',
'target_ref_type': r'(branch|book|tag|rev|\%\(target_ref_type\)s)',
"source_ref_type": r"(branch|book|tag|rev|\%\(source_ref_type\)s)",
"target_ref_type": r"(branch|book|tag|rev|\%\(target_ref_type\)s)",
}
def add_route_with_slash(config,name, pattern, **kw):
def add_route_with_slash(config, name, pattern, **kw):
config.add_route(name, pattern, **kw)
if not pattern.endswith('/'):
config.add_route(name + '_slash', pattern + '/', **kw)
if not pattern.endswith("/"):
config.add_route(name + "_slash", pattern + "/", **kw)
def add_route_requirements(route_path, requirements=None):
@ -73,7 +77,7 @@ def add_route_requirements(route_path, requirements=None):
"""
requirements = requirements or URL_NAME_REQUIREMENTS
for key, regex in list(requirements.items()):
route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
route_path = route_path.replace("{%s}" % key, "{%s:%s}" % (key, regex))
return route_path
@ -92,7 +96,7 @@ def _format_ref_id(name, raw_id):
def _format_ref_id_svn(name, raw_id):
"""Special way of formatting a reference for Subversion including path"""
return f'{name}@{raw_id}'
return f"{name}@{raw_id}"
class TemplateArgs(StrictAttributeDict):
@ -100,38 +104,37 @@ class TemplateArgs(StrictAttributeDict):
class BaseAppView(object):
def __init__(self, context, request):
self.request = request
self.context = context
self.session = request.session
if not hasattr(request, 'user'):
if not hasattr(request, "user"):
# NOTE(marcink): edge case, we ended up in matched route
# but probably of web-app context, e.g API CALL/VCS CALL
if hasattr(request, 'vcs_call') or hasattr(request, 'rpc_method'):
log.warning('Unable to process request `%s` in this scope', request)
if hasattr(request, "vcs_call") or hasattr(request, "rpc_method"):
log.warning("Unable to process request `%s` in this scope", request)
raise HTTPBadRequest()
self._rhodecode_user = request.user # auth user
self._rhodecode_db_user = self._rhodecode_user.get_instance()
self._maybe_needs_password_change(
request.matched_route.name, self._rhodecode_db_user)
request.matched_route.name, self._rhodecode_db_user
)
def _maybe_needs_password_change(self, view_name, user_obj):
dont_check_views = [
'channelstream_connect',
'ops_ping'
]
dont_check_views = ["channelstream_connect", "ops_ping"]
if view_name in dont_check_views:
return
log.debug('Checking if user %s needs password change on view %s',
user_obj, view_name)
log.debug(
"Checking if user %s needs password change on view %s", user_obj, view_name
)
skip_user_views = [
'logout', 'login',
'my_account_password', 'my_account_password_update'
"logout",
"login",
"my_account_password",
"my_account_password_update",
]
if not user_obj:
@ -141,16 +144,18 @@ class BaseAppView(object):
return
now = time.time()
should_change = user_obj.user_data.get('force_password_change')
should_change = user_obj.user_data.get("force_password_change")
change_after = safe_int(should_change) or 0
if should_change and now > change_after:
log.debug('User %s requires password change', user_obj)
h.flash('You are required to change your password', 'warning',
ignore_duplicate=True)
log.debug("User %s requires password change", user_obj)
h.flash(
"You are required to change your password",
"warning",
ignore_duplicate=True,
)
if view_name not in skip_user_views:
raise HTTPFound(
self.request.route_path('my_account_password'))
raise HTTPFound(self.request.route_path("my_account_password"))
def _log_creation_exception(self, e, repo_name):
_ = self.request.translate
@ -158,15 +163,12 @@ class BaseAppView(object):
if len(e.args) == 2:
reason = e.args[1]
if reason == 'INVALID_CERTIFICATE':
log.exception(
'Exception creating a repository: invalid certificate')
msg = (_('Error creating repository %s: invalid certificate')
% repo_name)
if reason == "INVALID_CERTIFICATE":
log.exception("Exception creating a repository: invalid certificate")
msg = _("Error creating repository %s: invalid certificate") % repo_name
else:
log.exception("Exception creating a repository")
msg = (_('Error creating repository %s')
% repo_name)
msg = _("Error creating repository %s") % repo_name
return msg
def _get_local_tmpl_context(self, include_app_defaults=True):
@ -177,6 +179,7 @@ class BaseAppView(object):
if include_app_defaults:
from rhodecode.lib.base import attach_context_attributes
attach_context_attributes(c, self.request, self.request.user.user_id)
c.is_super_admin = c.auth_user.is_admin
@ -188,28 +191,28 @@ class BaseAppView(object):
c.is_delegated_admin = False
if not c.auth_user.is_default and not c.is_super_admin:
c.can_create_repo = h.HasPermissionAny('hg.create.repository')(
user=self.request.user)
c.can_create_repo = h.HasPermissionAny("hg.create.repository")(
user=self.request.user
)
repositories = c.auth_user.repositories_admin or c.can_create_repo
c.can_create_repo_group = h.HasPermissionAny('hg.repogroup.create.true')(
user=self.request.user)
repository_groups = c.auth_user.repository_groups_admin or c.can_create_repo_group
c.can_create_repo_group = h.HasPermissionAny("hg.repogroup.create.true")(
user=self.request.user
)
repository_groups = (
c.auth_user.repository_groups_admin or c.can_create_repo_group
)
c.can_create_user_group = h.HasPermissionAny('hg.usergroup.create.true')(
user=self.request.user)
c.can_create_user_group = h.HasPermissionAny("hg.usergroup.create.true")(
user=self.request.user
)
user_groups = c.auth_user.user_groups_admin or c.can_create_user_group
# delegated admin can create, or manage some objects
c.is_delegated_admin = repositories or repository_groups or user_groups
return c
def _get_template_context(self, tmpl_args, **kwargs):
local_tmpl_args = {
'defaults': {},
'errors': {},
'c': tmpl_args
}
local_tmpl_args = {"defaults": {}, "errors": {}, "c": tmpl_args}
local_tmpl_args.update(kwargs)
return local_tmpl_args
@ -223,11 +226,10 @@ class BaseAppView(object):
return c
"""
raise NotImplementedError('Needs implementation in view class')
raise NotImplementedError("Needs implementation in view class")
class RepoAppView(BaseAppView):
def __init__(self, context, request):
super().__init__(context, request)
self.db_repo = request.db_repo
@ -238,11 +240,13 @@ class RepoAppView(BaseAppView):
def _handle_missing_requirements(self, error):
log.error(
'Requirements are missing for repository %s: %s',
self.db_repo_name, safe_str(error))
"Requirements are missing for repository %s: %s",
self.db_repo_name,
safe_str(error),
)
def _prepare_and_set_clone_url(self, c):
username = ''
username = ""
if self._rhodecode_user.username != User.DEFAULT_USER:
username = self._rhodecode_user.username
@ -251,16 +255,18 @@ class RepoAppView(BaseAppView):
_def_clone_uri_ssh = c.clone_uri_ssh_tmpl
c.clone_repo_url = self.db_repo.clone_url(
user=username, uri_tmpl=_def_clone_uri)
user=username, uri_tmpl=_def_clone_uri
)
c.clone_repo_url_id = self.db_repo.clone_url(
user=username, uri_tmpl=_def_clone_uri_id)
user=username, uri_tmpl=_def_clone_uri_id
)
c.clone_repo_url_ssh = self.db_repo.clone_url(
uri_tmpl=_def_clone_uri_ssh, ssh=True)
uri_tmpl=_def_clone_uri_ssh, ssh=True
)
def _get_local_tmpl_context(self, include_app_defaults=True):
_ = self.request.translate
c = super()._get_local_tmpl_context(
include_app_defaults=include_app_defaults)
c = super()._get_local_tmpl_context(include_app_defaults=include_app_defaults)
# register common vars for this type of view
c.rhodecode_db_repo = self.db_repo
@ -268,7 +274,8 @@ class RepoAppView(BaseAppView):
c.repository_pull_requests = self.db_repo_pull_requests
c.repository_artifacts = self.db_repo_artifacts
c.repository_is_user_following = ScmModel().is_following_repo(
self.db_repo_name, self._rhodecode_user.user_id)
self.db_repo_name, self._rhodecode_user.user_id
)
self.path_filter = PathFilter(None)
c.repository_requirements_missing = {}
@ -279,10 +286,11 @@ class RepoAppView(BaseAppView):
# calculate
if self.rhodecode_vcs_repo is not None:
path_perms = self.rhodecode_vcs_repo.get_path_permissions(
c.auth_user.username)
c.auth_user.username
)
self.path_filter = PathFilter(path_perms)
except RepositoryRequirementError as e:
c.repository_requirements_missing = {'error': str(e)}
c.repository_requirements_missing = {"error": str(e)}
self._handle_missing_requirements(e)
self.rhodecode_vcs_repo = None
@ -290,29 +298,36 @@ class RepoAppView(BaseAppView):
if self.rhodecode_vcs_repo is None:
# unable to fetch this repo as vcs instance, report back to user
log.debug('Repository was not found on filesystem, check if it exists or is not damaged')
h.flash(_(
"The repository `%(repo_name)s` cannot be loaded in filesystem. "
"Please check if it exist, or is not damaged.") %
{'repo_name': c.repo_name},
category='error', ignore_duplicate=True)
log.debug(
"Repository was not found on filesystem, check if it exists or is not damaged"
)
h.flash(
_(
"The repository `%(repo_name)s` cannot be loaded in filesystem. "
"Please check if it exist, or is not damaged."
)
% {"repo_name": c.repo_name},
category="error",
ignore_duplicate=True,
)
if c.repository_requirements_missing:
route = self.request.matched_route.name
if route.startswith(('edit_repo', 'repo_summary')):
if route.startswith(("edit_repo", "repo_summary")):
# allow summary and edit repo on missing requirements
return c
raise HTTPFound(
h.route_path('repo_summary', repo_name=self.db_repo_name))
h.route_path("repo_summary", repo_name=self.db_repo_name)
)
else: # redirect if we don't show missing requirements
raise HTTPFound(h.route_path('home'))
raise HTTPFound(h.route_path("home"))
c.has_origin_repo_read_perm = False
if self.db_repo.fork:
c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
'repository.write', 'repository.read', 'repository.admin')(
self.db_repo.fork.repo_name, 'summary fork link')
"repository.write", "repository.read", "repository.admin"
)(self.db_repo.fork.repo_name, "summary fork link")
return c
@ -320,10 +335,10 @@ class RepoAppView(BaseAppView):
"""
Should only be used by redirects, everything else should call _get_f_path
"""
f_path = matchdict.get('f_path')
f_path = matchdict.get("f_path")
if f_path:
# fix for multiple initial slashes that causes errors for GIT
return f_path.lstrip('/')
return f_path.lstrip("/")
return default
@ -341,8 +356,8 @@ class RepoAppView(BaseAppView):
settings = settings_model.get_repo_settings_inherited()
return settings.get(settings_key, default)
def _get_readme_data(self, db_repo, renderer_type, commit_id=None, path='/'):
log.debug('Looking for README file at path %s', path)
def _get_readme_data(self, db_repo, renderer_type, commit_id=None, path="/"):
log.debug("Looking for README file at path %s", path)
if commit_id:
landing_commit_id = commit_id
else:
@ -351,49 +366,73 @@ class RepoAppView(BaseAppView):
return None, None
landing_commit_id = landing_commit.raw_id
cache_namespace_uid = f'repo.{db_repo.repo_id}'
region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid, use_async_runner=True)
cache_namespace_uid = f"repo.{db_repo.repo_id}"
region = rc_cache.get_or_create_region(
"cache_repo", cache_namespace_uid, use_async_runner=False
)
start = time.time()
@region.conditional_cache_on_arguments(namespace=cache_namespace_uid)
def generate_repo_readme(repo_id, _commit_id, _repo_name, _readme_search_path, _renderer_type):
def generate_repo_readme(
repo_id, _commit_id, _repo_name, _readme_search_path, _renderer_type
):
readme_data = None
readme_filename = None
commit = db_repo.get_commit(_commit_id)
log.debug("Searching for a README file at commit %s.", _commit_id)
readme_node = ReadmeFinder(_renderer_type).search(commit, path=_readme_search_path)
readme_node = ReadmeFinder(_renderer_type).search(
commit, path=_readme_search_path
)
if readme_node:
log.debug('Found README node: %s', readme_node)
log.debug("Found README node: %s", readme_node)
relative_urls = {
'raw': h.route_path(
'repo_file_raw', repo_name=_repo_name,
commit_id=commit.raw_id, f_path=readme_node.path),
'standard': h.route_path(
'repo_files', repo_name=_repo_name,
commit_id=commit.raw_id, f_path=readme_node.path),
"raw": h.route_path(
"repo_file_raw",
repo_name=_repo_name,
commit_id=commit.raw_id,
f_path=readme_node.path,
),
"standard": h.route_path(
"repo_files",
repo_name=_repo_name,
commit_id=commit.raw_id,
f_path=readme_node.path,
),
}
readme_data = self._render_readme_or_none(commit, readme_node, relative_urls)
readme_data = self._render_readme_or_none(
commit, readme_node, relative_urls
)
readme_filename = readme_node.str_path
return readme_data, readme_filename
readme_data, readme_filename = generate_repo_readme(
db_repo.repo_id, landing_commit_id, db_repo.repo_name, path, renderer_type,)
db_repo.repo_id,
landing_commit_id,
db_repo.repo_name,
path,
renderer_type,
)
compute_time = time.time() - start
log.debug('Repo README for path %s generated and computed in %.4fs',
path, compute_time)
log.debug(
"Repo README for path %s generated and computed in %.4fs",
path,
compute_time,
)
return readme_data, readme_filename
def _render_readme_or_none(self, commit, readme_node, relative_urls):
log.debug('Found README file `%s` rendering...', readme_node.path)
log.debug("Found README file `%s` rendering...", readme_node.path)
renderer = MarkupRenderer()
try:
html_source = renderer.render(
readme_node.str_content, filename=readme_node.path)
readme_node.str_content, filename=readme_node.path
)
if relative_urls:
return relative_links(html_source, relative_urls)
return html_source
@ -401,20 +440,27 @@ class RepoAppView(BaseAppView):
log.exception("Exception while trying to render the README")
def get_recache_flag(self):
for flag_name in ['force_recache', 'force-recache', 'no-cache']:
for flag_name in ["force_recache", "force-recache", "no-cache"]:
flag_val = self.request.GET.get(flag_name)
if str2bool(flag_val):
return True
return False
def get_commit_preload_attrs(cls):
pre_load = ['author', 'branch', 'date', 'message', 'parents',
'obsolete', 'phase', 'hidden']
pre_load = [
"author",
"branch",
"date",
"message",
"parents",
"obsolete",
"phase",
"hidden",
]
return pre_load
class PathFilter(object):
# Expects and instance of BasePathPermissionChecker or None
def __init__(self, permission_checker):
self.permission_checker = permission_checker
@ -425,13 +471,15 @@ class PathFilter(object):
raise HTTPForbidden()
def path_access_allowed(self, path):
log.debug('Checking ACL permissions for PathFilter for `%s`', path)
log.debug("Checking ACL permissions for PathFilter for `%s`", path)
if self.permission_checker:
has_access = path and self.permission_checker.has_access(path)
log.debug('ACL Permissions checker enabled, ACL Check has_access: %s', has_access)
log.debug(
"ACL Permissions checker enabled, ACL Check has_access: %s", has_access
)
return has_access
log.debug('ACL permissions checker not enabled, skipping...')
log.debug("ACL permissions checker not enabled, skipping...")
return True
def filter_patchset(self, patchset):
@ -440,23 +488,27 @@ class PathFilter(object):
had_filtered = False
filtered_patchset = []
for patch in patchset:
filename = patch.get('filename', None)
filename = patch.get("filename", None)
if not filename or self.permission_checker.has_access(filename):
filtered_patchset.append(patch)
else:
had_filtered = True
if had_filtered:
if isinstance(patchset, diffs.LimitedDiffContainer):
filtered_patchset = diffs.LimitedDiffContainer(patchset.diff_limit, patchset.cur_diff_size, filtered_patchset)
filtered_patchset = diffs.LimitedDiffContainer(
patchset.diff_limit, patchset.cur_diff_size, filtered_patchset
)
return filtered_patchset, True
else:
return patchset, False
def render_patchset_filtered(self, diffset, patchset, source_ref=None, target_ref=None):
def render_patchset_filtered(
self, diffset, patchset, source_ref=None, target_ref=None
):
filtered_patchset, has_hidden_changes = self.filter_patchset(patchset)
result = diffset.render_patchset(
filtered_patchset, source_ref=source_ref, target_ref=target_ref)
filtered_patchset, source_ref=source_ref, target_ref=target_ref
)
result.has_hidden_changes = has_hidden_changes
return result
@ -466,7 +518,7 @@ class PathFilter(object):
elif self.permission_checker.has_full_access:
return diff_processor.as_raw()
else:
return '# Repository has user-specific filters, raw patch generation is disabled.'
return "# Repository has user-specific filters, raw patch generation is disabled."
@property
def is_enabled(self):
@ -481,19 +533,35 @@ class RepoGroupAppView(BaseAppView):
def _get_local_tmpl_context(self, include_app_defaults=True):
_ = self.request.translate
c = super()._get_local_tmpl_context(
include_app_defaults=include_app_defaults)
c = super()._get_local_tmpl_context(include_app_defaults=include_app_defaults)
c.repo_group = self.db_repo_group
return c
def _revoke_perms_on_yourself(self, form_result):
_updates = [u for u in form_result['perm_updates'] if self._rhodecode_user.user_id == int(u[0])]
_additions = [u for u in form_result['perm_additions'] if self._rhodecode_user.user_id == int(u[0])]
_deletions = [u for u in form_result['perm_deletions'] if self._rhodecode_user.user_id == int(u[0])]
admin_perm = 'group.admin'
if _updates and _updates[0][1] != admin_perm or \
_additions and _additions[0][1] != admin_perm or \
_deletions and _deletions[0][1] != admin_perm:
_updates = [
u
for u in form_result["perm_updates"]
if self._rhodecode_user.user_id == int(u[0])
]
_additions = [
u
for u in form_result["perm_additions"]
if self._rhodecode_user.user_id == int(u[0])
]
_deletions = [
u
for u in form_result["perm_deletions"]
if self._rhodecode_user.user_id == int(u[0])
]
admin_perm = "group.admin"
if (
_updates
and _updates[0][1] != admin_perm
or _additions
and _additions[0][1] != admin_perm
or _deletions
and _deletions[0][1] != admin_perm
):
return True
return False
@ -514,9 +582,11 @@ class UserAppView(BaseAppView):
_ = self.request.translate
if not request.db_user_supports_default:
if self.db_user.username == User.DEFAULT_USER:
h.flash(_("Editing user `{}` is disabled.".format(
User.DEFAULT_USER)), category='warning')
raise HTTPFound(h.route_path('users'))
h.flash(
_("Editing user `{}` is disabled.".format(User.DEFAULT_USER)),
category="warning",
)
raise HTTPFound(h.route_path("users"))
class DataGridAppView(object):
@ -526,22 +596,20 @@ class DataGridAppView(object):
def _extract_ordering(self, request, column_map=None):
column_map = column_map or {}
column_index = safe_int(request.GET.get('order[0][column]'))
order_dir = request.GET.get(
'order[0][dir]', 'desc')
order_by = request.GET.get(
'columns[%s][data][sort]' % column_index, 'name_raw')
column_index = safe_int(request.GET.get("order[0][column]"))
order_dir = request.GET.get("order[0][dir]", "desc")
order_by = request.GET.get("columns[%s][data][sort]" % column_index, "name_raw")
# translate datatable to DB columns
order_by = column_map.get(order_by) or order_by
search_q = request.GET.get('search[value]')
search_q = request.GET.get("search[value]")
return search_q, order_by, order_dir
def _extract_chunk(self, request):
start = safe_int(request.GET.get('start'), 0)
length = safe_int(request.GET.get('length'), 25)
draw = safe_int(request.GET.get('draw'))
start = safe_int(request.GET.get("start"), 0)
length = safe_int(request.GET.get("length"), 25)
draw = safe_int(request.GET.get("draw"))
return draw, start, length
def _get_order_col(self, order_by, model):
@ -558,6 +626,7 @@ class BaseReferencesView(RepoAppView):
"""
Base for reference view for branches, tags and bookmarks.
"""
def load_default_context(self):
c = self._get_local_tmpl_context()
return c
@ -578,42 +647,47 @@ class BaseReferencesView(RepoAppView):
data = []
for ref_name, commit_id in ref_items:
commit = self.rhodecode_vcs_repo.get_commit(
commit_id=commit_id, pre_load=pre_load)
commit_id=commit_id, pre_load=pre_load
)
closed = ref_name in closed_refs
# TODO: johbo: Unify generation of reference links
use_commit_id = '/' in ref_name or is_svn
use_commit_id = "/" in ref_name or is_svn
if use_commit_id:
files_url = h.route_path(
'repo_files',
"repo_files",
repo_name=self.db_repo_name,
f_path=ref_name if is_svn else '',
f_path=ref_name if is_svn else "",
commit_id=commit_id,
_query=dict(at=ref_name)
_query=dict(at=ref_name),
)
else:
files_url = h.route_path(
'repo_files',
"repo_files",
repo_name=self.db_repo_name,
f_path=ref_name if is_svn else '',
f_path=ref_name if is_svn else "",
commit_id=ref_name,
_query=dict(at=ref_name)
_query=dict(at=ref_name),
)
data.append({
"name": _render('name', ref_name, files_url, closed),
"name_raw": ref_name,
"date": _render('date', commit.date),
"date_raw": datetime_to_time(commit.date),
"author": _render('author', commit.author),
"commit": _render(
'commit', commit.message, commit.raw_id, commit.idx),
"commit_raw": commit.idx,
"compare": _render(
'compare', format_ref_id(ref_name, commit.raw_id)),
})
data.append(
{
"name": _render("name", ref_name, files_url, closed),
"name_raw": ref_name,
"date": _render("date", commit.date),
"date_raw": datetime_to_time(commit.date),
"author": _render("author", commit.author),
"commit": _render(
"commit", commit.message, commit.raw_id, commit.idx
),
"commit_raw": commit.idx,
"compare": _render(
"compare", format_ref_id(ref_name, commit.raw_id)
),
}
)
return data
@ -623,23 +697,25 @@ class RepoRoutePredicate(object):
self.val = val
def text(self):
return f'repo_route = {self.val}'
return f"repo_route = {self.val}"
phash = text
def __call__(self, info, request):
if hasattr(request, 'vcs_call'):
if hasattr(request, "vcs_call"):
# skip vcs calls
return
repo_name = info['match']['repo_name']
repo_name = info["match"]["repo_name"]
repo_name_parts = repo_name.split('/')
repo_name_parts = repo_name.split("/")
repo_slugs = [x for x in (repo_name_slug(x) for x in repo_name_parts)]
if repo_name_parts != repo_slugs:
# short-skip if the repo-name doesn't follow slug rule
log.warning('repo_name: %s is different than slug %s', repo_name_parts, repo_slugs)
log.warning(
"repo_name: %s is different than slug %s", repo_name_parts, repo_slugs
)
return False
repo_model = repo.RepoModel()
@ -647,8 +723,8 @@ class RepoRoutePredicate(object):
by_name_match = repo_model.get_by_repo_name(repo_name, cache=False)
def redirect_if_creating(route_info, db_repo):
skip_views = ['edit_repo_advanced_delete']
route = route_info['route']
skip_views = ["edit_repo_advanced_delete"]
route = route_info["route"]
# we should skip delete view so we can actually "remove" repositories
# if they get stuck in creating state.
if route.name in skip_views:
@ -656,7 +732,8 @@ class RepoRoutePredicate(object):
if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
repo_creating_url = request.route_path(
'repo_creating', repo_name=db_repo.repo_name)
"repo_creating", repo_name=db_repo.repo_name
)
raise HTTPFound(repo_creating_url)
if by_name_match:
@ -682,7 +759,7 @@ class RepoForbidArchivedRoutePredicate(object):
self.val = val
def text(self):
return f'repo_forbid_archived = {self.val}'
return f"repo_forbid_archived = {self.val}"
phash = text
@ -691,47 +768,58 @@ class RepoForbidArchivedRoutePredicate(object):
rhodecode_db_repo = request.db_repo
log.debug(
'%s checking if archived flag for repo for %s',
self.__class__.__name__, rhodecode_db_repo.repo_name)
"%s checking if archived flag for repo for %s",
self.__class__.__name__,
rhodecode_db_repo.repo_name,
)
if rhodecode_db_repo.archived:
log.warning('Current view is not supported for archived repo:%s',
rhodecode_db_repo.repo_name)
log.warning(
"Current view is not supported for archived repo:%s",
rhodecode_db_repo.repo_name,
)
h.flash(
h.literal(_('Action not supported for archived repository.')),
category='warning')
h.literal(_("Action not supported for archived repository.")),
category="warning",
)
summary_url = request.route_path(
'repo_summary', repo_name=rhodecode_db_repo.repo_name)
"repo_summary", repo_name=rhodecode_db_repo.repo_name
)
raise HTTPFound(summary_url)
return True
class RepoTypeRoutePredicate(object):
def __init__(self, val, config):
self.val = val or ['hg', 'git', 'svn']
self.val = val or ["hg", "git", "svn"]
def text(self):
return f'repo_accepted_type = {self.val}'
return f"repo_accepted_type = {self.val}"
phash = text
def __call__(self, info, request):
if hasattr(request, 'vcs_call'):
if hasattr(request, "vcs_call"):
# skip vcs calls
return
rhodecode_db_repo = request.db_repo
log.debug(
'%s checking repo type for %s in %s',
self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
"%s checking repo type for %s in %s",
self.__class__.__name__,
rhodecode_db_repo.repo_type,
self.val,
)
if rhodecode_db_repo.repo_type in self.val:
return True
else:
log.warning('Current view is not supported for repo type:%s',
rhodecode_db_repo.repo_type)
log.warning(
"Current view is not supported for repo type:%s",
rhodecode_db_repo.repo_type,
)
return False
@ -740,22 +828,28 @@ class RepoGroupRoutePredicate(object):
self.val = val
def text(self):
return f'repo_group_route = {self.val}'
return f"repo_group_route = {self.val}"
phash = text
def __call__(self, info, request):
if hasattr(request, 'vcs_call'):
if hasattr(request, "vcs_call"):
# skip vcs calls
return
repo_group_name = info['match']['repo_group_name']
repo_group_name = info["match"]["repo_group_name"]
repo_group_name_parts = repo_group_name.split('/')
repo_group_slugs = [x for x in [repo_name_slug(x) for x in repo_group_name_parts]]
repo_group_name_parts = repo_group_name.split("/")
repo_group_slugs = [
x for x in [repo_name_slug(x) for x in repo_group_name_parts]
]
if repo_group_name_parts != repo_group_slugs:
# short-skip if the repo-name doesn't follow slug rule
log.warning('repo_group_name: %s is different than slug %s', repo_group_name_parts, repo_group_slugs)
log.warning(
"repo_group_name: %s is different than slug %s",
repo_group_name_parts,
repo_group_slugs,
)
return False
repo_group_model = repo_group.RepoGroupModel()
@ -775,16 +869,16 @@ class UserGroupRoutePredicate(object):
self.val = val
def text(self):
return f'user_group_route = {self.val}'
return f"user_group_route = {self.val}"
phash = text
def __call__(self, info, request):
if hasattr(request, 'vcs_call'):
if hasattr(request, "vcs_call"):
# skip vcs calls
return
user_group_id = info['match']['user_group_id']
user_group_id = info["match"]["user_group_id"]
user_group_model = user_group.UserGroup()
by_id_match = user_group_model.get(user_group_id, cache=False)
@ -806,11 +900,11 @@ class UserRoutePredicateBase(object):
raise NotImplementedError()
def __call__(self, info, request):
if hasattr(request, 'vcs_call'):
if hasattr(request, "vcs_call"):
# skip vcs calls
return
user_id = info['match']['user_id']
user_id = info["match"]["user_id"]
user_model = user.User()
by_id_match = user_model.get(user_id, cache=False)
@ -827,7 +921,7 @@ class UserRoutePredicate(UserRoutePredicateBase):
supports_default = False
def text(self):
return f'user_route = {self.val}'
return f"user_route = {self.val}"
phash = text
@ -836,23 +930,18 @@ class UserRouteWithDefaultPredicate(UserRoutePredicateBase):
supports_default = True
def text(self):
return f'user_with_default_route = {self.val}'
return f"user_with_default_route = {self.val}"
phash = text
def includeme(config):
config.add_route_predicate("repo_route", RepoRoutePredicate)
config.add_route_predicate("repo_accepted_types", RepoTypeRoutePredicate)
config.add_route_predicate(
'repo_route', RepoRoutePredicate)
config.add_route_predicate(
'repo_accepted_types', RepoTypeRoutePredicate)
config.add_route_predicate(
'repo_forbid_when_archived', RepoForbidArchivedRoutePredicate)
config.add_route_predicate(
'repo_group_route', RepoGroupRoutePredicate)
config.add_route_predicate(
'user_group_route', UserGroupRoutePredicate)
config.add_route_predicate(
'user_route_with_default', UserRouteWithDefaultPredicate)
config.add_route_predicate(
'user_route', UserRoutePredicate)
"repo_forbid_when_archived", RepoForbidArchivedRoutePredicate
)
config.add_route_predicate("repo_group_route", RepoGroupRoutePredicate)
config.add_route_predicate("user_group_route", UserGroupRoutePredicate)
config.add_route_predicate("user_route_with_default", UserRouteWithDefaultPredicate)
config.add_route_predicate("user_route", UserRoutePredicate)