diff --git a/.bumpversion.cfg b/.bumpversion.cfg
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,6 @@
[bumpversion]
-current_version = 4.25.0
+current_version = 4.25.2
message = release: Bump version {current_version} to {new_version}
[bumpversion:file:rhodecode/VERSION]
+
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -75,3 +75,6 @@ 56310d93b33b97535908ef9c7b0985b89bb7fad2
7637c38528fa38c1eabc1fde6a869c20995a0da7 v4.23.2
6aeb4ac3ef7f0ac699c914740dad3688c9495e83 v4.24.0
6eaf953da06e468a4c4e5239d3d0e700bda6b163 v4.24.1
+f8161cbc2d94a935d3c395a0e758d9a094287169 v4.25.0
+77fe47b5b39338e71b2c040de2c0359b529b6251 v4.25.1
+27475bd8a718b9a00a37a8563c4927120865ad85 v4.25.2
diff --git a/.release.cfg b/.release.cfg
--- a/.release.cfg
+++ b/.release.cfg
@@ -21,7 +21,7 @@ done = true
[release]
state = prepared
-version = 4.11.6
+version = 4.25.2
[task:updated_translation]
diff --git a/docs/release-notes/release-notes-4.25.1.rst b/docs/release-notes/release-notes-4.25.1.rst
new file mode 100644
--- /dev/null
+++ b/docs/release-notes/release-notes-4.25.1.rst
@@ -0,0 +1,40 @@
+|RCE| 4.25.1 |RNS|
+------------------
+
+Release Date
+^^^^^^^^^^^^
+
+- 2021-04-06
+
+
+New Features
+^^^^^^^^^^^^
+
+
+
+General
+^^^^^^^
+
+
+
+Security
+^^^^^^^^
+
+
+
+Performance
+^^^^^^^^^^^
+
+
+
+Fixes
+^^^^^
+
+- Artifacts: fixed admin panel bad urls generated for the new artifacts admin view in CE edition.
+
+
+
+Upgrade notes
+^^^^^^^^^^^^^
+
+- Un-scheduled release addressing problems in 4.25.X releases.
diff --git a/docs/release-notes/release-notes-4.25.2.rst b/docs/release-notes/release-notes-4.25.2.rst
new file mode 100644
--- /dev/null
+++ b/docs/release-notes/release-notes-4.25.2.rst
@@ -0,0 +1,53 @@
+|RCE| 4.25.2 |RNS|
+------------------
+
+Release Date
+^^^^^^^^^^^^
+
+- 2021-04-14
+
+
+New Features
+^^^^^^^^^^^^
+
+
+
+General
+^^^^^^^
+
+- Comments: refresh on draft sidebar on draft submit.
+- Vcsserver: log exceptions into the logs
+- Archiving: make it explicit archiving a repo is irreversible.
+- My-account: updated bookmarks UX
+- Pull requests: added awaiting my review filter for users pull-requests.
+ Additionally the awaiting my review now properly filters pull requests that have no review votes on them.
+
+
+Security
+^^^^^^^^
+
+
+
+Performance
+^^^^^^^^^^^
+
+
+
+Fixes
+^^^^^
+
+- Draft comments: fixed logic in toggle all draft for submit.
+- Draft comments: when submitting edited drafts also clear the history to prevent DB problems.
+- Mercurial: fixed a case of lookup branches that had 40 characters in length.
+- Gists: block id input for public gists.
+- Pull requests: fixed problems with unicode characters in branches.
+- Pull requests: small ui fix for grid.
+- Summary: fixed ui on summary page for non-admins.
+ The setup instructions were broken if user had no write permissions.
+- Users: make user data loading more resilient to errors.
+
+
+Upgrade notes
+^^^^^^^^^^^^^
+
+- Scheduled release addressing problems in 4.25.X releases.
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,8 @@ Release Notes
.. toctree::
:maxdepth: 1
+ release-notes-4.25.2.rst
+ release-notes-4.25.1.rst
release-notes-4.25.0.rst
release-notes-4.24.1.rst
release-notes-4.24.0.rst
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.25.0";
+ name = "rhodecode-enterprise-ce-4.25.2";
buildInputs = [
self."pytest"
self."py"
diff --git a/rhodecode/VERSION b/rhodecode/VERSION
--- a/rhodecode/VERSION
+++ b/rhodecode/VERSION
@@ -1,1 +1,1 @@
-4.25.0
\ No newline at end of file
+4.25.2
\ No newline at end of file
diff --git a/rhodecode/api/views/repo_group_api.py b/rhodecode/api/views/repo_group_api.py
--- a/rhodecode/api/views/repo_group_api.py
+++ b/rhodecode/api/views/repo_group_api.py
@@ -232,6 +232,9 @@ def create_repo_group(
user=apiuser)
Session().commit()
+
+ PermissionModel().trigger_permission_flush()
+
return {
'msg': 'Created new repo group `%s`' % validated_group_name,
'repo_group': repo_group.get_api_data()
diff --git a/rhodecode/apps/admin/__init__.py b/rhodecode/apps/admin/__init__.py
--- a/rhodecode/apps/admin/__init__.py
+++ b/rhodecode/apps/admin/__init__.py
@@ -27,6 +27,7 @@ def admin_routes(config):
Admin prefixed routes
"""
from rhodecode.apps.admin.views.audit_logs import AdminAuditLogsView
+ from rhodecode.apps.admin.views.artifacts import AdminArtifactsView
from rhodecode.apps.admin.views.defaults import AdminDefaultSettingsView
from rhodecode.apps.admin.views.exception_tracker import ExceptionsTrackerView
from rhodecode.apps.admin.views.main_views import AdminMainView
@@ -60,6 +61,34 @@ def admin_routes(config):
route_name='admin_audit_log_entry', request_method='GET',
renderer='rhodecode:templates/admin/admin_audit_log_entry.mako')
+ # Artifacts EE feature
+ config.add_route(
+ 'admin_artifacts',
+ pattern=ADMIN_PREFIX + '/artifacts')
+ config.add_route(
+ 'admin_artifacts_show_all',
+ pattern=ADMIN_PREFIX + '/artifacts')
+ config.add_view(
+ AdminArtifactsView,
+ attr='artifacts',
+ route_name='admin_artifacts', request_method='GET',
+ renderer='rhodecode:templates/admin/artifacts/artifacts.mako')
+ config.add_view(
+ AdminArtifactsView,
+ attr='artifacts',
+ route_name='admin_artifacts_show_all', request_method='GET',
+ renderer='rhodecode:templates/admin/artifacts/artifacts.mako')
+ # EE views
+ config.add_route(
+ name='admin_artifacts_show_info',
+ pattern=ADMIN_PREFIX + '/artifacts/{uid}')
+ config.add_route(
+ name='admin_artifacts_delete',
+ pattern=ADMIN_PREFIX + '/artifacts/{uid}/delete')
+ config.add_route(
+ name='admin_artifacts_update',
+ pattern=ADMIN_PREFIX + '/artifacts/{uid}/update')
+
config.add_route(
name='admin_settings_open_source',
pattern='/settings/open_source')
diff --git a/rhodecode/apps/admin/views/artifacts.py b/rhodecode/apps/admin/views/artifacts.py
new file mode 100644
--- /dev/null
+++ b/rhodecode/apps/admin/views/artifacts.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2020 RhodeCode GmbH
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License, version 3
+# (only), as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# This program is dual-licensed. If you wish to learn more about the
+# RhodeCode Enterprise Edition, including its added features, Support services,
+# and proprietary license terms, please see https://rhodecode.com/licenses/
+
+import logging
+
+from rhodecode.apps._base import BaseAppView, DataGridAppView
+from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
+
+log = logging.getLogger(__name__)
+
+
+class AdminArtifactsView(BaseAppView, DataGridAppView):
+
+ def load_default_context(self):
+ c = self._get_local_tmpl_context()
+ return c
+
+ @LoginRequired()
+ @HasPermissionAllDecorator('hg.admin')
+ def artifacts(self):
+ c = self.load_default_context()
+ c.active = 'artifacts'
+ return self._get_template_context(c)
diff --git a/rhodecode/apps/admin/views/repo_groups.py b/rhodecode/apps/admin/views/repo_groups.py
--- a/rhodecode/apps/admin/views/repo_groups.py
+++ b/rhodecode/apps/admin/views/repo_groups.py
@@ -349,13 +349,7 @@ class AdminRepoGroupsView(BaseAppView, D
% repo_group_name, category='error')
raise HTTPFound(h.route_path('home'))
- affected_user_ids = [self._rhodecode_user.user_id]
- if copy_permissions:
- user_group_perms = repo_group.permissions(expand_from_user_groups=True)
- copy_perms = [perm['user_id'] for perm in user_group_perms]
- # also include those newly created by copy
- affected_user_ids.extend(copy_perms)
- PermissionModel().trigger_permission_flush(affected_user_ids)
+ PermissionModel().trigger_permission_flush()
raise HTTPFound(
h.route_path('repo_group_home',
diff --git a/rhodecode/apps/admin/views/repositories.py b/rhodecode/apps/admin/views/repositories.py
--- a/rhodecode/apps/admin/views/repositories.py
+++ b/rhodecode/apps/admin/views/repositories.py
@@ -242,11 +242,7 @@ class AdminReposView(BaseAppView, DataGr
repo_name = form_result.get('repo_name_full')
- affected_user_ids = [self._rhodecode_user.user_id]
- if copy_permissions:
- # permission flush is done in repo creating
- pass
- PermissionModel().trigger_permission_flush(affected_user_ids)
+ PermissionModel().trigger_permission_flush()
raise HTTPFound(
h.route_path('repo_creating', repo_name=repo_name,
diff --git a/rhodecode/apps/my_account/tests/test_my_account_edit.py b/rhodecode/apps/my_account/tests/test_my_account_edit.py
--- a/rhodecode/apps/my_account/tests/test_my_account_edit.py
+++ b/rhodecode/apps/my_account/tests/test_my_account_edit.py
@@ -76,7 +76,11 @@ class TestMyAccountEdit(TestController):
'requests requiring your participation.')
@pytest.mark.backends("git", "hg")
- def test_my_account_my_pullrequests_data(self, pr_util, xhr_header):
+ @pytest.mark.parametrize('params, expected_title', [
+ ({'closed': 1}, 'Closed'),
+ ({'awaiting_my_review': 1}, 'Awaiting my review'),
+ ])
+ def test_my_account_my_pullrequests_data(self, pr_util, xhr_header, params, expected_title):
self.log_user()
response = self.app.get(route_path('my_account_pullrequests_data'),
extra_environ=xhr_header)
diff --git a/rhodecode/apps/my_account/views/my_account.py b/rhodecode/apps/my_account/views/my_account.py
--- a/rhodecode/apps/my_account/views/my_account.py
+++ b/rhodecode/apps/my_account/views/my_account.py
@@ -43,7 +43,7 @@ from rhodecode.model.comment import Comm
from rhodecode.model.db import (
IntegrityError, or_, in_filter_generator,
Repository, UserEmailMap, UserApiKeys, UserFollowing,
- PullRequest, UserBookmark, RepoGroup)
+ PullRequest, UserBookmark, RepoGroup, ChangesetStatus)
from rhodecode.model.meta import Session
from rhodecode.model.pull_request import PullRequestModel
from rhodecode.model.user import UserModel
@@ -654,21 +654,31 @@ class MyAccountView(BaseAppView, DataGri
Session().commit()
return user.user_data['notification_status']
- def _get_pull_requests_list(self, statuses):
+ def _get_pull_requests_list(self, statuses, filter_type=None):
draw, start, limit = self._extract_chunk(self.request)
search_q, order_by, order_dir = self._extract_ordering(self.request)
_render = self.request.get_partial_renderer(
'rhodecode:templates/data_table/_dt_elements.mako')
- pull_requests = PullRequestModel().get_im_participating_in(
- user_id=self._rhodecode_user.user_id,
- statuses=statuses, query=search_q,
- offset=start, length=limit, order_by=order_by,
- order_dir=order_dir)
+ if filter_type == 'awaiting_my_review':
+ pull_requests = PullRequestModel().get_im_participating_in_for_review(
+ user_id=self._rhodecode_user.user_id,
+ statuses=statuses, query=search_q,
+ offset=start, length=limit, order_by=order_by,
+ order_dir=order_dir)
- pull_requests_total_count = PullRequestModel().count_im_participating_in(
- user_id=self._rhodecode_user.user_id, statuses=statuses, query=search_q)
+ pull_requests_total_count = PullRequestModel().count_im_participating_in_for_review(
+ user_id=self._rhodecode_user.user_id, statuses=statuses, query=search_q)
+ else:
+ pull_requests = PullRequestModel().get_im_participating_in(
+ user_id=self._rhodecode_user.user_id,
+ statuses=statuses, query=search_q,
+ offset=start, length=limit, order_by=order_by,
+ order_dir=order_dir)
+
+ pull_requests_total_count = PullRequestModel().count_im_participating_in(
+ user_id=self._rhodecode_user.user_id, statuses=statuses, query=search_q)
data = []
comments_model = CommentsModel()
@@ -678,6 +688,12 @@ class MyAccountView(BaseAppView, DataGri
repo_id, pull_request=pr, include_drafts=False, count_only=True)
owned = pr.user_id == self._rhodecode_user.user_id
+ review_statuses = pr.reviewers_statuses(user=self._rhodecode_db_user)
+ my_review_status = ChangesetStatus.STATUS_NOT_REVIEWED
+ if review_statuses and review_statuses[4]:
+ _review_obj, _user, _reasons, _mandatory, statuses = review_statuses
+ my_review_status = statuses[0][1].status
+
data.append({
'target_repo': _render('pullrequest_target_repo',
pr.target_repo.repo_name),
@@ -688,6 +704,8 @@ class MyAccountView(BaseAppView, DataGri
'name_raw': pr.pull_request_id,
'status': _render('pullrequest_status',
pr.calculated_review_status()),
+ 'my_status': _render('pullrequest_status',
+ my_review_status),
'title': _render('pullrequest_title', pr.title, pr.description),
'description': h.escape(pr.description),
'updated_on': _render('pullrequest_updated_on',
@@ -723,7 +741,14 @@ class MyAccountView(BaseAppView, DataGri
c.active = 'pullrequests'
req_get = self.request.GET
- c.closed = str2bool(req_get.get('pr_show_closed'))
+ c.closed = str2bool(req_get.get('closed'))
+ c.awaiting_my_review = str2bool(req_get.get('awaiting_my_review'))
+
+ c.selected_filter = 'all'
+ if c.closed:
+ c.selected_filter = 'all_closed'
+ if c.awaiting_my_review:
+ c.selected_filter = 'awaiting_my_review'
return self._get_template_context(c)
@@ -732,13 +757,19 @@ class MyAccountView(BaseAppView, DataGri
def my_account_pullrequests_data(self):
self.load_default_context()
req_get = self.request.GET
+
+ awaiting_my_review = str2bool(req_get.get('awaiting_my_review'))
closed = str2bool(req_get.get('closed'))
statuses = [PullRequest.STATUS_NEW, PullRequest.STATUS_OPEN]
if closed:
statuses += [PullRequest.STATUS_CLOSED]
- data = self._get_pull_requests_list(statuses=statuses)
+ filter_type = \
+ 'awaiting_my_review' if awaiting_my_review \
+ else None
+
+ data = self._get_pull_requests_list(statuses=statuses, filter_type=filter_type)
return data
@LoginRequired()
diff --git a/rhodecode/apps/repository/tests/test_pull_requests_list.py b/rhodecode/apps/repository/tests/test_pull_requests_list.py
--- a/rhodecode/apps/repository/tests/test_pull_requests_list.py
+++ b/rhodecode/apps/repository/tests/test_pull_requests_list.py
@@ -41,7 +41,7 @@ class TestPullRequestList(object):
@pytest.mark.parametrize('params, expected_title', [
({'source': 0, 'closed': 1}, 'Closed'),
- ({'source': 0, 'my': 1}, 'Opened by me'),
+ ({'source': 0, 'my': 1}, 'Created by me'),
({'source': 0, 'awaiting_review': 1}, 'Awaiting review'),
({'source': 0, 'awaiting_my_review': 1}, 'Awaiting my review'),
({'source': 1}, 'From this repo'),
diff --git a/rhodecode/apps/repository/views/repo_commits.py b/rhodecode/apps/repository/views/repo_commits.py
--- a/rhodecode/apps/repository/views/repo_commits.py
+++ b/rhodecode/apps/repository/views/repo_commits.py
@@ -539,8 +539,14 @@ class RepoCommitsView(RepoAppView):
@CSRFRequired()
def repo_commit_comment_history_view(self):
c = self.load_default_context()
+ comment_history_id = self.request.matchdict['comment_history_id']
- comment_history_id = self.request.matchdict['comment_history_id']
+ comment = ChangesetComment.get_or_404(comment_history_id)
+ comment_owner = (comment.author.user_id == self._rhodecode_db_user.user_id)
+ if comment.draft and not comment_owner:
+ # if we see draft comments history, we only allow this for owner
+ raise HTTPNotFound()
+
comment_history = ChangesetCommentHistory.get_or_404(comment_history_id)
is_repo_comment = comment_history.comment.repo.repo_id == self.db_repo.repo_id
@@ -549,8 +555,7 @@ class RepoCommitsView(RepoAppView):
rendered_comment = render(
'rhodecode:templates/changeset/comment_history.mako',
- self._get_template_context(c)
- , self.request)
+ self._get_template_context(c), self.request)
return rendered_comment
else:
log.warning('No permissions for user %s to show comment_history_id: %s',
diff --git a/rhodecode/apps/repository/views/repo_pull_requests.py b/rhodecode/apps/repository/views/repo_pull_requests.py
--- a/rhodecode/apps/repository/views/repo_pull_requests.py
+++ b/rhodecode/apps/repository/views/repo_pull_requests.py
@@ -39,7 +39,7 @@ from rhodecode.lib.ext_json import json
from rhodecode.lib.auth import (
LoginRequired, HasRepoPermissionAny, HasRepoPermissionAnyDecorator,
NotAnonymous, CSRFRequired)
-from rhodecode.lib.utils2 import str2bool, safe_str, safe_unicode, safe_int, aslist
+from rhodecode.lib.utils2 import str2bool, safe_str, safe_unicode, safe_int, aslist, retry
from rhodecode.lib.vcs.backends.base import (
EmptyCommit, UpdateFailureReason, unicode_to_reference)
from rhodecode.lib.vcs.exceptions import (
@@ -79,21 +79,20 @@ class RepoPullRequestsView(RepoAppView,
if filter_type == 'awaiting_review':
pull_requests = PullRequestModel().get_awaiting_review(
- repo_name, search_q=search_q, source=source, opened_by=opened_by,
- statuses=statuses, offset=start, length=limit,
- order_by=order_by, order_dir=order_dir)
+ repo_name,
+ search_q=search_q, statuses=statuses,
+ offset=start, length=limit, order_by=order_by, order_dir=order_dir)
pull_requests_total_count = PullRequestModel().count_awaiting_review(
- repo_name, search_q=search_q, source=source, statuses=statuses,
- opened_by=opened_by)
+ repo_name,
+ search_q=search_q, statuses=statuses)
elif filter_type == 'awaiting_my_review':
pull_requests = PullRequestModel().get_awaiting_my_review(
- repo_name, search_q=search_q, source=source, opened_by=opened_by,
- user_id=self._rhodecode_user.user_id, statuses=statuses,
- offset=start, length=limit, order_by=order_by,
- order_dir=order_dir)
+ repo_name, self._rhodecode_user.user_id,
+ search_q=search_q, statuses=statuses,
+ offset=start, length=limit, order_by=order_by, order_dir=order_dir)
pull_requests_total_count = PullRequestModel().count_awaiting_my_review(
- repo_name, search_q=search_q, source=source, user_id=self._rhodecode_user.user_id,
- statuses=statuses, opened_by=opened_by)
+ repo_name, self._rhodecode_user.user_id,
+ search_q=search_q, statuses=statuses)
else:
pull_requests = PullRequestModel().get_all(
repo_name, search_q=search_q, source=source, opened_by=opened_by,
@@ -110,6 +109,12 @@ class RepoPullRequestsView(RepoAppView,
self.db_repo.repo_id, pull_request=pr,
include_drafts=False, count_only=True)
+ review_statuses = pr.reviewers_statuses(user=self._rhodecode_db_user)
+ my_review_status = ChangesetStatus.STATUS_NOT_REVIEWED
+ if review_statuses and review_statuses[4]:
+ _review_obj, _user, _reasons, _mandatory, statuses = review_statuses
+ my_review_status = statuses[0][1].status
+
data.append({
'name': _render('pullrequest_name',
pr.pull_request_id, pr.pull_request_state,
@@ -118,6 +123,8 @@ class RepoPullRequestsView(RepoAppView,
'name_raw': pr.pull_request_id,
'status': _render('pullrequest_status',
pr.calculated_review_status()),
+ 'my_status': _render('pullrequest_status',
+ my_review_status),
'title': _render('pullrequest_title', pr.title, pr.description),
'description': h.escape(pr.description),
'updated_on': _render('pullrequest_updated_on',
@@ -1346,9 +1353,13 @@ class RepoPullRequestsView(RepoAppView,
def _update_commits(self, c, pull_request):
_ = self.request.translate
+ @retry(exception=Exception, n_tries=3)
+ def commits_update():
+ return PullRequestModel().update_commits(
+ pull_request, self._rhodecode_db_user)
+
with pull_request.set_state(PullRequest.STATE_UPDATING):
- resp = PullRequestModel().update_commits(
- pull_request, self._rhodecode_db_user)
+ resp = commits_update() # retry x3
if resp.executed:
diff --git a/rhodecode/i18n/rhodecode.pot b/rhodecode/i18n/rhodecode.pot
--- a/rhodecode/i18n/rhodecode.pot
+++ b/rhodecode/i18n/rhodecode.pot
@@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: rhodecode-enterprise-ce 4.24.0\n"
+"Project-Id-Version: rhodecode-enterprise-ce 4.25.0\n"
"Report-Msgid-Bugs-To: marcin@rhodecode.com\n"
-"POT-Creation-Date: 2021-01-14 15:36+0000\n"
+"POT-Creation-Date: 2021-04-05 19:29+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -111,7 +111,7 @@ msgstr ""
#: rhodecode/apps/admin/views/settings.py:156
#: rhodecode/apps/admin/views/settings.py:291
#: rhodecode/apps/admin/views/settings.py:360
-#: rhodecode/apps/admin/views/settings.py:663
+#: rhodecode/apps/admin/views/settings.py:664
#: rhodecode/apps/repository/views/repo_settings_vcs.py:116
msgid "Some form inputs contain invalid data."
msgstr ""
@@ -135,54 +135,54 @@ msgstr ""
msgid "Updated application settings"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:399
+#: rhodecode/apps/admin/views/settings.py:400
msgid "Updated visualisation settings"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:402
+#: rhodecode/apps/admin/views/settings.py:403
msgid "Error occurred during updating visualisation settings"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:464
+#: rhodecode/apps/admin/views/settings.py:465
#: rhodecode/apps/repository/views/repo_settings_issue_trackers.py:115
msgid "Invalid issue tracker pattern: {}"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:481
+#: rhodecode/apps/admin/views/settings.py:482
#: rhodecode/apps/repository/views/repo_settings_issue_trackers.py:124
msgid "Updated issue tracker entries"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:498
+#: rhodecode/apps/admin/views/settings.py:499
#: rhodecode/apps/repository/views/repo_settings_issue_trackers.py:82
msgid "Removed issue tracker entry."
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:530
+#: rhodecode/apps/admin/views/settings.py:531
msgid "Please enter email address"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:546
+#: rhodecode/apps/admin/views/settings.py:547
msgid "Send email task created"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:587
+#: rhodecode/apps/admin/views/settings.py:588
msgid "Added new hook"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:602
+#: rhodecode/apps/admin/views/settings.py:603
msgid "Updated hooks"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:606
+#: rhodecode/apps/admin/views/settings.py:607
msgid "Error occurred during hook creation"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:687
+#: rhodecode/apps/admin/views/settings.py:688
msgid "Error occurred during updating labs settings"
msgstr ""
-#: rhodecode/apps/admin/views/settings.py:692
+#: rhodecode/apps/admin/views/settings.py:693
msgid "Updated Labs settings"
msgstr ""
@@ -592,7 +592,7 @@ msgstr ""
msgid "1 month"
msgstr ""
-#: rhodecode/apps/gist/views.py:63 rhodecode/public/js/scripts.js:48529
+#: rhodecode/apps/gist/views.py:63 rhodecode/public/js/scripts.js:48670
#: rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:48
#: rhodecode/public/js/src/rhodecode.js:634
@@ -653,8 +653,8 @@ msgstr ""
#: rhodecode/templates/admin/repos/repo_add.mako:19
#: rhodecode/templates/admin/users/user_edit_advanced.mako:12
#: rhodecode/templates/base/base.mako:114
-#: rhodecode/templates/base/base.mako:133
-#: rhodecode/templates/base/base.mako:1191
+#: rhodecode/templates/base/base.mako:134
+#: rhodecode/templates/base/base.mako:1192
msgid "Repositories"
msgstr ""
@@ -894,104 +894,104 @@ msgstr ""
msgid "No such commit exists for this repository. Commit: {}"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:358
+#: rhodecode/apps/repository/views/repo_files.py:359
msgid "Downloads disabled"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:364
+#: rhodecode/apps/repository/views/repo_files.py:365
msgid "Unknown archive type for: `{}`"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:370
+#: rhodecode/apps/repository/views/repo_files.py:371
msgid "Unknown commit_id {}"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:373
+#: rhodecode/apps/repository/views/repo_files.py:374
msgid "Empty repository"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:378
+#: rhodecode/apps/repository/views/repo_files.py:384
msgid "No node at path {} for this repository"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:429
+#: rhodecode/apps/repository/views/repo_files.py:436
msgid "Unknown archive type"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:986
+#: rhodecode/apps/repository/views/repo_files.py:993
msgid "Changesets"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1007
-#: rhodecode/apps/repository/views/repo_summary.py:243
-#: rhodecode/model/pull_request.py:1910 rhodecode/model/scm.py:999
+#: rhodecode/apps/repository/views/repo_files.py:1014
+#: rhodecode/apps/repository/views/repo_summary.py:239
+#: rhodecode/model/pull_request.py:1912 rhodecode/model/scm.py:999
#: rhodecode/templates/base/vcs_settings.mako:235
#: rhodecode/templates/summary/components.mako:10
msgid "Branches"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1011
+#: rhodecode/apps/repository/views/repo_files.py:1018
#: rhodecode/model/scm.py:1016 rhodecode/templates/base/vcs_settings.mako:260
#: rhodecode/templates/summary/components.mako:34
msgid "Tags"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1155
-#: rhodecode/apps/repository/views/repo_files.py:1181
+#: rhodecode/apps/repository/views/repo_files.py:1162
+#: rhodecode/apps/repository/views/repo_files.py:1188
msgid "Deleted file {} via RhodeCode Enterprise"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1202
+#: rhodecode/apps/repository/views/repo_files.py:1209
msgid "Successfully deleted file `{}`"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1206
+#: rhodecode/apps/repository/views/repo_files.py:1213
+#: rhodecode/apps/repository/views/repo_files.py:1326
+#: rhodecode/apps/repository/views/repo_files.py:1450
+#: rhodecode/apps/repository/views/repo_files.py:1571
+msgid "Error occurred during commit"
+msgstr ""
+
+#: rhodecode/apps/repository/views/repo_files.py:1243
+#: rhodecode/apps/repository/views/repo_files.py:1272
+msgid "Edited file {} via RhodeCode Enterprise"
+msgstr ""
+
+#: rhodecode/apps/repository/views/repo_files.py:1295
+msgid "No changes detected on {}"
+msgstr ""
+
#: rhodecode/apps/repository/views/repo_files.py:1319
-#: rhodecode/apps/repository/views/repo_files.py:1443
-#: rhodecode/apps/repository/views/repo_files.py:1564
-msgid "Error occurred during commit"
-msgstr ""
-
-#: rhodecode/apps/repository/views/repo_files.py:1236
-#: rhodecode/apps/repository/views/repo_files.py:1265
-msgid "Edited file {} via RhodeCode Enterprise"
-msgstr ""
-
-#: rhodecode/apps/repository/views/repo_files.py:1288
-msgid "No changes detected on {}"
-msgstr ""
-
-#: rhodecode/apps/repository/views/repo_files.py:1312
msgid "Successfully committed changes to file `{}`"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1348
-#: rhodecode/apps/repository/views/repo_files.py:1387
+#: rhodecode/apps/repository/views/repo_files.py:1355
+#: rhodecode/apps/repository/views/repo_files.py:1394
msgid "Added file via RhodeCode Enterprise"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1403
+#: rhodecode/apps/repository/views/repo_files.py:1410
msgid "No filename specified"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1428
+#: rhodecode/apps/repository/views/repo_files.py:1435
msgid "Successfully committed new file `{}`"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1436
-#: rhodecode/apps/repository/views/repo_files.py:1546
+#: rhodecode/apps/repository/views/repo_files.py:1443
+#: rhodecode/apps/repository/views/repo_files.py:1553
msgid "The location specified must be a relative path and must not contain .. in the path"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1491
+#: rhodecode/apps/repository/views/repo_files.py:1498
msgid "Uploaded file via RhodeCode Enterprise"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1535
+#: rhodecode/apps/repository/views/repo_files.py:1542
msgid "Successfully committed {} new files"
msgstr ""
-#: rhodecode/apps/repository/views/repo_files.py:1537
+#: rhodecode/apps/repository/views/repo_files.py:1544
msgid "Successfully committed 1 new file"
msgstr ""
@@ -1215,23 +1215,23 @@ msgstr ""
msgid "Error occurred during updating repository VCS settings"
msgstr ""
-#: rhodecode/apps/repository/views/repo_summary.py:222
+#: rhodecode/apps/repository/views/repo_summary.py:218
#: rhodecode/templates/admin/permissions/permissions.mako:42
#: rhodecode/templates/summary/components.mako:8
msgid "Branch"
msgstr ""
-#: rhodecode/apps/repository/views/repo_summary.py:223
+#: rhodecode/apps/repository/views/repo_summary.py:219
#: rhodecode/templates/summary/components.mako:32
msgid "Tag"
msgstr ""
-#: rhodecode/apps/repository/views/repo_summary.py:224
+#: rhodecode/apps/repository/views/repo_summary.py:220
#: rhodecode/templates/summary/components.mako:44
msgid "Bookmark"
msgstr ""
-#: rhodecode/apps/repository/views/repo_summary.py:244
+#: rhodecode/apps/repository/views/repo_summary.py:240
msgid "Closed branches"
msgstr ""
@@ -1291,9 +1291,9 @@ msgid "Enable or disable this authentica
msgstr ""
#: rhodecode/authentication/schema.py:38 rhodecode/integrations/schema.py:32
-#: rhodecode/model/permission.py:110 rhodecode/model/permission.py:114
-#: rhodecode/model/permission.py:118 rhodecode/model/permission.py:122
-#: rhodecode/model/permission.py:126 rhodecode/model/permission.py:130
+#: rhodecode/model/permission.py:112 rhodecode/model/permission.py:116
+#: rhodecode/model/permission.py:120 rhodecode/model/permission.py:124
+#: rhodecode/model/permission.py:128 rhodecode/model/permission.py:132
#: rhodecode/model/validation_schema/schemas/integration_schema.py:195
#: rhodecode/templates/admin/auth/auth_settings.mako:64
#: rhodecode/templates/admin/integrations/list.mako:71
@@ -1806,7 +1806,7 @@ msgstr ""
#: rhodecode/templates/admin/settings/settings_issuetracker.mako:16
#: rhodecode/templates/admin/settings/settings_labs.mako:49
#: rhodecode/templates/admin/settings/settings_vcs.mako:14
-#: rhodecode/templates/admin/settings/settings_visual.mako:215
+#: rhodecode/templates/admin/settings/settings_visual.mako:218
#: rhodecode/templates/admin/user_groups/user_group_edit_perms.mako:217
#: rhodecode/templates/admin/users/user_edit_auth_tokens.mako:107
#: rhodecode/templates/admin/users/user_edit_emails.mako:66
@@ -1841,7 +1841,7 @@ msgstr ""
#: rhodecode/templates/changeset/changeset_file_comment.mako:236
#: rhodecode/templates/changeset/changeset_file_comment.mako:250
#: rhodecode/templates/changeset/changeset_file_comment.mako:259
-#: rhodecode/templates/data_table/_dt_elements.mako:439
+#: rhodecode/templates/data_table/_dt_elements.mako:445
#: rhodecode/templates/debug_style/buttons.html:132
#: rhodecode/templates/files/files_source.mako:40
#: rhodecode/templates/files/files_source.mako:47
@@ -2229,15 +2229,15 @@ msgstr ""
msgid "Commit not found"
msgstr ""
-#: rhodecode/lib/auth.py:1769
+#: rhodecode/lib/auth.py:1771
msgid "IP {} not allowed"
msgstr ""
-#: rhodecode/lib/auth.py:1861
+#: rhodecode/lib/auth.py:1863
msgid "You need to be a registered user to perform this action"
msgstr ""
-#: rhodecode/lib/auth.py:1905
+#: rhodecode/lib/auth.py:1907
msgid "You need to be signed in to view this page"
msgstr ""
@@ -2249,7 +2249,7 @@ msgstr ""
msgid "Click to select line"
msgstr ""
-#: rhodecode/lib/helpers.py:1878
+#: rhodecode/lib/helpers.py:1883
msgid ""
"Example filter terms:\n"
" repository:vcs\n"
@@ -2271,7 +2271,7 @@ msgid ""
" \"username:test AND repository:test*\"\n"
msgstr ""
-#: rhodecode/lib/helpers.py:1902
+#: rhodecode/lib/helpers.py:1907
#, python-format
msgid "%s repository is not mapped to db perhaps it was created or renamed from the filesystem please run the application again in order to rescan repositories"
msgstr ""
@@ -2760,7 +2760,7 @@ msgstr ""
#: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:3011
#: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:3012
#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3230 rhodecode/model/db.py:3997
-#: rhodecode/public/js/scripts.js:42595 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42733 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:72
#: rhodecode/public/js/src/rhodecode/pullrequests.js:396
msgid "Not Reviewed"
@@ -3520,7 +3520,7 @@ msgstr ""
#: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2358
#: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2359
#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2559 rhodecode/model/db.py:3174
-#: rhodecode/model/permission.py:105
+#: rhodecode/model/permission.py:107
msgid "Manual activation of external account"
msgstr ""
@@ -3560,7 +3560,7 @@ msgstr ""
#: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2359
#: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2360
#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2560 rhodecode/model/db.py:3175
-#: rhodecode/model/permission.py:106
+#: rhodecode/model/permission.py:108
msgid "Automatic activation of external account"
msgstr ""
@@ -3986,51 +3986,51 @@ msgstr ""
msgid "Commit index"
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:186
+#: rhodecode/lib/vcs/backends/base.py:190
msgid "This pull request can be automatically merged."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:188
+#: rhodecode/lib/vcs/backends/base.py:192
msgid "This pull request cannot be merged because of an unhandled exception. {exception}"
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:191
+#: rhodecode/lib/vcs/backends/base.py:195
msgid "This pull request cannot be merged because of merge conflicts. {unresolved_files}"
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:193
+#: rhodecode/lib/vcs/backends/base.py:197
msgid "This pull request could not be merged because push to target:`{target}@{merge_commit}` failed."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:196
+#: rhodecode/lib/vcs/backends/base.py:200
msgid "This pull request cannot be merged because the target `{target_ref.name}` is not a head."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:199
+#: rhodecode/lib/vcs/backends/base.py:203
msgid "This pull request cannot be merged because the source contains more branches than the target."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:202
+#: rhodecode/lib/vcs/backends/base.py:206
msgid "This pull request cannot be merged because the target `{target_ref.name}` has multiple heads: `{heads}`."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:205
-msgid "This pull request cannot be merged because the target repository is locked by {locked_by}."
-msgstr ""
-
#: rhodecode/lib/vcs/backends/base.py:209
+msgid "This pull request cannot be merged because the target repository is locked by {locked_by}."
+msgstr ""
+
+#: rhodecode/lib/vcs/backends/base.py:213
msgid "This pull request cannot be merged because the target reference `{target_ref.name}` is missing."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:212
+#: rhodecode/lib/vcs/backends/base.py:216
msgid "This pull request cannot be merged because the source reference `{source_ref.name}` is missing."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:215
+#: rhodecode/lib/vcs/backends/base.py:219
msgid "This pull request cannot be merged because of conflicts related to sub repositories."
msgstr ""
-#: rhodecode/lib/vcs/backends/base.py:220
+#: rhodecode/lib/vcs/backends/base.py:224
msgid "This pull request cannot be merged because the target or the source reference is missing."
msgstr ""
@@ -4138,8 +4138,8 @@ msgstr ""
msgid "%(user)s commented on pull request at %(date_or_age)s"
msgstr ""
-#: rhodecode/model/permission.py:71 rhodecode/model/permission.py:77
-#: rhodecode/model/permission.py:83
+#: rhodecode/model/permission.py:73 rhodecode/model/permission.py:79
+#: rhodecode/model/permission.py:85
#: rhodecode/templates/admin/repo_groups/repo_group_edit_permissions.mako:11
#: rhodecode/templates/admin/repo_groups/repo_group_edit_permissions.mako:217
#: rhodecode/templates/admin/repos/repo_edit_permissions.mako:11
@@ -4147,27 +4147,27 @@ msgstr ""
msgid "None"
msgstr ""
-#: rhodecode/model/permission.py:72 rhodecode/model/permission.py:78
-#: rhodecode/model/permission.py:84
+#: rhodecode/model/permission.py:74 rhodecode/model/permission.py:80
+#: rhodecode/model/permission.py:86
#: rhodecode/templates/admin/repo_groups/repo_group_edit_permissions.mako:12
#: rhodecode/templates/admin/repos/repo_edit_permissions.mako:12
#: rhodecode/templates/admin/user_groups/user_group_edit_perms.mako:16
msgid "Read"
msgstr ""
-#: rhodecode/model/permission.py:73 rhodecode/model/permission.py:79
-#: rhodecode/model/permission.py:85
+#: rhodecode/model/permission.py:75 rhodecode/model/permission.py:81
+#: rhodecode/model/permission.py:87
#: rhodecode/templates/admin/repo_groups/repo_group_edit_permissions.mako:13
#: rhodecode/templates/admin/repos/repo_edit_permissions.mako:13
#: rhodecode/templates/admin/user_groups/user_group_edit_perms.mako:17
#: rhodecode/templates/changeset/changeset_file_comment.mako:392
#: rhodecode/templates/changeset/changeset_file_comment.mako:443
-#: rhodecode/templates/data_table/_dt_elements.mako:453
+#: rhodecode/templates/data_table/_dt_elements.mako:460
msgid "Write"
msgstr ""
-#: rhodecode/model/permission.py:74 rhodecode/model/permission.py:80
-#: rhodecode/model/permission.py:86
+#: rhodecode/model/permission.py:76 rhodecode/model/permission.py:82
+#: rhodecode/model/permission.py:88
#: rhodecode/templates/admin/auth/plugin_settings.mako:12
#: rhodecode/templates/admin/defaults/defaults.mako:12
#: rhodecode/templates/admin/integrations/base.mako:21
@@ -4189,51 +4189,51 @@ msgstr ""
#: rhodecode/templates/admin/user_groups/user_group_edit_perms.mako:18
#: rhodecode/templates/admin/users/user_add.mako:11
#: rhodecode/templates/admin/users/user_edit.mako:12
-#: rhodecode/templates/base/base.mako:838
+#: rhodecode/templates/base/base.mako:839
msgid "Admin"
msgstr ""
-#: rhodecode/model/permission.py:89
-msgid "Protected/No Access"
-msgstr ""
-
-#: rhodecode/model/permission.py:90
-msgid "Web merge"
-msgstr ""
-
#: rhodecode/model/permission.py:91
-msgid "Push"
+msgid "Protected/No Access"
msgstr ""
#: rhodecode/model/permission.py:92
+msgid "Web merge"
+msgstr ""
+
+#: rhodecode/model/permission.py:93
+msgid "Push"
+msgstr ""
+
+#: rhodecode/model/permission.py:94
msgid "Force Push"
msgstr ""
-#: rhodecode/model/permission.py:95 rhodecode/model/permission.py:109
-#: rhodecode/model/permission.py:113 rhodecode/model/permission.py:117
-#: rhodecode/model/permission.py:121 rhodecode/model/permission.py:125
-#: rhodecode/model/permission.py:129
+#: rhodecode/model/permission.py:97 rhodecode/model/permission.py:111
+#: rhodecode/model/permission.py:115 rhodecode/model/permission.py:119
+#: rhodecode/model/permission.py:123 rhodecode/model/permission.py:127
+#: rhodecode/model/permission.py:131
#: rhodecode/templates/admin/my_account/my_account_notifications.mako:27
msgid "Disabled"
msgstr ""
-#: rhodecode/model/permission.py:96
+#: rhodecode/model/permission.py:98
msgid "Allowed with manual account activation"
msgstr ""
-#: rhodecode/model/permission.py:97
+#: rhodecode/model/permission.py:99
msgid "Allowed with automatic account activation"
msgstr ""
-#: rhodecode/model/permission.py:100
-msgid "Allow password recovery"
-msgstr ""
-
-#: rhodecode/model/permission.py:101
-msgid "Hide password recovery link"
-msgstr ""
-
#: rhodecode/model/permission.py:102
+msgid "Allow password recovery"
+msgstr ""
+
+#: rhodecode/model/permission.py:103
+msgid "Hide password recovery link"
+msgstr ""
+
+#: rhodecode/model/permission.py:104
msgid "Disable password recovery"
msgstr ""
@@ -4261,79 +4261,79 @@ msgstr ""
msgid "This pull request cannot be updated because the source reference is missing."
msgstr ""
-#: rhodecode/model/pull_request.py:1688
+#: rhodecode/model/pull_request.py:1690
msgid "Server-side pull request merging is disabled."
msgstr ""
-#: rhodecode/model/pull_request.py:1691
+#: rhodecode/model/pull_request.py:1693
msgid "This pull request is closed."
msgstr ""
-#: rhodecode/model/pull_request.py:1705
+#: rhodecode/model/pull_request.py:1707
msgid "Pull request merging is not supported."
msgstr ""
-#: rhodecode/model/pull_request.py:1722
+#: rhodecode/model/pull_request.py:1724
msgid "Target repository large files support is disabled."
msgstr ""
-#: rhodecode/model/pull_request.py:1725
+#: rhodecode/model/pull_request.py:1727
msgid "Source repository large files support is disabled."
msgstr ""
-#: rhodecode/model/pull_request.py:1909 rhodecode/model/scm.py:1008
+#: rhodecode/model/pull_request.py:1911 rhodecode/model/scm.py:1008
#: rhodecode/templates/admin/my_account/my_account.mako:32
-#: rhodecode/templates/base/base.mako:638
+#: rhodecode/templates/base/base.mako:639
#: rhodecode/templates/summary/components.mako:46
msgid "Bookmarks"
msgstr ""
-#: rhodecode/model/pull_request.py:1914
+#: rhodecode/model/pull_request.py:1916
msgid "Commit IDs"
msgstr ""
-#: rhodecode/model/pull_request.py:1917
+#: rhodecode/model/pull_request.py:1919
#: rhodecode/templates/summary/components.mako:22
msgid "Closed Branches"
msgstr ""
-#: rhodecode/model/pull_request.py:2103
+#: rhodecode/model/pull_request.py:2105
msgid "WIP marker in title prevents from accidental merge."
msgstr ""
-#: rhodecode/model/pull_request.py:2113
+#: rhodecode/model/pull_request.py:2115
msgid "User `{}` not allowed to perform merge."
msgstr ""
-#: rhodecode/model/pull_request.py:2131
+#: rhodecode/model/pull_request.py:2133
msgid "Target branch `{}` changes rejected by rule {}."
msgstr ""
-#: rhodecode/model/pull_request.py:2146
+#: rhodecode/model/pull_request.py:2148
msgid "Pull request reviewer approval is pending."
msgstr ""
-#: rhodecode/model/pull_request.py:2160
+#: rhodecode/model/pull_request.py:2162
msgid "Cannot merge, {} TODO still not resolved."
msgstr ""
-#: rhodecode/model/pull_request.py:2163
+#: rhodecode/model/pull_request.py:2165
msgid "Cannot merge, {} TODOs still not resolved."
msgstr ""
-#: rhodecode/model/pull_request.py:2218
+#: rhodecode/model/pull_request.py:2220
msgid "Merge strategy: rebase"
msgstr ""
-#: rhodecode/model/pull_request.py:2223
+#: rhodecode/model/pull_request.py:2225
msgid "Merge strategy: explicit merge commit"
msgstr ""
-#: rhodecode/model/pull_request.py:2231
-msgid "Source branch will be closed before the merge."
-msgstr ""
-
#: rhodecode/model/pull_request.py:2233
+msgid "Source branch will be closed before the merge."
+msgstr ""
+
+#: rhodecode/model/pull_request.py:2235
msgid "Source branch will be deleted after the merge."
msgstr ""
@@ -4880,129 +4880,133 @@ msgstr ""
msgid "Note Comment"
msgstr ""
-#: rhodecode/public/js/scripts.js:39599 rhodecode/public/js/scripts.js:39987
+#: rhodecode/public/js/scripts.js:39599 rhodecode/public/js/scripts.js:39985
#: rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:103
#: rhodecode/public/js/src/rhodecode/codemirror.js:730
-#: rhodecode/public/js/src/rhodecode/comments.js:267
+#: rhodecode/public/js/src/rhodecode/comments.js:265
msgid "Status Review"
msgstr ""
-#: rhodecode/public/js/scripts.js:39614 rhodecode/public/js/scripts.js:40004
+#: rhodecode/public/js/scripts.js:39614 rhodecode/public/js/scripts.js:40002
#: rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:24
#: rhodecode/public/js/src/rhodecode/codemirror.js:745
-#: rhodecode/public/js/src/rhodecode/comments.js:284
+#: rhodecode/public/js/src/rhodecode/comments.js:282
msgid "Comment text will be set automatically based on currently selected status ({0}) ..."
msgstr ""
-#: rhodecode/public/js/scripts.js:39695 rhodecode/public/js/scripts.js:40213
-#: rhodecode/public/js/scripts.js:41745 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:39695 rhodecode/public/js/scripts.js:40211
+#: rhodecode/public/js/scripts.js:41883 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:49
#: rhodecode/public/js/src/rhodecode/codemirror.js:826
-#: rhodecode/public/js/src/rhodecode/comments.js:493
+#: rhodecode/public/js/src/rhodecode/comments.js:491
#: rhodecode/public/js/src/rhodecode/files.js:499
#: rhodecode/templates/files/files_browser_tree.mako:57
msgid "Loading ..."
msgstr ""
-#: rhodecode/public/js/scripts.js:39860 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:39859 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:123
-#: rhodecode/public/js/src/rhodecode/comments.js:140
+#: rhodecode/public/js/src/rhodecode/comments.js:139
msgid "Update Comment"
msgstr ""
-#: rhodecode/public/js/scripts.js:39884 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:39883 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:150
-#: rhodecode/public/js/src/rhodecode/comments.js:164
+#: rhodecode/public/js/src/rhodecode/comments.js:163
msgid "resolve comment"
msgstr ""
+#: rhodecode/public/js/scripts.js:40155 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/rhodecode/i18n/js_translations.js:83
+#: rhodecode/public/js/src/rhodecode/comments.js:435
+msgid "Saving Draft..."
+msgstr ""
+
#: rhodecode/public/js/scripts.js:40157 rhodecode/public/js/scripts.min.js:1
-#: rhodecode/public/js/rhodecode/i18n/js_translations.js:83
+#: rhodecode/public/js/rhodecode/i18n/js_translations.js:108
#: rhodecode/public/js/src/rhodecode/comments.js:437
-msgid "Saving Draft..."
-msgstr ""
-
-#: rhodecode/public/js/scripts.js:40159 rhodecode/public/js/scripts.min.js:1
-#: rhodecode/public/js/rhodecode/i18n/js_translations.js:108
-#: rhodecode/public/js/src/rhodecode/comments.js:439
msgid "Submitting..."
msgstr ""
-#: rhodecode/public/js/scripts.js:40481 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:40479 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:131
-#: rhodecode/public/js/src/rhodecode/comments.js:761
+#: rhodecode/public/js/src/rhodecode/comments.js:759
msgid "Yes, delete comment #{0}!"
msgstr ""
-#: rhodecode/public/js/scripts.js:40526 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:40524 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:106
-#: rhodecode/public/js/src/rhodecode/comments.js:806
+#: rhodecode/public/js/src/rhodecode/comments.js:804
msgid "Submit {0} draft comment."
msgstr ""
-#: rhodecode/public/js/scripts.js:40529 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:40527 rhodecode/public/js/scripts.js:41225
+#: rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:130
-#: rhodecode/public/js/src/rhodecode/comments.js:809
+#: rhodecode/public/js/src/rhodecode/comments.js:807
+#: rhodecode/public/js/src/rhodecode/comments.js:1505
msgid "Yes"
msgstr ""
-#: rhodecode/public/js/scripts.js:40621 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:40619 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:47
-#: rhodecode/public/js/src/rhodecode/comments.js:901
+#: rhodecode/public/js/src/rhodecode/comments.js:899
msgid "Leave a resolution comment, or click resolve button to resolve TODO comment #{0}"
msgstr ""
-#: rhodecode/public/js/scripts.js:40825 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:40823 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:23
-#: rhodecode/public/js/src/rhodecode/comments.js:1105
+#: rhodecode/public/js/src/rhodecode/comments.js:1103
msgid "Comment body was not changed."
msgstr ""
-#: rhodecode/public/js/scripts.js:41071 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41074 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:44
-#: rhodecode/public/js/src/rhodecode/comments.js:1351
+#: rhodecode/public/js/src/rhodecode/comments.js:1354
msgid "Leave a comment on file {0} line {1}."
msgstr ""
-#: rhodecode/public/js/scripts.js:41212 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41214 rhodecode/public/js/scripts.js:41267
+#: rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:113
-#: rhodecode/public/js/src/rhodecode/comments.js:1492
+#: rhodecode/public/js/src/rhodecode/comments.js:1494
+#: rhodecode/public/js/src/rhodecode/comments.js:1547
msgid "TODO from comment {0} was fixed."
msgstr ""
-#: rhodecode/public/js/scripts.js:41494 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41632 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:154
#: rhodecode/public/js/src/rhodecode/files.js:248
msgid "truncated result"
msgstr ""
-#: rhodecode/public/js/scripts.js:41496 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41634 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:155
#: rhodecode/public/js/src/rhodecode/files.js:250
msgid "truncated results"
msgstr ""
-#: rhodecode/public/js/scripts.js:41505 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41643 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:60
#: rhodecode/public/js/src/rhodecode/files.js:259
msgid "No matching files"
msgstr ""
-#: rhodecode/public/js/scripts.js:41563 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41701 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:86
#: rhodecode/public/js/src/rhodecode/files.js:317
msgid "Selection link"
msgstr ""
-#: rhodecode/public/js/scripts.js:41660 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41798 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:10
#: rhodecode/public/js/src/rhodecode/files.js:414
msgid "All Authors"
msgstr ""
-#: rhodecode/public/js/scripts.js:41810 rhodecode/public/js/scripts.js:41813
+#: rhodecode/public/js/scripts.js:41948 rhodecode/public/js/scripts.js:41951
#: rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:38
#: rhodecode/public/js/src/rhodecode/files.js:564
@@ -5010,141 +5014,141 @@ msgstr ""
msgid "File `{0}` has a newer version available, or has been removed. Click {1} to see the latest version."
msgstr ""
-#: rhodecode/public/js/scripts.js:41816 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41954 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:117
#: rhodecode/public/js/src/rhodecode/files.js:570
msgid "There is an existing path `{0}` at this commit."
msgstr ""
-#: rhodecode/public/js/scripts.js:41819 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:41957 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:116
#: rhodecode/public/js/src/rhodecode/files.js:573
msgid "There is a later version of file tree available. Click {0} to create a file at the latest tree."
msgstr ""
-#: rhodecode/public/js/scripts.js:41873 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42011 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:105
#: rhodecode/public/js/src/rhodecode/followers.js:26
msgid "Stopped watching this repository"
msgstr ""
-#: rhodecode/public/js/scripts.js:41874 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42012 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:129
#: rhodecode/public/js/src/rhodecode/followers.js:27
-#: rhodecode/templates/base/base.mako:310
+#: rhodecode/templates/base/base.mako:311
msgid "Watch"
msgstr ""
-#: rhodecode/public/js/scripts.js:41877 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42015 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:102
#: rhodecode/public/js/src/rhodecode/followers.js:30
msgid "Started watching this repository"
msgstr ""
-#: rhodecode/public/js/scripts.js:41878 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42016 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:122
#: rhodecode/public/js/src/rhodecode/followers.js:31
-#: rhodecode/templates/base/base.mako:308
+#: rhodecode/templates/base/base.mako:309
msgid "Unwatch"
msgstr ""
-#: rhodecode/public/js/scripts.js:42384 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42522 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:12
#: rhodecode/public/js/src/rhodecode/pullrequests.js:185
msgid "All reviewers must vote."
msgstr ""
-#: rhodecode/public/js/scripts.js:42408 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42546 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:54
#: rhodecode/public/js/src/rhodecode/pullrequests.js:209
msgid "No additional review rules set."
msgstr ""
-#: rhodecode/public/js/scripts.js:42454 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42592 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:50
#: rhodecode/public/js/src/rhodecode/pullrequests.js:255
msgid "Loading diff ..."
msgstr ""
-#: rhodecode/public/js/scripts.js:42507 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42645 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:115
#: rhodecode/public/js/src/rhodecode/pullrequests.js:308
msgid "There are no commits to merge."
msgstr ""
-#: rhodecode/public/js/scripts.js:42579 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42717 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:128
#: rhodecode/public/js/src/rhodecode/pullrequests.js:380
msgid "User `{0}` not allowed to be a reviewer"
msgstr ""
-#: rhodecode/public/js/scripts.js:42585 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42723 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:127
#: rhodecode/public/js/src/rhodecode/pullrequests.js:386
msgid "User `{0}` already in reviewers/observers"
msgstr ""
-#: rhodecode/public/js/scripts.js:42699 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42838 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:135
#: rhodecode/public/js/src/rhodecode/pullrequests.js:501
msgid "added manually by \"{0}\""
msgstr ""
-#: rhodecode/public/js/scripts.js:42704 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:42843 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:147
#: rhodecode/public/js/src/rhodecode/pullrequests.js:506
msgid "member of \"{0}\""
msgstr ""
-#: rhodecode/public/js/scripts.js:42937 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:43076 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:125
#: rhodecode/public/js/src/rhodecode/pullrequests.js:739
msgid "Updating..."
msgstr ""
-#: rhodecode/public/js/scripts.js:42947 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:43086 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:40
#: rhodecode/public/js/src/rhodecode/pullrequests.js:749
msgid "Force updating..."
msgstr ""
-#: rhodecode/public/js/scripts.js:47812 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:47953 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:98
#: rhodecode/public/js/src/rhodecode/users.js:54
msgid "Show this authentication token?"
msgstr ""
-#: rhodecode/public/js/scripts.js:47814 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:47955 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:90
#: rhodecode/public/js/src/rhodecode/users.js:56
msgid "Show"
msgstr ""
-#: rhodecode/public/js/scripts.js:47850 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:47991 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:16
#: rhodecode/public/js/src/rhodecode/users.js:92
msgid "Authentication Token"
msgstr ""
-#: rhodecode/public/js/scripts.js:48039 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:48180 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:139
#: rhodecode/public/js/src/rhodecode.js:144
msgid "file"
msgstr ""
-#: rhodecode/public/js/scripts.js:48183 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:48324 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:53
#: rhodecode/public/js/src/rhodecode.js:288
msgid "Loading..."
msgstr ""
-#: rhodecode/public/js/scripts.js:48565 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:48706 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:136
#: rhodecode/public/js/src/rhodecode.js:670
msgid "date not in future"
msgstr ""
-#: rhodecode/public/js/scripts.js:48573 rhodecode/public/js/scripts.min.js:1
+#: rhodecode/public/js/scripts.js:48714 rhodecode/public/js/scripts.min.js:1
#: rhodecode/public/js/rhodecode/i18n/js_translations.js:100
#: rhodecode/public/js/src/rhodecode.js:678
msgid "Specified expiration date"
@@ -5737,8 +5741,8 @@ msgid "%s Repository group dashboard"
msgstr ""
#: rhodecode/templates/index_repo_group.mako:13
-#: rhodecode/templates/base/base.mako:810
#: rhodecode/templates/base/base.mako:811
+#: rhodecode/templates/base/base.mako:812
msgid "Home"
msgstr ""
@@ -5933,9 +5937,9 @@ msgstr ""
#: rhodecode/templates/admin/admin_log_base.mako:10
#: rhodecode/templates/admin/defaults/defaults.mako:32
#: rhodecode/templates/admin/permissions/permissions_objects.mako:16
-#: rhodecode/templates/base/base.mako:658
-#: rhodecode/templates/base/base.mako:660
-#: rhodecode/templates/base/base.mako:662
+#: rhodecode/templates/base/base.mako:659
+#: rhodecode/templates/base/base.mako:661
+#: rhodecode/templates/base/base.mako:663
#: rhodecode/templates/search/search_commit.mako:8
#: rhodecode/templates/search/search_path.mako:7
msgid "Repository"
@@ -6261,7 +6265,7 @@ msgid "Expires"
msgstr ""
#: rhodecode/templates/admin/gists/gist_new.mako:5
-#: rhodecode/templates/base/base.mako:577
+#: rhodecode/templates/base/base.mako:578
msgid "New Gist"
msgstr ""
@@ -6353,7 +6357,7 @@ msgstr ""
#: rhodecode/templates/admin/integrations/new.mako:15
#: rhodecode/templates/admin/repo_groups/repo_group_edit.mako:33
#: rhodecode/templates/admin/repos/repo_edit.mako:74
-#: rhodecode/templates/base/base.mako:120
+#: rhodecode/templates/base/base.mako:121
msgid "Integrations"
msgstr ""
@@ -6368,7 +6372,7 @@ msgstr ""
#: rhodecode/templates/admin/settings/settings.mako:14
#: rhodecode/templates/admin/user_groups/user_group_edit.mako:34
#: rhodecode/templates/admin/user_groups/user_group_edit_settings.mako:9
-#: rhodecode/templates/base/base.mako:122
+#: rhodecode/templates/base/base.mako:123
msgid "Settings"
msgstr ""
@@ -6469,7 +6473,7 @@ msgid "No description available"
msgstr ""
#: rhodecode/templates/admin/my_account/my_account.mako:5
-#: rhodecode/templates/base/base.mako:622
+#: rhodecode/templates/base/base.mako:623
msgid "My account"
msgstr ""
@@ -6520,15 +6524,15 @@ msgstr ""
#: rhodecode/templates/admin/my_account/my_account.mako:45
#: rhodecode/templates/admin/notifications/notifications_show_all.mako:42
-#: rhodecode/templates/base/base.mako:385
-#: rhodecode/templates/base/base.mako:626
+#: rhodecode/templates/base/base.mako:386
+#: rhodecode/templates/base/base.mako:627
msgid "Pull Requests"
msgstr ""
#: rhodecode/templates/admin/my_account/my_account.mako:46
#: rhodecode/templates/admin/permissions/permissions.mako:14
#: rhodecode/templates/admin/user_groups/user_group_edit.mako:35
-#: rhodecode/templates/base/base.mako:118
+#: rhodecode/templates/base/base.mako:119
msgid "Permissions"
msgstr ""
@@ -7047,7 +7051,7 @@ msgstr ""
#: rhodecode/templates/admin/repo_groups/repo_group_add.mako:14
#: rhodecode/templates/admin/users/user_edit_advanced.mako:13
#: rhodecode/templates/base/base.mako:115
-#: rhodecode/templates/base/base.mako:136
+#: rhodecode/templates/base/base.mako:137
msgid "Repository groups"
msgstr ""
@@ -7062,7 +7066,7 @@ msgstr ""
#: rhodecode/templates/admin/repo_groups/repo_group_edit_settings.mako:25
#: rhodecode/templates/admin/repos/repo_add_base.mako:43
#: rhodecode/templates/admin/repos/repo_edit_settings.mako:33
-#: rhodecode/templates/base/base.mako:671
+#: rhodecode/templates/base/base.mako:672
#: rhodecode/templates/data_table/_dt_elements.mako:217
#: rhodecode/templates/forks/fork.mako:41
msgid "Repository group"
@@ -7312,7 +7316,7 @@ msgid "Import Existing Repository ?"
msgstr ""
#: rhodecode/templates/admin/repos/repo_add_base.mako:23
-#: rhodecode/templates/base/base.mako:332
+#: rhodecode/templates/base/base.mako:333
msgid "Clone from"
msgstr ""
@@ -8024,7 +8028,7 @@ msgstr ""
#: rhodecode/templates/admin/settings/settings_global.mako:140
#: rhodecode/templates/admin/settings/settings_labs.mako:48
#: rhodecode/templates/admin/settings/settings_vcs.mako:13
-#: rhodecode/templates/admin/settings/settings_visual.mako:214
+#: rhodecode/templates/admin/settings/settings_visual.mako:217
msgid "Save settings"
msgstr ""
@@ -8550,7 +8554,7 @@ msgstr ""
msgid "Clone URL templates"
msgstr ""
-#: rhodecode/templates/admin/settings/settings_visual.mako:181
+#: rhodecode/templates/admin/settings/settings_visual.mako:184
msgid ""
"Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
" {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
@@ -8562,11 +8566,11 @@ msgid ""
" {repoid} ID of repository, can be used to contruct clone-by-id"
msgstr ""
-#: rhodecode/templates/admin/settings/settings_visual.mako:196
+#: rhodecode/templates/admin/settings/settings_visual.mako:199
msgid "Custom Support Link"
msgstr ""
-#: rhodecode/templates/admin/settings/settings_visual.mako:204
+#: rhodecode/templates/admin/settings/settings_visual.mako:207
#, python-format
msgid ""
"Custom url for the support link located at the bottom.\n"
@@ -8582,7 +8586,7 @@ msgstr ""
#: rhodecode/templates/admin/user_groups/user_group_add.mako:13
#: rhodecode/templates/admin/users/user_edit_advanced.mako:14
#: rhodecode/templates/base/base.mako:117
-#: rhodecode/templates/base/base.mako:139
+#: rhodecode/templates/base/base.mako:140
msgid "User groups"
msgstr ""
@@ -9090,16 +9094,21 @@ msgstr ""
msgid "Delegated Admin Panel"
msgstr ""
-#: rhodecode/templates/base/base.mako:119
+#: rhodecode/templates/base/base.mako:118
+#: rhodecode/templates/base/base.mako:395
+msgid "Artifacts"
+msgstr ""
+
+#: rhodecode/templates/base/base.mako:120
msgid "Authentication"
msgstr ""
-#: rhodecode/templates/base/base.mako:121
+#: rhodecode/templates/base/base.mako:122
msgid "Defaults"
msgstr ""
-#: rhodecode/templates/base/base.mako:161
-#: rhodecode/templates/base/base.mako:201
+#: rhodecode/templates/base/base.mako:162
+#: rhodecode/templates/base/base.mako:202
#: rhodecode/templates/changeset/changeset.mako:140
#: rhodecode/templates/files/files_source_header.mako:57
#: rhodecode/templates/files/files_tree_header.mako:44
@@ -9107,40 +9116,40 @@ msgstr ""
msgid "Show More"
msgstr ""
-#: rhodecode/templates/base/base.mako:304
-#: rhodecode/templates/base/base.mako:315
+#: rhodecode/templates/base/base.mako:305
+#: rhodecode/templates/base/base.mako:316
msgid "RSS Feed"
msgstr ""
-#: rhodecode/templates/base/base.mako:306
+#: rhodecode/templates/base/base.mako:307
msgid "Watch this Repository and actions on it in your personalized journal"
msgstr ""
-#: rhodecode/templates/base/base.mako:324
+#: rhodecode/templates/base/base.mako:325
msgid "Fork of"
msgstr ""
-#: rhodecode/templates/base/base.mako:341
+#: rhodecode/templates/base/base.mako:342
#, python-format
msgid "Repository locked by %(user)s"
msgstr ""
-#: rhodecode/templates/base/base.mako:346
+#: rhodecode/templates/base/base.mako:347
msgid "Repository not locked. Pull repository to lock it."
msgstr ""
-#: rhodecode/templates/base/base.mako:362
+#: rhodecode/templates/base/base.mako:363
msgid "This repository has been archived. It is now read-only."
msgstr ""
-#: rhodecode/templates/base/base.mako:375
+#: rhodecode/templates/base/base.mako:376
#: rhodecode/templates/data_table/_dt_elements.mako:58
#: rhodecode/templates/data_table/_dt_elements.mako:59
#: rhodecode/templates/data_table/_dt_elements.mako:207
msgid "Summary"
msgstr ""
-#: rhodecode/templates/base/base.mako:376
+#: rhodecode/templates/base/base.mako:377
#: rhodecode/templates/data_table/_dt_elements.mako:63
#: rhodecode/templates/data_table/_dt_elements.mako:64
#: rhodecode/templates/files/file_authors_box.mako:30
@@ -9150,7 +9159,7 @@ msgstr ""
msgid "Commits"
msgstr ""
-#: rhodecode/templates/base/base.mako:377
+#: rhodecode/templates/base/base.mako:378
#: rhodecode/templates/data_table/_dt_elements.mako:68
#: rhodecode/templates/data_table/_dt_elements.mako:69
#: rhodecode/templates/files/files.mako:15
@@ -9158,87 +9167,83 @@ msgstr ""
msgid "Files"
msgstr ""
-#: rhodecode/templates/base/base.mako:378
+#: rhodecode/templates/base/base.mako:379
#: rhodecode/templates/bookmarks/bookmarks.mako:78
#: rhodecode/templates/branches/branches.mako:77
#: rhodecode/templates/tags/tags.mako:78
msgid "Compare"
msgstr ""
-#: rhodecode/templates/base/base.mako:383
+#: rhodecode/templates/base/base.mako:384
#, python-format
msgid "Show Pull Requests for %s"
msgstr ""
-#: rhodecode/templates/base/base.mako:394
-msgid "Artifacts"
-msgstr ""
-
-#: rhodecode/templates/base/base.mako:400
+#: rhodecode/templates/base/base.mako:401
msgid "Repository Settings"
msgstr ""
-#: rhodecode/templates/base/base.mako:406
+#: rhodecode/templates/base/base.mako:407
msgid "Options"
msgstr ""
-#: rhodecode/templates/base/base.mako:411
+#: rhodecode/templates/base/base.mako:412
msgid "Unlock Repository"
msgstr ""
-#: rhodecode/templates/base/base.mako:413
+#: rhodecode/templates/base/base.mako:414
msgid "Lock Repository"
msgstr ""
-#: rhodecode/templates/base/base.mako:466
+#: rhodecode/templates/base/base.mako:467
msgid "Group Home"
msgstr ""
-#: rhodecode/templates/base/base.mako:470
+#: rhodecode/templates/base/base.mako:471
msgid "You have admin right to this group, and can edit it"
msgstr ""
-#: rhodecode/templates/base/base.mako:470
+#: rhodecode/templates/base/base.mako:471
msgid "Group Settings"
msgstr ""
-#: rhodecode/templates/base/base.mako:521
+#: rhodecode/templates/base/base.mako:522
msgid "This Repository"
msgstr ""
-#: rhodecode/templates/base/base.mako:523
+#: rhodecode/templates/base/base.mako:524
msgid "Create Pull Request"
msgstr ""
-#: rhodecode/templates/base/base.mako:527
+#: rhodecode/templates/base/base.mako:528
msgid "Fork this repository"
msgstr ""
-#: rhodecode/templates/base/base.mako:534
+#: rhodecode/templates/base/base.mako:535
msgid "This Repository Group"
msgstr ""
-#: rhodecode/templates/base/base.mako:538
-#: rhodecode/templates/base/base.mako:554
-#: rhodecode/templates/base/base.mako:566
+#: rhodecode/templates/base/base.mako:539
+#: rhodecode/templates/base/base.mako:555
+#: rhodecode/templates/base/base.mako:567
msgid "New Repository"
msgstr ""
-#: rhodecode/templates/base/base.mako:544
-#: rhodecode/templates/base/base.mako:558
-#: rhodecode/templates/base/base.mako:572
+#: rhodecode/templates/base/base.mako:545
+#: rhodecode/templates/base/base.mako:559
+#: rhodecode/templates/base/base.mako:573
msgid "New Repository Group"
msgstr ""
-#: rhodecode/templates/base/base.mako:599
+#: rhodecode/templates/base/base.mako:600
msgid "Sign in"
msgstr ""
-#: rhodecode/templates/base/base.mako:624
+#: rhodecode/templates/base/base.mako:625
msgid "My personal group"
msgstr ""
-#: rhodecode/templates/base/base.mako:630
+#: rhodecode/templates/base/base.mako:631
#: rhodecode/templates/debug_style/alerts.html:5
#: rhodecode/templates/debug_style/buttons.html:5
#: rhodecode/templates/debug_style/code-block.html:6
@@ -9261,62 +9266,62 @@ msgstr ""
msgid "Style"
msgstr ""
-#: rhodecode/templates/base/base.mako:631
+#: rhodecode/templates/base/base.mako:632
msgid "[Style]"
msgstr ""
-#: rhodecode/templates/base/base.mako:648
+#: rhodecode/templates/base/base.mako:649
msgid "No Bookmarks yet."
msgstr ""
-#: rhodecode/templates/base/base.mako:686
+#: rhodecode/templates/base/base.mako:687
msgid "Sign Out"
msgstr ""
-#: rhodecode/templates/base/base.mako:731
+#: rhodecode/templates/base/base.mako:732
#: rhodecode/templates/changeset/changeset_file_comment.mako:538
msgid "dismiss"
msgstr ""
-#: rhodecode/templates/base/base.mako:772
+#: rhodecode/templates/base/base.mako:773
msgid "search / go to..."
msgstr ""
-#: rhodecode/templates/base/base.mako:817
-msgid "Show activity journal"
-msgstr ""
-
#: rhodecode/templates/base/base.mako:818
+msgid "Show activity journal"
+msgstr ""
+
+#: rhodecode/templates/base/base.mako:819
#: rhodecode/templates/journal/journal.mako:4
#: rhodecode/templates/journal/journal.mako:14
msgid "Journal"
msgstr ""
-#: rhodecode/templates/base/base.mako:823
-msgid "Show Public activity journal"
-msgstr ""
-
#: rhodecode/templates/base/base.mako:824
+msgid "Show Public activity journal"
+msgstr ""
+
+#: rhodecode/templates/base/base.mako:825
msgid "Public journal"
msgstr ""
-#: rhodecode/templates/base/base.mako:830
-msgid "Show Gists"
-msgstr ""
-
#: rhodecode/templates/base/base.mako:831
+msgid "Show Gists"
+msgstr ""
+
+#: rhodecode/templates/base/base.mako:832
msgid "Gists"
msgstr ""
-#: rhodecode/templates/base/base.mako:837
+#: rhodecode/templates/base/base.mako:838
msgid "Admin settings"
msgstr ""
-#: rhodecode/templates/base/base.mako:1154
+#: rhodecode/templates/base/base.mako:1155
msgid "Keyboard shortcuts"
msgstr ""
-#: rhodecode/templates/base/base.mako:1162
+#: rhodecode/templates/base/base.mako:1163
msgid "Site-wide shortcuts"
msgstr ""
@@ -9357,7 +9362,7 @@ msgid "Repository Forking"
msgstr ""
#: rhodecode/templates/base/default_perms_box.mako:65
-msgid "Permission to create root level repository forks. When disabled, users can still fork repositories inside their own repository groups."
+msgid "Permission to create repository forks. Root level forks will only work if repository creation is enabled."
msgstr ""
#: rhodecode/templates/base/default_perms_box.mako:70
@@ -9418,7 +9423,7 @@ msgstr ""
#: rhodecode/templates/base/issue_tracker_settings.mako:300
#: rhodecode/templates/changeset/changeset_file_comment.mako:395
#: rhodecode/templates/changeset/changeset_file_comment.mako:446
-#: rhodecode/templates/data_table/_dt_elements.mako:456
+#: rhodecode/templates/data_table/_dt_elements.mako:463
#: rhodecode/templates/files/files_add.mako:59
#: rhodecode/templates/files/files_edit.mako:61
msgid "Preview"
@@ -10481,11 +10486,11 @@ msgstr ""
msgid "Work in progress"
msgstr ""
-#: rhodecode/templates/data_table/_dt_elements.mako:432
+#: rhodecode/templates/data_table/_dt_elements.mako:438
msgid "Info"
msgstr ""
-#: rhodecode/templates/data_table/_dt_elements.mako:473
+#: rhodecode/templates/data_table/_dt_elements.mako:480
#, python-format
msgid "Parsed using %s syntax"
msgstr ""
@@ -10645,7 +10650,7 @@ msgid "{mention_prefix}{user} left a {co
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:54
-#: rhodecode/templates/email_templates/pull_request_comment.mako:63
+#: rhodecode/templates/email_templates/pull_request_comment.mako:62
msgid "Comment link"
msgstr ""
@@ -10662,26 +10667,26 @@ msgid "Commit message"
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:65
-#: rhodecode/templates/email_templates/pull_request_comment.mako:77
+#: rhodecode/templates/email_templates/pull_request_comment.mako:76
msgid "File: {comment_file} on line {comment_line}"
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:69
#: rhodecode/templates/email_templates/commit_comment.mako:161
-#: rhodecode/templates/email_templates/pull_request_comment.mako:81
-#: rhodecode/templates/email_templates/pull_request_comment.mako:191
+#: rhodecode/templates/email_templates/pull_request_comment.mako:80
+#: rhodecode/templates/email_templates/pull_request_comment.mako:190
msgid "`TODO` number"
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:71
#: rhodecode/templates/email_templates/commit_comment.mako:163
-#: rhodecode/templates/email_templates/pull_request_comment.mako:83
-#: rhodecode/templates/email_templates/pull_request_comment.mako:193
+#: rhodecode/templates/email_templates/pull_request_comment.mako:82
+#: rhodecode/templates/email_templates/pull_request_comment.mako:192
msgid "`Note` number"
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:104
-#: rhodecode/templates/email_templates/pull_request_comment.mako:124
+#: rhodecode/templates/email_templates/pull_request_comment.mako:123
msgid "left a"
msgstr ""
@@ -10702,18 +10707,18 @@ msgid "Commit Status"
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:153
-#: rhodecode/templates/email_templates/pull_request_comment.mako:183
+#: rhodecode/templates/email_templates/pull_request_comment.mako:182
#: rhodecode/templates/search/search_path.mako:9
msgid "File"
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:154
-#: rhodecode/templates/email_templates/pull_request_comment.mako:184
+#: rhodecode/templates/email_templates/pull_request_comment.mako:183
msgid "`{comment_file}` on line {comment_line}"
msgstr ""
#: rhodecode/templates/email_templates/commit_comment.mako:173
-#: rhodecode/templates/email_templates/pull_request_comment.mako:203
+#: rhodecode/templates/email_templates/pull_request_comment.mako:202
msgid "Reply"
msgstr ""
@@ -10729,35 +10734,35 @@ msgstr ""
msgid "{mention_prefix}{user} left a {comment_type} on pull request !{pr_id}: \"{pr_title}\""
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:65
+#: rhodecode/templates/email_templates/pull_request_comment.mako:64
#: rhodecode/templates/hovercards/hovercard_pull_request.mako:24
msgid "Pull Request"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:67
+#: rhodecode/templates/email_templates/pull_request_comment.mako:66
#: rhodecode/templates/email_templates/pull_request_review.mako:45
#: rhodecode/templates/email_templates/pull_request_update.mako:41
msgid "Commit flow: {source_ref_type}:{source_ref_name} of {source_repo_url} into {target_ref_type}:{target_ref_name} of {target_repo_url}"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:70
+#: rhodecode/templates/email_templates/pull_request_comment.mako:69
msgid "{user} submitted pull request !{pr_id} status: *{status}*"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:73
+#: rhodecode/templates/email_templates/pull_request_comment.mako:72
msgid "{user} submitted pull request !{pr_id} status: *{status} and closed*"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:127
+#: rhodecode/templates/email_templates/pull_request_comment.mako:126
msgid "{comment_type} on file `{comment_file}` in pull request."
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:129
+#: rhodecode/templates/email_templates/pull_request_comment.mako:128
msgid "{comment_type} on pull request."
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:134
-#: rhodecode/templates/email_templates/pull_request_comment.mako:164
+#: rhodecode/templates/email_templates/pull_request_comment.mako:133
+#: rhodecode/templates/email_templates/pull_request_comment.mako:163
#: rhodecode/templates/email_templates/pull_request_review.mako:100
#: rhodecode/templates/email_templates/pull_request_review.mako:116
#: rhodecode/templates/email_templates/pull_request_update.mako:104
@@ -10765,26 +10770,26 @@ msgstr ""
msgid "Pull request"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:153
+#: rhodecode/templates/email_templates/pull_request_comment.mako:152
msgid "Review Status"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:156
+#: rhodecode/templates/email_templates/pull_request_comment.mako:155
msgid "Closed pull request with status"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:158
+#: rhodecode/templates/email_templates/pull_request_comment.mako:157
msgid "Submitted review status"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:173
+#: rhodecode/templates/email_templates/pull_request_comment.mako:172
#: rhodecode/templates/email_templates/pull_request_review.mako:125
#: rhodecode/templates/email_templates/pull_request_update.mako:130
msgid "Commit Flow"
msgstr ""
-#: rhodecode/templates/email_templates/pull_request_comment.mako:175
-#: rhodecode/templates/email_templates/pull_request_comment.mako:177
+#: rhodecode/templates/email_templates/pull_request_comment.mako:174
+#: rhodecode/templates/email_templates/pull_request_comment.mako:176
#: rhodecode/templates/email_templates/pull_request_review.mako:127
#: rhodecode/templates/email_templates/pull_request_review.mako:129
#: rhodecode/templates/email_templates/pull_request_update.mako:132
@@ -11447,12 +11452,12 @@ msgstr ""
msgid "In pull request description"
msgstr ""
-#: rhodecode/templates/pullrequests/pullrequest_show.mako:838
-#: rhodecode/templates/pullrequests/pullrequest_show.mako:857
+#: rhodecode/templates/pullrequests/pullrequest_show.mako:840
+#: rhodecode/templates/pullrequests/pullrequest_show.mako:860
msgid "No Ticket data found."
msgstr ""
-#: rhodecode/templates/pullrequests/pullrequest_show.mako:843
+#: rhodecode/templates/pullrequests/pullrequest_show.mako:845
msgid "In commit messages"
msgstr ""
diff --git a/rhodecode/integrations/types/base.py b/rhodecode/integrations/types/base.py
--- a/rhodecode/integrations/types/base.py
+++ b/rhodecode/integrations/types/base.py
@@ -131,7 +131,7 @@ class IntegrationTypeBase(object):
:param event:
:return: bool
"""
- allowed_events = self.settings['events']
+ allowed_events = self.settings.get('events') or []
if event.name not in allowed_events:
log.debug('event ignored: %r event %s not in allowed set of events %s',
event, event.name, allowed_events)
diff --git a/rhodecode/lib/celerylib/tasks.py b/rhodecode/lib/celerylib/tasks.py
--- a/rhodecode/lib/celerylib/tasks.py
+++ b/rhodecode/lib/celerylib/tasks.py
@@ -38,6 +38,7 @@ from rhodecode.lib import hooks_base
from rhodecode.lib.utils2 import safe_int, str2bool, aslist
from rhodecode.model.db import (
Session, IntegrityError, true, Repository, RepoGroup, User)
+from rhodecode.model.permission import PermissionModel
@async_task(ignore_result=True, base=RequestContextTask)
@@ -216,6 +217,9 @@ def create_repo(form_data, cur_user):
repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
Session().commit()
+
+ PermissionModel().trigger_permission_flush()
+
except Exception as e:
log.warning('Exception occurred when creating repository, '
'doing cleanup...', exc_info=True)
diff --git a/rhodecode/lib/utils2.py b/rhodecode/lib/utils2.py
--- a/rhodecode/lib/utils2.py
+++ b/rhodecode/lib/utils2.py
@@ -35,7 +35,7 @@ import urllib
import urlobject
import uuid
import getpass
-from functools import update_wrapper, partial
+from functools import update_wrapper, partial, wraps
import pygments.lexers
import sqlalchemy
@@ -1038,16 +1038,17 @@ class CachedProperty(object):
"""
Lazy Attributes. With option to invalidate the cache by running a method
- class Foo():
+ >>> class Foo(object):
+ ...
+ ... @CachedProperty
+ ... def heavy_func(self):
+ ... return 'super-calculation'
+ ...
+ ... foo = Foo()
+ ... foo.heavy_func() # first computation
+ ... foo.heavy_func() # fetch from cache
+ ... foo._invalidate_prop_cache('heavy_func')
- @CachedProperty
- def heavy_func():
- return 'super-calculation'
-
- foo = Foo()
- foo.heavy_func() # first computions
- foo.heavy_func() # fetch from cache
- foo._invalidate_prop_cache('heavy_func')
# at this point calling foo.heavy_func() will be re-computed
"""
@@ -1072,3 +1073,76 @@ class CachedProperty(object):
def _invalidate_prop_cache(self, inst, name):
inst.__dict__.pop(name, None)
+
+
+def retry(func=None, exception=Exception, n_tries=5, delay=5, backoff=1, logger=True):
+ """
+ Retry decorator with exponential backoff.
+
+ Parameters
+ ----------
+ func : typing.Callable, optional
+ Callable on which the decorator is applied, by default None
+ exception : Exception or tuple of Exceptions, optional
+ Exception(s) that invoke retry, by default Exception
+ n_tries : int, optional
+ Number of tries before giving up, by default 5
+ delay : int, optional
+ Initial delay between retries in seconds, by default 5
+ backoff : int, optional
+ Backoff multiplier e.g. value of 2 will double the delay, by default 1
+ logger : bool, optional
+ Option to log or print, by default False
+
+ Returns
+ -------
+ typing.Callable
+ Decorated callable that calls itself when exception(s) occur.
+
+ Examples
+ --------
+ >>> import random
+ >>> @retry(exception=Exception, n_tries=3)
+ ... def test_random(text):
+ ... x = random.random()
+ ... if x < 0.5:
+ ... raise Exception("Fail")
+ ... else:
+ ... print("Success: ", text)
+ >>> test_random("It works!")
+ """
+
+ if func is None:
+ return partial(
+ retry,
+ exception=exception,
+ n_tries=n_tries,
+ delay=delay,
+ backoff=backoff,
+ logger=logger,
+ )
+
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ _n_tries, n_delay = n_tries, delay
+ log = logging.getLogger('rhodecode.retry')
+
+ while _n_tries > 1:
+ try:
+ return func(*args, **kwargs)
+ except exception as e:
+ e_details = repr(e)
+ msg = "Exception on calling func {func}: {e}, " \
+ "Retrying in {n_delay} seconds..."\
+ .format(func=func, e=e_details, n_delay=n_delay)
+ if logger:
+ log.warning(msg)
+ else:
+ print(msg)
+ time.sleep(n_delay)
+ _n_tries -= 1
+ n_delay *= backoff
+
+ return func(*args, **kwargs)
+
+ return wrapper
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
@@ -311,6 +311,7 @@ class BaseRepository(object):
DEFAULT_CONTACT = u"Unknown"
DEFAULT_DESCRIPTION = u"unknown"
EMPTY_COMMIT_ID = '0' * 40
+ COMMIT_ID_PAT = re.compile(r'[0-9a-fA-F]{40}')
path = None
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
@@ -618,7 +618,7 @@ class GitRepository(BaseRepository):
else:
output, __ = self.run_git_command(
['merge-base', commit_id1, commit_id2])
- ancestor_id = re.findall(r'[0-9a-fA-F]{40}', output)[0]
+ ancestor_id = self.COMMIT_ID_PAT.findall(output)[0]
log.debug('Found common ancestor with sha: %s', ancestor_id)
@@ -642,7 +642,7 @@ class GitRepository(BaseRepository):
'%s..%s' % (commit_id1, commit_id2)])
commits = [
repo1.get_commit(commit_id=commit_id, pre_load=pre_load)
- for commit_id in re.findall(r'[0-9a-fA-F]{40}', output)]
+ for commit_id in self.COMMIT_ID_PAT.findall(output)]
return commits
diff --git a/rhodecode/model/changeset_status.py b/rhodecode/model/changeset_status.py
--- a/rhodecode/model/changeset_status.py
+++ b/rhodecode/model/changeset_status.py
@@ -354,7 +354,7 @@ class ChangesetStatusModel(BaseModel):
Session().add(new_status)
return new_statuses
- def aggregate_votes_by_user(self, commit_statuses, reviewers_data):
+ def aggregate_votes_by_user(self, commit_statuses, reviewers_data, user=None):
commit_statuses_map = collections.defaultdict(list)
for st in commit_statuses:
@@ -368,6 +368,10 @@ class ChangesetStatusModel(BaseModel):
for obj in reviewers_data:
if not obj.user:
continue
+ if user and obj.user.username != user.username:
+ # single user filter
+ continue
+
statuses = commit_statuses_map.get(obj.user.username, None)
if statuses:
status_groups = itertools.groupby(
@@ -376,16 +380,19 @@ class ChangesetStatusModel(BaseModel):
reviewers.append((obj, obj.user, obj.reasons, obj.mandatory, statuses))
- return reviewers
+ if user:
+ return reviewers[0] if reviewers else reviewers
+ else:
+ return reviewers
- def reviewers_statuses(self, pull_request):
+ def reviewers_statuses(self, pull_request, user=None):
_commit_statuses = self.get_statuses(
pull_request.source_repo,
pull_request=pull_request,
with_revisions=True)
reviewers = pull_request.get_pull_request_reviewers(
role=PullRequestReviewers.ROLE_REVIEWER)
- return self.aggregate_votes_by_user(_commit_statuses, reviewers)
+ return self.aggregate_votes_by_user(_commit_statuses, reviewers, user=user)
def calculated_review_status(self, pull_request):
"""
diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py
--- a/rhodecode/model/db.py
+++ b/rhodecode/model/db.py
@@ -41,10 +41,10 @@ from sqlalchemy import (
Index, Sequence, UniqueConstraint, ForeignKey, CheckConstraint, Column,
Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
Text, Float, PickleType, BigInteger)
-from sqlalchemy.sql.expression import true, false, case
+from sqlalchemy.sql.expression import true, false, case, null
from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
from sqlalchemy.orm import (
- relationship, joinedload, class_mapper, validates, aliased)
+ relationship, lazyload, joinedload, class_mapper, validates, aliased)
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.exc import IntegrityError # pragma: no cover
@@ -911,7 +911,7 @@ class User(Base, BaseModel):
return {}
try:
- return json.loads(self._user_data)
+ return json.loads(self._user_data) or {}
except TypeError:
return {}
@@ -4062,7 +4062,7 @@ class _SetState(object):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
- if exc_val is not None:
+ if exc_val is not None or exc_type is not None:
log.error(traceback.format_exc(exc_tb))
return None
@@ -4479,9 +4479,9 @@ class PullRequest(Base, _PullRequestBase
from rhodecode.model.changeset_status import ChangesetStatusModel
return ChangesetStatusModel().calculated_review_status(self)
- def reviewers_statuses(self):
+ def reviewers_statuses(self, user=None):
from rhodecode.model.changeset_status import ChangesetStatusModel
- return ChangesetStatusModel().reviewers_statuses(self)
+ return ChangesetStatusModel().reviewers_statuses(self, user=user)
def get_pull_request_reviewers(self, role=None):
qry = PullRequestReviewers.query()\
diff --git a/rhodecode/model/pull_request.py b/rhodecode/model/pull_request.py
--- a/rhodecode/model/pull_request.py
+++ b/rhodecode/model/pull_request.py
@@ -56,7 +56,7 @@ from rhodecode.model import BaseModel
from rhodecode.model.changeset_status import ChangesetStatusModel
from rhodecode.model.comment import CommentsModel
from rhodecode.model.db import (
- or_, String, cast, PullRequest, PullRequestReviewers, ChangesetStatus,
+ aliased, null, lazyload, and_, or_, func, String, cast, PullRequest, PullRequestReviewers, ChangesetStatus,
PullRequestVersion, ChangesetComment, Repository, RepoReviewRule, User)
from rhodecode.model.meta import Session
from rhodecode.model.notification import NotificationModel, \
@@ -319,7 +319,7 @@ class PullRequestModel(BaseModel):
if search_q:
like_expression = u'%{}%'.format(safe_unicode(search_q))
- q = q.join(User)
+ q = q.join(User, User.user_id == PullRequest.user_id)
q = q.filter(or_(
cast(PullRequest.pull_request_id, String).ilike(like_expression),
User.username.ilike(like_expression),
@@ -405,36 +405,30 @@ class PullRequestModel(BaseModel):
return pull_requests
- def count_awaiting_review(self, repo_name, search_q=None, source=False, statuses=None,
- opened_by=None):
+ def count_awaiting_review(self, repo_name, search_q=None, statuses=None):
"""
Count the number of pull requests for a specific repository that are
awaiting review.
:param repo_name: target or source repo
:param search_q: filter by text
- :param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
- :param opened_by: author user of the pull request
:returns: int number of pull requests
"""
pull_requests = self.get_awaiting_review(
- repo_name, search_q=search_q, source=source, statuses=statuses, opened_by=opened_by)
+ repo_name, search_q=search_q, statuses=statuses)
return len(pull_requests)
- def get_awaiting_review(self, repo_name, search_q=None, source=False, statuses=None,
- opened_by=None, offset=0, length=None,
- order_by=None, order_dir='desc'):
+ def get_awaiting_review(self, repo_name, search_q=None, statuses=None,
+ offset=0, length=None, order_by=None, order_dir='desc'):
"""
Get all pull requests for a specific repository that are awaiting
review.
:param repo_name: target or source repo
:param search_q: filter by text
- :param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
- :param opened_by: author user of the pull request
:param offset: pagination offset
:param length: length of returned list
:param order_by: order of the returned list
@@ -442,8 +436,8 @@ class PullRequestModel(BaseModel):
:returns: list of pull requests
"""
pull_requests = self.get_all(
- repo_name, search_q=search_q, source=source, statuses=statuses,
- opened_by=opened_by, order_by=order_by, order_dir=order_dir)
+ repo_name, search_q=search_q, statuses=statuses,
+ order_by=order_by, order_dir=order_dir)
_filtered_pull_requests = []
for pr in pull_requests:
@@ -456,68 +450,117 @@ class PullRequestModel(BaseModel):
else:
return _filtered_pull_requests
- def count_awaiting_my_review(self, repo_name, search_q=None, source=False, statuses=None,
- opened_by=None, user_id=None):
+ def _prepare_awaiting_my_review_review_query(
+ self, repo_name, user_id, search_q=None, statuses=None,
+ order_by=None, order_dir='desc'):
+
+ for_review_statuses = [
+ ChangesetStatus.STATUS_UNDER_REVIEW, ChangesetStatus.STATUS_NOT_REVIEWED
+ ]
+
+ pull_request_alias = aliased(PullRequest)
+ status_alias = aliased(ChangesetStatus)
+ reviewers_alias = aliased(PullRequestReviewers)
+ repo_alias = aliased(Repository)
+
+ last_ver_subq = Session()\
+ .query(func.min(ChangesetStatus.version)) \
+ .filter(ChangesetStatus.pull_request_id == reviewers_alias.pull_request_id)\
+ .filter(ChangesetStatus.user_id == reviewers_alias.user_id) \
+ .subquery()
+
+ q = Session().query(pull_request_alias) \
+ .options(lazyload(pull_request_alias.author)) \
+ .join(reviewers_alias,
+ reviewers_alias.pull_request_id == pull_request_alias.pull_request_id) \
+ .join(repo_alias,
+ repo_alias.repo_id == pull_request_alias.target_repo_id) \
+ .outerjoin(status_alias,
+ and_(status_alias.user_id == reviewers_alias.user_id,
+ status_alias.pull_request_id == reviewers_alias.pull_request_id)) \
+ .filter(or_(status_alias.version == null(),
+ status_alias.version == last_ver_subq)) \
+ .filter(reviewers_alias.user_id == user_id) \
+ .filter(repo_alias.repo_name == repo_name) \
+ .filter(or_(status_alias.status == null(), status_alias.status.in_(for_review_statuses))) \
+ .group_by(pull_request_alias)
+
+ # closed,opened
+ if statuses:
+ q = q.filter(pull_request_alias.status.in_(statuses))
+
+ if search_q:
+ like_expression = u'%{}%'.format(safe_unicode(search_q))
+ q = q.join(User, User.user_id == pull_request_alias.user_id)
+ q = q.filter(or_(
+ cast(pull_request_alias.pull_request_id, String).ilike(like_expression),
+ User.username.ilike(like_expression),
+ pull_request_alias.title.ilike(like_expression),
+ pull_request_alias.description.ilike(like_expression),
+ ))
+
+ if order_by:
+ order_map = {
+ 'name_raw': pull_request_alias.pull_request_id,
+ 'title': pull_request_alias.title,
+ 'updated_on_raw': pull_request_alias.updated_on,
+ 'target_repo': pull_request_alias.target_repo_id
+ }
+ if order_dir == 'asc':
+ q = q.order_by(order_map[order_by].asc())
+ else:
+ q = q.order_by(order_map[order_by].desc())
+
+ return q
+
+ def count_awaiting_my_review(self, repo_name, user_id, search_q=None, statuses=None):
"""
Count the number of pull requests for a specific repository that are
awaiting review from a specific user.
:param repo_name: target or source repo
+ :param user_id: reviewer user of the pull request
:param search_q: filter by text
- :param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
- :param opened_by: author user of the pull request
- :param user_id: reviewer user of the pull request
:returns: int number of pull requests
"""
- pull_requests = self.get_awaiting_my_review(
- repo_name, search_q=search_q, source=source, statuses=statuses,
- opened_by=opened_by, user_id=user_id)
+ q = self._prepare_awaiting_my_review_review_query(
+ repo_name, user_id, search_q=search_q, statuses=statuses)
+ return q.count()
- return len(pull_requests)
-
- def get_awaiting_my_review(self, repo_name, search_q=None, source=False, statuses=None,
- opened_by=None, user_id=None, offset=0,
- length=None, order_by=None, order_dir='desc'):
+ def get_awaiting_my_review(self, repo_name, user_id, search_q=None, statuses=None,
+ offset=0, length=None, order_by=None, order_dir='desc'):
"""
Get all pull requests for a specific repository that are awaiting
review from a specific user.
:param repo_name: target or source repo
+ :param user_id: reviewer user of the pull request
:param search_q: filter by text
- :param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
- :param opened_by: author user of the pull request
- :param user_id: reviewer user of the pull request
:param offset: pagination offset
:param length: length of returned list
:param order_by: order of the returned list
:param order_dir: 'asc' or 'desc' ordering direction
:returns: list of pull requests
"""
- pull_requests = self.get_all(
- repo_name, search_q=search_q, source=source, statuses=statuses,
- opened_by=opened_by, order_by=order_by, order_dir=order_dir)
- _my = PullRequestModel().get_not_reviewed(user_id)
- my_participation = []
- for pr in pull_requests:
- if pr in _my:
- my_participation.append(pr)
- _filtered_pull_requests = my_participation
+ q = self._prepare_awaiting_my_review_review_query(
+ repo_name, user_id, search_q=search_q, statuses=statuses,
+ order_by=order_by, order_dir=order_dir)
+
if length:
- return _filtered_pull_requests[offset:offset+length]
+ pull_requests = q.limit(length).offset(offset).all()
else:
- return _filtered_pull_requests
+ pull_requests = q.all()
+
+ return pull_requests
- def get_not_reviewed(self, user_id):
- return [
- x.pull_request for x in PullRequestReviewers.query().filter(
- PullRequestReviewers.user_id == user_id).all()
- ]
-
- def _prepare_participating_query(self, user_id=None, statuses=None, query='',
- order_by=None, order_dir='desc'):
+ def _prepare_im_participating_query(self, user_id=None, statuses=None, query='',
+ order_by=None, order_dir='desc'):
+ """
+ return a query of pull-requests user is an creator, or he's added as a reviewer
+ """
q = PullRequest.query()
if user_id:
reviewers_subquery = Session().query(
@@ -535,7 +578,7 @@ class PullRequestModel(BaseModel):
if query:
like_expression = u'%{}%'.format(safe_unicode(query))
- q = q.join(User)
+ q = q.join(User, User.user_id == PullRequest.user_id)
q = q.filter(or_(
cast(PullRequest.pull_request_id, String).ilike(like_expression),
User.username.ilike(like_expression),
@@ -557,17 +600,97 @@ class PullRequestModel(BaseModel):
return q
def count_im_participating_in(self, user_id=None, statuses=None, query=''):
- q = self._prepare_participating_query(user_id, statuses=statuses, query=query)
+ q = self._prepare_im_participating_query(user_id, statuses=statuses, query=query)
return q.count()
def get_im_participating_in(
self, user_id=None, statuses=None, query='', offset=0,
length=None, order_by=None, order_dir='desc'):
"""
- Get all Pull requests that i'm participating in, or i have opened
+ Get all Pull requests that i'm participating in as a reviewer, or i have opened
"""
- q = self._prepare_participating_query(
+ q = self._prepare_im_participating_query(
+ user_id, statuses=statuses, query=query, order_by=order_by,
+ order_dir=order_dir)
+
+ if length:
+ pull_requests = q.limit(length).offset(offset).all()
+ else:
+ pull_requests = q.all()
+
+ return pull_requests
+
+ def _prepare_participating_in_for_review_query(
+ self, user_id, statuses=None, query='', order_by=None, order_dir='desc'):
+
+ for_review_statuses = [
+ ChangesetStatus.STATUS_UNDER_REVIEW, ChangesetStatus.STATUS_NOT_REVIEWED
+ ]
+
+ pull_request_alias = aliased(PullRequest)
+ status_alias = aliased(ChangesetStatus)
+ reviewers_alias = aliased(PullRequestReviewers)
+
+ last_ver_subq = Session()\
+ .query(func.min(ChangesetStatus.version)) \
+ .filter(ChangesetStatus.pull_request_id == reviewers_alias.pull_request_id)\
+ .filter(ChangesetStatus.user_id == reviewers_alias.user_id) \
+ .subquery()
+
+ q = Session().query(pull_request_alias) \
+ .options(lazyload(pull_request_alias.author)) \
+ .join(reviewers_alias,
+ reviewers_alias.pull_request_id == pull_request_alias.pull_request_id) \
+ .outerjoin(status_alias,
+ and_(status_alias.user_id == reviewers_alias.user_id,
+ status_alias.pull_request_id == reviewers_alias.pull_request_id)) \
+ .filter(or_(status_alias.version == null(),
+ status_alias.version == last_ver_subq)) \
+ .filter(reviewers_alias.user_id == user_id) \
+ .filter(or_(status_alias.status == null(), status_alias.status.in_(for_review_statuses))) \
+ .group_by(pull_request_alias)
+
+ # closed,opened
+ if statuses:
+ q = q.filter(pull_request_alias.status.in_(statuses))
+
+ if query:
+ like_expression = u'%{}%'.format(safe_unicode(query))
+ q = q.join(User, User.user_id == pull_request_alias.user_id)
+ q = q.filter(or_(
+ cast(pull_request_alias.pull_request_id, String).ilike(like_expression),
+ User.username.ilike(like_expression),
+ pull_request_alias.title.ilike(like_expression),
+ pull_request_alias.description.ilike(like_expression),
+ ))
+
+ if order_by:
+ order_map = {
+ 'name_raw': pull_request_alias.pull_request_id,
+ 'title': pull_request_alias.title,
+ 'updated_on_raw': pull_request_alias.updated_on,
+ 'target_repo': pull_request_alias.target_repo_id
+ }
+ if order_dir == 'asc':
+ q = q.order_by(order_map[order_by].asc())
+ else:
+ q = q.order_by(order_map[order_by].desc())
+
+ return q
+
+ def count_im_participating_in_for_review(self, user_id, statuses=None, query=''):
+ q = self._prepare_participating_in_for_review_query(user_id, statuses=statuses, query=query)
+ return q.count()
+
+ def get_im_participating_in_for_review(
+ self, user_id, statuses=None, query='', offset=0,
+ length=None, order_by=None, order_dir='desc'):
+ """
+ Get all Pull requests that needs user approval or rejection
+ """
+
+ q = self._prepare_participating_in_for_review_query(
user_id, statuses=statuses, query=query, order_by=order_by,
order_dir=order_dir)
diff --git a/rhodecode/public/css/buttons.less b/rhodecode/public/css/buttons.less
--- a/rhodecode/public/css/buttons.less
+++ b/rhodecode/public/css/buttons.less
@@ -618,13 +618,13 @@ input[type="reset"] {
text-align: right;
li {
-
-
+ list-style: none;
+ text-align: right;
+ display: inline-block;
}
- li.active {
- background-color: @grey6;
- .border ( @border-thickness, @grey4 );
+ a.active {
+ border: 2px solid @rcblue;
}
}
diff --git a/rhodecode/public/css/panels.less b/rhodecode/public/css/panels.less
--- a/rhodecode/public/css/panels.less
+++ b/rhodecode/public/css/panels.less
@@ -44,7 +44,7 @@
padding: @panel-padding;
&.panel-body-min-height {
- min-height: 150px
+ min-height: 200px
}
}
diff --git a/rhodecode/public/js/src/rhodecode/comments.js b/rhodecode/public/js/src/rhodecode/comments.js
--- a/rhodecode/public/js/src/rhodecode/comments.js
+++ b/rhodecode/public/js/src/rhodecode/comments.js
@@ -791,6 +791,11 @@ var CommentsController = function() {
refreshDraftComments()
}
+ if (window.refreshAllComments !== undefined) {
+ // if we have this handler, run it, and refresh all comments boxes
+ refreshAllComments()
+ }
+
return false;
};
diff --git a/rhodecode/templates/admin/artifacts/artifacts.mako b/rhodecode/templates/admin/artifacts/artifacts.mako
new file mode 100644
--- /dev/null
+++ b/rhodecode/templates/admin/artifacts/artifacts.mako
@@ -0,0 +1,39 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.mako"/>
+
+<%def name="title()">
+ ${_('Artifacts Admin')}
+ %if c.rhodecode_name:
+ · ${h.branding(c.rhodecode_name)}
+ %endif
+%def>
+
+<%def name="breadcrumbs_links()">%def>
+
+<%def name="menu_bar_nav()">
+ ${self.menu_items(active='admin')}
+%def>
+
+<%def name="menu_bar_subnav()">
+ ${self.admin_menu(active='artifacts')}
+%def>
+
+<%def name="main()">
+
+
+
+
+
+
${_('Artifacts Administration.')}
+
+
+
${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='sales@rhodecode.com')|n}