release: merge back stable branch into default

This commit is contained in:
Marcin Kuzminski 2020-07-27 21:22:49 +02:00
commit 8781a7b312
26 changed files with 1323 additions and 1111 deletions

View file

@ -0,0 +1,42 @@
|RCE| 4.20.1 |RNS|
------------------
Release Date
^^^^^^^^^^^^
- 2020-07-27
New Features
^^^^^^^^^^^^
General
^^^^^^^
- Permissions: rename write+ to write or higher for more explicit meaning.
Security
^^^^^^^^
Performance
^^^^^^^^^^^
Fixes
^^^^^
- Files: fixed creation of new files for empty repos.
- Notifications: properly inject the custom email headers into templates.
- Store file integration: fixed support for nested subdirs.
Upgrade notes
^^^^^^^^^^^^^
- Un-scheduled release addressing problems in 4.20.X releases.

View file

@ -9,6 +9,7 @@ Release Notes
.. toctree::
:maxdepth: 1
release-notes-4.20.1.rst
release-notes-4.20.0.rst
release-notes-4.19.3.rst
release-notes-4.19.2.rst

View file

@ -211,7 +211,7 @@ class RepoFilesView(RepoAppView):
return file_node
def _is_valid_head(self, commit_id, repo):
def _is_valid_head(self, commit_id, repo, landing_ref):
branch_name = sha_commit_id = ''
is_head = False
log.debug('Checking if commit_id `%s` is a head for %s.', commit_id, repo)
@ -237,7 +237,11 @@ class RepoFilesView(RepoAppView):
return branch_name, sha_commit_id, is_head
# checked branches, means we only need to try to get the branch/commit_sha
if not repo.is_empty():
if repo.is_empty():
is_head = True
branch_name = landing_ref
sha_commit_id = EmptyCommit().raw_id
else:
commit = repo.get_commit(commit_id=commit_id)
if commit:
branch_name = commit.branch
@ -696,8 +700,9 @@ class RepoFilesView(RepoAppView):
if not c.renderer:
c.lines = filenode_as_lines_tokens(c.file)
_branch_name, _sha_commit_id, is_head = self._is_valid_head(
commit_id, self.rhodecode_vcs_repo)
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
c.on_branch_head = is_head
branch = c.commit.branch if (
@ -1135,7 +1140,8 @@ class RepoFilesView(RepoAppView):
commit_id, f_path = self._get_commit_and_path()
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
new_path = self.request.POST.get('path')
operation = self.request.POST.get('operation')
@ -1173,7 +1179,8 @@ class RepoFilesView(RepoAppView):
self._ensure_not_locked()
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
self.forbid_non_head(is_head, f_path)
self.check_branch_permission(_branch_name)
@ -1201,7 +1208,8 @@ class RepoFilesView(RepoAppView):
self._ensure_not_locked()
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
self.forbid_non_head(is_head, f_path)
self.check_branch_permission(_branch_name)
@ -1251,7 +1259,8 @@ class RepoFilesView(RepoAppView):
self._ensure_not_locked()
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
self.forbid_non_head(is_head, f_path, commit_id=commit_id)
self.check_branch_permission(_branch_name, commit_id=commit_id)
@ -1292,7 +1301,8 @@ class RepoFilesView(RepoAppView):
commit_id=c.commit.raw_id, f_path=f_path))
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
self.forbid_non_head(is_head, f_path, commit_id=commit_id)
self.check_branch_permission(_branch_name, commit_id=commit_id)
@ -1380,7 +1390,8 @@ class RepoFilesView(RepoAppView):
_branch_name, _sha_commit_id, is_head = c.commit.branch, '', True
else:
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
self.forbid_non_head(is_head, f_path, commit_id=commit_id)
self.check_branch_permission(_branch_name, commit_id=commit_id)
@ -1421,7 +1432,8 @@ class RepoFilesView(RepoAppView):
_branch_name, _sha_commit_id, is_head = c.commit.branch, '', True
else:
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
self.forbid_non_head(is_head, f_path, commit_id=commit_id)
self.check_branch_permission(_branch_name, commit_id=commit_id)
@ -1517,7 +1529,8 @@ class RepoFilesView(RepoAppView):
_branch_name, _sha_commit_id, is_head = c.commit.branch, '', True
else:
_branch_name, _sha_commit_id, is_head = \
self._is_valid_head(commit_id, self.rhodecode_vcs_repo)
self._is_valid_head(commit_id, self.rhodecode_vcs_repo,
landing_ref=self.db_repo.landing_ref_name)
error = self.forbid_non_head(is_head, f_path, json_mode=True)
if error:

View file

@ -54,7 +54,7 @@ class RepoSettingsPermissionsView(RepoAppView):
c = self.load_default_context()
c.active = 'permissions'
if self.request.GET.get('branch_permissions'):
h.flash(_('Explicitly add user or user group with write+ '
h.flash(_('Explicitly add user or user group with write or higher '
'permission to modify their branch permissions.'),
category='notice')
return self._get_template_context(c)

View file

@ -604,68 +604,74 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
if not force_recache and has_proper_diff_cache:
c.diffset = cached_diff['diff']
else:
c.diffset = self._get_diffset(
c.source_repo.repo_name, commits_source_repo,
c.ancestor_commit,
source_ref_id, target_ref_id,
target_commit, source_commit,
diff_limit, file_limit, c.fulldiff,
hide_whitespace_changes, diff_context,
use_ancestor=use_ancestor
)
# save cached diff
if caching_enabled:
cache_diff(cache_file_path, c.diffset, diff_commit_cache)
c.limited_diff = c.diffset.limited_diff
# calculate removed files that are bound to comments
comment_deleted_files = [
fname for fname in display_inline_comments
if fname not in c.diffset.file_stats]
c.deleted_files_comments = collections.defaultdict(dict)
for fname, per_line_comments in display_inline_comments.items():
if fname in comment_deleted_files:
c.deleted_files_comments[fname]['stats'] = 0
c.deleted_files_comments[fname]['comments'] = list()
for lno, comments in per_line_comments.items():
c.deleted_files_comments[fname]['comments'].extend(comments)
# maybe calculate the range diff
if c.range_diff_on:
# TODO(marcink): set whitespace/context
context_lcl = 3
ign_whitespace_lcl = False
for commit in c.commit_ranges:
commit2 = commit
commit1 = commit.first_parent
range_diff_cache_file_path = diff_cache_exist(
cache_path, 'diff', commit.raw_id,
ign_whitespace_lcl, context_lcl, c.fulldiff)
cached_diff = None
if caching_enabled:
cached_diff = load_cached_diff(range_diff_cache_file_path)
has_proper_diff_cache = cached_diff and cached_diff.get('diff')
if not force_recache and has_proper_diff_cache:
diffset = cached_diff['diff']
else:
diffset = self._get_range_diffset(
commits_source_repo, source_repo,
commit1, commit2, diff_limit, file_limit,
c.fulldiff, ign_whitespace_lcl, context_lcl
)
try:
c.diffset = self._get_diffset(
c.source_repo.repo_name, commits_source_repo,
c.ancestor_commit,
source_ref_id, target_ref_id,
target_commit, source_commit,
diff_limit, file_limit, c.fulldiff,
hide_whitespace_changes, diff_context,
use_ancestor=use_ancestor
)
# save cached diff
if caching_enabled:
cache_diff(range_diff_cache_file_path, diffset, None)
cache_diff(cache_file_path, c.diffset, diff_commit_cache)
except CommitDoesNotExistError:
log.exception('Failed to generate diffset')
c.missing_commits = True
c.changes[commit.raw_id] = diffset
if not c.missing_commits:
c.limited_diff = c.diffset.limited_diff
# calculate removed files that are bound to comments
comment_deleted_files = [
fname for fname in display_inline_comments
if fname not in c.diffset.file_stats]
c.deleted_files_comments = collections.defaultdict(dict)
for fname, per_line_comments in display_inline_comments.items():
if fname in comment_deleted_files:
c.deleted_files_comments[fname]['stats'] = 0
c.deleted_files_comments[fname]['comments'] = list()
for lno, comments in per_line_comments.items():
c.deleted_files_comments[fname]['comments'].extend(comments)
# maybe calculate the range diff
if c.range_diff_on:
# TODO(marcink): set whitespace/context
context_lcl = 3
ign_whitespace_lcl = False
for commit in c.commit_ranges:
commit2 = commit
commit1 = commit.first_parent
range_diff_cache_file_path = diff_cache_exist(
cache_path, 'diff', commit.raw_id,
ign_whitespace_lcl, context_lcl, c.fulldiff)
cached_diff = None
if caching_enabled:
cached_diff = load_cached_diff(range_diff_cache_file_path)
has_proper_diff_cache = cached_diff and cached_diff.get('diff')
if not force_recache and has_proper_diff_cache:
diffset = cached_diff['diff']
else:
diffset = self._get_range_diffset(
commits_source_repo, source_repo,
commit1, commit2, diff_limit, file_limit,
c.fulldiff, ign_whitespace_lcl, context_lcl
)
# save cached diff
if caching_enabled:
cache_diff(range_diff_cache_file_path, diffset, None)
c.changes[commit.raw_id] = diffset
# this is a hack to properly display links, when creating PR, the
# compare view and others uses different notation, and

View file

@ -83,7 +83,7 @@ class VcsServer(object):
else:
if permission in self.write_perms:
log.info(
'WRITE+ Permissions for User "%s" detected to repo "%s"!',
'WRITE, or Higher Permissions for User "%s" detected to repo "%s"!',
self.user, self.repo_name)
return 0

File diff suppressed because it is too large Load diff

View file

@ -644,7 +644,7 @@ def load_rcextensions(root_path):
rcextensions = None
if rcextensions:
log.debug('Found rcextensions module loaded %s...', rcextensions)
log.info('Loaded rcextensions from %s...', rcextensions)
rhodecode.EXTENSIONS = rcextensions
# Additional mappings that are not present in the pygments lexers

View file

@ -587,51 +587,17 @@ def cleaned_uri(uri):
return urllib.quote(uri, safe='@$:/')
def uri_filter(uri):
"""
Removes user:password from given url string
:param uri:
:rtype: unicode
:returns: filtered list of strings
"""
if not uri:
return ''
proto = ''
for pat in ('https://', 'http://'):
if uri.startswith(pat):
uri = uri[len(pat):]
proto = pat
break
# remove passwords and username
uri = uri[uri.find('@') + 1:]
# get the port
cred_pos = uri.find(':')
if cred_pos == -1:
host, port = uri, None
else:
host, port = uri[:cred_pos], uri[cred_pos + 1:]
return filter(None, [proto, host, port])
def credentials_filter(uri):
"""
Returns a url with removed credentials
:param uri:
"""
import urlobject
url_obj = urlobject.URLObject(cleaned_uri(uri))
url_obj = url_obj.without_password().without_username()
uri = uri_filter(uri)
# check if we have port
if len(uri) > 2 and uri[2]:
uri[2] = ':' + uri[2]
return ''.join(uri)
return url_obj
def get_host_info(request):

View file

@ -384,7 +384,15 @@ class EmailNotificationModel(BaseModel):
instance_url = h.route_url('home')
_kwargs = {
'instance_url': instance_url,
'whitespace_filter': self.whitespace_filter
'whitespace_filter': self.whitespace_filter,
'email_pr_update_subject_template': EMAIL_PR_UPDATE_SUBJECT_TEMPLATE,
'email_pr_review_subject_template': EMAIL_PR_REVIEW_SUBJECT_TEMPLATE,
'email_pr_comment_subject_template': EMAIL_PR_COMMENT_SUBJECT_TEMPLATE,
'email_pr_comment_status_change_subject_template': EMAIL_PR_COMMENT_STATUS_CHANGE_SUBJECT_TEMPLATE,
'email_pr_comment_file_subject_template': EMAIL_PR_COMMENT_FILE_SUBJECT_TEMPLATE,
'email_comment_subject_template': EMAIL_COMMENT_SUBJECT_TEMPLATE,
'email_comment_status_change_subject_template': EMAIL_COMMENT_STATUS_CHANGE_SUBJECT_TEMPLATE,
'email_comment_file_subject_template': EMAIL_COMMENT_FILE_SUBJECT_TEMPLATE,
}
_kwargs.update(kwargs)
return _kwargs

View file

@ -561,7 +561,7 @@ class PermissionModel(BaseModel):
default_user_id = User.get_default_user_id()
user_write_permissions = collections.OrderedDict()
# write+ and DEFAULT user for inheritance
# write or higher and DEFAULT user for inheritance
for perm in db_repo.permissions():
if perm.permission in write_plus or perm.user_id == default_user_id:
user_write_permissions[perm.user_id] = perm
@ -571,7 +571,7 @@ class PermissionModel(BaseModel):
write_plus = ['repository.write', 'repository.admin']
user_group_write_permissions = collections.OrderedDict()
# write+ and DEFAULT user for inheritance
# write or higher and DEFAULT user for inheritance
for p in db_repo.permission_user_groups():
if p.permission in write_plus:
user_group_write_permissions[p.users_group_id] = p

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Unfollow',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Unfollow',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Unfollow',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Unfollow',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Unfollow',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Smetti di seguire',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': '選択したステータス ({0}) を元にコメントが自動的に設定されます...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'アンフォロー',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -18,6 +18,7 @@ _gettext('Close');
_gettext('Collapse all files');
_gettext('Collapse {0} commit');
_gettext('Collapse {0} commits');
_gettext('Comment body was not changed.');
_gettext('Comment text will be set automatically based on currently selected status ({0}) ...');
_gettext('Commit Authors are not allowed to be a reviewer.');
_gettext('Context file: ');
@ -106,6 +107,7 @@ _gettext('This pull requests will consist of <strong>{0} commits</strong>.');
_gettext('Toggle Wide Mode diff');
_gettext('Unfollow');
_gettext('Unwatch');
_gettext('Updated Comment');
_gettext('Updating...');
_gettext('User `{0}` already in reviewers');
_gettext('User `{0}` not allowed to be a reviewer');

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Nie obserwuj',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Parar de seguir',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Не наблюдать',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -24,6 +24,7 @@ var _TM = {
'Collapse all files': 'Collapse all files',
'Collapse {0} commit': 'Collapse {0} commit',
'Collapse {0} commits': 'Collapse {0} commits',
'Comment body was not changed.': 'Comment body was not changed.',
'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...',
'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.',
'Context file: ': 'Context file: ',
@ -112,6 +113,7 @@ var _TM = {
'Toggle Wide Mode diff': 'Toggle Wide Mode diff',
'Unfollow': 'Unfollow',
'Unwatch': 'Unwatch',
'Updated Comment': 'Updated Comment',
'Updating...': 'Updating...',
'User `{0}` already in reviewers': 'User `{0}` already in reviewers',
'User `{0}` not allowed to be a reviewer': 'User `{0}` not allowed to be a reviewer',

View file

@ -106,9 +106,9 @@
%if getattr(_user, 'branch_rules', None):
% if used_by_n_rules == 1:
(${_('used by {} branch rule, requires write+ permissions').format(used_by_n_rules)})
(${_('used by {} branch rule, requires write or higher permissions').format(used_by_n_rules)})
% else:
(${_('used by {} branch rules, requires write+ permissions').format(used_by_n_rules)})
(${_('used by {} branch rules, requires write or higher permissions').format(used_by_n_rules)})
% endif
%endif
% endif

View file

@ -465,9 +465,9 @@
<div class="alert alert-warning">
<div>
<strong>${_('Missing commits')}:</strong>
${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}<br/>
${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}<br/>
${_('Consider doing a `force update commits` in case you think this is an error.')}
</div>
</div>
</div>

View file

@ -38,36 +38,29 @@ from rhodecode.lib.utils2 import AttributeDict
from rhodecode.model.db import Repository, CacheKey
def _urls_for_proto(proto):
return [
('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
'%s://127.0.0.1' % proto),
('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
'%s://127.0.0.1' % proto),
('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
'%s://127.0.0.1' % proto),
('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
'%s://127.0.0.1:8080' % proto),
('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
'%s://domain.org' % proto),
('%s://user:pass@domain.org:8080' % proto,
['%s://' % proto, 'domain.org', '8080'],
'%s://domain.org:8080' % proto),
TEST_URLS = [
('127.0.0.1', '127.0.0.1'),
('marcink@127.0.0.1', '127.0.0.1'),
('marcink:pass@127.0.0.1', '127.0.0.1'),
('marcink@domain.name:pass@127.0.0.1', '127.0.0.1'),
('127.0.0.1:8080', '127.0.0.1:8080'),
('marcink@127.0.0.1:8080', '127.0.0.1:8080'),
('marcink:pass@127.0.0.1:8080', '127.0.0.1:8080'),
('marcink@domain.name:pass@127.0.0.1:8080', '127.0.0.1:8080'),
('domain.org', 'domain.org'),
('user:pass@domain.org:8080', 'domain.org:8080'),
('user@domain.org:pass@domain.org:8080', 'domain.org:8080'),
]
TEST_URLS = _urls_for_proto('http') + _urls_for_proto('https')
@pytest.mark.parametrize("test_url, expected, expected_creds", TEST_URLS)
def test_uri_filter(test_url, expected, expected_creds):
from rhodecode.lib.utils2 import uri_filter
assert uri_filter(test_url) == expected
@pytest.mark.parametrize("test_url, expected, expected_creds", TEST_URLS)
def test_credentials_filter(test_url, expected, expected_creds):
@pytest.mark.parametrize("protocol", ['http://', 'https://'])
@pytest.mark.parametrize("test_url, expected", TEST_URLS)
def test_credentials_filter(protocol, test_url, expected):
from rhodecode.lib.utils2 import credentials_filter
assert credentials_filter(test_url) == expected_creds
test_url = protocol + test_url
assert credentials_filter(test_url) == protocol + expected
@pytest.mark.parametrize("str_bool, expected", [