diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -68,3 +68,5 @@ 7ac623a4a2405917e2af660d645ded662011e40d ef7ffda65eeb90c3ba88590a6cb816ef9b0bc232 v4.19.3 3e635489bb7961df93b01e42454ad1a8730ae968 v4.20.0 7e2eb896a02ca7cd2cd9f0f853ef3dac3f0039e3 v4.20.1 +8bb5fece08ab65986225b184e46f53d2a71729cb v4.21.0 +90734aac31ee4563bbe665a43ff73190cc762275 v4.22.0 diff --git a/docs/api/methods/pull-request-methods.rst b/docs/api/methods/pull-request-methods.rst --- a/docs/api/methods/pull-request-methods.rst +++ b/docs/api/methods/pull-request-methods.rst @@ -90,7 +90,7 @@ comment_pull_request create_pull_request ------------------- -.. py:function:: create_pull_request(apiuser, source_repo, target_repo, source_ref, target_ref, owner=>, title=, description=, description_renderer=, reviewers=) +.. py:function:: create_pull_request(apiuser, source_repo, target_repo, source_ref, target_ref, owner=>, title=, description=, description_renderer=, reviewers=, observers=) Creates a new pull request. @@ -128,6 +128,13 @@ create_pull_request Accepts username strings or objects of the format: [{'username': 'nick', 'reasons': ['original author'], 'mandatory': }] + :param observers: Set the new pull request observers list. + Reviewer defined by review rules will be added automatically to the + defined list. This feature is only available in RhodeCode EE + :type observers: Optional(list) + Accepts username strings or objects of the format: + + [{'username': 'nick', 'reasons': ['original author']}] get_pull_request @@ -392,7 +399,7 @@ merge_pull_request update_pull_request ------------------- -.. py:function:: update_pull_request(apiuser, pullrequestid, repoid=, title=, description=, description_renderer=, reviewers=, update_commits=) +.. py:function:: update_pull_request(apiuser, pullrequestid, repoid=, title=, description=, description_renderer=, reviewers=, observers=, update_commits=) Updates a pull request. @@ -414,7 +421,11 @@ update_pull_request Accepts username strings or objects of the format: [{'username': 'nick', 'reasons': ['original author'], 'mandatory': }] + :param observers: Update pull request observers list with new value. + :type observers: Optional(list) + Accepts username strings or objects of the format: + [{'username': 'nick', 'reasons': ['should be aware about this PR']}] :param update_commits: Trigger update of commits for this pull request :type: update_commits: Optional(bool) @@ -432,6 +443,12 @@ update_pull_request ], "removed": [] }, + "updated_observers": { + "added": [ + "username" + ], + "removed": [] + }, "updated_commits": { "added": [ "" diff --git a/docs/release-notes/release-notes-4.21.0.rst b/docs/release-notes/release-notes-4.21.0.rst new file mode 100644 --- /dev/null +++ b/docs/release-notes/release-notes-4.21.0.rst @@ -0,0 +1,54 @@ +|RCE| 4.21.0 |RNS| +------------------ + +Release Date +^^^^^^^^^^^^ + +- 2020-09-28 + + +New Features +^^^^^^^^^^^^ + +- Pull requests: overhaul of the UX/UI by adding new sidebar +- Pull requests: new live reviewer present indicator (requires channelstream enabled) +- Pull requests: new live new comments indicator (requires channelstream enabled) +- Pull requests: new sidebar with comments/todos/referenced tickets navigation +- Commits page: Introduced sidebar for single commits pages + + +General +^^^^^^^ + +- API: allow repo admins to get/set settings. + Previously it was only super-admins that could do that. +- Sessions: patch baker to take expire time for redis for auto session cleanup feature. +- Git: bumped git version to 2.27.0 +- Packages: bumped to channelstream==0.6.14 + + +Security +^^^^^^^^ + +- Issue trackers: fix XSS with description field. + + +Performance +^^^^^^^^^^^ + +- Artifacts: speed-up of artifacts download request processing. + + +Fixes +^^^^^ + +- Pull requests: properly save merge failure metadata. + In rare cases merge check reported conflicts which there were none. +- Sessions: fixed cleanup with corrupted session data issue. + + +Upgrade notes +^^^^^^^^^^^^^ + +- Scheduled feature release. +- Git version was bumped to 2.27.0 diff --git a/docs/release-notes/release-notes-4.22.0.rst b/docs/release-notes/release-notes-4.22.0.rst new file mode 100644 --- /dev/null +++ b/docs/release-notes/release-notes-4.22.0.rst @@ -0,0 +1,55 @@ +|RCE| 4.22.0 |RNS| +------------------ + +Release Date +^^^^^^^^^^^^ + +- 2020-10-12 + + +New Features +^^^^^^^^^^^^ + +- Reviewers: added observers as another role for reviewers. + Observers is a role that doesn't require voting, but still gets notified about + PR and should participate in review process. +- Issue trackers: implemented more sophisticated ticket data extraction based on + advanced regex module. This allows using ticket references without false positives + like catching ticket data in an URL. +- Channelstream: Notification about updates and comments now works via API, and both + Pull-requests and individual commits. + + +General +^^^^^^^ + +- Data tables: unified tables look for main pages of rhodecode repo pages. +- Users: autocomplete now sorts by matched username to show best matches first. +- Pull requests: only allow actual reviewers to leave status/votes in order to not + confuse others users about voting from people who aren't actual reviewers. + +Security +^^^^^^^^ + + + +Performance +^^^^^^^^^^^ + +- Default reviewers: optimize diff data, and creation of PR with advanced default reviewers +- default-reviewers: diff data should load more things lazy for better performance. +- Pull requests: limit the amount of data saved in default reviewers data for better memory usage +- DB: don't use lazy loaders on PR related objects, to optimize memory usage on large + Pull requests with lots of comments, and commits. + +Fixes +^^^^^ + +- Quick search bar: fixes #5634, crash when search on non-ascii characters. +- Sidebar: few fixes for panel rendering of reviewers/observers for both commits and PRS. + +Upgrade notes +^^^^^^^^^^^^^ + +- Scheduled feature release. + 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.22.0.rst + release-notes-4.21.0.rst release-notes-4.20.1.rst release-notes-4.20.0.rst release-notes-4.19.3.rst diff --git a/pkgs/python-packages.nix b/pkgs/python-packages.nix --- a/pkgs/python-packages.nix +++ b/pkgs/python-packages.nix @@ -1816,6 +1816,17 @@ self: super: { license = [ pkgs.lib.licenses.mit ]; }; }; + "regex" = super.buildPythonPackage { + name = "regex-2020.9.27"; + doCheck = false; + src = fetchurl { + url = "https://files.pythonhosted.org/packages/93/8c/17f45cdfb39b13d4b5f909e4b4c2917abcbdef9c0036919a0399769148cf/regex-2020.9.27.tar.gz"; + sha256 = "179ngfzwbsjvn5vhyzdahvmg0f7acahkwwy9bpjy1pv08bm2mwx6"; + }; + meta = { + license = [ pkgs.lib.licenses.psfl ]; + }; + }; "redis" = super.buildPythonPackage { name = "redis-3.4.1"; doCheck = false; @@ -1872,7 +1883,7 @@ self: super: { }; }; "rhodecode-enterprise-ce" = super.buildPythonPackage { - name = "rhodecode-enterprise-ce-4.20.0"; + name = "rhodecode-enterprise-ce-4.22.0"; buildInputs = [ self."pytest" self."py" @@ -1946,6 +1957,7 @@ self: super: { self."tzlocal" self."pyzmq" self."py-gfm" + self."regex" self."redis" self."repoze.lru" self."requests" diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -56,6 +56,7 @@ pytz==2019.3 tzlocal==1.5.1 pyzmq==14.6.0 py-gfm==0.1.4 +regex==2020.9.27 redis==3.4.1 repoze.lru==0.7 requests==2.22.0 diff --git a/rhodecode/__init__.py b/rhodecode/__init__.py --- a/rhodecode/__init__.py +++ b/rhodecode/__init__.py @@ -48,7 +48,7 @@ PYRAMID_SETTINGS = {} EXTENSIONS = {} __version__ = ('.'.join((str(each) for each in VERSION[:3]))) -__dbversion__ = 109 # defines current db version for migrations +__dbversion__ = 110 # defines current db version for migrations __platform__ = platform.system() __license__ = 'AGPLv3, and Commercial License' __author__ = 'RhodeCode GmbH' diff --git a/rhodecode/api/tests/test_create_pull_request.py b/rhodecode/api/tests/test_create_pull_request.py --- a/rhodecode/api/tests/test_create_pull_request.py +++ b/rhodecode/api/tests/test_create_pull_request.py @@ -320,7 +320,7 @@ class TestCreatePullRequestApi(object): id_, params = build_data( self.apikey_regular, 'create_pull_request', **data) response = api_call(self.app, params) - expected_message = 'no commits found' + expected_message = 'no commits found for merge between specified references' assert_error(id_, expected_message, given=response.body) @pytest.mark.backends("git", "hg") diff --git a/rhodecode/api/tests/test_get_pull_requests.py b/rhodecode/api/tests/test_get_pull_requests.py --- a/rhodecode/api/tests/test_get_pull_requests.py +++ b/rhodecode/api/tests/test_get_pull_requests.py @@ -29,6 +29,7 @@ from rhodecode.api.tests.utils import ( @pytest.mark.usefixtures("testuser_api", "app") class TestGetPullRequest(object): + @pytest.mark.backends("git", "hg") def test_api_get_pull_requests(self, pr_util): pull_request = pr_util.create_pull_request() @@ -40,6 +41,7 @@ class TestGetPullRequest(object): target_ref=pull_request.target_ref, revisions=pull_request.revisions, reviewers=(), + observers=(), title=pull_request.title, description=pull_request.description, ) diff --git a/rhodecode/api/tests/test_update_pull_request.py b/rhodecode/api/tests/test_update_pull_request.py --- a/rhodecode/api/tests/test_update_pull_request.py +++ b/rhodecode/api/tests/test_update_pull_request.py @@ -51,6 +51,7 @@ class TestUpdatePullRequest(object): "pull_request": response.json['result']['pull_request'], "updated_commits": {"added": [], "common": [], "removed": []}, "updated_reviewers": {"added": [], "removed": []}, + "updated_observers": {"added": [], "removed": []}, } response_json = response.json['result'] @@ -111,6 +112,7 @@ class TestUpdatePullRequest(object): "total": total_commits, "removed": []}, "updated_reviewers": {"added": [], "removed": []}, + "updated_observers": {"added": [], "removed": []}, } assert_ok(id_, expected, response.body) @@ -122,7 +124,7 @@ class TestUpdatePullRequest(object): b = user_util.create_user() c = user_util.create_user() new_reviewers = [ - {'username': b.username,'reasons': ['updated via API'], + {'username': b.username, 'reasons': ['updated via API'], 'mandatory':False}, {'username': c.username, 'reasons': ['updated via API'], 'mandatory':False}, @@ -132,7 +134,7 @@ class TestUpdatePullRequest(object): removed = [a.username] pull_request = pr_util.create_pull_request( - reviewers=[(a.username, ['added via API'], False, [])]) + reviewers=[(a.username, ['added via API'], False, 'reviewer', [])]) id_, params = build_data( self.apikey, 'update_pull_request', @@ -146,6 +148,7 @@ class TestUpdatePullRequest(object): "pull_request": response.json['result']['pull_request'], "updated_commits": {"added": [], "common": [], "removed": []}, "updated_reviewers": {"added": added, "removed": removed}, + "updated_observers": {"added": [], "removed": []}, } assert_ok(id_, expected, response.body) diff --git a/rhodecode/api/views/pull_request_api.py b/rhodecode/api/views/pull_request_api.py --- a/rhodecode/api/views/pull_request_api.py +++ b/rhodecode/api/views/pull_request_api.py @@ -26,12 +26,15 @@ from rhodecode.api.utils import ( has_superadmin_permission, Optional, OAttr, get_repo_or_error, get_pull_request_or_error, get_commit_or_error, get_user_or_error, validate_repo_permissions, resolve_ref_or_error, validate_set_owner_permissions) +from rhodecode.lib import channelstream from rhodecode.lib.auth import (HasRepoPermissionAnyApi) from rhodecode.lib.base import vcs_operation_context from rhodecode.lib.utils2 import str2bool +from rhodecode.lib.vcs.backends.base import unicode_to_reference from rhodecode.model.changeset_status import ChangesetStatusModel from rhodecode.model.comment import CommentsModel -from rhodecode.model.db import Session, ChangesetStatus, ChangesetComment, PullRequest +from rhodecode.model.db import ( + Session, ChangesetStatus, ChangesetComment, PullRequest, PullRequestReviewers) from rhodecode.model.pull_request import PullRequestModel, MergeCheck from rhodecode.model.settings import SettingsModel from rhodecode.model.validation_schema import Invalid @@ -502,16 +505,19 @@ def comment_pull_request( }, error : null """ + _ = request.translate + pull_request = get_pull_request_or_error(pullrequestid) if Optional.extract(repoid): repo = get_repo_or_error(repoid) else: repo = pull_request.target_repo + db_repo_name = repo.repo_name auth_user = apiuser if not isinstance(userid, Optional): is_repo_admin = HasRepoPermissionAnyApi('repository.admin')( - user=apiuser, repo_name=repo.repo_name) + user=apiuser, repo_name=db_repo_name) if has_superadmin_permission(apiuser) or is_repo_admin: apiuser = get_user_or_error(userid) auth_user = apiuser.AuthUser() @@ -596,6 +602,7 @@ def comment_pull_request( extra_recipients=extra_recipients, send_email=send_email ) + is_inline = comment.is_inline if allowed_to_change_status and status: old_calculated_status = pull_request.calculated_review_status() @@ -628,14 +635,39 @@ def comment_pull_request( 'comment_id': comment.comment_id if comment else None, 'status': {'given': status, 'was_changed': status_change}, } + + comment_broadcast_channel = channelstream.comment_channel( + db_repo_name, pull_request_obj=pull_request) + + comment_data = data + comment_type = 'inline' if is_inline else 'general' + channelstream.comment_channelstream_push( + request, comment_broadcast_channel, apiuser, + _('posted a new {} comment').format(comment_type), + comment_data=comment_data) + return data +def _reviewers_validation(obj_list): + schema = ReviewerListSchema() + try: + reviewer_objects = schema.deserialize(obj_list) + except Invalid as err: + raise JSONRPCValidationError(colander_exc=err) + + # validate users + for reviewer_object in reviewer_objects: + user = get_user_or_error(reviewer_object['username']) + reviewer_object['user_id'] = user.user_id + return reviewer_objects + @jsonrpc_method() def create_pull_request( request, apiuser, source_repo, target_repo, source_ref, target_ref, owner=Optional(OAttr('apiuser')), title=Optional(''), description=Optional(''), - description_renderer=Optional(''), reviewers=Optional(None)): + description_renderer=Optional(''), + reviewers=Optional(None), observers=Optional(None)): """ Creates a new pull request. @@ -673,6 +705,13 @@ def create_pull_request( Accepts username strings or objects of the format: [{'username': 'nick', 'reasons': ['original author'], 'mandatory': }] + :param observers: Set the new pull request observers list. + Reviewer defined by review rules will be added automatically to the + defined list. This feature is only available in RhodeCode EE + :type observers: Optional(list) + Accepts username strings or objects of the format: + + [{'username': 'nick', 'reasons': ['original author']}] """ source_db_repo = get_repo_or_error(source_repo) @@ -686,34 +725,39 @@ def create_pull_request( full_source_ref = resolve_ref_or_error(source_ref, source_db_repo) full_target_ref = resolve_ref_or_error(target_ref, target_db_repo) - source_commit = get_commit_or_error(full_source_ref, source_db_repo) - target_commit = get_commit_or_error(full_target_ref, target_db_repo) + get_commit_or_error(full_source_ref, source_db_repo) + get_commit_or_error(full_target_ref, target_db_repo) reviewer_objects = Optional.extract(reviewers) or [] + observer_objects = Optional.extract(observers) or [] # serialize and validate passed in given reviewers if reviewer_objects: - schema = ReviewerListSchema() - try: - reviewer_objects = schema.deserialize(reviewer_objects) - except Invalid as err: - raise JSONRPCValidationError(colander_exc=err) + reviewer_objects = _reviewers_validation(reviewer_objects) + + if observer_objects: + observer_objects = _reviewers_validation(reviewer_objects) - # validate users - for reviewer_object in reviewer_objects: - user = get_user_or_error(reviewer_object['username']) - reviewer_object['user_id'] = user.user_id + get_default_reviewers_data, validate_default_reviewers, validate_observers = \ + PullRequestModel().get_reviewer_functions() - get_default_reviewers_data, validate_default_reviewers = \ - PullRequestModel().get_reviewer_functions() + source_ref_obj = unicode_to_reference(full_source_ref) + target_ref_obj = unicode_to_reference(full_target_ref) # recalculate reviewers logic, to make sure we can validate this default_reviewers_data = get_default_reviewers_data( - owner, source_db_repo, - source_commit, target_db_repo, target_commit) + owner, + source_db_repo, + source_ref_obj, + target_db_repo, + target_ref_obj, + ) - # now MERGE our given with the calculated - reviewer_objects = default_reviewers_data['reviewers'] + reviewer_objects + # now MERGE our given with the calculated from the default rules + just_reviewers = [ + x for x in default_reviewers_data['reviewers'] + if x['role'] == PullRequestReviewers.ROLE_REVIEWER] + reviewer_objects = just_reviewers + reviewer_objects try: reviewers = validate_default_reviewers( @@ -721,9 +765,21 @@ def create_pull_request( except ValueError as e: raise JSONRPCError('Reviewers Validation: {}'.format(e)) + # now MERGE our given with the calculated from the default rules + just_observers = [ + x for x in default_reviewers_data['reviewers'] + if x['role'] == PullRequestReviewers.ROLE_OBSERVER] + observer_objects = just_observers + observer_objects + + try: + observers = validate_observers( + observer_objects, default_reviewers_data) + except ValueError as e: + raise JSONRPCError('Observer Validation: {}'.format(e)) + title = Optional.extract(title) if not title: - title_source_ref = source_ref.split(':', 2)[1] + title_source_ref = source_ref_obj.name title = PullRequestModel().generate_pullrequest_title( source=source_repo, source_ref=title_source_ref, @@ -732,20 +788,17 @@ def create_pull_request( diff_info = default_reviewers_data['diff_info'] common_ancestor_id = diff_info['ancestor'] - commits = diff_info['commits'] + # NOTE(marcink): reversed is consistent with how we open it in the WEB interface + commits = [commit['commit_id'] for commit in reversed(diff_info['commits'])] if not common_ancestor_id: - raise JSONRPCError('no common ancestor found') + raise JSONRPCError('no common ancestor found between specified references') if not commits: - raise JSONRPCError('no commits found') - - # NOTE(marcink): reversed is consistent with how we open it in the WEB interface - revisions = [commit.raw_id for commit in reversed(commits)] + raise JSONRPCError('no commits found for merge between specified references') # recalculate target ref based on ancestor - target_ref_type, target_ref_name, __ = full_target_ref.split(':') - full_target_ref = ':'.join((target_ref_type, target_ref_name, common_ancestor_id)) + full_target_ref = ':'.join((target_ref_obj.type, target_ref_obj.name, common_ancestor_id)) # fetch renderer, if set fallback to plain in case of PR rc_config = SettingsModel().get_all_settings() @@ -760,8 +813,9 @@ def create_pull_request( target_repo=target_repo, target_ref=full_target_ref, common_ancestor_id=common_ancestor_id, - revisions=revisions, + revisions=commits, reviewers=reviewers, + observers=observers, title=title, description=description, description_renderer=description_renderer, @@ -781,7 +835,7 @@ def create_pull_request( def update_pull_request( request, apiuser, pullrequestid, repoid=Optional(None), title=Optional(''), description=Optional(''), description_renderer=Optional(''), - reviewers=Optional(None), update_commits=Optional(None)): + reviewers=Optional(None), observers=Optional(None), update_commits=Optional(None)): """ Updates a pull request. @@ -803,7 +857,11 @@ def update_pull_request( Accepts username strings or objects of the format: [{'username': 'nick', 'reasons': ['original author'], 'mandatory': }] + :param observers: Update pull request observers list with new value. + :type observers: Optional(list) + Accepts username strings or objects of the format: + [{'username': 'nick', 'reasons': ['should be aware about this PR']}] :param update_commits: Trigger update of commits for this pull request :type: update_commits: Optional(bool) @@ -821,6 +879,12 @@ def update_pull_request( ], "removed": [] }, + "updated_observers": { + "added": [ + "username" + ], + "removed": [] + }, "updated_commits": { "added": [ "" @@ -852,36 +916,14 @@ def update_pull_request( pullrequestid,)) reviewer_objects = Optional.extract(reviewers) or [] - - if reviewer_objects: - schema = ReviewerListSchema() - try: - reviewer_objects = schema.deserialize(reviewer_objects) - except Invalid as err: - raise JSONRPCValidationError(colander_exc=err) - - # validate users - for reviewer_object in reviewer_objects: - user = get_user_or_error(reviewer_object['username']) - reviewer_object['user_id'] = user.user_id - - get_default_reviewers_data, get_validated_reviewers = \ - PullRequestModel().get_reviewer_functions() - - # re-use stored rules - reviewer_rules = pull_request.reviewer_data - try: - reviewers = get_validated_reviewers( - reviewer_objects, reviewer_rules) - except ValueError as e: - raise JSONRPCError('Reviewers Validation: {}'.format(e)) - else: - reviewers = [] + observer_objects = Optional.extract(observers) or [] title = Optional.extract(title) description = Optional.extract(description) description_renderer = Optional.extract(description_renderer) + # Update title/description + title_changed = False if title or description: PullRequestModel().edit( pull_request, @@ -890,8 +932,12 @@ def update_pull_request( description_renderer or pull_request.description_renderer, apiuser) Session().commit() + title_changed = True commit_changes = {"added": [], "common": [], "removed": []} + + # Update commits + commits_changed = False if str2bool(Optional.extract(update_commits)): if pull_request.pull_request_state != PullRequest.STATE_CREATED: @@ -907,12 +953,44 @@ def update_pull_request( pull_request, db_user) commit_changes = update_response.changes or commit_changes Session().commit() + commits_changed = True + # Update reviewers + # serialize and validate passed in given reviewers + if reviewer_objects: + reviewer_objects = _reviewers_validation(reviewer_objects) + + if observer_objects: + observer_objects = _reviewers_validation(reviewer_objects) + + # re-use stored rules + default_reviewers_data = pull_request.reviewer_data + + __, validate_default_reviewers, validate_observers = \ + PullRequestModel().get_reviewer_functions() + + if reviewer_objects: + try: + reviewers = validate_default_reviewers(reviewer_objects, default_reviewers_data) + except ValueError as e: + raise JSONRPCError('Reviewers Validation: {}'.format(e)) + else: + reviewers = [] + + if observer_objects: + try: + observers = validate_default_reviewers(reviewer_objects, default_reviewers_data) + except ValueError as e: + raise JSONRPCError('Observer Validation: {}'.format(e)) + else: + observers = [] + + reviewers_changed = False reviewers_changes = {"added": [], "removed": []} if reviewers: old_calculated_status = pull_request.calculated_review_status() added_reviewers, removed_reviewers = \ - PullRequestModel().update_reviewers(pull_request, reviewers, apiuser) + PullRequestModel().update_reviewers(pull_request, reviewers, apiuser.get_instance()) reviewers_changes['added'] = sorted( [get_user_or_error(n).username for n in added_reviewers]) @@ -926,13 +1004,35 @@ def update_pull_request( PullRequestModel().trigger_pull_request_hook( pull_request, apiuser, 'review_status_change', data={'status': calculated_status}) + reviewers_changed = True + + observers_changed = False + observers_changes = {"added": [], "removed": []} + if observers: + added_observers, removed_observers = \ + PullRequestModel().update_observers(pull_request, observers, apiuser.get_instance()) + + observers_changes['added'] = sorted( + [get_user_or_error(n).username for n in added_observers]) + observers_changes['removed'] = sorted( + [get_user_or_error(n).username for n in removed_observers]) + Session().commit() + + reviewers_changed = True + + # push changed to channelstream + if commits_changed or reviewers_changed or observers_changed: + pr_broadcast_channel = channelstream.pr_channel(pull_request) + msg = 'Pull request was updated.' + channelstream.pr_update_channelstream_push( + request, pr_broadcast_channel, apiuser, msg) data = { - 'msg': 'Updated pull request `{}`'.format( - pull_request.pull_request_id), + 'msg': 'Updated pull request `{}`'.format(pull_request.pull_request_id), 'pull_request': pull_request.get_api_data(), 'updated_commits': commit_changes, - 'updated_reviewers': reviewers_changes + 'updated_reviewers': reviewers_changes, + 'updated_observers': observers_changes, } return data diff --git a/rhodecode/api/views/repo_api.py b/rhodecode/api/views/repo_api.py --- a/rhodecode/api/views/repo_api.py +++ b/rhodecode/api/views/repo_api.py @@ -29,7 +29,7 @@ from rhodecode.api.utils import ( get_user_group_or_error, get_user_or_error, validate_repo_permissions, get_perm_or_error, parse_args, get_origin, build_commit_data, validate_set_owner_permissions) -from rhodecode.lib import audit_logger, rc_cache +from rhodecode.lib import audit_logger, rc_cache, channelstream from rhodecode.lib import repo_maintenance from rhodecode.lib.auth import ( HasPermissionAnyApi, HasUserGroupPermissionAnyApi, @@ -1597,10 +1597,13 @@ def comment_commit( } """ + _ = request.translate + repo = get_repo_or_error(repoid) if not has_superadmin_permission(apiuser): _perms = ('repository.read', 'repository.write', 'repository.admin') validate_repo_permissions(apiuser, repoid, repo, _perms) + db_repo_name = repo.repo_name try: commit = repo.scm_instance().get_commit(commit_id=commit_id) @@ -1650,6 +1653,8 @@ def comment_commit( extra_recipients=extra_recipients, send_email=send_email ) + is_inline = comment.is_inline + if status: # also do a status change try: @@ -1669,6 +1674,17 @@ def comment_commit( data={'comment': comment, 'commit': commit}) Session().commit() + + comment_broadcast_channel = channelstream.comment_channel( + db_repo_name, commit_obj=commit) + + comment_data = {'comment': comment, 'comment_id': comment.comment_id} + comment_type = 'inline' if is_inline else 'general' + channelstream.comment_channelstream_push( + request, comment_broadcast_channel, apiuser, + _('posted a new {} comment').format(comment_type), + comment_data=comment_data) + return { 'msg': ( 'Commented on commit `%s` for repository `%s`' % ( diff --git a/rhodecode/apps/admin/views/settings.py b/rhodecode/apps/admin/views/settings.py --- a/rhodecode/apps/admin/views/settings.py +++ b/rhodecode/apps/admin/views/settings.py @@ -474,9 +474,18 @@ class AdminSettingsView(BaseAppView): route_name='admin_settings_issuetracker_test', request_method='POST', renderer='string', xhr=True) def settings_issuetracker_test(self): - return h.urlify_commit_message( + error_container = [] + + urlified_commit = h.urlify_commit_message( self.request.POST.get('test_text', ''), - 'repo_group/test_repo1') + 'repo_group/test_repo1', error_container=error_container) + if error_container: + def converter(inp): + return h.html_escape(unicode(inp)) + + return 'ERRORS: ' + '\n'.join(map(converter, error_container)) + + return urlified_commit @LoginRequired() @HasPermissionAllDecorator('hg.admin') diff --git a/rhodecode/apps/debug_style/views.py b/rhodecode/apps/debug_style/views.py --- a/rhodecode/apps/debug_style/views.py +++ b/rhodecode/apps/debug_style/views.py @@ -34,6 +34,7 @@ log = logging.getLogger(__name__) class DebugStyleView(BaseAppView): + def load_default_context(self): c = self._get_local_tmpl_context() @@ -75,6 +76,7 @@ Check if we should use full-topic or min source_ref_parts=AttributeDict(type='branch', name='fix-ticket-2000'), target_ref_parts=AttributeDict(type='branch', name='master'), ) + target_repo = AttributeDict(repo_name='repo_group/target_repo') source_repo = AttributeDict(repo_name='repo_group/source_repo') user = User.get_by_username(self.request.GET.get('user')) or self._rhodecode_db_user @@ -83,6 +85,7 @@ Check if we should use full-topic or min 'added': ['aaaaaaabbbbb', 'cccccccddddddd'], 'removed': ['eeeeeeeeeee'], }) + file_changes = AttributeDict({ 'added': ['a/file1.md', 'file2.py'], 'modified': ['b/modified_file.rst'], @@ -97,15 +100,19 @@ Check if we should use full-topic or min 'exc_message': 'Traceback (most recent call last):\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/tweens.py", line 41, in excview_tween\n response = handler(request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/router.py", line 148, in handle_request\n registry, request, context, context_iface, view_name\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/view.py", line 667, in _call_view\n response = view_callable(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 188, in attr_view\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/config/views.py", line 214, in predicate_wrapper\n return view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 401, in viewresult_to_response\n result = view(context, request)\n File "/nix/store/s43k2r9rysfbzmsjdqnxgzvvb7zjhkxb-python2.7-pyramid-1.10.4/lib/python2.7/site-packages/pyramid/viewderivers.py", line 132, in _class_view\n response = getattr(inst, attr)()\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/apps/debug_style/views.py", line 355, in render_email\n template_type, **email_kwargs.get(email_id, {}))\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/model/notification.py", line 402, in render_email\n body = email_template.render(None, **_kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 95, in render\n return self._render_with_exc(tmpl, args, kwargs)\n File "/mnt/hgfs/marcink/workspace/rhodecode-enterprise-ce/rhodecode/lib/partial_renderer.py", line 79, in _render_with_exc\n return render_func.render(*args, **kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/template.py", line 476, in render\n return runtime._render(self, self.callable_, args, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 883, in _render\n **_kwargs_for_callable(callable_, data)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 920, in _render_context\n _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)\n File "/nix/store/dakh34sxz4yfr435c0cwjz0sd6hnd5g3-python2.7-mako-1.1.0/lib/python2.7/site-packages/mako/runtime.py", line 947, in _exec_template\n callable_(context, *args, **kwargs)\n File "rhodecode_templates_email_templates_base_mako", line 63, in render_body\n File "rhodecode_templates_email_templates_exception_tracker_mako", line 43, in render_body\nAttributeError: \'str\' object has no attribute \'get\'\n', 'exc_type': 'AttributeError' } + email_kwargs = { 'test': {}, + 'message': { 'body': 'message body !' }, + 'email_test': { 'user': user, 'date': datetime.datetime.now(), }, + 'exception': { 'email_prefix': '[RHODECODE ERROR]', 'exc_id': exc_traceback['exc_id'], @@ -113,6 +120,7 @@ Check if we should use full-topic or min 'exc_type_name': 'NameError', 'exc_traceback': exc_traceback, }, + 'password_reset': { 'password_reset_url': 'http://example.com/reset-rhodecode-password/token', @@ -121,6 +129,7 @@ Check if we should use full-topic or min 'email': 'test@rhodecode.com', 'first_admin_email': User.get_first_super_admin().email }, + 'password_reset_confirmation': { 'new_password': 'new-password-example', 'user': user, @@ -128,6 +137,7 @@ Check if we should use full-topic or min 'email': 'test@rhodecode.com', 'first_admin_email': User.get_first_super_admin().email }, + 'registration': { 'user': user, 'date': datetime.datetime.now(), @@ -161,6 +171,7 @@ Check if we should use full-topic or min 'mention': True, }, + 'pull_request_comment+status': { 'user': user, @@ -201,6 +212,7 @@ def db(): 'mention': True, }, + 'pull_request_comment+file': { 'user': user, @@ -303,6 +315,7 @@ This should work better ! 'renderer_type': 'markdown', 'mention': True, }, + 'cs_comment+status': { 'user': user, 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'), @@ -328,6 +341,7 @@ This is a multiline comment :) 'renderer_type': 'markdown', 'mention': True, }, + 'cs_comment+file': { 'user': user, 'commit': AttributeDict(idx=123, raw_id='a' * 40, message='Commit message'), @@ -348,12 +362,37 @@ This is a multiline comment :) 'renderer_type': 'markdown', 'mention': True, }, - + 'pull_request': { 'user': user, 'pull_request': pr, 'pull_request_commits': [ ('472d1df03bf7206e278fcedc6ac92b46b01c4e21', '''\ + my-account: moved email closer to profile as it's similar data just moved outside. + '''), + ('cbfa3061b6de2696c7161ed15ba5c6a0045f90a7', '''\ + users: description edit fixes + + - tests + - added metatags info + '''), + ], + + 'pull_request_target_repo': target_repo, + 'pull_request_target_repo_url': 'http://target-repo/url', + + 'pull_request_source_repo': source_repo, + 'pull_request_source_repo_url': 'http://source-repo/url', + + 'pull_request_url': 'http://code.rhodecode.com/_pull-request/123', + 'user_role': 'reviewer', + }, + + 'pull_request+reviewer_role': { + 'user': user, + 'pull_request': pr, + 'pull_request_commits': [ + ('472d1df03bf7206e278fcedc6ac92b46b01c4e21', '''\ my-account: moved email closer to profile as it's similar data just moved outside. '''), ('cbfa3061b6de2696c7161ed15ba5c6a0045f90a7', '''\ @@ -371,8 +410,33 @@ users: description edit fixes 'pull_request_source_repo_url': 'http://source-repo/url', 'pull_request_url': 'http://code.rhodecode.com/_pull-request/123', + 'user_role': 'reviewer', + }, + + 'pull_request+observer_role': { + 'user': user, + 'pull_request': pr, + 'pull_request_commits': [ + ('472d1df03bf7206e278fcedc6ac92b46b01c4e21', '''\ + my-account: moved email closer to profile as it's similar data just moved outside. + '''), + ('cbfa3061b6de2696c7161ed15ba5c6a0045f90a7', '''\ + users: description edit fixes + + - tests + - added metatags info + '''), + ], + + 'pull_request_target_repo': target_repo, + 'pull_request_target_repo_url': 'http://target-repo/url', + + 'pull_request_source_repo': source_repo, + 'pull_request_source_repo_url': 'http://source-repo/url', + + 'pull_request_url': 'http://code.rhodecode.com/_pull-request/123', + 'user_role': 'observer' } - } template_type = email_id.split('+')[0] @@ -401,6 +465,7 @@ users: description edit fixes c = self.load_default_context() c.active = os.path.splitext(t_path)[0] c.came_from = '' + # NOTE(marcink): extend the email types with variations based on data sets c.email_types = { 'cs_comment+file': {}, 'cs_comment+status': {}, @@ -409,6 +474,9 @@ users: description edit fixes 'pull_request_comment+status': {}, 'pull_request_update': {}, + + 'pull_request+reviewer_role': {}, + 'pull_request+observer_role': {}, } c.email_types.update(EmailNotificationModel.email_types) diff --git a/rhodecode/apps/home/views.py b/rhodecode/apps/home/views.py --- a/rhodecode/apps/home/views.py +++ b/rhodecode/apps/home/views.py @@ -32,7 +32,7 @@ from rhodecode.lib.auth import ( HasRepoGroupPermissionAny, AuthUser) from rhodecode.lib.codeblocks import filenode_as_lines_tokens from rhodecode.lib.index import searcher_from_config -from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int +from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int, safe_str from rhodecode.lib.vcs.nodes import FileNode from rhodecode.model.db import ( func, true, or_, case, cast, in_filter_generator, String, Session, @@ -331,7 +331,8 @@ class HomeView(BaseAppView, DataGridAppV { 'id': obj.pull_request_id, 'value': org_query, - 'value_display': 'pull request: `!{} - {}`'.format(obj.pull_request_id, obj.title[:50]), + 'value_display': 'pull request: `!{} - {}`'.format( + obj.pull_request_id, safe_str(obj.title[:50])), 'type': 'pull_request', 'url': h.route_path('pull_requests_global', pull_request_id=obj.pull_request_id) } 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 @@ -734,8 +734,8 @@ class MyAccountView(BaseAppView, DataGri comments_model = CommentsModel() for pr in pull_requests: repo_id = pr.target_repo_id - comments = comments_model.get_all_comments( - repo_id, pull_request=pr) + comments_count = comments_model.get_all_comments( + repo_id, pull_request=pr, count_only=True) owned = pr.user_id == self._rhodecode_user.user_id data.append({ @@ -760,8 +760,8 @@ class MyAccountView(BaseAppView, DataGri 'author': _render('pullrequest_author', pr.author.full_contact, ), 'author_raw': pr.author.full_name, - 'comments': _render('pullrequest_comments', len(comments)), - 'comments_raw': len(comments), + 'comments': _render('pullrequest_comments', comments_count), + 'comments_raw': comments_count, 'closed': pr.is_closed(), 'owned': owned }) diff --git a/rhodecode/apps/repository/tests/test_repo_pullrequests.py b/rhodecode/apps/repository/tests/test_repo_pullrequests.py --- a/rhodecode/apps/repository/tests/test_repo_pullrequests.py +++ b/rhodecode/apps/repository/tests/test_repo_pullrequests.py @@ -523,7 +523,9 @@ class TestPullrequestsView(object): pull_request = pr_util.create_pull_request() pull_request_id = pull_request.pull_request_id PullRequestModel().update_reviewers( - pull_request_id, [(1, ['reason'], False, []), (2, ['reason2'], False, [])], + pull_request_id, [ + (1, ['reason'], False, 'reviewer', []), + (2, ['reason2'], False, 'reviewer', [])], pull_request.author) author = pull_request.user_id repo = pull_request.target_repo.repo_id @@ -906,12 +908,13 @@ class TestPullrequestsView(object): # Change reviewers and check that a notification was made PullRequestModel().update_reviewers( - pull_request.pull_request_id, [(1, [], False, [])], + pull_request.pull_request_id, [ + (1, [], False, 'reviewer', []) + ], pull_request.author) assert len(notifications.all()) == 2 - def test_create_pull_request_stores_ancestor_commit_id(self, backend, - csrf_token): + def test_create_pull_request_stores_ancestor_commit_id(self, backend, csrf_token): commits = [ {'message': 'ancestor', 'added': [FileNode('file_A', content='content_of_ancestor')]}, diff --git a/rhodecode/apps/repository/utils.py b/rhodecode/apps/repository/utils.py --- a/rhodecode/apps/repository/utils.py +++ b/rhodecode/apps/repository/utils.py @@ -18,14 +18,16 @@ # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ -from rhodecode.lib import helpers as h +from rhodecode.lib import helpers as h, rc_cache from rhodecode.lib.utils2 import safe_int from rhodecode.model.pull_request import get_diff_info - -REVIEWER_API_VERSION = 'V3' +from rhodecode.model.db import PullRequestReviewers +# V3 - Reviewers, with default rules data +# v4 - Added observers metadata +REVIEWER_API_VERSION = 'V4' -def reviewer_as_json(user, reasons=None, mandatory=False, rules=None, user_group=None): +def reviewer_as_json(user, reasons=None, role=None, mandatory=False, rules=None, user_group=None): """ Returns json struct of a reviewer for frontend @@ -33,11 +35,15 @@ def reviewer_as_json(user, reasons=None, :param reasons: list of strings of why they are reviewers :param mandatory: bool, to set user as mandatory """ + role = role or PullRequestReviewers.ROLE_REVIEWER + if role not in PullRequestReviewers.ROLES: + raise ValueError('role is not one of %s', PullRequestReviewers.ROLES) return { 'user_id': user.user_id, 'reasons': reasons or [], 'rules': rules or [], + 'role': role, 'mandatory': mandatory, 'user_group': user_group, 'username': user.username, @@ -48,21 +54,36 @@ def reviewer_as_json(user, reasons=None, } -def get_default_reviewers_data( - current_user, source_repo, source_commit, target_repo, target_commit): +def to_reviewers(e): + if isinstance(e, (tuple, list)): + return map(reviewer_as_json, e) + else: + return reviewer_as_json(e) + + +def get_default_reviewers_data(current_user, source_repo, source_ref, target_repo, target_ref, + include_diff_info=True): """ Return json for default reviewers of a repository """ - diff_info = get_diff_info( - source_repo, source_commit.raw_id, target_repo, target_commit.raw_id) + diff_info = {} + if include_diff_info: + diff_info = get_diff_info( + source_repo, source_ref.commit_id, target_repo, target_ref.commit_id) reasons = ['Default reviewer', 'Repository owner'] json_reviewers = [reviewer_as_json( - user=target_repo.user, reasons=reasons, mandatory=False, rules=None)] + user=target_repo.user, reasons=reasons, mandatory=False, rules=None, role=None)] + + compute_key = rc_cache.utils.compute_key_from_params( + current_user.user_id, source_repo.repo_id, source_ref.type, source_ref.name, + source_ref.commit_id, target_repo.repo_id, target_ref.type, target_ref.name, + target_ref.commit_id) return { 'api_ver': REVIEWER_API_VERSION, # define version for later possible schema upgrade + 'compute_key': compute_key, 'diff_info': diff_info, 'reviewers': json_reviewers, 'rules': {}, @@ -73,15 +94,18 @@ def get_default_reviewers_data( def validate_default_reviewers(review_members, reviewer_rules): """ Function to validate submitted reviewers against the saved rules - """ reviewers = [] reviewer_by_id = {} for r in review_members: reviewer_user_id = safe_int(r['user_id']) - entry = (reviewer_user_id, r['reasons'], r['mandatory'], r['rules']) + entry = (reviewer_user_id, r['reasons'], r['mandatory'], r['role'], r['rules']) reviewer_by_id[reviewer_user_id] = entry reviewers.append(entry) return reviewers + + +def validate_observers(observer_members, reviewer_rules): + return {} 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 @@ -31,7 +31,7 @@ from rhodecode.apps._base import RepoApp from rhodecode.apps.file_store import utils as store_utils from rhodecode.apps.file_store.exceptions import FileNotAllowedException, FileOverSizeException -from rhodecode.lib import diffs, codeblocks +from rhodecode.lib import diffs, codeblocks, channelstream from rhodecode.lib.auth import ( LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired) from rhodecode.lib.ext_json import json @@ -170,7 +170,9 @@ class RepoCommitsView(RepoAppView): ) reviewers_duplicates.add(_user_id) - c.allowed_reviewers = reviewers + c.reviewers_count = len(reviewers) + c.observers_count = 0 + # from associated statuses, check the pull requests, and # show comments from them for pr in prs: @@ -193,7 +195,7 @@ class RepoCommitsView(RepoAppView): for review_obj, member, reasons, mandatory, status in review_statuses: member_reviewer = h.reviewer_as_json( - member, reasons=reasons, mandatory=mandatory, + member, reasons=reasons, mandatory=mandatory, role=None, user_group=None ) @@ -207,10 +209,7 @@ class RepoCommitsView(RepoAppView): # NOTE(marcink): this uses the same voting logic as in pull-requests c.commit_review_status = ChangesetStatusModel().calculate_status(review_statuses) - c.commit_broadcast_channel = u'/repo${}$/commit/{}'.format( - c.repo_name, - commit.raw_id - ) + c.commit_broadcast_channel = channelstream.comment_channel(c.repo_name, commit_obj=commit) diff = None # Iterate over ranges (default commit view is always one commit) @@ -414,6 +413,7 @@ class RepoCommitsView(RepoAppView): resolves_comment_id=resolves_comment_id, auth_user=self._rhodecode_user ) + is_inline = comment.is_inline # get status if set ! if status: @@ -461,6 +461,16 @@ class RepoCommitsView(RepoAppView): data.update(comment.get_dict()) data.update({'rendered_text': rendered_comment}) + comment_broadcast_channel = channelstream.comment_channel( + self.db_repo_name, commit_obj=commit) + + comment_data = data + comment_type = 'inline' if is_inline else 'general' + channelstream.comment_channelstream_push( + self.request, comment_broadcast_channel, self._rhodecode_user, + _('posted a new {} comment').format(comment_type), + comment_data=comment_data) + return data @LoginRequired() 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,14 +39,16 @@ 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 -from rhodecode.lib.vcs.backends.base import EmptyCommit, UpdateFailureReason +from rhodecode.lib.utils2 import str2bool, safe_str, safe_unicode, safe_int, aslist +from rhodecode.lib.vcs.backends.base import ( + EmptyCommit, UpdateFailureReason, unicode_to_reference) from rhodecode.lib.vcs.exceptions import ( CommitDoesNotExistError, RepositoryRequirementError, EmptyRepositoryError) from rhodecode.model.changeset_status import ChangesetStatusModel from rhodecode.model.comment import CommentsModel from rhodecode.model.db import ( - func, or_, PullRequest, ChangesetComment, ChangesetStatus, Repository) + func, or_, PullRequest, ChangesetComment, ChangesetStatus, Repository, + PullRequestReviewers) from rhodecode.model.forms import PullRequestForm from rhodecode.model.meta import Session from rhodecode.model.pull_request import PullRequestModel, MergeCheck @@ -104,13 +106,14 @@ class RepoPullRequestsView(RepoAppView, data = [] comments_model = CommentsModel() for pr in pull_requests: - comments = comments_model.get_all_comments( - self.db_repo.repo_id, pull_request=pr) + comments_count = comments_model.get_all_comments( + self.db_repo.repo_id, pull_request=pr, count_only=True) data.append({ 'name': _render('pullrequest_name', pr.pull_request_id, pr.pull_request_state, - pr.work_in_progress, pr.target_repo.repo_name), + pr.work_in_progress, pr.target_repo.repo_name, + short=True), 'name_raw': pr.pull_request_id, 'status': _render('pullrequest_status', pr.calculated_review_status()), @@ -126,8 +129,8 @@ class RepoPullRequestsView(RepoAppView, 'author': _render('pullrequest_author', pr.author.full_contact, ), 'author_raw': pr.author.full_name, - 'comments': _render('pullrequest_comments', len(comments)), - 'comments_raw': len(comments), + 'comments': _render('pullrequest_comments', comments_count), + 'comments_raw': comments_count, 'closed': pr.is_closed(), }) @@ -310,8 +313,7 @@ class RepoPullRequestsView(RepoAppView, pull_request_id = pull_request.pull_request_id c.state_progressing = pull_request.is_state_changing() - c.pr_broadcast_channel = '/repo${}$/pr/{}'.format( - pull_request.target_repo.repo_name, pull_request.pull_request_id) + c.pr_broadcast_channel = channelstream.pr_channel(pull_request) _new_state = { 'created': PullRequest.STATE_CREATED, @@ -454,15 +456,18 @@ class RepoPullRequestsView(RepoAppView, 'rhodecode:templates/pullrequests/pullrequest_merge_checks.mako' return self._get_template_context(c) - c.allowed_reviewers = [obj.user_id for obj in pull_request.reviewers if obj.user] + c.reviewers_count = pull_request.reviewers_count + c.observers_count = pull_request.observers_count # reviewers and statuses c.pull_request_default_reviewers_data_json = json.dumps(pull_request.reviewer_data) c.pull_request_set_reviewers_data_json = collections.OrderedDict({'reviewers': []}) + c.pull_request_set_observers_data_json = collections.OrderedDict({'observers': []}) for review_obj, member, reasons, mandatory, status in pull_request_at_ver.reviewers_statuses(): member_reviewer = h.reviewer_as_json( member, reasons=reasons, mandatory=mandatory, + role=review_obj.role, user_group=review_obj.rule_user_group_data() ) @@ -474,6 +479,17 @@ class RepoPullRequestsView(RepoAppView, c.pull_request_set_reviewers_data_json = json.dumps(c.pull_request_set_reviewers_data_json) + for observer_obj, member in pull_request_at_ver.observers(): + member_observer = h.reviewer_as_json( + member, reasons=[], mandatory=False, + role=observer_obj.role, + user_group=observer_obj.rule_user_group_data() + ) + member_observer['allowed_to_update'] = c.allowed_to_update + c.pull_request_set_observers_data_json['observers'].append(member_observer) + + c.pull_request_set_observers_data_json = json.dumps(c.pull_request_set_observers_data_json) + general_comments, inline_comments = \ self.register_comments_vars(c, pull_request_latest, versions) @@ -745,7 +761,9 @@ class RepoPullRequestsView(RepoAppView, # current user review statuses for each version c.review_versions = {} - if self._rhodecode_user.user_id in c.allowed_reviewers: + is_reviewer = PullRequestModel().is_user_reviewer( + pull_request, self._rhodecode_user) + if is_reviewer: for co in general_comments: if co.author.user_id == self._rhodecode_user.user_id: status = co.status_change @@ -961,13 +979,16 @@ class RepoPullRequestsView(RepoAppView, } return data + def _get_existing_ids(self, post_data): + return filter(lambda e: e, map(safe_int, aslist(post_data.get('comments'), ','))) + @LoginRequired() @NotAnonymous() @HasRepoPermissionAnyDecorator( 'repository.read', 'repository.write', 'repository.admin') @view_config( route_name='pullrequest_comments', request_method='POST', - renderer='string', xhr=True) + renderer='string_html', xhr=True) def pullrequest_comments(self): self.load_default_context() @@ -997,8 +1018,7 @@ class RepoPullRequestsView(RepoAppView, self.register_comments_vars(c, pull_request_latest, versions) all_comments = c.inline_comments_flat + c.comments - existing_ids = filter( - lambda e: e, map(safe_int, self.request.POST.getall('comments[]'))) + existing_ids = self._get_existing_ids(self.request.POST) return _render('comments_table', all_comments, len(all_comments), existing_ids=existing_ids) @@ -1008,7 +1028,7 @@ class RepoPullRequestsView(RepoAppView, 'repository.read', 'repository.write', 'repository.admin') @view_config( route_name='pullrequest_todos', request_method='POST', - renderer='string', xhr=True) + renderer='string_html', xhr=True) def pullrequest_todos(self): self.load_default_context() @@ -1040,8 +1060,7 @@ class RepoPullRequestsView(RepoAppView, .get_pull_request_resolved_todos(pull_request) all_comments = c.unresolved_comments + c.resolved_comments - existing_ids = filter( - lambda e: e, map(safe_int, self.request.POST.getall('comments[]'))) + existing_ids = self._get_existing_ids(self.request.POST) return _render('comments_table', all_comments, len(c.unresolved_comments), todo_comments=True, existing_ids=existing_ids) @@ -1128,30 +1147,35 @@ class RepoPullRequestsView(RepoAppView, source_scm = source_db_repo.scm_instance() target_scm = target_db_repo.scm_instance() - source_commit = source_scm.get_commit(source_ref.split(':')[-1]) - target_commit = target_scm.get_commit(target_ref.split(':')[-1]) + source_ref_obj = unicode_to_reference(source_ref) + target_ref_obj = unicode_to_reference(target_ref) + + source_commit = source_scm.get_commit(source_ref_obj.commit_id) + target_commit = target_scm.get_commit(target_ref_obj.commit_id) ancestor = source_scm.get_common_ancestor( source_commit.raw_id, target_commit.raw_id, target_scm) # recalculate target ref based on ancestor - target_ref_type, target_ref_name, __ = _form['target_ref'].split(':') - target_ref = ':'.join((target_ref_type, target_ref_name, ancestor)) + target_ref = ':'.join((target_ref_obj.type, target_ref_obj.name, ancestor)) - get_default_reviewers_data, validate_default_reviewers = \ + get_default_reviewers_data, validate_default_reviewers, validate_observers = \ PullRequestModel().get_reviewer_functions() # recalculate reviewers logic, to make sure we can validate this reviewer_rules = get_default_reviewers_data( - self._rhodecode_db_user, source_db_repo, - source_commit, target_db_repo, target_commit) + self._rhodecode_db_user, + source_db_repo, + source_ref_obj, + target_db_repo, + target_ref_obj, + include_diff_info=False) - given_reviewers = _form['review_members'] - reviewers = validate_default_reviewers( - given_reviewers, reviewer_rules) + reviewers = validate_default_reviewers(_form['review_members'], reviewer_rules) + observers = validate_observers(_form['observer_members'], reviewer_rules) pullrequest_title = _form['pullrequest_title'] - title_source_ref = source_ref.split(':', 2)[1] + title_source_ref = source_ref_obj.name if not pullrequest_title: pullrequest_title = PullRequestModel().generate_pullrequest_title( source=source_repo, @@ -1172,6 +1196,7 @@ class RepoPullRequestsView(RepoAppView, revisions=commit_ids, common_ancestor_id=common_ancestor_id, reviewers=reviewers, + observers=observers, title=pullrequest_title, description=description, description_renderer=description_renderer, @@ -1221,20 +1246,28 @@ class RepoPullRequestsView(RepoAppView, 'redirect_url': redirect_url} is_state_changing = pull_request.is_state_changing() - c.pr_broadcast_channel = '/repo${}$/pr/{}'.format( - pull_request.target_repo.repo_name, pull_request.pull_request_id) + c.pr_broadcast_channel = channelstream.pr_channel(pull_request) # only owner or admin can update it allowed_to_update = PullRequestModel().check_user_update( pull_request, self._rhodecode_user) + if allowed_to_update: controls = peppercorn.parse(self.request.POST.items()) force_refresh = str2bool(self.request.POST.get('force_refresh')) if 'review_members' in controls: self._update_reviewers( + c, pull_request, controls['review_members'], - pull_request.reviewer_data) + pull_request.reviewer_data, + PullRequestReviewers.ROLE_REVIEWER) + elif 'observer_members' in controls: + self._update_reviewers( + c, + pull_request, controls['observer_members'], + pull_request.reviewer_data, + PullRequestReviewers.ROLE_OBSERVER) elif str2bool(self.request.POST.get('update_commits', 'false')): if is_state_changing: log.debug('commits update: forbidden because pull request is in state %s', @@ -1255,6 +1288,7 @@ class RepoPullRequestsView(RepoAppView, elif str2bool(self.request.POST.get('edit_pull_request', 'false')): self._edit_pull_request(pull_request) else: + log.error('Unhandled update data.') raise HTTPBadRequest() return {'response': True, @@ -1262,6 +1296,9 @@ class RepoPullRequestsView(RepoAppView, raise HTTPForbidden() def _edit_pull_request(self, pull_request): + """ + Edit title and description + """ _ = self.request.translate try: @@ -1302,27 +1339,15 @@ class RepoPullRequestsView(RepoAppView, msg = _(u'Pull request updated to "{source_commit_id}" with ' u'{count_added} added, {count_removed} removed commits. ' - u'Source of changes: {change_source}') + u'Source of changes: {change_source}.') msg = msg.format( source_commit_id=pull_request.source_ref_parts.commit_id, count_added=len(resp.changes.added), count_removed=len(resp.changes.removed), change_source=changed) h.flash(msg, category='success') - - message = msg + ( - ' - ' - '{}'.format(_('Reload page'))) - - message_obj = { - 'message': message, - 'level': 'success', - 'topic': '/notifications' - } - - channelstream.post_message( - c.pr_broadcast_channel, message_obj, self._rhodecode_user.username, - registry=self.request.registry) + channelstream.pr_update_channelstream_push( + self.request, c.pr_broadcast_channel, self._rhodecode_user, msg) else: msg = PullRequestModel.UPDATE_STATUS_MESSAGES[resp.reason] warning_reasons = [ @@ -1332,6 +1357,55 @@ class RepoPullRequestsView(RepoAppView, category = 'warning' if resp.reason in warning_reasons else 'error' h.flash(msg, category=category) + def _update_reviewers(self, c, pull_request, review_members, reviewer_rules, role): + _ = self.request.translate + + get_default_reviewers_data, validate_default_reviewers, validate_observers = \ + PullRequestModel().get_reviewer_functions() + + if role == PullRequestReviewers.ROLE_REVIEWER: + try: + reviewers = validate_default_reviewers(review_members, reviewer_rules) + except ValueError as e: + log.error('Reviewers Validation: {}'.format(e)) + h.flash(e, category='error') + return + + old_calculated_status = pull_request.calculated_review_status() + PullRequestModel().update_reviewers( + pull_request, reviewers, self._rhodecode_db_user) + + Session().commit() + + msg = _('Pull request reviewers updated.') + h.flash(msg, category='success') + channelstream.pr_update_channelstream_push( + self.request, c.pr_broadcast_channel, self._rhodecode_user, msg) + + # trigger status changed if change in reviewers changes the status + calculated_status = pull_request.calculated_review_status() + if old_calculated_status != calculated_status: + PullRequestModel().trigger_pull_request_hook( + pull_request, self._rhodecode_user, 'review_status_change', + data={'status': calculated_status}) + + elif role == PullRequestReviewers.ROLE_OBSERVER: + try: + observers = validate_observers(review_members, reviewer_rules) + except ValueError as e: + log.error('Observers Validation: {}'.format(e)) + h.flash(e, category='error') + return + + PullRequestModel().update_observers( + pull_request, observers, self._rhodecode_db_user) + + Session().commit() + msg = _('Pull request observers updated.') + h.flash(msg, category='success') + channelstream.pr_update_channelstream_push( + self.request, c.pr_broadcast_channel, self._rhodecode_user, msg) + @LoginRequired() @NotAnonymous() @HasRepoPermissionAnyDecorator( @@ -1408,32 +1482,6 @@ class RepoPullRequestsView(RepoAppView, msg = merge_resp.merge_status_message h.flash(msg, category='error') - def _update_reviewers(self, pull_request, review_members, reviewer_rules): - _ = self.request.translate - - get_default_reviewers_data, validate_default_reviewers = \ - PullRequestModel().get_reviewer_functions() - - try: - reviewers = validate_default_reviewers(review_members, reviewer_rules) - except ValueError as e: - log.error('Reviewers Validation: {}'.format(e)) - h.flash(e, category='error') - return - - old_calculated_status = pull_request.calculated_review_status() - PullRequestModel().update_reviewers( - pull_request, reviewers, self._rhodecode_user) - h.flash(_('Pull request reviewers updated.'), category='success') - Session().commit() - - # trigger status changed if change in reviewers changes the status - calculated_status = pull_request.calculated_review_status() - if old_calculated_status != calculated_status: - PullRequestModel().trigger_pull_request_hook( - pull_request, self._rhodecode_user, 'review_status_change', - data={'status': calculated_status}) - @LoginRequired() @NotAnonymous() @HasRepoPermissionAnyDecorator( @@ -1488,8 +1536,7 @@ class RepoPullRequestsView(RepoAppView, allowed_to_comment = PullRequestModel().check_user_comment( pull_request, self._rhodecode_user) if not allowed_to_comment: - log.debug( - 'comment: forbidden because pull request is from forbidden repo') + log.debug('comment: forbidden because pull request is from forbidden repo') raise HTTPForbidden() c = self.load_default_context() @@ -1518,6 +1565,7 @@ class RepoPullRequestsView(RepoAppView, pull_request, self._rhodecode_user, self.db_repo, message=text, auth_user=self._rhodecode_user) Session().flush() + is_inline = comment.is_inline PullRequestModel().trigger_pull_request_hook( pull_request, self._rhodecode_user, 'comment', @@ -1551,6 +1599,7 @@ class RepoPullRequestsView(RepoAppView, resolves_comment_id=resolves_comment_id, auth_user=self._rhodecode_user ) + is_inline = comment.is_inline if allowed_to_change_status: # calculate old status before we change it @@ -1599,6 +1648,16 @@ class RepoPullRequestsView(RepoAppView, data.update(comment.get_dict()) data.update({'rendered_text': rendered_comment}) + comment_broadcast_channel = channelstream.comment_channel( + self.db_repo_name, pull_request_obj=pull_request) + + comment_data = data + comment_type = 'inline' if is_inline else 'general' + channelstream.comment_channelstream_push( + self.request, comment_broadcast_channel, self._rhodecode_user, + _('posted a new {} comment').format(comment_type), + comment_data=comment_data) + return data @LoginRequired() diff --git a/rhodecode/apps/repository/views/repo_review_rules.py b/rhodecode/apps/repository/views/repo_review_rules.py --- a/rhodecode/apps/repository/views/repo_review_rules.py +++ b/rhodecode/apps/repository/views/repo_review_rules.py @@ -25,6 +25,7 @@ from pyramid.view import view_config from rhodecode.apps._base import RepoAppView from rhodecode.apps.repository.utils import get_default_reviewers_data from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator +from rhodecode.lib.vcs.backends.base import Reference from rhodecode.model.db import Repository log = logging.getLogger(__name__) @@ -61,13 +62,28 @@ class RepoReviewRulesView(RepoAppView): target_repo_name = request.GET.get('target_repo', source_repo_name) target_repo = Repository.get_by_repo_name(target_repo_name) - source_ref = request.GET['source_ref'] - target_ref = request.GET['target_ref'] - source_commit = source_repo.get_commit(source_ref) - target_commit = target_repo.get_commit(target_ref) + current_user = request.user.get_instance() + + source_commit_id = request.GET['source_ref'] + source_type = request.GET['source_ref_type'] + source_name = request.GET['source_ref_name'] + + target_commit_id = request.GET['target_ref'] + target_type = request.GET['target_ref_type'] + target_name = request.GET['target_ref_name'] - current_user = request.user.get_instance() - review_data = get_default_reviewers_data( - current_user, source_repo, source_commit, target_repo, target_commit) + try: + review_data = get_default_reviewers_data( + current_user, + source_repo, + Reference(source_type, source_name, source_commit_id), + target_repo, + Reference(target_type, target_name, target_commit_id) + ) + except ValueError: + # No common ancestor + msg = "No Common ancestor found between target and source reference" + log.exception(msg) + return {'diff_info': {'error': msg}} return review_data diff --git a/rhodecode/config/middleware.py b/rhodecode/config/middleware.py --- a/rhodecode/config/middleware.py +++ b/rhodecode/config/middleware.py @@ -341,6 +341,10 @@ def includeme(config): name='json_ext', factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json') + config.add_renderer( + name='string_html', + factory='rhodecode.lib.string_renderer.html') + # include RhodeCode plugins includes = aslist(settings.get('rhodecode.includes', [])) for inc in includes: @@ -408,6 +412,7 @@ def sanitize_settings_and_apply_defaults """ settings.setdefault('rhodecode.edition', 'Community Edition') + settings.setdefault('rhodecode.edition_id', 'CE') if 'mako.default_filters' not in settings: # set custom default filters if we don't have it defined diff --git a/rhodecode/events/repo.py b/rhodecode/events/repo.py --- a/rhodecode/events/repo.py +++ b/rhodecode/events/repo.py @@ -113,7 +113,7 @@ def _commits_as_dict(event, commit_ids, cs_data['permalink_url'] = RepoModel().get_commit_url( repo, cs_data['raw_id'], request=event.request, permalink=True) - urlified_message, issues_data = process_patterns( + urlified_message, issues_data, errors = process_patterns( cs_data['message'], repo.repo_name) cs_data['issues'] = issues_data cs_data['message_html'] = urlify_commit_message( 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.20.0\n" +"Project-Id-Version: rhodecode-enterprise-ce 4.21.0\n" "Report-Msgid-Bugs-To: marcin@rhodecode.com\n" -"POT-Creation-Date: 2020-07-20 11:46+0000\n" +"POT-Creation-Date: 2020-10-12 13:39+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,6 +17,13 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" +#: rhodecode/api/views/pull_request_api.py:646 +#: rhodecode/api/views/repo_api.py:1685 +#: rhodecode/apps/repository/views/repo_commits.py:471 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1658 +msgid "posted a new {} comment" +msgstr "" + #: rhodecode/apps/admin/views/defaults.py:90 msgid "Default settings updated successfully" msgstr "" @@ -55,10 +62,10 @@ msgstr "" #: rhodecode/templates/admin/gists/gist_show.mako:50 #: rhodecode/templates/admin/integrations/list.mako:172 #: rhodecode/templates/admin/my_account/my_account_profile.mako:7 -#: rhodecode/templates/base/issue_tracker_settings.mako:137 -#: rhodecode/templates/changeset/changeset_file_comment.mako:201 -#: rhodecode/templates/changeset/changeset_file_comment.mako:205 -#: rhodecode/templates/changeset/changeset_file_comment.mako:209 +#: rhodecode/templates/base/issue_tracker_settings.mako:138 +#: rhodecode/templates/changeset/changeset_file_comment.mako:213 +#: rhodecode/templates/changeset/changeset_file_comment.mako:221 +#: rhodecode/templates/changeset/changeset_file_comment.mako:230 #: rhodecode/templates/data_table/_dt_elements.mako:173 #: rhodecode/templates/data_table/_dt_elements.mako:251 #: rhodecode/templates/data_table/_dt_elements.mako:266 @@ -69,8 +76,9 @@ msgstr "" #: rhodecode/templates/files/files_edit.mako:57 #: rhodecode/templates/files/files_source.mako:39 #: rhodecode/templates/files/files_source.mako:52 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:74 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:302 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:83 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:588 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:645 #: rhodecode/templates/user_group/profile.mako:8 #: rhodecode/templates/users/user_profile.mako:8 msgid "Edit" @@ -105,7 +113,7 @@ msgstr "" #: rhodecode/apps/admin/views/settings.py:163 #: rhodecode/apps/admin/views/settings.py:319 #: rhodecode/apps/admin/views/settings.py:394 -#: rhodecode/apps/admin/views/settings.py:727 +#: rhodecode/apps/admin/views/settings.py:736 #: rhodecode/apps/repository/views/repo_settings_vcs.py:124 msgid "Some form inputs contain invalid data." msgstr "" @@ -137,46 +145,46 @@ msgstr "" msgid "Error occurred during updating visualisation settings" msgstr "" -#: rhodecode/apps/admin/views/settings.py:498 +#: rhodecode/apps/admin/views/settings.py:507 #: rhodecode/apps/repository/views/repo_settings_issue_trackers.py:127 msgid "Invalid issue tracker pattern: {}" msgstr "" -#: rhodecode/apps/admin/views/settings.py:515 +#: rhodecode/apps/admin/views/settings.py:524 #: rhodecode/apps/repository/views/repo_settings_issue_trackers.py:136 msgid "Updated issue tracker entries" msgstr "" -#: rhodecode/apps/admin/views/settings.py:535 +#: rhodecode/apps/admin/views/settings.py:544 #: rhodecode/apps/repository/views/repo_settings_issue_trackers.py:91 msgid "Removed issue tracker entry." msgstr "" -#: rhodecode/apps/admin/views/settings.py:573 +#: rhodecode/apps/admin/views/settings.py:582 msgid "Please enter email address" msgstr "" -#: rhodecode/apps/admin/views/settings.py:589 +#: rhodecode/apps/admin/views/settings.py:598 msgid "Send email task created" msgstr "" -#: rhodecode/apps/admin/views/settings.py:639 +#: rhodecode/apps/admin/views/settings.py:648 msgid "Added new hook" msgstr "" -#: rhodecode/apps/admin/views/settings.py:654 +#: rhodecode/apps/admin/views/settings.py:663 msgid "Updated hooks" msgstr "" -#: rhodecode/apps/admin/views/settings.py:658 +#: rhodecode/apps/admin/views/settings.py:667 msgid "Error occurred during hook creation" msgstr "" -#: rhodecode/apps/admin/views/settings.py:751 +#: rhodecode/apps/admin/views/settings.py:760 msgid "Error occurred during updating labs settings" msgstr "" -#: rhodecode/apps/admin/views/settings.py:756 +#: rhodecode/apps/admin/views/settings.py:765 msgid "Updated Labs settings" msgstr "" @@ -586,10 +594,10 @@ msgstr "" msgid "1 month" msgstr "" -#: rhodecode/apps/gist/views.py:64 rhodecode/public/js/scripts.js:47676 +#: rhodecode/apps/gist/views.py:64 rhodecode/public/js/scripts.js:48330 #: rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:42 -#: rhodecode/public/js/src/rhodecode.js:625 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:47 +#: rhodecode/public/js/src/rhodecode.js:634 msgid "Lifetime" msgstr "" @@ -640,19 +648,19 @@ msgstr "" msgid "Error occurred during update of gist %s" msgstr "" -#: rhodecode/apps/home/views.py:452 -#: rhodecode/apps/repository/views/repo_pull_requests.py:930 +#: rhodecode/apps/home/views.py:453 +#: rhodecode/apps/repository/views/repo_pull_requests.py:976 #: rhodecode/templates/admin/repo_groups/repo_group_edit_permissions.mako:219 #: rhodecode/templates/admin/repos/repo_add.mako:15 #: rhodecode/templates/admin/repos/repo_add.mako:19 #: rhodecode/templates/admin/users/user_edit_advanced.mako:12 -#: rhodecode/templates/base/base.mako:112 -#: rhodecode/templates/base/base.mako:131 -#: rhodecode/templates/base/base.mako:1192 +#: rhodecode/templates/base/base.mako:114 +#: rhodecode/templates/base/base.mako:133 +#: rhodecode/templates/base/base.mako:1191 msgid "Repositories" msgstr "" -#: rhodecode/apps/home/views.py:479 +#: rhodecode/apps/home/views.py:480 #: rhodecode/templates/admin/integrations/form.mako:17 #: rhodecode/templates/admin/integrations/list.mako:10 #: rhodecode/templates/admin/permissions/permissions_objects.mako:31 @@ -779,7 +787,7 @@ msgstr "" #: rhodecode/apps/repository/views/repo_changelog.py:66 #: rhodecode/apps/repository/views/repo_compare.py:64 -#: rhodecode/apps/repository/views/repo_pull_requests.py:779 +#: rhodecode/apps/repository/views/repo_pull_requests.py:825 msgid "There are no commits yet" msgstr "" @@ -807,13 +815,13 @@ msgstr "" msgid "No such commit exists. Org exception: `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_commits.py:331 -#: rhodecode/apps/repository/views/repo_pull_requests.py:1415 +#: rhodecode/apps/repository/views/repo_commits.py:388 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1582 #, python-format msgid "Status change %(transition_icon)s %(status)s" msgstr "" -#: rhodecode/apps/repository/views/repo_commits.py:376 +#: rhodecode/apps/repository/views/repo_commits.py:434 msgid "Changing the status of a commit associated with a closed pull request is not allowed" msgstr "" @@ -878,104 +886,104 @@ msgstr "" msgid "No such commit exists for this repository. Commit: {}" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:341 +#: rhodecode/apps/repository/views/repo_files.py:345 msgid "Downloads disabled" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:347 +#: rhodecode/apps/repository/views/repo_files.py:351 msgid "Unknown archive type for: `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:353 +#: rhodecode/apps/repository/views/repo_files.py:357 msgid "Unknown commit_id {}" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:356 +#: rhodecode/apps/repository/views/repo_files.py:360 msgid "Empty repository" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:361 +#: rhodecode/apps/repository/views/repo_files.py:365 msgid "No node at path {} for this repository" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:410 +#: rhodecode/apps/repository/views/repo_files.py:414 msgid "Unknown archive type" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1005 +#: rhodecode/apps/repository/views/repo_files.py:1010 msgid "Changesets" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1026 +#: rhodecode/apps/repository/views/repo_files.py:1031 #: rhodecode/apps/repository/views/repo_summary.py:264 -#: rhodecode/model/pull_request.py:1740 rhodecode/model/scm.py:995 +#: rhodecode/model/pull_request.py:1903 rhodecode/model/scm.py:995 #: rhodecode/templates/base/vcs_settings.mako:235 #: rhodecode/templates/summary/components.mako:10 msgid "Branches" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1030 +#: rhodecode/apps/repository/views/repo_files.py:1035 #: rhodecode/model/scm.py:1012 rhodecode/templates/base/vcs_settings.mako:260 #: rhodecode/templates/summary/components.mako:34 msgid "Tags" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1184 -#: rhodecode/apps/repository/views/repo_files.py:1212 +#: rhodecode/apps/repository/views/repo_files.py:1191 +#: rhodecode/apps/repository/views/repo_files.py:1220 msgid "Deleted file {} via RhodeCode Enterprise" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1233 +#: rhodecode/apps/repository/views/repo_files.py:1241 msgid "Successfully deleted file `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1237 -#: rhodecode/apps/repository/views/repo_files.py:1354 -#: rhodecode/apps/repository/views/repo_files.py:1485 -#: rhodecode/apps/repository/views/repo_files.py:1608 +#: rhodecode/apps/repository/views/repo_files.py:1245 +#: rhodecode/apps/repository/views/repo_files.py:1364 +#: rhodecode/apps/repository/views/repo_files.py:1497 +#: rhodecode/apps/repository/views/repo_files.py:1621 msgid "Error occurred during commit" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1269 -#: rhodecode/apps/repository/views/repo_files.py:1300 +#: rhodecode/apps/repository/views/repo_files.py:1278 +#: rhodecode/apps/repository/views/repo_files.py:1310 msgid "Edited file {} via RhodeCode Enterprise" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1323 +#: rhodecode/apps/repository/views/repo_files.py:1333 msgid "No changes detected on {}" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1347 +#: rhodecode/apps/repository/views/repo_files.py:1357 msgid "Successfully committed changes to file `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1388 -#: rhodecode/apps/repository/views/repo_files.py:1429 +#: rhodecode/apps/repository/views/repo_files.py:1399 +#: rhodecode/apps/repository/views/repo_files.py:1441 msgid "Added file via RhodeCode Enterprise" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1445 +#: rhodecode/apps/repository/views/repo_files.py:1457 msgid "No filename specified" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1470 +#: rhodecode/apps/repository/views/repo_files.py:1482 msgid "Successfully committed new file `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1478 -#: rhodecode/apps/repository/views/repo_files.py:1590 +#: rhodecode/apps/repository/views/repo_files.py:1490 +#: rhodecode/apps/repository/views/repo_files.py:1603 msgid "The location specified must be a relative path and must not contain .. in the path" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1535 +#: rhodecode/apps/repository/views/repo_files.py:1548 msgid "Uploaded file via RhodeCode Enterprise" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1579 +#: rhodecode/apps/repository/views/repo_files.py:1592 msgid "Successfully committed {} new files" msgstr "" -#: rhodecode/apps/repository/views/repo_files.py:1581 +#: rhodecode/apps/repository/views/repo_files.py:1594 msgid "Successfully committed 1 new file" msgstr "" @@ -989,7 +997,7 @@ msgid "An error occurred during reposito msgstr "" #: rhodecode/apps/repository/views/repo_permissions.py:57 -msgid "Explicitly add user or user group with write+ permission to modify their branch permissions." +msgid "Explicitly add user or user group with write or higher permission to modify their branch permissions." msgstr "" #: rhodecode/apps/repository/views/repo_permissions.py:92 @@ -1005,72 +1013,72 @@ msgstr "" msgid "Error occurred during update of repository {}" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:291 +#: rhodecode/apps/repository/views/repo_pull_requests.py:325 msgid "Pull Request state was force changed to `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:809 +#: rhodecode/apps/repository/views/repo_pull_requests.py:855 msgid "Commit does not exist" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:961 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1092 msgid "Error creating pull request: {}" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:981 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1112 msgid "source_repo or target repo not found" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:992 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1123 msgid "Not Enough permissions to source repo `{}`." msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1007 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1138 msgid "Not Enough permissions to target repo `{}`." msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1071 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1208 msgid "Successfully opened new pull request" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1074 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1211 msgid "Error occurred during creation of this pull request." msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1106 -#: rhodecode/apps/repository/views/repo_pull_requests.py:1161 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1243 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1312 msgid "Cannot update closed pull requests." msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1128 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1275 msgid "Cannot update pull requests commits in state other than `{}`. Current state is: `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1167 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1318 msgid "Pull request title & description updated." msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1189 -msgid "Pull request updated to \"{source_commit_id}\" with {count_added} added, {count_removed} removed commits. Source of changes: {change_source}" -msgstr "" - -#: rhodecode/apps/repository/views/repo_pull_requests.py:1203 -msgid "Reload page" -msgstr "" - -#: rhodecode/apps/repository/views/repo_pull_requests.py:1238 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1340 +msgid "Pull request updated to \"{source_commit_id}\" with {count_added} added, {count_removed} removed commits. Source of changes: {change_source}." +msgstr "" + +#: rhodecode/apps/repository/views/repo_pull_requests.py:1380 +msgid "Pull request reviewers updated." +msgstr "" + +#: rhodecode/apps/repository/views/repo_pull_requests.py:1404 +msgid "Pull request observers updated." +msgstr "" + +#: rhodecode/apps/repository/views/repo_pull_requests.py:1431 msgid "Cannot merge pull requests in state other than `{}`. Current state is: `{}`" msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1284 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1477 msgid "Pull request was successfully merged and closed." msgstr "" -#: rhodecode/apps/repository/views/repo_pull_requests.py:1308 -msgid "Pull request reviewers updated." -msgstr "" - -#: rhodecode/apps/repository/views/repo_pull_requests.py:1341 +#: rhodecode/apps/repository/views/repo_pull_requests.py:1508 msgid "Successfully deleted pull request" msgstr "" @@ -1801,10 +1809,10 @@ msgstr "" msgid "Reset" msgstr "" -#: rhodecode/forms/__init__.py:36 rhodecode/public/js/scripts.js:38311 +#: rhodecode/forms/__init__.py:36 rhodecode/public/js/scripts.js:38315 #: rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:24 -#: rhodecode/public/js/src/rhodecode/utils/ajax.js:161 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:29 +#: rhodecode/public/js/src/rhodecode/utils/ajax.js:165 #: rhodecode/templates/admin/gists/gist_show.mako:59 #: rhodecode/templates/admin/integrations/list.mako:179 #: rhodecode/templates/admin/my_account/my_account_auth_tokens.mako:65 @@ -1819,12 +1827,12 @@ msgstr "" #: rhodecode/templates/admin/users/user_edit_emails.mako:34 #: rhodecode/templates/admin/users/user_edit_ips.mako:40 #: rhodecode/templates/admin/users/user_edit_ssh_keys.mako:35 -#: rhodecode/templates/base/issue_tracker_settings.mako:146 +#: rhodecode/templates/base/issue_tracker_settings.mako:147 #: rhodecode/templates/base/vcs_settings.mako:244 #: rhodecode/templates/base/vcs_settings.mako:269 -#: rhodecode/templates/changeset/changeset_file_comment.mako:203 -#: rhodecode/templates/changeset/changeset_file_comment.mako:206 -#: rhodecode/templates/changeset/changeset_file_comment.mako:210 +#: rhodecode/templates/changeset/changeset_file_comment.mako:216 +#: rhodecode/templates/changeset/changeset_file_comment.mako:224 +#: rhodecode/templates/changeset/changeset_file_comment.mako:233 #: rhodecode/templates/data_table/_dt_elements.mako:436 #: rhodecode/templates/debug_style/buttons.html:132 #: rhodecode/templates/files/files_source.mako:40 @@ -2225,11 +2233,19 @@ msgstr "" msgid "You need to be signed in to view this page" msgstr "" +#: rhodecode/lib/channelstream.py:318 +msgid " Reload page to load changes" +msgstr "" + +#: rhodecode/lib/channelstream.py:348 +msgid "Reload page to see new comments" +msgstr "" + #: rhodecode/lib/diffs.py:903 msgid "Click to select line" msgstr "" -#: rhodecode/lib/helpers.py:1803 +#: rhodecode/lib/helpers.py:1878 msgid "" "Example filter terms:\n" " repository:vcs\n" @@ -2251,7 +2267,7 @@ msgid "" " \"username:test AND repository:test*\"\n" msgstr "" -#: rhodecode/lib/helpers.py:1827 +#: rhodecode/lib/helpers.py:1902 #, 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 "" @@ -2290,7 +2306,7 @@ msgstr "" #: rhodecode/lib/utils2.py:571 rhodecode/public/js/scripts.js:22612 #: rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:127 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:136 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:174 msgid "just now" msgstr "" @@ -2326,6 +2342,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2987 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3073 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3079 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3110 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2275 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2267 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2266 @@ -2333,7 +2350,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2270 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2321 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2322 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2522 rhodecode/model/db.py:3110 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2522 rhodecode/model/db.py:3111 msgid "Repository no access" msgstr "" @@ -2368,6 +2385,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2988 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3074 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3080 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3111 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2276 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2268 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2267 @@ -2375,7 +2393,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2271 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2322 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2323 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2523 rhodecode/model/db.py:3111 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2523 rhodecode/model/db.py:3112 msgid "Repository read access" msgstr "" @@ -2410,6 +2428,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2989 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3075 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3081 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3112 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2277 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2269 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2268 @@ -2417,7 +2436,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2272 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2323 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2324 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2524 rhodecode/model/db.py:3112 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2524 rhodecode/model/db.py:3113 msgid "Repository write access" msgstr "" @@ -2452,6 +2471,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2990 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3076 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3082 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3113 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2278 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2270 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2269 @@ -2459,7 +2479,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2273 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2324 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2325 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2525 rhodecode/model/db.py:3113 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2525 rhodecode/model/db.py:3114 msgid "Repository admin access" msgstr "" @@ -2534,6 +2554,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3013 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3099 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3105 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3136 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2296 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2288 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2287 @@ -2541,7 +2562,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2291 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2342 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2343 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2543 rhodecode/model/db.py:3136 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2543 rhodecode/model/db.py:3137 msgid "Repository creation disabled" msgstr "" @@ -2576,6 +2597,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3014 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3100 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3106 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3137 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2297 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2289 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2288 @@ -2583,7 +2605,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2292 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2343 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2344 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2544 rhodecode/model/db.py:3137 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2544 rhodecode/model/db.py:3138 msgid "Repository creation enabled" msgstr "" @@ -2618,6 +2640,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3018 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3104 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3110 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3141 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2301 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2293 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2292 @@ -2625,7 +2648,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2296 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2347 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2348 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2548 rhodecode/model/db.py:3141 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2548 rhodecode/model/db.py:3142 msgid "Repository forking disabled" msgstr "" @@ -2660,6 +2683,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3019 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3105 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3111 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3142 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2302 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2294 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2293 @@ -2667,7 +2691,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2297 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2348 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2349 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2549 rhodecode/model/db.py:3142 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2549 rhodecode/model/db.py:3143 msgid "Repository forking enabled" msgstr "" @@ -2723,6 +2747,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3757 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3843 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3890 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3935 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2915 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2907 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2907 @@ -2730,10 +2755,10 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2910 #: 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:3935 -#: rhodecode/public/js/scripts.js:42219 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:64 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:352 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3230 rhodecode/model/db.py:3971 +#: rhodecode/public/js/scripts.js:42424 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:70 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:445 msgid "Not Reviewed" msgstr "" @@ -2768,6 +2793,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3758 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3844 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3891 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3936 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2916 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2908 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2908 @@ -2775,7 +2801,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2911 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:3012 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:3013 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3231 rhodecode/model/db.py:3936 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3231 rhodecode/model/db.py:3972 msgid "Approved" msgstr "" @@ -2810,6 +2836,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3759 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3845 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3892 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3937 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2917 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2909 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2909 @@ -2817,7 +2844,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2912 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:3013 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:3014 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3232 rhodecode/model/db.py:3937 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3232 rhodecode/model/db.py:3973 msgid "Rejected" msgstr "" @@ -2852,6 +2879,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3760 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3846 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3893 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3938 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2918 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2910 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2910 @@ -2859,7 +2887,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2913 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:3014 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:3015 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3233 rhodecode/model/db.py:3938 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:3233 rhodecode/model/db.py:3974 msgid "Under Review" msgstr "" @@ -2891,6 +2919,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2992 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3078 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3084 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3115 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2280 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2272 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2271 @@ -2898,7 +2927,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2275 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2326 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2327 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2527 rhodecode/model/db.py:3115 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2527 rhodecode/model/db.py:3116 msgid "Repository group no access" msgstr "" @@ -2930,6 +2959,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2993 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3079 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3085 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3116 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2281 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2273 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2272 @@ -2937,7 +2967,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2276 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2327 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2328 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2528 rhodecode/model/db.py:3116 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2528 rhodecode/model/db.py:3117 msgid "Repository group read access" msgstr "" @@ -2969,6 +2999,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2994 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3080 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3086 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3117 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2282 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2274 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2273 @@ -2976,7 +3007,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2277 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2328 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2329 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2529 rhodecode/model/db.py:3117 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2529 rhodecode/model/db.py:3118 msgid "Repository group write access" msgstr "" @@ -3008,6 +3039,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2995 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3081 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3087 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3118 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2283 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2275 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2274 @@ -3015,7 +3047,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2278 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2329 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2330 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2530 rhodecode/model/db.py:3118 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2530 rhodecode/model/db.py:3119 msgid "Repository group admin access" msgstr "" @@ -3046,6 +3078,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2997 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3083 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3089 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3120 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2285 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2277 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2276 @@ -3053,7 +3086,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2280 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2331 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2332 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2532 rhodecode/model/db.py:3120 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2532 rhodecode/model/db.py:3121 msgid "User group no access" msgstr "" @@ -3084,6 +3117,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2998 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3084 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3090 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3121 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2286 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2278 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2277 @@ -3091,7 +3125,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2281 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2332 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2333 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2533 rhodecode/model/db.py:3121 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2533 rhodecode/model/db.py:3122 msgid "User group read access" msgstr "" @@ -3122,6 +3156,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2999 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3085 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3091 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3122 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2287 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2279 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2278 @@ -3129,7 +3164,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2282 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2333 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2334 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2534 rhodecode/model/db.py:3122 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2534 rhodecode/model/db.py:3123 msgid "User group write access" msgstr "" @@ -3160,6 +3195,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3000 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3086 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3092 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3123 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2288 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2280 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2279 @@ -3167,7 +3203,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2283 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2334 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2335 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2535 rhodecode/model/db.py:3123 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2535 rhodecode/model/db.py:3124 msgid "User group admin access" msgstr "" @@ -3198,6 +3234,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3007 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3093 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3099 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3130 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2290 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2282 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2281 @@ -3205,7 +3242,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2285 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2336 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2337 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2537 rhodecode/model/db.py:3130 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2537 rhodecode/model/db.py:3131 msgid "Repository Group creation disabled" msgstr "" @@ -3236,6 +3273,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3008 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3094 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3100 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3131 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2291 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2283 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2282 @@ -3243,7 +3281,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2286 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2337 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2338 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2538 rhodecode/model/db.py:3131 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2538 rhodecode/model/db.py:3132 msgid "Repository Group creation enabled" msgstr "" @@ -3274,6 +3312,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3010 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3096 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3102 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3133 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2293 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2285 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2284 @@ -3281,7 +3320,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2288 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2339 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2340 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2540 rhodecode/model/db.py:3133 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2540 rhodecode/model/db.py:3134 msgid "User Group creation disabled" msgstr "" @@ -3312,6 +3351,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3011 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3097 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3103 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3134 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2294 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2286 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2285 @@ -3319,7 +3359,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2289 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2340 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2341 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2541 rhodecode/model/db.py:3134 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2541 rhodecode/model/db.py:3135 msgid "User Group creation enabled" msgstr "" @@ -3350,6 +3390,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3021 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3107 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3113 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3144 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2304 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2296 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2295 @@ -3357,7 +3398,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2299 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2350 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2351 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2551 rhodecode/model/db.py:3144 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2551 rhodecode/model/db.py:3145 msgid "Registration disabled" msgstr "" @@ -3388,6 +3429,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3022 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3108 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3114 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3145 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2305 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2297 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2296 @@ -3395,7 +3437,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2300 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2351 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2352 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2552 rhodecode/model/db.py:3145 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2552 rhodecode/model/db.py:3146 msgid "User Registration with manual account activation" msgstr "" @@ -3426,6 +3468,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3023 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3109 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3115 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3146 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2306 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2298 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2297 @@ -3433,7 +3476,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2301 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2352 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2353 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2553 rhodecode/model/db.py:3146 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2553 rhodecode/model/db.py:3147 msgid "User Registration with automatic account activation" msgstr "" @@ -3464,6 +3507,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3029 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3115 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3121 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3152 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2308 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2300 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2299 @@ -3471,7 +3515,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2303 #: 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:3152 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2559 rhodecode/model/db.py:3153 #: rhodecode/model/permission.py:105 msgid "Manual activation of external account" msgstr "" @@ -3503,6 +3547,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3030 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3116 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3122 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3153 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2309 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2301 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2300 @@ -3510,7 +3555,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2304 #: 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:3153 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2560 rhodecode/model/db.py:3154 #: rhodecode/model/permission.py:106 msgid "Automatic activation of external account" msgstr "" @@ -3536,6 +3581,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3015 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3101 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3107 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3138 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2298 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2290 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2289 @@ -3543,7 +3589,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2293 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2344 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2345 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2545 rhodecode/model/db.py:3138 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2545 rhodecode/model/db.py:3139 msgid "Repository creation enabled with write permission to a repository group" msgstr "" @@ -3568,6 +3614,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3016 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3102 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3108 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3139 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2299 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2291 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2290 @@ -3575,7 +3622,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2294 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2345 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2346 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2546 rhodecode/model/db.py:3139 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2546 rhodecode/model/db.py:3140 msgid "Repository creation disabled with write permission to a repository group" msgstr "" @@ -3597,6 +3644,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2985 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3071 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3077 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3108 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2273 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2265 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2264 @@ -3604,7 +3652,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2268 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2319 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2320 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2520 rhodecode/model/db.py:3108 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2520 rhodecode/model/db.py:3109 msgid "RhodeCode Super Administrator" msgstr "" @@ -3624,6 +3672,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3032 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3118 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3124 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3155 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2311 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2303 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2302 @@ -3631,7 +3680,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2306 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2361 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2362 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2562 rhodecode/model/db.py:3155 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2562 rhodecode/model/db.py:3156 msgid "Inherit object permissions from default user disabled" msgstr "" @@ -3651,6 +3700,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3033 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3119 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3125 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3156 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2312 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2304 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2303 @@ -3658,7 +3708,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2307 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2362 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2363 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2563 rhodecode/model/db.py:3156 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2563 rhodecode/model/db.py:3157 msgid "Inherit object permissions from default user enabled" msgstr "" @@ -3670,6 +3720,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:1137 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:1189 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:1195 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1202 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:910 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:911 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:910 @@ -3677,7 +3728,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:912 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:955 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:956 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1050 rhodecode/model/db.py:1202 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1050 rhodecode/model/db.py:1203 msgid "all" msgstr "" @@ -3689,6 +3740,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:1138 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:1190 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:1196 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1203 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:911 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:912 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:911 @@ -3696,7 +3748,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:913 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:956 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:957 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1051 rhodecode/model/db.py:1203 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1051 rhodecode/model/db.py:1204 msgid "http/web interface" msgstr "" @@ -3708,6 +3760,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:1139 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:1191 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:1197 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1204 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:912 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:913 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:912 @@ -3715,7 +3768,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:914 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:957 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:958 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1052 rhodecode/model/db.py:1204 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1052 rhodecode/model/db.py:1205 msgid "vcs (git/hg/svn protocol)" msgstr "" @@ -3727,6 +3780,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:1140 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:1192 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:1198 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1205 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:913 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:914 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:913 @@ -3734,7 +3788,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:915 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:958 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:959 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1053 rhodecode/model/db.py:1205 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1053 rhodecode/model/db.py:1206 msgid "api calls" msgstr "" @@ -3746,6 +3800,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:1141 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:1193 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:1199 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1206 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:914 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:915 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:914 @@ -3753,7 +3808,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:916 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:959 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:960 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1054 rhodecode/model/db.py:1206 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:1054 rhodecode/model/db.py:1207 msgid "feed access" msgstr "" @@ -3765,6 +3820,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:2638 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:2729 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:2735 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:2766 #: rhodecode/lib/dbmigrate/schema/db_4_3_0_0.py:2051 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_0.py:2043 #: rhodecode/lib/dbmigrate/schema/db_4_4_0_1.py:2042 @@ -3772,7 +3828,7 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_5_0_0.py:2046 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2090 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2091 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2284 rhodecode/model/db.py:2766 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2284 rhodecode/model/db.py:2767 msgid "No parent" msgstr "" @@ -3784,9 +3840,10 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3025 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3111 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3117 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3148 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2354 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2355 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2555 rhodecode/model/db.py:3148 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2555 rhodecode/model/db.py:3149 msgid "Password reset enabled" msgstr "" @@ -3798,9 +3855,10 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3026 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3112 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3118 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3149 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2355 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2356 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2556 rhodecode/model/db.py:3149 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2556 rhodecode/model/db.py:3150 msgid "Password reset hidden" msgstr "" @@ -3812,9 +3870,10 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3027 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3113 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3119 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3150 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_0.py:2356 #: rhodecode/lib/dbmigrate/schema/db_4_7_0_1.py:2357 -#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2557 rhodecode/model/db.py:3150 +#: rhodecode/lib/dbmigrate/schema/db_4_9_0_0.py:2557 rhodecode/model/db.py:3151 msgid "Password reset disabled" msgstr "" @@ -3825,7 +3884,8 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3002 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3088 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3094 -#: rhodecode/model/db.py:3125 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3125 +#: rhodecode/model/db.py:3126 msgid "Branch no permissions" msgstr "" @@ -3836,7 +3896,8 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3003 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3089 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3095 -#: rhodecode/model/db.py:3126 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3126 +#: rhodecode/model/db.py:3127 msgid "Branch access by web merge" msgstr "" @@ -3847,7 +3908,8 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3004 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3090 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3096 -#: rhodecode/model/db.py:3127 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3127 +#: rhodecode/model/db.py:3128 msgid "Branch access by push" msgstr "" @@ -3858,16 +3920,48 @@ msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_18_0_1.py:3005 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:3091 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:3097 -#: rhodecode/model/db.py:3128 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:3128 +#: rhodecode/model/db.py:3129 msgid "Branch access by push with force" msgstr "" #: rhodecode/lib/dbmigrate/schema/db_4_19_0_0.py:1194 #: rhodecode/lib/dbmigrate/schema/db_4_19_0_2.py:1200 -#: rhodecode/model/db.py:1207 +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1207 +#: rhodecode/model/db.py:1208 msgid "artifacts downloads" msgstr "" +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1213 +#: rhodecode/model/db.py:1214 +msgid "Token for all actions." +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1214 +#: rhodecode/model/db.py:1215 +msgid "Token to access RhodeCode pages via web interface without login using `api_access_controllers_whitelist` functionality." +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1216 +#: rhodecode/model/db.py:1217 +msgid "Token to interact over git/hg/svn protocols. Requires auth_token authentication plugin to be active.
Such Token should be used then instead of a password to interact with a repository, and additionally can be limited to single repository using repo scope." +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1221 +#: rhodecode/model/db.py:1222 +msgid "Token limited to api calls." +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1222 +#: rhodecode/model/db.py:1223 +msgid "Token to read RSS/ATOM feed." +msgstr "" + +#: rhodecode/lib/dbmigrate/schema/db_4_20_0_0.py:1223 +#: rhodecode/model/db.py:1224 +msgid "Token for artifacts downloads." +msgstr "" + #: rhodecode/lib/index/whoosh.py:189 msgid "Index Type" msgstr "" @@ -3888,51 +3982,51 @@ msgstr "" msgid "Commit index" msgstr "" -#: rhodecode/lib/vcs/backends/base.py:150 +#: rhodecode/lib/vcs/backends/base.py:186 msgid "This pull request can be automatically merged." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:152 +#: rhodecode/lib/vcs/backends/base.py:188 msgid "This pull request cannot be merged because of an unhandled exception. {exception}" msgstr "" -#: rhodecode/lib/vcs/backends/base.py:155 +#: rhodecode/lib/vcs/backends/base.py:191 msgid "This pull request cannot be merged because of merge conflicts. {unresolved_files}" msgstr "" -#: rhodecode/lib/vcs/backends/base.py:157 +#: rhodecode/lib/vcs/backends/base.py:193 msgid "This pull request could not be merged because push to target:`{target}@{merge_commit}` failed." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:160 +#: rhodecode/lib/vcs/backends/base.py:196 msgid "This pull request cannot be merged because the target `{target_ref.name}` is not a head." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:163 +#: rhodecode/lib/vcs/backends/base.py:199 msgid "This pull request cannot be merged because the source contains more branches than the target." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:166 +#: rhodecode/lib/vcs/backends/base.py:202 msgid "This pull request cannot be merged because the target `{target_ref.name}` has multiple heads: `{heads}`." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:169 +#: 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:173 +#: rhodecode/lib/vcs/backends/base.py:209 msgid "This pull request cannot be merged because the target reference `{target_ref.name}` is missing." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:176 +#: rhodecode/lib/vcs/backends/base.py:212 msgid "This pull request cannot be merged because the source reference `{source_ref.name}` is missing." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:179 +#: rhodecode/lib/vcs/backends/base.py:215 msgid "This pull request cannot be merged because of conflicts related to sub repositories." msgstr "" -#: rhodecode/lib/vcs/backends/base.py:184 +#: rhodecode/lib/vcs/backends/base.py:220 msgid "This pull request cannot be merged because the target or the source reference is missing." msgstr "" @@ -3952,38 +4046,6 @@ msgstr "" msgid "1 month {end_date}" msgstr "" -#: rhodecode/model/comment.py:485 -msgid "made a comment" -msgstr "" - -#: rhodecode/model/comment.py:486 -msgid "Show it now" -msgstr "" - -#: rhodecode/model/db.py:1213 -msgid "Token for all actions." -msgstr "" - -#: rhodecode/model/db.py:1214 -msgid "Token to access RhodeCode pages via web interface without login using `api_access_controllers_whitelist` functionality." -msgstr "" - -#: rhodecode/model/db.py:1216 -msgid "Token to interact over git/hg/svn protocols. Requires auth_token authentication plugin to be active.
Such Token should be used then instead of a password to interact with a repository, and additionally can be limited to single repository using repo scope." -msgstr "" - -#: rhodecode/model/db.py:1221 -msgid "Token limited to api calls." -msgstr "" - -#: rhodecode/model/db.py:1222 -msgid "Token to read RSS/ATOM feed." -msgstr "" - -#: rhodecode/model/db.py:1223 -msgid "Token for artifacts downloads." -msgstr "" - #: rhodecode/model/forms.py:88 msgid "Please enter a login" msgstr "" @@ -4094,8 +4156,8 @@ msgstr "" #: 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:337 -#: rhodecode/templates/changeset/changeset_file_comment.mako:388 +#: rhodecode/templates/changeset/changeset_file_comment.mako:364 +#: rhodecode/templates/changeset/changeset_file_comment.mako:415 #: rhodecode/templates/data_table/_dt_elements.mako:450 msgid "Write" msgstr "" @@ -4123,7 +4185,7 @@ 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:839 +#: rhodecode/templates/base/base.mako:838 msgid "Admin" msgstr "" @@ -4171,103 +4233,103 @@ msgstr "" msgid "Disable password recovery" msgstr "" -#: rhodecode/model/pull_request.py:215 +#: rhodecode/model/pull_request.py:245 msgid "Pull request update successful." msgstr "" -#: rhodecode/model/pull_request.py:217 +#: rhodecode/model/pull_request.py:247 msgid "Pull request update failed because of an unknown error." msgstr "" -#: rhodecode/model/pull_request.py:219 +#: rhodecode/model/pull_request.py:249 msgid "No update needed because the source and target have not changed." msgstr "" -#: rhodecode/model/pull_request.py:221 +#: rhodecode/model/pull_request.py:251 msgid "Pull request cannot be updated because the reference type is not supported for an update. Only Branch, Tag or Bookmark is allowed." msgstr "" -#: rhodecode/model/pull_request.py:224 +#: rhodecode/model/pull_request.py:254 msgid "This pull request cannot be updated because the target reference is missing." msgstr "" -#: rhodecode/model/pull_request.py:227 +#: rhodecode/model/pull_request.py:257 msgid "This pull request cannot be updated because the source reference is missing." msgstr "" -#: rhodecode/model/pull_request.py:1518 +#: rhodecode/model/pull_request.py:1681 msgid "Server-side pull request merging is disabled." msgstr "" -#: rhodecode/model/pull_request.py:1521 +#: rhodecode/model/pull_request.py:1684 msgid "This pull request is closed." msgstr "" -#: rhodecode/model/pull_request.py:1535 +#: rhodecode/model/pull_request.py:1698 msgid "Pull request merging is not supported." msgstr "" -#: rhodecode/model/pull_request.py:1552 +#: rhodecode/model/pull_request.py:1715 msgid "Target repository large files support is disabled." msgstr "" -#: rhodecode/model/pull_request.py:1555 +#: rhodecode/model/pull_request.py:1718 msgid "Source repository large files support is disabled." msgstr "" -#: rhodecode/model/pull_request.py:1739 rhodecode/model/scm.py:1004 +#: rhodecode/model/pull_request.py:1902 rhodecode/model/scm.py:1004 #: rhodecode/templates/admin/my_account/my_account.mako:32 -#: rhodecode/templates/base/base.mako:636 +#: rhodecode/templates/base/base.mako:638 #: rhodecode/templates/summary/components.mako:46 msgid "Bookmarks" msgstr "" -#: rhodecode/model/pull_request.py:1744 +#: rhodecode/model/pull_request.py:1907 msgid "Commit IDs" msgstr "" -#: rhodecode/model/pull_request.py:1747 +#: rhodecode/model/pull_request.py:1910 #: rhodecode/templates/summary/components.mako:22 msgid "Closed Branches" msgstr "" -#: rhodecode/model/pull_request.py:1929 +#: rhodecode/model/pull_request.py:2094 msgid "WIP marker in title prevents from accidental merge." msgstr "" -#: rhodecode/model/pull_request.py:1939 +#: rhodecode/model/pull_request.py:2104 msgid "User `{}` not allowed to perform merge." msgstr "" -#: rhodecode/model/pull_request.py:1957 +#: rhodecode/model/pull_request.py:2122 msgid "Target branch `{}` changes rejected by rule {}." msgstr "" -#: rhodecode/model/pull_request.py:1971 +#: rhodecode/model/pull_request.py:2136 msgid "Pull request reviewer approval is pending." msgstr "" -#: rhodecode/model/pull_request.py:1985 +#: rhodecode/model/pull_request.py:2150 msgid "Cannot merge, {} TODO still not resolved." msgstr "" -#: rhodecode/model/pull_request.py:1988 +#: rhodecode/model/pull_request.py:2153 msgid "Cannot merge, {} TODOs still not resolved." msgstr "" -#: rhodecode/model/pull_request.py:2043 +#: rhodecode/model/pull_request.py:2208 msgid "Merge strategy: rebase" msgstr "" -#: rhodecode/model/pull_request.py:2048 +#: rhodecode/model/pull_request.py:2213 msgid "Merge strategy: explicit merge commit" msgstr "" -#: rhodecode/model/pull_request.py:2056 +#: rhodecode/model/pull_request.py:2221 msgid "Source branch will be closed before the merge." msgstr "" -#: rhodecode/model/pull_request.py:2058 +#: rhodecode/model/pull_request.py:2223 msgid "Source branch will be deleted after the merge." msgstr "" @@ -4613,222 +4675,222 @@ msgid ": , " msgstr "" #: rhodecode/public/js/scripts.js:20822 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:59 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:64 #: rhodecode/public/js/src/plugins/jquery.autocomplete.js:87 msgid "No results" msgstr "" #: rhodecode/public/js/scripts.js:22547 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:161 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:170 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:109 msgid "{0} year" msgstr "" #: rhodecode/public/js/scripts.js:22548 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:149 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:158 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:110 msgid "{0} month" msgstr "" #: rhodecode/public/js/scripts.js:22549 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:144 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:153 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:111 msgid "{0} day" msgstr "" #: rhodecode/public/js/scripts.js:22550 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:146 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:155 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:112 msgid "{0} hour" msgstr "" #: rhodecode/public/js/scripts.js:22551 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:148 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:157 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:113 msgid "{0} min" msgstr "" #: rhodecode/public/js/scripts.js:22552 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:158 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:167 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:114 msgid "{0} sec" msgstr "" #: rhodecode/public/js/scripts.js:22572 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:124 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:133 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:134 msgid "in {0}" msgstr "" #: rhodecode/public/js/scripts.js:22580 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:141 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:150 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:142 msgid "{0} ago" msgstr "" #: rhodecode/public/js/scripts.js:22592 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:163 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:172 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:154 msgid "{0}, {1} ago" msgstr "" #: rhodecode/public/js/scripts.js:22594 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:126 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:135 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:156 msgid "in {0}, {1}" msgstr "" #: rhodecode/public/js/scripts.js:22598 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:142 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:151 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:160 msgid "{0} and {1}" msgstr "" #: rhodecode/public/js/scripts.js:22600 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:143 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:152 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:162 msgid "{0} and {1} ago" msgstr "" #: rhodecode/public/js/scripts.js:22602 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:125 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:134 #: rhodecode/public/js/src/plugins/jquery.timeago-extension.js:164 msgid "in {0} and {1}" msgstr "" #: rhodecode/public/js/scripts.js:37600 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:46 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:51 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:4 msgid "Loading more results..." msgstr "" #: rhodecode/public/js/scripts.js:37603 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:76 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:82 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:7 msgid "Searching..." msgstr "" #: rhodecode/public/js/scripts.js:37606 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:52 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:57 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:10 msgid "No matches found" msgstr "" #: rhodecode/public/js/scripts.js:37609 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:45 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:50 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:13 msgid "Loading failed" msgstr "" #: rhodecode/public/js/scripts.js:37613 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:66 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:72 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:17 msgid "One result is available, press enter to select it." msgstr "" #: rhodecode/public/js/scripts.js:37615 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:157 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:166 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:19 msgid "{0} results are available, use up and down arrow keys to navigate." msgstr "" #: rhodecode/public/js/scripts.js:37620 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:71 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:77 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:24 msgid "Please enter {0} or more character" msgstr "" #: rhodecode/public/js/scripts.js:37622 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:72 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:78 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:26 msgid "Please enter {0} or more characters" msgstr "" #: rhodecode/public/js/scripts.js:37627 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:69 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:75 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:31 msgid "Please delete {0} character" msgstr "" #: rhodecode/public/js/scripts.js:37629 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:70 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:76 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:33 msgid "Please delete {0} characters" msgstr "" #: rhodecode/public/js/scripts.js:37633 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:114 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:123 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:37 msgid "You can only select {0} item" msgstr "" #: rhodecode/public/js/scripts.js:37635 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:115 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:124 #: rhodecode/public/js/rhodecode/i18n/select2/translations.js:39 msgid "You can only select {0} items" msgstr "" -#: rhodecode/public/js/scripts.js:38285 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:7 -#: rhodecode/public/js/src/rhodecode/utils/ajax.js:135 +#: rhodecode/public/js/scripts.js:38289 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:9 +#: rhodecode/public/js/src/rhodecode/utils/ajax.js:139 msgid "Ajax Request Error" msgstr "" -#: rhodecode/public/js/scripts.js:38687 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:133 +#: rhodecode/public/js/scripts.js:38691 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:142 #: rhodecode/public/js/src/rhodecode/changelog.js:35 msgid "showing {0} out of {1} commit" msgstr "" -#: rhodecode/public/js/scripts.js:38689 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:134 +#: rhodecode/public/js/scripts.js:38693 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:143 #: rhodecode/public/js/src/rhodecode/changelog.js:37 msgid "showing {0} out of {1} commits" msgstr "" -#: rhodecode/public/js/scripts.js:39227 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:79 +#: rhodecode/public/js/scripts.js:39232 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:85 #: rhodecode/public/js/src/rhodecode/codemirror.js:363 msgid "Set status to Approved" msgstr "" -#: rhodecode/public/js/scripts.js:39247 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:80 +#: rhodecode/public/js/scripts.js:39252 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:86 #: rhodecode/public/js/src/rhodecode/codemirror.js:383 msgid "Set status to Rejected" msgstr "" -#: rhodecode/public/js/scripts.js:39266 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:99 +#: rhodecode/public/js/scripts.js:39271 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:106 #: rhodecode/public/js/src/rhodecode/codemirror.js:402 msgid "TODO comment" msgstr "" -#: rhodecode/public/js/scripts.js:39286 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:65 +#: rhodecode/public/js/scripts.js:39291 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:71 #: rhodecode/public/js/src/rhodecode/codemirror.js:422 msgid "Note Comment" msgstr "" -#: rhodecode/public/js/scripts.js:39587 rhodecode/public/js/scripts.js:39962 +#: rhodecode/public/js/scripts.js:39592 rhodecode/public/js/scripts.js:39967 #: rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:93 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:99 #: rhodecode/public/js/src/rhodecode/codemirror.js:723 #: rhodecode/public/js/src/rhodecode/comments.js:254 msgid "Status Review" msgstr "" -#: rhodecode/public/js/scripts.js:39602 rhodecode/public/js/scripts.js:39977 +#: rhodecode/public/js/scripts.js:39607 rhodecode/public/js/scripts.js:39982 #: rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:21 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:24 #: rhodecode/public/js/src/rhodecode/codemirror.js:738 #: rhodecode/public/js/src/rhodecode/comments.js:269 msgid "Comment text will be set automatically based on currently selected status ({0}) ..." msgstr "" -#: rhodecode/public/js/scripts.js:39683 rhodecode/public/js/scripts.js:40172 -#: rhodecode/public/js/scripts.js:41495 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:43 +#: rhodecode/public/js/scripts.js:39688 rhodecode/public/js/scripts.js:40177 +#: rhodecode/public/js/scripts.js:41535 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:48 #: rhodecode/public/js/src/rhodecode/codemirror.js:819 #: rhodecode/public/js/src/rhodecode/comments.js:464 #: rhodecode/public/js/src/rhodecode/files.js:499 @@ -4836,263 +4898,270 @@ msgstr "" msgid "Loading ..." msgstr "" -#: rhodecode/public/js/scripts.js:39844 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/scripts.js:39849 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:117 #: rhodecode/public/js/src/rhodecode/comments.js:136 msgid "Updated Comment" msgstr "" -#: rhodecode/public/js/scripts.js:39868 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:132 +#: rhodecode/public/js/scripts.js:39873 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:141 #: rhodecode/public/js/src/rhodecode/comments.js:160 msgid "resolve comment" msgstr "" -#: rhodecode/public/js/scripts.js:40121 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:96 +#: rhodecode/public/js/scripts.js:40126 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:102 #: rhodecode/public/js/src/rhodecode/comments.js:413 msgid "Submitting..." msgstr "" -#: rhodecode/public/js/scripts.js:40403 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:113 -#: rhodecode/public/js/src/rhodecode/comments.js:695 +#: rhodecode/public/js/scripts.js:40423 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:122 +#: rhodecode/public/js/src/rhodecode/comments.js:710 msgid "Yes, delete comment #{0}!" msgstr "" -#: rhodecode/public/js/scripts.js:40458 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:41 -#: rhodecode/public/js/src/rhodecode/comments.js:750 +#: rhodecode/public/js/scripts.js:40487 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:46 +#: rhodecode/public/js/src/rhodecode/comments.js:774 msgid "Leave a resolution comment, or click resolve button to resolve TODO comment #{0}" msgstr "" -#: rhodecode/public/js/scripts.js:40667 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/src/rhodecode/comments.js:959 +#: rhodecode/public/js/scripts.js:40696 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:23 +#: rhodecode/public/js/src/rhodecode/comments.js:983 msgid "Comment body was not changed." msgstr "" -#: rhodecode/public/js/scripts.js:40840 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:39 -#: rhodecode/public/js/src/rhodecode/comments.js:1132 +#: rhodecode/public/js/scripts.js:40875 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:44 +#: rhodecode/public/js/src/rhodecode/comments.js:1162 msgid "Leave a comment on line {0}." msgstr "" -#: rhodecode/public/js/scripts.js:40966 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:100 -#: rhodecode/public/js/src/rhodecode/comments.js:1258 +#: rhodecode/public/js/scripts.js:41006 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:107 +#: rhodecode/public/js/src/rhodecode/comments.js:1293 msgid "TODO from comment {0} was fixed." msgstr "" -#: rhodecode/public/js/scripts.js:41244 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:136 +#: rhodecode/public/js/scripts.js:41284 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:145 #: rhodecode/public/js/src/rhodecode/files.js:248 msgid "truncated result" msgstr "" -#: rhodecode/public/js/scripts.js:41246 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:137 +#: rhodecode/public/js/scripts.js:41286 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:146 #: rhodecode/public/js/src/rhodecode/files.js:250 msgid "truncated results" msgstr "" -#: rhodecode/public/js/scripts.js:41255 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:53 +#: rhodecode/public/js/scripts.js:41295 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:58 #: rhodecode/public/js/src/rhodecode/files.js:259 msgid "No matching files" msgstr "" -#: rhodecode/public/js/scripts.js:41313 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:77 +#: rhodecode/public/js/scripts.js:41353 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:83 #: rhodecode/public/js/src/rhodecode/files.js:317 msgid "Selection link" msgstr "" -#: rhodecode/public/js/scripts.js:41410 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:8 +#: rhodecode/public/js/scripts.js:41450 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:41560 rhodecode/public/js/scripts.js:41563 +#: rhodecode/public/js/scripts.js:41600 rhodecode/public/js/scripts.js:41603 #: rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:33 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:38 #: rhodecode/public/js/src/rhodecode/files.js:564 #: rhodecode/public/js/src/rhodecode/files.js:567 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:41566 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:103 +#: rhodecode/public/js/scripts.js:41606 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:111 #: rhodecode/public/js/src/rhodecode/files.js:570 msgid "There is an existing path `{0}` at this commit." msgstr "" -#: rhodecode/public/js/scripts.js:41569 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:102 +#: rhodecode/public/js/scripts.js:41609 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:110 #: 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:41623 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:95 +#: rhodecode/public/js/scripts.js:41663 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:101 #: rhodecode/public/js/src/rhodecode/followers.js:26 msgid "Stopped watching this repository" msgstr "" -#: rhodecode/public/js/scripts.js:41624 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:112 +#: rhodecode/public/js/scripts.js:41664 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:121 #: rhodecode/public/js/src/rhodecode/followers.js:27 -#: rhodecode/templates/base/base.mako:308 +#: rhodecode/templates/base/base.mako:310 msgid "Watch" msgstr "" -#: rhodecode/public/js/scripts.js:41627 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:92 +#: rhodecode/public/js/scripts.js:41667 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:98 #: rhodecode/public/js/src/rhodecode/followers.js:30 msgid "Started watching this repository" msgstr "" -#: rhodecode/public/js/scripts.js:41628 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:108 +#: rhodecode/public/js/scripts.js:41668 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:116 #: rhodecode/public/js/src/rhodecode/followers.js:31 -#: rhodecode/templates/base/base.mako:306 +#: rhodecode/templates/base/base.mako:308 msgid "Unwatch" msgstr "" -#: rhodecode/public/js/scripts.js:42010 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:10 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:143 +#: rhodecode/public/js/scripts.js:42165 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:12 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:186 msgid "All reviewers must vote." msgstr "" -#: rhodecode/public/js/scripts.js:42019 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:9 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:152 +#: rhodecode/public/js/scripts.js:42174 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:11 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:195 msgid "All individual reviewers must vote." msgstr "" -#: rhodecode/public/js/scripts.js:42024 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:12 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:157 +#: rhodecode/public/js/scripts.js:42179 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:14 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:200 msgid "At least {0} reviewer must vote." msgstr "" -#: rhodecode/public/js/scripts.js:42030 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:13 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:163 +#: rhodecode/public/js/scripts.js:42185 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:15 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:206 msgid "At least {0} reviewers must vote." msgstr "" -#: rhodecode/public/js/scripts.js:42046 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:74 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:179 +#: rhodecode/public/js/scripts.js:42201 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:80 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:222 msgid "Reviewers picked from source code changes." msgstr "" -#: rhodecode/public/js/scripts.js:42053 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:6 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:186 +#: rhodecode/public/js/scripts.js:42209 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:8 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:230 msgid "Adding new reviewers is forbidden." msgstr "" -#: rhodecode/public/js/scripts.js:42060 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:15 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:193 +#: rhodecode/public/js/scripts.js:42217 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:17 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:238 msgid "Author is not allowed to be a reviewer." msgstr "" -#: rhodecode/public/js/scripts.js:42074 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:22 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:207 +#: rhodecode/public/js/scripts.js:42231 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:25 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:252 msgid "Commit Authors are not allowed to be a reviewer." msgstr "" -#: rhodecode/public/js/scripts.js:42096 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:44 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:229 +#: rhodecode/public/js/scripts.js:42238 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:65 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:259 +msgid "No review rules set." +msgstr "" + +#: rhodecode/public/js/scripts.js:42283 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:49 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:304 msgid "Loading diff ..." msgstr "" -#: rhodecode/public/js/scripts.js:42135 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:130 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:268 -msgid "no commits" -msgstr "" - -#: rhodecode/public/js/scripts.js:42206 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:111 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:339 +#: rhodecode/public/js/scripts.js:42336 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:109 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:357 +msgid "There are no commits to merge." +msgstr "" + +#: rhodecode/public/js/scripts.js:42408 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:120 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:429 msgid "User `{0}` not allowed to be a reviewer" msgstr "" -#: rhodecode/public/js/scripts.js:42212 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:110 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:345 -msgid "User `{0}` already in reviewers" -msgstr "" - -#: rhodecode/public/js/scripts.js:42315 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:117 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:448 +#: rhodecode/public/js/scripts.js:42414 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:435 +msgid "User `{0}` already in reviewers/observers" +msgstr "" + +#: rhodecode/public/js/scripts.js:42528 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:126 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:549 msgid "added manually by \"{0}\"" msgstr "" -#: rhodecode/public/js/scripts.js:42319 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:129 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:452 +#: rhodecode/public/js/scripts.js:42533 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:138 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:554 msgid "member of \"{0}\"" msgstr "" -#: rhodecode/public/js/scripts.js:42510 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:109 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:643 +#: rhodecode/public/js/scripts.js:42766 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:118 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:787 msgid "Updating..." msgstr "" -#: rhodecode/public/js/scripts.js:42520 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:35 -#: rhodecode/public/js/src/rhodecode/pullrequests.js:653 +#: rhodecode/public/js/scripts.js:42776 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:40 +#: rhodecode/public/js/src/rhodecode/pullrequests.js:797 msgid "Force updating..." msgstr "" -#: rhodecode/public/js/scripts.js:46968 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:88 +#: rhodecode/public/js/scripts.js:47613 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:94 #: rhodecode/public/js/src/rhodecode/users.js:54 msgid "Show this authentication token?" msgstr "" -#: rhodecode/public/js/scripts.js:46970 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:81 +#: rhodecode/public/js/scripts.js:47615 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:87 #: rhodecode/public/js/src/rhodecode/users.js:56 msgid "Show" msgstr "" -#: rhodecode/public/js/scripts.js:47006 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:14 +#: rhodecode/public/js/scripts.js:47651 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:47195 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:121 +#: rhodecode/public/js/scripts.js:47840 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:130 #: rhodecode/public/js/src/rhodecode.js:144 msgid "file" msgstr "" -#: rhodecode/public/js/scripts.js:47339 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:47 +#: rhodecode/public/js/scripts.js:47984 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:52 #: rhodecode/public/js/src/rhodecode.js:288 msgid "Loading..." msgstr "" -#: rhodecode/public/js/scripts.js:47712 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:118 -#: rhodecode/public/js/src/rhodecode.js:661 +#: rhodecode/public/js/scripts.js:48366 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:127 +#: rhodecode/public/js/src/rhodecode.js:670 msgid "date not in future" msgstr "" -#: rhodecode/public/js/scripts.js:47720 rhodecode/public/js/scripts.min.js:1 -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:90 -#: rhodecode/public/js/src/rhodecode.js:669 +#: rhodecode/public/js/scripts.js:48374 rhodecode/public/js/scripts.min.js:1 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:96 +#: rhodecode/public/js/src/rhodecode.js:678 msgid "Specified expiration date" msgstr "" @@ -5113,339 +5182,370 @@ msgid "(from usergroup {0})" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:3 -msgid "{0} file changed, " +msgid ", and {0} file changed." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:4 -msgid "{0} files changed, " +msgid ", and {0} files changed." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:5 -#: rhodecode/templates/codeblocks/diffs.mako:618 -#: rhodecode/templates/codeblocks/diffs.mako:622 +msgid "{0} file changed, " +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:6 +msgid "{0} files changed, " +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:7 +#: rhodecode/templates/codeblocks/diffs.mako:648 +#: rhodecode/templates/codeblocks/diffs.mako:652 msgid "Add another comment" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:11 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:13 msgid "Are you sure to close this pull request without merging?" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:16 -msgid "Changed files" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:17 -#: rhodecode/public/js/src/i18n_messages.js:5 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:288 -msgid "Close" -msgstr "" - #: rhodecode/public/js/rhodecode/i18n/js_translations.js:18 -#: rhodecode/templates/codeblocks/diffs.mako:131 -msgid "Collapse all files" +msgid "Changed files" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:19 -msgid "Collapse {0} commit" +#: rhodecode/public/js/src/i18n_messages.js:5 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:589 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:592 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:646 +msgid "Close" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:20 +#: rhodecode/templates/codeblocks/diffs.mako:133 +msgid "Collapse all files" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:21 +msgid "Collapse {0} commit" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:22 msgid "Collapse {0} commits" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:23 -msgid "Context file: " -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:25 -msgid "Delete this comment?" -msgstr "" - #: rhodecode/public/js/rhodecode/i18n/js_translations.js:26 -msgid "Diff to Commit " +msgid "Compare summary: {0} commit" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:27 -msgid "Error during search operation" +msgid "Compare summary: {0} commits" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:28 -#: rhodecode/templates/codeblocks/diffs.mako:129 -msgid "Expand all files" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:29 -msgid "Expand {0} commit" +msgid "Context file: " msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:30 -msgid "Expand {0} commits" +msgid "Delete this comment?" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:31 -msgid "Fetching repository state failed. Error code: {0} {1}. Try refreshing this page." +msgid "Diff to Commit " msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:32 -msgid "Fetching repository state failed. Error code: {0} {1}. Try refreshing this page." +msgid "Error during search operation" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:33 +#: rhodecode/templates/codeblocks/diffs.mako:131 +msgid "Expand all files" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:34 -msgid "Follow" +msgid "Expand {0} commit" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:35 +msgid "Expand {0} commits" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:36 -msgid "Hide full context diff" +msgid "Fetching repository state failed. Error code: {0} {1}. Try refreshing this page." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:37 +msgid "Fetching repository state failed. Error code: {0} {1}. Try refreshing this page." +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:39 +msgid "Follow" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:41 +msgid "Hide full context diff" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:42 msgid "Hide whitespace changes" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:38 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:43 #: rhodecode/public/js/src/i18n_messages.js:4 msgid "Invite reviewers to this discussion" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:40 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:45 msgid "Leave a comment, or click resolve button to resolve TODO comment #{0}" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:48 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:53 msgid "No bookmarks available yet." msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:49 -msgid "No branches available yet." -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:50 -msgid "No forks available yet." -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:51 -msgid "No gists available yet." -msgstr "" - #: rhodecode/public/js/rhodecode/i18n/js_translations.js:54 -msgid "No pull requests available yet." +msgid "No branches available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:55 -msgid "No repositories available yet." +msgid "No forks available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:56 -msgid "No repositories present." -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:57 -msgid "No repository groups available yet." -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:58 -msgid "No repository groups present." +msgid "No gists available yet." +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:59 +msgid "No pull requests available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:60 -msgid "No ssh keys available yet." +msgid "No repositories available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:61 -msgid "No tags available yet." +msgid "No repositories present." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:62 -msgid "No user groups available yet." +msgid "No repository groups available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:63 -msgid "No users available yet." +msgid "No repository groups present." +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:66 +msgid "No ssh keys available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:67 -#: rhodecode/templates/commits/changelog.mako:78 -msgid "Open new pull request" +msgid "No tags available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:68 -msgid "Open new pull request for selected commit" +msgid "No user groups available yet." +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:69 +msgid "No users available yet." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:73 +#: rhodecode/templates/commits/changelog.mako:78 +msgid "Open new pull request" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:74 +msgid "Open new pull request for selected commit" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:79 msgid "Please wait creating pull request..." msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:75 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:81 msgid "Saving..." msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:78 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:84 #: rhodecode/public/js/src/i18n_messages.js:6 #: rhodecode/templates/admin/settings/settings_email.mako:50 msgid "Send" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:82 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:88 msgid "Show at Commit " msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:83 -msgid "Show commit range {0} ... {1}" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:84 -msgid "Show full context diff" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:85 -#: rhodecode/templates/admin/settings/settings_exceptions_browse.mako:40 -msgid "Show more" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:86 -msgid "Show selected commit __S" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:87 -msgid "Show selected commits __S ... __E" -msgstr "" - #: rhodecode/public/js/rhodecode/i18n/js_translations.js:89 -msgid "Show whitespace changes" +msgid "Show commit range {0} ... {1}" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:90 +msgid "Show full context diff" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:91 -msgid "Start following this repository" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:94 -msgid "Stop following this repository" +#: rhodecode/templates/admin/settings/settings_exceptions_browse.mako:40 +msgid "Show more" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:92 +msgid "Show selected commit __S" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:93 +msgid "Show selected commits __S ... __E" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:95 +msgid "Show whitespace changes" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:97 -#: rhodecode/public/js/src/i18n_messages.js:7 -msgid "Switch to chat" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:98 -#: rhodecode/public/js/src/i18n_messages.js:8 -msgid "Switch to comment" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:101 -msgid "There are currently no open pull requests requiring your participation." +msgid "Start following this repository" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:100 +msgid "Stop following this repository" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:103 +msgid "Switch target repository with the source." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:104 -msgid "This pull requests will consist of {0} commit." +#: rhodecode/public/js/src/i18n_messages.js:7 +msgid "Switch to chat" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:105 +#: rhodecode/public/js/src/i18n_messages.js:8 +msgid "Switch to comment" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:108 +msgid "There are currently no open pull requests requiring your participation." +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:112 +msgid "This pull requests will consist of {0} commit." +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:113 msgid "This pull requests will consist of {0} commits." msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:106 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:114 msgid "Toggle Wide Mode diff" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:107 +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:115 msgid "Unfollow" msgstr "" -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:116 -#: rhodecode/templates/admin/auth/auth_settings.mako:69 -msgid "activated" -msgstr "" - #: rhodecode/public/js/rhodecode/i18n/js_translations.js:119 -msgid "disabled" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:120 -msgid "enabled" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:122 -msgid "files" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:123 -msgid "go to numeric commit" +msgid "User `{0}` already in reviewers" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:125 +#: rhodecode/templates/admin/auth/auth_settings.mako:69 +msgid "activated" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:128 -#: rhodecode/templates/index_base.mako:27 -#: rhodecode/templates/pullrequests/pullrequest.mako:136 -msgid "loading..." +msgid "disabled" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:129 +msgid "enabled" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:131 -#: rhodecode/templates/admin/auth/auth_settings.mako:69 -msgid "not active" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:135 -msgid "specify commit" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:138 -msgid "{0} ({1} inactive) of {2} user groups ({3} inactive)" +msgid "files" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:132 +msgid "go to numeric commit" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:137 +#: rhodecode/templates/index_base.mako:27 +#: rhodecode/templates/pullrequests/pullrequest.mako:154 +#: rhodecode/templates/pullrequests/pullrequest.mako:178 +msgid "loading..." msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:139 -msgid "{0} ({1} inactive) of {2} users ({3} inactive)" +msgid "no commits" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:140 -msgid "{0} active out of {1} users" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:145 -msgid "{0} days" +#: rhodecode/templates/admin/auth/auth_settings.mako:69 +msgid "not active" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:144 +msgid "specify commit" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:147 -msgid "{0} hours" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:150 -msgid "{0} months" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:151 -msgid "{0} of {1} repositories" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:152 -msgid "{0} of {1} repository groups" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:153 -msgid "{0} out of {1} ssh keys" +msgid "{0} ({1} inactive) of {2} user groups ({3} inactive)" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:148 +msgid "{0} ({1} inactive) of {2} users ({3} inactive)" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:149 +msgid "{0} active out of {1} users" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:154 -msgid "{0} out of {1} users" -msgstr "" - -#: rhodecode/public/js/rhodecode/i18n/js_translations.js:155 -msgid "{0} repositories" +msgid "{0} days" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:156 -msgid "{0} repository groups" +msgid "{0} hours" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:159 -msgid "{0} user groups ({1} inactive)" +msgid "{0} months" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:160 -msgid "{0} users ({1} inactive)" +msgid "{0} of {1} repositories" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:161 +msgid "{0} of {1} repository groups" msgstr "" #: rhodecode/public/js/rhodecode/i18n/js_translations.js:162 +msgid "{0} out of {1} ssh keys" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:163 +msgid "{0} out of {1} users" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:164 +msgid "{0} repositories" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:165 +msgid "{0} repository groups" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:168 +msgid "{0} user groups ({1} inactive)" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:169 +msgid "{0} users ({1} inactive)" +msgstr "" + +#: rhodecode/public/js/rhodecode/i18n/js_translations.js:171 msgid "{0} years" msgstr "" @@ -5479,10 +5579,10 @@ msgstr "" #: rhodecode/templates/admin/users/user_edit_groups.mako:57 #: rhodecode/templates/base/perms_summary.mako:173 #: rhodecode/templates/base/perms_summary.mako:247 -#: rhodecode/templates/bookmarks/bookmarks.mako:57 -#: rhodecode/templates/branches/branches.mako:56 +#: rhodecode/templates/bookmarks/bookmarks.mako:69 +#: rhodecode/templates/branches/branches.mako:68 #: rhodecode/templates/files/files_browser_tree.mako:16 -#: rhodecode/templates/tags/tags.mako:57 +#: rhodecode/templates/tags/tags.mako:69 msgid "Name" msgstr "" @@ -5513,16 +5613,16 @@ msgstr "" #: rhodecode/templates/admin/users/user_edit_profile.mako:74 #: rhodecode/templates/admin/users/user_edit_ssh_keys.mako:15 #: rhodecode/templates/admin/users/user_edit_ssh_keys.mako:57 -#: rhodecode/templates/base/issue_tracker_settings.mako:78 +#: rhodecode/templates/base/issue_tracker_settings.mako:79 #: rhodecode/templates/compare/compare_commits.mako:19 -#: rhodecode/templates/email_templates/pull_request_review.mako:45 -#: rhodecode/templates/email_templates/pull_request_review.mako:126 +#: rhodecode/templates/email_templates/pull_request_review.mako:49 +#: rhodecode/templates/email_templates/pull_request_review.mako:134 #: rhodecode/templates/email_templates/pull_request_update.mako:45 #: rhodecode/templates/email_templates/pull_request_update.mako:139 #: rhodecode/templates/forks/fork.mako:56 #: rhodecode/templates/forks/forks.mako:62 -#: rhodecode/templates/pullrequests/pullrequest.mako:50 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:560 +#: rhodecode/templates/pullrequests/pullrequest.mako:104 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:400 #: rhodecode/templates/summary/components.mako:159 #: rhodecode/templates/user_group/profile.mako:25 #: rhodecode/templates/users/user_profile.mako:59 @@ -5557,19 +5657,18 @@ msgstr "" #: rhodecode/templates/index_base.mako:190 #: rhodecode/templates/admin/repos/repos.mako:98 -#: rhodecode/templates/bookmarks/bookmarks.mako:64 -#: rhodecode/templates/branches/branches.mako:63 +#: rhodecode/templates/bookmarks/bookmarks.mako:76 +#: rhodecode/templates/branches/branches.mako:75 #: rhodecode/templates/compare/compare_commits.mako:17 #: rhodecode/templates/email_templates/commit_comment.mako:60 #: rhodecode/templates/email_templates/commit_comment.mako:114 #: rhodecode/templates/email_templates/commit_comment.mako:141 #: rhodecode/templates/files/file_authors_box.mako:28 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:558 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:398 #: rhodecode/templates/search/search_commit.mako:9 #: rhodecode/templates/summary/components.mako:117 #: rhodecode/templates/summary/components.mako:125 -#: rhodecode/templates/summary/summary_commits.mako:8 -#: rhodecode/templates/tags/tags.mako:64 +#: rhodecode/templates/tags/tags.mako:76 msgid "Commit" msgstr "" @@ -5579,8 +5678,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 "" @@ -5618,7 +5717,7 @@ msgid "Please contact " msgstr "" #: rhodecode/templates/login.mako:84 rhodecode/templates/password_reset.mako:39 -#: rhodecode/templates/base/base.mako:61 +#: rhodecode/templates/base/base.mako:63 msgid "Support" msgstr "" @@ -5732,9 +5831,9 @@ msgstr "" #: rhodecode/templates/admin/admin_audit_log_entry.mako:46 #: rhodecode/templates/admin/admin_log_base.mako:11 -#: rhodecode/templates/bookmarks/bookmarks.mako:59 -#: rhodecode/templates/branches/branches.mako:58 -#: rhodecode/templates/tags/tags.mako:59 +#: rhodecode/templates/bookmarks/bookmarks.mako:71 +#: rhodecode/templates/branches/branches.mako:70 +#: rhodecode/templates/tags/tags.mako:71 msgid "Date" msgstr "" @@ -5775,16 +5874,16 @@ 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:656 #: rhodecode/templates/base/base.mako:658 #: rhodecode/templates/base/base.mako:660 +#: rhodecode/templates/base/base.mako:662 #: rhodecode/templates/search/search_commit.mako:8 #: rhodecode/templates/search/search_path.mako:7 msgid "Repository" msgstr "" #: rhodecode/templates/admin/admin_audit_logs.mako:5 -#: rhodecode/templates/base/base.mako:111 +#: rhodecode/templates/base/base.mako:113 msgid "Admin audit logs" msgstr "" @@ -5891,7 +5990,7 @@ msgid "Plugin Name" msgstr "" #: rhodecode/templates/admin/auth/auth_settings.mako:62 -#: rhodecode/templates/base/base.mako:62 +#: rhodecode/templates/base/base.mako:64 msgid "Documentation" msgstr "" @@ -6008,10 +6107,10 @@ msgid "Update Gist" msgstr "" #: rhodecode/templates/admin/gists/gist_edit.mako:100 -#: rhodecode/templates/base/issue_tracker_settings.mako:150 -#: rhodecode/templates/changeset/changeset_file_comment.mako:460 -#: rhodecode/templates/codeblocks/diffs.mako:88 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:75 +#: rhodecode/templates/base/issue_tracker_settings.mako:151 +#: rhodecode/templates/changeset/changeset_file_comment.mako:487 +#: rhodecode/templates/codeblocks/diffs.mako:90 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:84 msgid "Cancel" msgstr "" @@ -6065,26 +6164,26 @@ msgstr "" #: rhodecode/templates/admin/repos/repos.mako:25 #: rhodecode/templates/admin/user_groups/user_groups.mako:25 #: rhodecode/templates/admin/users/users.mako:26 -#: rhodecode/templates/bookmarks/bookmarks.mako:33 -#: rhodecode/templates/branches/branches.mako:33 +#: rhodecode/templates/bookmarks/bookmarks.mako:39 +#: rhodecode/templates/branches/branches.mako:39 #: rhodecode/templates/journal/journal.mako:12 #: rhodecode/templates/pullrequests/pullrequests.mako:53 -#: rhodecode/templates/tags/tags.mako:33 +#: rhodecode/templates/tags/tags.mako:39 msgid "quick filter..." msgstr "" #: rhodecode/templates/admin/gists/gist_index.mako:103 -#: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:91 -#: rhodecode/templates/bookmarks/bookmarks.mako:61 -#: rhodecode/templates/branches/branches.mako:60 +#: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:85 +#: rhodecode/templates/bookmarks/bookmarks.mako:73 +#: rhodecode/templates/branches/branches.mako:72 #: rhodecode/templates/commits/changelog.mako:119 #: rhodecode/templates/compare/compare_commits.mako:16 #: rhodecode/templates/files/files_browser_tree.mako:20 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:557 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:397 #: rhodecode/templates/pullrequests/pullrequests.mako:98 #: rhodecode/templates/search/search_commit.mako:18 #: rhodecode/templates/summary/summary_commits.mako:11 -#: rhodecode/templates/tags/tags.mako:61 +#: rhodecode/templates/tags/tags.mako:73 msgid "Author" msgstr "" @@ -6096,7 +6195,7 @@ msgstr "" #: rhodecode/templates/admin/user_groups/user_group_edit_advanced.mako:7 #: rhodecode/templates/admin/users/user_edit_advanced.mako:6 #: rhodecode/templates/admin/users/user_edit_ssh_keys.mako:16 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:51 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:60 msgid "Created on" msgstr "" @@ -6105,7 +6204,7 @@ msgid "Expires" msgstr "" #: rhodecode/templates/admin/gists/gist_new.mako:5 -#: rhodecode/templates/base/base.mako:575 +#: rhodecode/templates/base/base.mako:577 msgid "New Gist" msgstr "" @@ -6197,7 +6296,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:118 +#: rhodecode/templates/base/base.mako:120 msgid "Integrations" msgstr "" @@ -6212,7 +6311,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:120 +#: rhodecode/templates/base/base.mako:122 msgid "Settings" msgstr "" @@ -6313,7 +6412,7 @@ msgid "No description available" msgstr "" #: rhodecode/templates/admin/my_account/my_account.mako:5 -#: rhodecode/templates/base/base.mako:620 +#: rhodecode/templates/base/base.mako:622 msgid "My account" msgstr "" @@ -6364,15 +6463,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:383 -#: rhodecode/templates/base/base.mako:624 +#: rhodecode/templates/base/base.mako:385 +#: rhodecode/templates/base/base.mako:626 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:116 +#: rhodecode/templates/base/base.mako:118 msgid "Permissions" msgstr "" @@ -6592,27 +6691,27 @@ msgstr "" msgid "Pull Requests You Participate In" msgstr "" -#: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:67 -msgid "Target Repo" +#: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:73 +#: rhodecode/templates/pullrequests/pullrequests.mako:94 +msgid "Id" msgstr "" #: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:79 -#: rhodecode/templates/pullrequests/pullrequests.mako:94 -msgid "Id" -msgstr "" - -#: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:85 #: rhodecode/templates/admin/settings/settings_global.mako:9 -#: rhodecode/templates/email_templates/pull_request_review.mako:43 +#: rhodecode/templates/email_templates/pull_request_review.mako:47 #: rhodecode/templates/email_templates/pull_request_update.mako:43 -#: rhodecode/templates/pullrequests/pullrequest.mako:38 +#: rhodecode/templates/pullrequests/pullrequest.mako:91 #: rhodecode/templates/pullrequests/pullrequests.mako:96 msgid "Title" msgstr "" +#: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:97 +#: rhodecode/templates/pullrequests/pullrequests.mako:102 +msgid "Last Update" +msgstr "" + #: rhodecode/templates/admin/my_account/my_account_pullrequests.mako:103 -#: rhodecode/templates/pullrequests/pullrequests.mako:102 -msgid "Last Update" +msgid "Target Repo" msgstr "" #: rhodecode/templates/admin/my_account/my_account_repos.mako:3 @@ -6717,8 +6816,10 @@ msgid "Unread" msgstr "" #: rhodecode/templates/admin/notifications/notifications_show_all.mako:41 -#: rhodecode/templates/changeset/changeset.mako:172 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:670 +#: rhodecode/templates/changeset/changeset.mako:254 +#: rhodecode/templates/changeset/changeset.mako:264 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:729 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:739 msgid "Comments" msgstr "" @@ -6798,6 +6899,7 @@ msgstr "" #: rhodecode/templates/admin/repos/repo_edit_reviewers.mako:6 #: rhodecode/templates/admin/settings/settings_automation.mako:6 #: rhodecode/templates/artifacts/artifact_list.mako:24 +#: rhodecode/templates/pullrequests/pullrequest.mako:197 msgid "This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license." msgstr "" @@ -6887,8 +6989,8 @@ 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:113 -#: rhodecode/templates/base/base.mako:134 +#: rhodecode/templates/base/base.mako:115 +#: rhodecode/templates/base/base.mako:136 msgid "Repository groups" msgstr "" @@ -6903,7 +7005,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:669 +#: rhodecode/templates/base/base.mako:671 #: rhodecode/templates/data_table/_dt_elements.mako:217 #: rhodecode/templates/forks/fork.mako:41 msgid "Repository group" @@ -7153,7 +7255,7 @@ msgid "Import Existing Repository ?" msgstr "" #: rhodecode/templates/admin/repos/repo_add_base.mako:23 -#: rhodecode/templates/base/base.mako:330 +#: rhodecode/templates/base/base.mako:332 msgid "Clone from" msgstr "" @@ -7538,13 +7640,13 @@ msgid "Inherited Issue Tracker Patterns" msgstr "" #: rhodecode/templates/admin/repos/repo_edit_issuetracker.mako:31 -#: rhodecode/templates/base/issue_tracker_settings.mako:79 +#: rhodecode/templates/base/issue_tracker_settings.mako:80 #: rhodecode/templates/base/perms_summary.mako:174 msgid "Pattern" msgstr "" #: rhodecode/templates/admin/repos/repo_edit_issuetracker.mako:32 -#: rhodecode/templates/base/issue_tracker_settings.mako:80 +#: rhodecode/templates/base/issue_tracker_settings.mako:81 msgid "Url" msgstr "" @@ -7608,11 +7710,11 @@ msgid "un-set private mode" msgstr "" #: rhodecode/templates/admin/repos/repo_edit_permissions.mako:109 -msgid "used by {} branch rule, requires write+ permissions" +msgid "used by {} branch rule, requires write or higher permissions" msgstr "" #: rhodecode/templates/admin/repos/repo_edit_permissions.mako:111 -msgid "used by {} branch rules, requires write+ permissions" +msgid "used by {} branch rules, requires write or higher permissions" msgstr "" #: rhodecode/templates/admin/repos/repo_edit_permissions.mako:125 @@ -8422,8 +8524,8 @@ 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:115 -#: rhodecode/templates/base/base.mako:137 +#: rhodecode/templates/base/base.mako:117 +#: rhodecode/templates/base/base.mako:139 msgid "User groups" msgstr "" @@ -8555,7 +8657,7 @@ msgstr "" #: rhodecode/templates/admin/users/user_add.mako:13 #: rhodecode/templates/admin/users/user_edit.mako:14 -#: rhodecode/templates/base/base.mako:114 +#: rhodecode/templates/base/base.mako:116 msgid "Users" msgstr "" @@ -8919,69 +9021,69 @@ msgstr "" msgid "{} Artifacts" msgstr "" -#: rhodecode/templates/base/base.mako:71 +#: rhodecode/templates/base/base.mako:73 msgid "RhodeCode instance id: {}" msgstr "" -#: rhodecode/templates/base/base.mako:99 -msgid "Super-admin Panel" -msgstr "" - #: rhodecode/templates/base/base.mako:101 +msgid "Super-admin Panel" +msgstr "" + +#: rhodecode/templates/base/base.mako:103 msgid "Delegated Admin Panel" msgstr "" -#: rhodecode/templates/base/base.mako:117 -msgid "Authentication" -msgstr "" - #: rhodecode/templates/base/base.mako:119 +msgid "Authentication" +msgstr "" + +#: rhodecode/templates/base/base.mako:121 msgid "Defaults" msgstr "" -#: rhodecode/templates/base/base.mako:159 -#: rhodecode/templates/base/base.mako:199 -#: rhodecode/templates/changeset/changeset.mako:154 +#: rhodecode/templates/base/base.mako:161 +#: rhodecode/templates/base/base.mako:201 +#: rhodecode/templates/changeset/changeset.mako:142 #: rhodecode/templates/files/files_source_header.mako:57 #: rhodecode/templates/files/files_tree_header.mako:44 #: rhodecode/templates/summary/components.mako:275 msgid "Show More" msgstr "" -#: rhodecode/templates/base/base.mako:302 -#: rhodecode/templates/base/base.mako:313 +#: rhodecode/templates/base/base.mako:304 +#: rhodecode/templates/base/base.mako:315 msgid "RSS Feed" msgstr "" -#: rhodecode/templates/base/base.mako:304 +#: rhodecode/templates/base/base.mako:306 msgid "Watch this Repository and actions on it in your personalized journal" msgstr "" -#: rhodecode/templates/base/base.mako:322 +#: rhodecode/templates/base/base.mako:324 msgid "Fork of" msgstr "" -#: rhodecode/templates/base/base.mako:339 +#: rhodecode/templates/base/base.mako:341 #, python-format msgid "Repository locked by %(user)s" msgstr "" -#: rhodecode/templates/base/base.mako:344 +#: rhodecode/templates/base/base.mako:346 msgid "Repository not locked. Pull repository to lock it." msgstr "" -#: rhodecode/templates/base/base.mako:360 +#: rhodecode/templates/base/base.mako:362 msgid "This repository has been archived. It is now read-only." msgstr "" -#: rhodecode/templates/base/base.mako:373 +#: rhodecode/templates/base/base.mako:375 #: 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:374 +#: rhodecode/templates/base/base.mako:376 #: rhodecode/templates/data_table/_dt_elements.mako:63 #: rhodecode/templates/data_table/_dt_elements.mako:64 #: rhodecode/templates/files/file_authors_box.mako:30 @@ -8991,7 +9093,7 @@ msgstr "" msgid "Commits" msgstr "" -#: rhodecode/templates/base/base.mako:375 +#: rhodecode/templates/base/base.mako:377 #: rhodecode/templates/data_table/_dt_elements.mako:68 #: rhodecode/templates/data_table/_dt_elements.mako:69 #: rhodecode/templates/files/files.mako:15 @@ -8999,87 +9101,87 @@ msgstr "" msgid "Files" msgstr "" -#: rhodecode/templates/base/base.mako:376 -#: rhodecode/templates/bookmarks/bookmarks.mako:66 -#: rhodecode/templates/branches/branches.mako:65 -#: rhodecode/templates/tags/tags.mako:66 +#: rhodecode/templates/base/base.mako:378 +#: 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:381 +#: rhodecode/templates/base/base.mako:383 #, python-format msgid "Show Pull Requests for %s" msgstr "" -#: rhodecode/templates/base/base.mako:392 +#: rhodecode/templates/base/base.mako:394 msgid "Artifacts" msgstr "" -#: rhodecode/templates/base/base.mako:398 +#: rhodecode/templates/base/base.mako:400 msgid "Repository Settings" msgstr "" -#: rhodecode/templates/base/base.mako:404 +#: rhodecode/templates/base/base.mako:406 msgid "Options" msgstr "" -#: rhodecode/templates/base/base.mako:409 -msgid "Unlock Repository" -msgstr "" - #: rhodecode/templates/base/base.mako:411 +msgid "Unlock Repository" +msgstr "" + +#: rhodecode/templates/base/base.mako:413 msgid "Lock Repository" msgstr "" -#: rhodecode/templates/base/base.mako:464 +#: rhodecode/templates/base/base.mako:466 msgid "Group Home" msgstr "" -#: rhodecode/templates/base/base.mako:468 +#: rhodecode/templates/base/base.mako:470 msgid "You have admin right to this group, and can edit it" msgstr "" -#: rhodecode/templates/base/base.mako:468 +#: rhodecode/templates/base/base.mako:470 msgid "Group Settings" msgstr "" -#: rhodecode/templates/base/base.mako:519 -msgid "This Repository" -msgstr "" - #: rhodecode/templates/base/base.mako:521 +msgid "This Repository" +msgstr "" + +#: rhodecode/templates/base/base.mako:523 msgid "Create Pull Request" msgstr "" -#: rhodecode/templates/base/base.mako:525 +#: rhodecode/templates/base/base.mako:527 msgid "Fork this repository" msgstr "" -#: rhodecode/templates/base/base.mako:532 +#: rhodecode/templates/base/base.mako:534 msgid "This Repository Group" msgstr "" -#: rhodecode/templates/base/base.mako:536 -#: rhodecode/templates/base/base.mako:552 -#: rhodecode/templates/base/base.mako:564 +#: rhodecode/templates/base/base.mako:538 +#: rhodecode/templates/base/base.mako:554 +#: rhodecode/templates/base/base.mako:566 msgid "New Repository" msgstr "" -#: rhodecode/templates/base/base.mako:542 -#: rhodecode/templates/base/base.mako:556 -#: rhodecode/templates/base/base.mako:570 +#: rhodecode/templates/base/base.mako:544 +#: rhodecode/templates/base/base.mako:558 +#: rhodecode/templates/base/base.mako:572 msgid "New Repository Group" msgstr "" -#: rhodecode/templates/base/base.mako:597 +#: rhodecode/templates/base/base.mako:599 msgid "Sign in" msgstr "" -#: rhodecode/templates/base/base.mako:622 +#: rhodecode/templates/base/base.mako:624 msgid "My personal group" msgstr "" -#: rhodecode/templates/base/base.mako:628 +#: rhodecode/templates/base/base.mako:630 #: rhodecode/templates/debug_style/alerts.html:5 #: rhodecode/templates/debug_style/buttons.html:5 #: rhodecode/templates/debug_style/code-block.html:6 @@ -9102,61 +9204,61 @@ msgstr "" msgid "Style" msgstr "" -#: rhodecode/templates/base/base.mako:629 +#: rhodecode/templates/base/base.mako:631 msgid "[Style]" msgstr "" -#: rhodecode/templates/base/base.mako:646 +#: rhodecode/templates/base/base.mako:648 msgid "No Bookmarks yet." msgstr "" -#: rhodecode/templates/base/base.mako:684 +#: rhodecode/templates/base/base.mako:686 msgid "Sign Out" msgstr "" -#: rhodecode/templates/base/base.mako:732 +#: rhodecode/templates/base/base.mako:731 msgid "dismiss" msgstr "" -#: rhodecode/templates/base/base.mako:773 +#: rhodecode/templates/base/base.mako:772 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:824 +#: rhodecode/templates/base/base.mako:823 msgid "Show Public activity journal" msgstr "" -#: rhodecode/templates/base/base.mako:825 +#: rhodecode/templates/base/base.mako:824 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:838 +#: rhodecode/templates/base/base.mako:837 msgid "Admin settings" msgstr "" -#: rhodecode/templates/base/base.mako:1155 +#: rhodecode/templates/base/base.mako:1154 msgid "Keyboard shortcuts" msgstr "" -#: rhodecode/templates/base/base.mako:1163 +#: rhodecode/templates/base/base.mako:1162 msgid "Site-wide shortcuts" msgstr "" @@ -9235,36 +9337,36 @@ msgid "" "permission by members of user groups." msgstr "" -#: rhodecode/templates/base/issue_tracker_settings.mako:81 +#: rhodecode/templates/base/issue_tracker_settings.mako:82 msgid "Extra Prefix" msgstr "" -#: rhodecode/templates/base/issue_tracker_settings.mako:92 +#: rhodecode/templates/base/issue_tracker_settings.mako:93 msgid "show examples" msgstr "" -#: rhodecode/templates/base/issue_tracker_settings.mako:160 +#: rhodecode/templates/base/issue_tracker_settings.mako:161 msgid "Add new" msgstr "" -#: rhodecode/templates/base/issue_tracker_settings.mako:168 +#: rhodecode/templates/base/issue_tracker_settings.mako:169 msgid "New Entry" msgstr "" -#: rhodecode/templates/base/issue_tracker_settings.mako:172 +#: rhodecode/templates/base/issue_tracker_settings.mako:173 msgid "Confirm to remove this pattern:" msgstr "" -#: rhodecode/templates/base/issue_tracker_settings.mako:293 -#: rhodecode/templates/changeset/changeset_file_comment.mako:340 -#: rhodecode/templates/changeset/changeset_file_comment.mako:391 +#: rhodecode/templates/base/issue_tracker_settings.mako:300 +#: rhodecode/templates/changeset/changeset_file_comment.mako:367 +#: rhodecode/templates/changeset/changeset_file_comment.mako:418 #: rhodecode/templates/data_table/_dt_elements.mako:453 #: rhodecode/templates/files/files_add.mako:59 #: rhodecode/templates/files/files_edit.mako:61 msgid "Preview" msgstr "" -#: rhodecode/templates/base/issue_tracker_settings.mako:294 +#: rhodecode/templates/base/issue_tracker_settings.mako:301 msgid "Test Pattern Preview" msgstr "" @@ -9593,10 +9695,6 @@ msgstr "" msgid "Compare Selected Bookmarks" msgstr "" -#: rhodecode/templates/bookmarks/bookmarks.mako:34 -msgid "bookmarks" -msgstr "" - #: rhodecode/templates/branches/branches.mako:5 #, python-format msgid "%s Branches" @@ -9606,15 +9704,11 @@ msgstr "" msgid "Compare Selected Branches" msgstr "" -#: rhodecode/templates/branches/branches.mako:34 -msgid "branches" -msgstr "" - -#: rhodecode/templates/changeset/changeset.mako:9 +#: rhodecode/templates/changeset/changeset.mako:11 msgid "{} Commit" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:78 +#: rhodecode/templates/changeset/changeset.mako:80 #: rhodecode/templates/commits/changelog_elements.mako:56 #: rhodecode/templates/files/files_source_header.mako:48 #: rhodecode/templates/files/files_tree_header.mako:35 @@ -9622,166 +9716,119 @@ msgstr "" msgid "Copy the full commit id" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:83 +#: rhodecode/templates/changeset/changeset.mako:85 msgid "Commit phase" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:90 -#: rhodecode/templates/changeset/changeset.mako:97 +#: rhodecode/templates/changeset/changeset.mako:92 +#: rhodecode/templates/changeset/changeset.mako:99 msgid "Evolve State" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:91 +#: rhodecode/templates/changeset/changeset.mako:93 msgid "obsolete" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:98 +#: rhodecode/templates/changeset/changeset.mako:100 msgid "hidden" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:117 -msgid "Commit navigation" +#: rhodecode/templates/changeset/changeset.mako:106 +msgid "Parent Commit" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:106 +msgid "parent" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:110 +msgid "Child Commit" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:110 +msgid "child" msgstr "" #: rhodecode/templates/changeset/changeset.mako:120 -msgid "Parent Commit" -msgstr "" - -#: rhodecode/templates/changeset/changeset.mako:120 -msgid "parent" +msgid "Diff options" msgstr "" #: rhodecode/templates/changeset/changeset.mako:124 -msgid "Child Commit" -msgstr "" - -#: rhodecode/templates/changeset/changeset.mako:124 -msgid "child" +msgid "Raw Diff" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:128 +msgid "Patch Diff" msgstr "" #: rhodecode/templates/changeset/changeset.mako:132 -msgid "Diff options" -msgstr "" - -#: rhodecode/templates/changeset/changeset.mako:136 -msgid "Raw Diff" -msgstr "" - -#: rhodecode/templates/changeset/changeset.mako:140 -msgid "Patch Diff" -msgstr "" - -#: rhodecode/templates/changeset/changeset.mako:144 msgid "Download Diff" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:224 +#: rhodecode/templates/changeset/changeset.mako:162 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:504 +msgid "General Comments" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:203 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:585 +msgid "Reviewers" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:244 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:718 +msgid "No TODOs yet" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:276 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:769 +msgid "No Comments yet" +msgstr "" + +#: rhodecode/templates/changeset/changeset.mako:332 msgid "No Child Commits" msgstr "" -#: rhodecode/templates/changeset/changeset.mako:263 +#: rhodecode/templates/changeset/changeset.mako:379 msgid "No Parent Commits" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:41 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:401 +#: rhodecode/templates/changeset/changeset_file_comment.mako:47 msgid "Resolved by comment #{}" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:49 +#: rhodecode/templates/changeset/changeset_file_comment.mako:55 msgid "Click to create resolution comment." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:58 +#: rhodecode/templates/changeset/changeset_file_comment.mako:64 msgid "This comment resolves TODO #{}" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:90 +#: rhodecode/templates/changeset/changeset_file_comment.mako:96 msgid "Status from pull request." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:107 +#: rhodecode/templates/changeset/changeset_file_comment.mako:113 msgid "Pull request author" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:108 +#: rhodecode/templates/changeset/changeset_file_comment.mako:114 msgid "author" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:163 -#: rhodecode/templates/changeset/changeset_file_comment.mako:179 -msgid "Outdated comment from pull request version v{0}, latest v{1}" -msgstr "" - #: rhodecode/templates/changeset/changeset_file_comment.mako:167 -#: rhodecode/templates/changeset/changeset_file_comment.mako:183 +#: rhodecode/templates/changeset/changeset_file_comment.mako:181 +msgid "Outdated comment from pull request version v{0}, latest v{1}" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:170 +#: rhodecode/templates/changeset/changeset_file_comment.mako:186 msgid "Comment from pull request version v{0}, latest v{1}" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:205 -#: rhodecode/templates/changeset/changeset_file_comment.mako:206 -#: rhodecode/templates/changeset/changeset_file_comment.mako:209 -#: rhodecode/templates/changeset/changeset_file_comment.mako:210 -msgid "Action unavailable" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:214 -msgid "Jump to the previous outdated comment" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:215 -msgid "Jump to the next outdated comment" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:217 -msgid "Jump to the previous comment" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:218 -msgid "Jump to the next comment" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:257 -msgid "Leave a comment on this Pull Request." -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:259 -msgid "Leave a comment on {} commits in this range." -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:261 -msgid "Leave a comment on this Commit." -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:348 -#: rhodecode/templates/codeblocks/diffs.mako:83 -msgid "You need to be logged in to leave comments." -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:349 -#: rhodecode/templates/codeblocks/diffs.mako:83 -msgid "Login now" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:396 -msgid "Mark as" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:419 -#: rhodecode/templates/files/files_upload.mako:86 -msgid "Drag'n Drop files here or" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:419 -#: rhodecode/templates/files/files_upload.mako:86 -msgid "Choose your files" -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:422 -msgid "uploading..." -msgstr "" - -#: rhodecode/templates/changeset/changeset_file_comment.mako:453 +#: rhodecode/templates/changeset/changeset_file_comment.mako:202 +#: rhodecode/templates/changeset/changeset_file_comment.mako:480 #: rhodecode/templates/compare/compare_diff.mako:108 #: rhodecode/templates/compare/compare_diff.mako:116 #: rhodecode/templates/compare/compare_diff.mako:124 @@ -9789,30 +9836,97 @@ msgstr "" msgid "Comment" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:472 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:39 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:103 +#: rhodecode/templates/changeset/changeset_file_comment.mako:203 +#: rhodecode/templates/files/files_source.mako:117 +msgid "Copy permalink" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:221 +#: rhodecode/templates/changeset/changeset_file_comment.mako:224 +#: rhodecode/templates/changeset/changeset_file_comment.mako:230 +#: rhodecode/templates/changeset/changeset_file_comment.mako:233 +msgid "Action unavailable" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:241 +msgid "Jump to the previous outdated comment" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:242 +msgid "Jump to the next outdated comment" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:244 +msgid "Jump to the previous comment" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:245 +msgid "Jump to the next comment" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:284 +msgid "Leave a comment on this Pull Request." +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:286 +msgid "Leave a comment on {} commits in this range." +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:288 +msgid "Leave a comment on this Commit." +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:375 +#: rhodecode/templates/codeblocks/diffs.mako:85 +msgid "You need to be logged in to leave comments." +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:376 +#: rhodecode/templates/codeblocks/diffs.mako:85 +msgid "Login now" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:423 +msgid "Mark as" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:446 +#: rhodecode/templates/files/files_upload.mako:86 +msgid "Drag'n Drop files here or" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:446 +#: rhodecode/templates/files/files_upload.mako:86 +msgid "Choose your files" +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:449 +msgid "uploading..." +msgstr "" + +#: rhodecode/templates/changeset/changeset_file_comment.mako:499 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:48 #: rhodecode/templates/pullrequests/pullrequests.mako:31 msgid "Closed" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:481 +#: rhodecode/templates/changeset/changeset_file_comment.mako:508 msgid "Comments parsed using {} syntax." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:482 +#: rhodecode/templates/changeset/changeset_file_comment.mako:509 msgid "Use @username inside this text to send notification to this RhodeCode user" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:483 +#: rhodecode/templates/changeset/changeset_file_comment.mako:510 msgid "and" msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:484 +#: rhodecode/templates/changeset/changeset_file_comment.mako:511 msgid "Start typing with / for certain actions to be triggered via text box." msgstr "" -#: rhodecode/templates/changeset/changeset_file_comment.mako:485 +#: rhodecode/templates/changeset/changeset_file_comment.mako:512 msgid "actions supported." msgstr "" @@ -9845,8 +9959,8 @@ msgstr "" #: rhodecode/templates/changeset/diff_block.mako:10 #: rhodecode/templates/changeset/diff_block.mako:25 #: rhodecode/templates/changeset/diff_block.mako:46 -#: rhodecode/templates/codeblocks/diffs.mako:208 -#: rhodecode/templates/codeblocks/diffs.mako:283 +#: rhodecode/templates/codeblocks/diffs.mako:210 +#: rhodecode/templates/codeblocks/diffs.mako:341 msgid "Showing a big diff might take some time and resources, continue?" msgstr "" @@ -9854,8 +9968,8 @@ msgstr "" #: rhodecode/templates/changeset/diff_block.mako:10 #: rhodecode/templates/changeset/diff_block.mako:25 #: rhodecode/templates/changeset/diff_block.mako:46 -#: rhodecode/templates/codeblocks/diffs.mako:208 -#: rhodecode/templates/codeblocks/diffs.mako:283 +#: rhodecode/templates/codeblocks/diffs.mako:210 +#: rhodecode/templates/codeblocks/diffs.mako:341 msgid "Show full diff" msgstr "" @@ -9868,173 +9982,148 @@ msgstr "" msgid "Diff was truncated. File content available only in full diff." msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:141 +#: rhodecode/templates/codeblocks/diffs.mako:143 msgid "not available in this view" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:150 +#: rhodecode/templates/codeblocks/diffs.mako:152 msgid "{} unresolved" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:153 +#: rhodecode/templates/codeblocks/diffs.mako:155 msgid "0 unresolved" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:156 +#: rhodecode/templates/codeblocks/diffs.mako:158 msgid "{} Resolved" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:170 -msgid "0 General" -msgstr "" - -#: rhodecode/templates/codeblocks/diffs.mako:178 -msgid "0 Inline" -msgstr "" - -#: rhodecode/templates/codeblocks/diffs.mako:189 -#: rhodecode/templates/codeblocks/diffs.mako:194 -msgid "{} Outdated" -msgstr "" - -#: rhodecode/templates/codeblocks/diffs.mako:191 -msgid "show outdated" -msgstr "" - -#: rhodecode/templates/codeblocks/diffs.mako:192 -msgid "hide outdated" -msgstr "" - -#: rhodecode/templates/codeblocks/diffs.mako:207 +#: rhodecode/templates/codeblocks/diffs.mako:209 msgid "The requested changes are too big and content was truncated." msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:231 +#: rhodecode/templates/codeblocks/diffs.mako:226 msgid "Some changes may be hidden" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:233 +#: rhodecode/templates/codeblocks/diffs.mako:228 msgid "No files" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:283 +#: rhodecode/templates/codeblocks/diffs.mako:341 msgid "The requested commit or file is too big and content was truncated." msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:290 +#: rhodecode/templates/codeblocks/diffs.mako:348 #, python-format msgid "This diff has been collapsed as it changes many lines, (%i lines changed)" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:292 +#: rhodecode/templates/codeblocks/diffs.mako:350 msgid "Show them" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:295 +#: rhodecode/templates/codeblocks/diffs.mako:353 msgid "Hide them" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:332 -#: rhodecode/templates/codeblocks/diffs.mako:351 +#: rhodecode/templates/codeblocks/diffs.mako:390 +#: rhodecode/templates/codeblocks/diffs.mako:409 msgid "Unmatched/outdated inline comments below" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:357 +#: rhodecode/templates/codeblocks/diffs.mako:415 msgid "Unmatched/outdated comments below" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:431 +#: rhodecode/templates/codeblocks/diffs.mako:489 msgid "This file was removed from diff during updates to this pull-request." msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:432 +#: rhodecode/templates/codeblocks/diffs.mako:490 msgid "There are still outdated/unresolved comments attached to it." msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:499 -msgid "Copy file path" -msgstr "" - -#: rhodecode/templates/codeblocks/diffs.mako:566 -#: rhodecode/templates/codeblocks/diffs.mako:584 +#: rhodecode/templates/codeblocks/diffs.mako:596 +#: rhodecode/templates/codeblocks/diffs.mako:614 #, python-format msgid "Show file at commit: %(commit_id)s" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:568 -#: rhodecode/templates/codeblocks/diffs.mako:575 +#: rhodecode/templates/codeblocks/diffs.mako:598 +#: rhodecode/templates/codeblocks/diffs.mako:605 msgid "Show file before" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:573 -#: rhodecode/templates/codeblocks/diffs.mako:591 +#: rhodecode/templates/codeblocks/diffs.mako:603 +#: rhodecode/templates/codeblocks/diffs.mako:621 #, python-format msgid "File not present at commit: %(commit_id)s" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:586 -#: rhodecode/templates/codeblocks/diffs.mako:593 +#: rhodecode/templates/codeblocks/diffs.mako:616 +#: rhodecode/templates/codeblocks/diffs.mako:623 msgid "Show file after" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:600 +#: rhodecode/templates/codeblocks/diffs.mako:630 msgid "Show comments" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:600 +#: rhodecode/templates/codeblocks/diffs.mako:630 msgid "Hide comments" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:691 -#: rhodecode/templates/codeblocks/diffs.mako:734 -#: rhodecode/templates/codeblocks/diffs.mako:796 +#: rhodecode/templates/codeblocks/diffs.mako:721 +#: rhodecode/templates/codeblocks/diffs.mako:764 +#: rhodecode/templates/codeblocks/diffs.mako:826 msgid "comments including outdated: {}. Click here to display them." msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:693 -#: rhodecode/templates/codeblocks/diffs.mako:736 -#: rhodecode/templates/codeblocks/diffs.mako:798 +#: rhodecode/templates/codeblocks/diffs.mako:723 +#: rhodecode/templates/codeblocks/diffs.mako:766 +#: rhodecode/templates/codeblocks/diffs.mako:828 msgid "comments: {}. Click to toggle them." msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:867 +#: rhodecode/templates/codeblocks/diffs.mako:897 msgid "Toggle wide diff" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:875 +#: rhodecode/templates/codeblocks/diffs.mako:905 msgid "View diff as side by side" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:877 +#: rhodecode/templates/codeblocks/diffs.mako:907 msgid "Side by Side" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:882 +#: rhodecode/templates/codeblocks/diffs.mako:912 msgid "View diff as unified" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:883 +#: rhodecode/templates/codeblocks/diffs.mako:913 msgid "Unified" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:888 +#: rhodecode/templates/codeblocks/diffs.mako:918 msgid "Turn off: Show the diff as commit range" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:891 -#: rhodecode/templates/codeblocks/diffs.mako:898 +#: rhodecode/templates/codeblocks/diffs.mako:921 +#: rhodecode/templates/codeblocks/diffs.mako:928 msgid "Range Diff" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:895 +#: rhodecode/templates/codeblocks/diffs.mako:925 msgid "Show the diff as commit range" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:960 +#: rhodecode/templates/codeblocks/diffs.mako:990 msgid "Disabled on range diff" msgstr "" -#: rhodecode/templates/codeblocks/diffs.mako:1267 +#: rhodecode/templates/codeblocks/diffs.mako:1297 msgid "..." msgstr "" @@ -10139,8 +10228,8 @@ msgid "Hidden Evolve State" msgstr "" #: rhodecode/templates/commits/changelog_elements.mako:80 -#: rhodecode/templates/compare/compare_commits.mako:46 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:595 +#: rhodecode/templates/compare/compare_commits.mako:47 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:435 #: rhodecode/templates/search/search_commit.mako:34 msgid "Expand commit message" msgstr "" @@ -10192,11 +10281,11 @@ msgid "Compare was calculated based on t msgstr "" #: rhodecode/templates/compare/compare_commits.mako:15 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:556 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:396 msgid "Time" msgstr "" -#: rhodecode/templates/compare/compare_commits.mako:64 +#: rhodecode/templates/compare/compare_commits.mako:65 msgid "No commits in this compare" msgstr "" @@ -10313,11 +10402,11 @@ msgid "personal" msgstr "" #: rhodecode/templates/data_table/_dt_elements.mako:387 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:50 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:59 msgid "Pull request !{}" msgstr "" -#: rhodecode/templates/data_table/_dt_elements.mako:395 +#: rhodecode/templates/data_table/_dt_elements.mako:396 msgid "Work in progress" msgstr "" @@ -10575,7 +10664,7 @@ msgid "Pull Request" msgstr "" #: rhodecode/templates/email_templates/pull_request_comment.mako:67 -#: rhodecode/templates/email_templates/pull_request_review.mako:41 +#: 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 "" @@ -10598,8 +10687,8 @@ 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_review.mako:91 -#: rhodecode/templates/email_templates/pull_request_review.mako:108 +#: 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 #: rhodecode/templates/email_templates/pull_request_update.mako:121 msgid "Pull request" @@ -10618,39 +10707,43 @@ msgid "Submitted review status" msgstr "" #: rhodecode/templates/email_templates/pull_request_comment.mako:173 -#: rhodecode/templates/email_templates/pull_request_review.mako:117 +#: 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_review.mako:119 -#: rhodecode/templates/email_templates/pull_request_review.mako:121 +#: 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 #: rhodecode/templates/email_templates/pull_request_update.mako:134 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:128 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:137 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:114 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:123 msgid "of" msgstr "" -#: rhodecode/templates/email_templates/pull_request_review.mako:14 +#: rhodecode/templates/email_templates/pull_request_review.mako:15 +msgid "{user} added you as observer to pull request. !{pr_id}: \"{pr_title}\"" +msgstr "" + +#: rhodecode/templates/email_templates/pull_request_review.mako:17 msgid "{user} requested a pull request review. !{pr_id}: \"{pr_title}\"" msgstr "" -#: rhodecode/templates/email_templates/pull_request_review.mako:39 +#: rhodecode/templates/email_templates/pull_request_review.mako:43 #: rhodecode/templates/email_templates/pull_request_update.mako:39 msgid "Pull Request link" msgstr "" -#: rhodecode/templates/email_templates/pull_request_review.mako:85 +#: rhodecode/templates/email_templates/pull_request_review.mako:89 +msgid "added you as observer to" +msgstr "" + +#: rhodecode/templates/email_templates/pull_request_review.mako:95 msgid "requested a" msgstr "" -#: rhodecode/templates/email_templates/pull_request_review.mako:87 -msgid "pull request review." -msgstr "" - #: rhodecode/templates/email_templates/pull_request_update.mako:14 msgid "{updating_user} updated pull request. !{pr_id}: \"{pr_title}\"" msgstr "" @@ -10865,10 +10958,6 @@ msgstr "" msgid "Raw" msgstr "" -#: rhodecode/templates/files/files_source.mako:117 -msgid "Copy permalink" -msgstr "" - #: rhodecode/templates/files/files_source.mako:133 msgid "Binary file ({})" msgstr "" @@ -10971,64 +11060,59 @@ msgid "RSS public journal feed" msgstr "" #: rhodecode/templates/pullrequests/pullrequest.mako:5 -#: rhodecode/templates/pullrequests/pullrequest.mako:28 msgid "New pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:60 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:118 +#: rhodecode/templates/pullrequests/pullrequest.mako:33 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:104 msgid "Commit flow" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:68 +#: rhodecode/templates/pullrequests/pullrequest.mako:41 msgid "Source repository" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:86 +#: rhodecode/templates/pullrequests/pullrequest.mako:69 +msgid "Target repository" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest.mako:76 msgid "Loading refs..." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:97 -msgid "Submit Pull Request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.mako:111 -msgid "Author of this pull request" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.mako:125 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:286 +#: rhodecode/templates/pullrequests/pullrequest.mako:115 +msgid "Reviewers / Observers" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest.mako:121 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:571 msgid "Reviewer rules" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:135 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:300 -msgid "Pull request reviewers" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.mako:146 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:344 +#: rhodecode/templates/pullrequests/pullrequest.mako:167 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:613 msgid "Add reviewer or reviewer group" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:317 +#: rhodecode/templates/pullrequests/pullrequest.mako:191 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:666 +msgid "Add observer or observer group" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest.mako:216 +msgid "Submit Pull Request" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest.mako:392 msgid "Show detailed compare." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:324 -msgid "There are no commits to merge." -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.mako:418 -#: rhodecode/templates/pullrequests/pullrequest.mako:444 +#: rhodecode/templates/pullrequests/pullrequest.mako:498 +#: rhodecode/templates/pullrequests/pullrequest.mako:526 msgid "Select commit reference" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest.mako:434 -msgid "Target repository" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest.mako:513 +#: rhodecode/templates/pullrequests/pullrequest.mako:594 msgid "Please select source and target" msgstr "" @@ -11063,212 +11147,230 @@ msgstr "" msgid "Login to Merge this Pull Request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:6 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:8 msgid "{} Pull Request !{}" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:52 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:61 msgid "Last updated on" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:53 -msgid "by" -msgstr "" - #: rhodecode/templates/pullrequests/pullrequest_show.mako:62 -msgid "Update title & description" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:68 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:71 -msgid "Delete pull request" +msgid "by" msgstr "" #: rhodecode/templates/pullrequests/pullrequest_show.mako:71 +msgid "Update title & description" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:77 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:80 +msgid "Delete pull request" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:80 msgid "Not allowed to delete this pull request" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:81 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:90 msgid "Rendered using {} renderer" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:95 -msgid "Review status" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:151 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:137 msgid "Common ancestor" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:155 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:141 msgid "not available" msgstr "" +#: rhodecode/templates/pullrequests/pullrequest_show.mako:153 +msgid "Pull changes from source" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:154 +msgid "Copy the pull url" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:166 +msgid "Clone repository in its merged state using shadow repository" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:166 +msgid "Clone from shadow repository" +msgstr "" + #: rhodecode/templates/pullrequests/pullrequest_show.mako:167 -msgid "Pull changes from source" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:168 -msgid "Copy the pull url" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:180 -msgid "Clone repository in its merged state using shadow repository" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:180 -msgid "Clone from shadow repository" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:181 #: rhodecode/templates/summary/components.mako:78 msgid "Copy the clone url" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:185 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:171 msgid "Shadow repository data not available" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:201 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:187 msgid "Versions" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:213 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:215 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:199 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:201 msgid "show versions" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:214 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:200 msgid "hide versions" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:239 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:225 msgid "Your review status at this version" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:244 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:230 msgid "Comments from pull request version v{0}" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:262 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:266 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:248 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:252 msgid "select versions to show changes" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:263 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:249 msgid "show changes between versions" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:264 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:250 msgid "show pull request for this version" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:273 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:259 msgid "Pull request versions not available" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:349 -msgid "Save Changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:386 -msgid "unresolved TODOs unavailable in this view" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:422 -msgid "No unresolved TODOs" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:440 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:279 msgid "Cannot show diff when pull request state is changing. Current progress state" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:458 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:297 msgid "Missing requirements:" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:459 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:298 msgid "These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:467 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:306 msgid "Missing commits" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:468 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:307 msgid "This pull request cannot be displayed, because one or more commits no longer exist in the source repository." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:469 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:308 msgid "Please update this pull request, push the commits back into the source repository, or consider closing this pull request." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:470 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:309 msgid "Consider doing a `force update commits` in case you think this is an error." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:478 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:317 msgid "There are new changes for `{}:{}` in source repository, please consider updating this pull request." msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:489 -#, python-format -msgid "Showing changes at v%d, commenting is disabled." +#: rhodecode/templates/pullrequests/pullrequest_show.mako:328 +msgid "Showing changes at v{}, commenting is disabled." +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:351 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:373 +msgid "Update commits" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:354 +msgid "more update options" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:362 +msgid "Force update commits" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:365 +msgid "Update commits and force refresh this pull request." +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:373 +msgid "Update is disabled for current view" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:385 +msgid "Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:389 +msgid "commits added: {}, removed: {}" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:407 +msgid "Commit added in displayed changes" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:409 +msgid "Commit removed in displayed changes" msgstr "" #: rhodecode/templates/pullrequests/pullrequest_show.mako:512 -#: rhodecode/templates/pullrequests/pullrequest_show.mako:534 -msgid "Update commits" +msgid "there is {num} general comment from older versions" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:513 +msgid "show it" msgstr "" #: rhodecode/templates/pullrequests/pullrequest_show.mako:515 -msgid "more update options" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:523 -msgid "Force update commits" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:526 -msgid "Update commits and force refresh this pull request." -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:534 -msgid "Update is disabled for current view" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:545 -msgid "Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:549 -msgid "commits added: {}, removed: {}" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:567 -msgid "Commit added in displayed changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:569 -msgid "Commit removed in displayed changes" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:678 -msgid "there is {num} general comment from older versions" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:679 -msgid "show it" -msgstr "" - -#: rhodecode/templates/pullrequests/pullrequest_show.mako:681 msgid "there are {num} general comments from older versions" msgstr "" -#: rhodecode/templates/pullrequests/pullrequest_show.mako:682 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:516 msgid "show them" msgstr "" +#: rhodecode/templates/pullrequests/pullrequest_show.mako:591 +msgid "Show rules" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:618 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:671 +msgid "Save Changes" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:642 +msgid "Observers" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:708 +msgid "TODOs unavailable when browsing versions" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:780 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:788 +msgid "Referenced Tickets" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:794 +msgid "In pull request description" +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:808 +#: rhodecode/templates/pullrequests/pullrequest_show.mako:827 +msgid "No Ticket data found." +msgstr "" + +#: rhodecode/templates/pullrequests/pullrequest_show.mako:813 +msgid "In commit messages" +msgstr "" + #: rhodecode/templates/pullrequests/pullrequests.mako:4 msgid "{} Pull Requests" msgstr "" @@ -11461,10 +11563,6 @@ msgstr "" msgid "Compare Selected Tags" msgstr "" -#: rhodecode/templates/tags/tags.mako:34 -msgid "tags" -msgstr "" - #: rhodecode/templates/user_group/profile.mako:6 msgid "User Group Profile" msgstr "" diff --git a/rhodecode/lib/audit_logger.py b/rhodecode/lib/audit_logger.py --- a/rhodecode/lib/audit_logger.py +++ b/rhodecode/lib/audit_logger.py @@ -88,6 +88,9 @@ ACTIONS_V1 = { 'repo.pull_request.reviewer.add': '', 'repo.pull_request.reviewer.delete': '', + 'repo.pull_request.observer.add': '', + 'repo.pull_request.observer.delete': '', + 'repo.commit.strip': {'commit_id': ''}, 'repo.commit.comment.create': {'data': {}}, 'repo.commit.comment.delete': {'data': {}}, diff --git a/rhodecode/lib/base.py b/rhodecode/lib/base.py --- a/rhodecode/lib/base.py +++ b/rhodecode/lib/base.py @@ -293,6 +293,7 @@ def attach_context_attributes(context, r context.rc_config = rc_config context.rhodecode_version = rhodecode.__version__ context.rhodecode_edition = config.get('rhodecode.edition') + context.rhodecode_edition_id = config.get('rhodecode.edition_id') # unique secret + version does not leak the version but keep consistency context.rhodecode_version_hash = calculate_version_hash(config) diff --git a/rhodecode/lib/channelstream.py b/rhodecode/lib/channelstream.py --- a/rhodecode/lib/channelstream.py +++ b/rhodecode/lib/channelstream.py @@ -225,14 +225,26 @@ def write_history(config, message): def get_connection_validators(registry): validators = [] - for k, config in registry.rhodecode_plugins.iteritems(): + for k, config in registry.rhodecode_plugins.items(): validator = config.get('channelstream', {}).get('connect_validator') if validator: validators.append(validator) return validators +def get_channelstream_config(registry=None): + if not registry: + registry = get_current_registry() + + rhodecode_plugins = getattr(registry, 'rhodecode_plugins', {}) + channelstream_config = rhodecode_plugins.get('channelstream', {}) + return channelstream_config + + def post_message(channel, message, username, registry=None): + channelstream_config = get_channelstream_config(registry) + if not channelstream_config.get('enabled'): + return message_obj = message if isinstance(message, basestring): @@ -242,26 +254,118 @@ def post_message(channel, message, usern 'topic': '/notifications' } - if not registry: - registry = get_current_registry() + log.debug('Channelstream: sending notification to channel %s', channel) + payload = { + 'type': 'message', + 'timestamp': datetime.datetime.utcnow(), + 'user': 'system', + 'exclude_users': [username], + 'channel': channel, + 'message': message_obj + } + + try: + return channelstream_request( + channelstream_config, [payload], '/message', + raise_exc=False) + except ChannelstreamException: + log.exception('Failed to send channelstream data') + raise + + +def _reload_link(label): + return ( + '' + '{}' + ''.format(label) + ) + + +def pr_channel(pull_request): + repo_name = pull_request.target_repo.repo_name + pull_request_id = pull_request.pull_request_id + channel = '/repo${}$/pr/{}'.format(repo_name, pull_request_id) + log.debug('Getting pull-request channelstream broadcast channel: %s', channel) + return channel + + +def comment_channel(repo_name, commit_obj=None, pull_request_obj=None): + channel = None + if commit_obj: + channel = u'/repo${}$/commit/{}'.format( + repo_name, commit_obj.raw_id + ) + elif pull_request_obj: + channel = u'/repo${}$/pr/{}'.format( + repo_name, pull_request_obj.pull_request_id + ) + log.debug('Getting comment channelstream broadcast channel: %s', channel) + + return channel + + +def pr_update_channelstream_push(request, pr_broadcast_channel, user, msg, **kwargs): + """ + Channel push on pull request update + """ + if not pr_broadcast_channel: + return - log.debug('Channelstream: sending notification to channel %s', channel) - rhodecode_plugins = getattr(registry, 'rhodecode_plugins', {}) - channelstream_config = rhodecode_plugins.get('channelstream', {}) - if channelstream_config.get('enabled'): - payload = { - 'type': 'message', - 'timestamp': datetime.datetime.utcnow(), - 'user': 'system', - 'exclude_users': [username], - 'channel': channel, - 'message': message_obj - } + _ = request.translate + + message = '{} {}'.format( + msg, + _reload_link(_(' Reload page to load changes'))) + + message_obj = { + 'message': message, + 'level': 'success', + 'topic': '/notifications' + } + + post_message( + pr_broadcast_channel, message_obj, user.username, + registry=request.registry) + + +def comment_channelstream_push(request, comment_broadcast_channel, user, msg, **kwargs): + """ + Channelstream push on comment action, on commit, or pull-request + """ + if not comment_broadcast_channel: + return + + _ = request.translate - try: - return channelstream_request( - channelstream_config, [payload], '/message', - raise_exc=False) - except ChannelstreamException: - log.exception('Failed to send channelstream data') - raise + comment_data = kwargs.pop('comment_data', {}) + user_data = kwargs.pop('user_data', {}) + comment_id = comment_data.get('comment_id') + + message = '{} {} #{}, {}'.format( + user.username, + msg, + comment_id, + _reload_link(_('Reload page to see new comments')), + ) + + message_obj = { + 'message': message, + 'level': 'success', + 'topic': '/notifications' + } + + post_message( + comment_broadcast_channel, message_obj, user.username, + registry=request.registry) + + message_obj = { + 'message': None, + 'user': user.username, + 'comment_id': comment_id, + 'comment_data': comment_data, + 'user_data': user_data, + 'topic': '/comment' + } + post_message( + comment_broadcast_channel, message_obj, user.username, + registry=request.registry) diff --git a/rhodecode/lib/dbmigrate/versions/110_version_4_22_0.py b/rhodecode/lib/dbmigrate/versions/110_version_4_22_0.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/dbmigrate/versions/110_version_4_22_0.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- + +import logging +from sqlalchemy import * + +from alembic.migration import MigrationContext +from alembic.operations import Operations + +from rhodecode.lib.dbmigrate.versions import _reset_base +from rhodecode.model import meta, init_model_encryption + + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from rhodecode.lib.dbmigrate.schema import db_4_20_0_0 as db + + init_model_encryption(db) + + context = MigrationContext.configure(migrate_engine.connect()) + op = Operations(context) + + table = db.RepoReviewRuleUser.__table__ + with op.batch_alter_table(table.name) as batch_op: + new_column = Column('role', Unicode(255), nullable=True) + batch_op.add_column(new_column) + + _fill_rule_user_role(op, meta.Session) + + table = db.RepoReviewRuleUserGroup.__table__ + with op.batch_alter_table(table.name) as batch_op: + new_column = Column('role', Unicode(255), nullable=True) + batch_op.add_column(new_column) + + _fill_rule_user_group_role(op, meta.Session) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + pass + + +def _fill_rule_user_role(op, session): + params = {'role': 'reviewer'} + query = text( + 'UPDATE repo_review_rules_users SET role = :role' + ).bindparams(**params) + op.execute(query) + session().commit() + + +def _fill_rule_user_group_role(op, session): + params = {'role': 'reviewer'} + query = text( + 'UPDATE repo_review_rules_users_groups SET role = :role' + ).bindparams(**params) + op.execute(query) + session().commit() diff --git a/rhodecode/lib/exc_tracking.py b/rhodecode/lib/exc_tracking.py --- a/rhodecode/lib/exc_tracking.py +++ b/rhodecode/lib/exc_tracking.py @@ -131,7 +131,7 @@ def send_exc_email(request, exc_id, exc_ # NOTE(marcink): needed for email template rendering user_id = None - if request: + if hasattr(request, 'user'): user_id = request.user.user_id attach_context_attributes(TemplateArgs(), request, user_id=user_id, is_api=True) diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -38,6 +38,7 @@ import re import time import string import hashlib +import regex from collections import OrderedDict import pygments @@ -1103,6 +1104,10 @@ def bool2icon(value, show_at_false=True) return HTML.tag('i', class_="icon-false", title='False') return HTML.tag('i') + +def b64(inp): + return base64.b64encode(inp) + #============================================================================== # PERMS #============================================================================== @@ -1653,7 +1658,7 @@ def get_active_pattern_entries(repo_name return active_entries -pr_pattern_re = re.compile(r'(?:(?:^!)|(?: !))(\d+)') +pr_pattern_re = regex.compile(r'(?:(?:^!)|(?: !))(\d+)') allowed_link_formats = [ 'html', 'rst', 'markdown', 'html+hovercard', 'rst+hovercard', 'markdown+hovercard'] @@ -1670,6 +1675,7 @@ def process_patterns(text_string, repo_n active_entries = get_active_pattern_entries(repo_name) issues_data = [] + errors = [] new_text = text_string log.debug('Got %s entries to process', len(active_entries)) @@ -1687,9 +1693,11 @@ def process_patterns(text_string, repo_n pattern = entry['pat_compiled'] else: try: - pattern = re.compile(r'%s' % entry['pat']) - except re.error: - log.exception('issue tracker pattern: `%s` failed to compile', entry['pat']) + pattern = regex.compile(r'%s' % entry['pat']) + except regex.error as e: + regex_err = ValueError('{}:{}'.format(entry['pat'], e)) + log.exception('issue tracker pattern: `%s` failed to compile', regex_err) + errors.append(regex_err) continue data_func = partial( @@ -1721,11 +1729,11 @@ def process_patterns(text_string, repo_n new_text = pr_pattern_re.sub(pr_url_func, new_text) log.debug('processed !pr pattern') - return new_text, issues_data + return new_text, issues_data, errors def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None, - issues_container=None): + issues_container=None, error_container=None): """ Parses given text message and makes proper links. issues are linked to given issue-server, and rest is a commit link @@ -1745,12 +1753,15 @@ def urlify_commit_message(commit_text, r new_text = urlify_commits(new_text, repository) # process issue tracker patterns - new_text, issues = process_patterns(new_text, repository or '', - active_entries=active_pattern_entries) + new_text, issues, errors = process_patterns( + new_text, repository or '', active_entries=active_pattern_entries) if issues_container is not None: issues_container.extend(issues) + if error_container is not None: + error_container.extend(errors) + return literal(new_text) @@ -1805,7 +1816,7 @@ def render(source, renderer='rst', menti elif renderer == 'rst': if repo_name: # process patterns on comments if we pass in repo name - source, issues = process_patterns( + source, issues, errors = process_patterns( source, repo_name, link_format='rst', active_entries=active_pattern_entries) if issues_container is not None: @@ -1819,7 +1830,7 @@ def render(source, renderer='rst', menti elif renderer == 'markdown': if repo_name: # process patterns on comments if we pass in repo name - source, issues = process_patterns( + source, issues, errors = process_patterns( source, repo_name, link_format='markdown', active_entries=active_pattern_entries) if issues_container is not None: diff --git a/rhodecode/lib/string_renderer.py b/rhodecode/lib/string_renderer.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/string_renderer.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2010-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/ + + +def html(info): + """ + Custom string as html content_type renderer for pyramid + """ + def _render(value, system): + request = system.get('request') + if request is not None: + response = request.response + ct = response.content_type + if ct == response.default_content_type: + response.content_type = 'text/html' + return value + + return _render 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 @@ -57,7 +57,43 @@ FILEMODE_DEFAULT = 0o100644 FILEMODE_EXECUTABLE = 0o100755 EMPTY_COMMIT_ID = '0' * 40 -Reference = collections.namedtuple('Reference', ('type', 'name', 'commit_id')) +_Reference = collections.namedtuple('Reference', ('type', 'name', 'commit_id')) + + +class Reference(_Reference): + + @property + def branch(self): + if self.type == 'branch': + return self.name + + @property + def bookmark(self): + if self.type == 'book': + return self.name + + +def unicode_to_reference(raw): + """ + Convert a unicode (or string) to a reference object. + If unicode evaluates to False it returns None. + """ + if raw: + refs = raw.split(':') + return Reference(*refs) + else: + return None + + +def reference_to_unicode(ref): + """ + Convert a reference object to unicode. + If reference is None it returns None. + """ + if ref: + return u':'.join(ref) + else: + return None class MergeFailureReason(object): 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 @@ -25,7 +25,7 @@ import collections from rhodecode.model import BaseModel from rhodecode.model.db import ( - ChangesetStatus, ChangesetComment, PullRequest, Session) + ChangesetStatus, ChangesetComment, PullRequest, PullRequestReviewers, Session) from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError from rhodecode.lib.markup_renderer import ( DEFAULT_COMMENTS_RENDERER, RstTemplateRenderer) @@ -383,15 +383,14 @@ class ChangesetStatusModel(BaseModel): 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, pull_request.reviewers) - - def calculated_review_status(self, pull_request, reviewers_statuses=None): + def calculated_review_status(self, pull_request): """ calculate pull request status based on reviewers, it should be a list of two element lists. - - :param reviewers_statuses: """ - reviewers = reviewers_statuses or self.reviewers_statuses(pull_request) + reviewers = self.reviewers_statuses(pull_request) return self.calculate_status(reviewers) diff --git a/rhodecode/model/comment.py b/rhodecode/model/comment.py --- a/rhodecode/model/comment.py +++ b/rhodecode/model/comment.py @@ -399,7 +399,7 @@ class CommentsModel(BaseModel): recipients += [pull_request_obj.author] # add the reviewers to notification - recipients += [x.user for x in pull_request_obj.reviewers] + recipients += [x.user for x in pull_request_obj.get_pull_request_reviewers()] pr_target_repo = pull_request_obj.target_repo pr_source_repo = pull_request_obj.source_repo @@ -436,9 +436,8 @@ class CommentsModel(BaseModel): 'thread_ids': [pr_url, pr_comment_url], }) - recipients += [self._get_user(u) for u in (extra_recipients or [])] - if send_email: + recipients += [self._get_user(u) for u in (extra_recipients or [])] # pre-generate the subject for notification itself (subject, _e, body_plaintext) = EmailNotificationModel().render_email( notification_type, **kwargs) @@ -463,55 +462,11 @@ class CommentsModel(BaseModel): else: action = 'repo.commit.comment.create' - comment_id = comment.comment_id comment_data = comment.get_api_data() self._log_audit_action( action, {'data': comment_data}, auth_user, comment) - channel = None - if commit_obj: - repo_name = repo.repo_name - channel = u'/repo${}$/commit/{}'.format( - repo_name, - commit_obj.raw_id - ) - elif pull_request_obj: - repo_name = pr_target_repo.repo_name - channel = u'/repo${}$/pr/{}'.format( - repo_name, - pull_request_obj.pull_request_id - ) - - if channel: - username = user.username - message = '{} {} #{}, {}' - message = message.format( - username, - _('posted a new comment'), - comment_id, - _('Refresh the page to see new comments.')) - - message_obj = { - 'message': message, - 'level': 'success', - 'topic': '/notifications' - } - - channelstream.post_message( - channel, message_obj, user.username, - registry=get_current_registry()) - - message_obj = { - 'message': None, - 'user': username, - 'comment_id': comment_id, - 'topic': '/comment' - } - channelstream.post_message( - channel, message_obj, user.username, - registry=get_current_registry()) - return comment def edit(self, comment_id, text, auth_user, version): @@ -586,17 +541,20 @@ class CommentsModel(BaseModel): return comment - def get_all_comments(self, repo_id, revision=None, pull_request=None): + def get_all_comments(self, repo_id, revision=None, pull_request=None, count_only=False): q = ChangesetComment.query()\ .filter(ChangesetComment.repo_id == repo_id) if revision: q = q.filter(ChangesetComment.revision == revision) elif pull_request: pull_request = self.__get_pull_request(pull_request) - q = q.filter(ChangesetComment.pull_request == pull_request) + q = q.filter(ChangesetComment.pull_request_id == pull_request.pull_request_id) else: raise Exception('Please specify commit or pull_request') q = q.order_by(ChangesetComment.created_on) + if count_only: + return q.count() + return q.all() def get_url(self, comment, request=None, permalink=False, anchor=None): diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -56,7 +56,8 @@ from webhelpers2.text import remove_form from rhodecode.translation import _ from rhodecode.lib.vcs import get_vcs_instance, VCSError -from rhodecode.lib.vcs.backends.base import EmptyCommit, Reference +from rhodecode.lib.vcs.backends.base import ( + EmptyCommit, Reference, unicode_to_reference, reference_to_unicode) from rhodecode.lib.utils2 import ( str2bool, safe_str, get_commit_safe, safe_unicode, sha1_safe, time_to_datetime, aslist, Optional, safe_int, get_clone_url, AttributeDict, @@ -3773,12 +3774,12 @@ class ChangesetComment(Base, BaseModel): resolved_comment = relationship('ChangesetComment', remote_side=comment_id, back_populates='resolved_by') resolved_by = relationship('ChangesetComment', back_populates='resolved_comment') - author = relationship('User', lazy='joined') + author = relationship('User', lazy='select') repo = relationship('Repository') - status_change = relationship('ChangesetStatus', cascade="all, delete-orphan", lazy='joined') - pull_request = relationship('PullRequest', lazy='joined') - pull_request_version = relationship('PullRequestVersion') - history = relationship('ChangesetCommentHistory', cascade='all, delete-orphan', lazy='joined', order_by='ChangesetCommentHistory.version') + status_change = relationship('ChangesetStatus', cascade="all, delete-orphan", lazy='select') + pull_request = relationship('PullRequest', lazy='select') + pull_request_version = relationship('PullRequestVersion', lazy='select') + history = relationship('ChangesetCommentHistory', cascade='all, delete-orphan', lazy='select', order_by='ChangesetCommentHistory.version') @classmethod def get_users(cls, revision=None, pull_request_id=None): @@ -3983,10 +3984,10 @@ class ChangesetStatus(Base, BaseModel): version = Column('version', Integer(), nullable=False, default=0) pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) - author = relationship('User', lazy='joined') - repo = relationship('Repository') - comment = relationship('ChangesetComment', lazy='joined') - pull_request = relationship('PullRequest', lazy='joined') + author = relationship('User', lazy='select') + repo = relationship('Repository', lazy='select') + comment = relationship('ChangesetComment', lazy='select') + pull_request = relationship('PullRequest', lazy='select') def __unicode__(self): return u"<%s('%s[v%s]:%s')>" % ( @@ -4248,26 +4249,11 @@ class _PullRequestBase(BaseModel): @staticmethod def unicode_to_reference(raw): - """ - Convert a unicode (or string) to a reference object. - If unicode evaluates to False it returns None. - """ - if raw: - refs = raw.split(':') - return Reference(*refs) - else: - return None + return unicode_to_reference(raw) @staticmethod def reference_to_unicode(ref): - """ - Convert a reference object to unicode. - If reference is None it returns None. - """ - if ref: - return u':'.join(ref) - else: - return None + return reference_to_unicode(ref) def get_api_data(self, with_merge_state=True): from rhodecode.model.pull_request import PullRequestModel @@ -4465,6 +4451,37 @@ class PullRequest(Base, _PullRequestBase from rhodecode.model.changeset_status import ChangesetStatusModel return ChangesetStatusModel().reviewers_statuses(self) + def get_pull_request_reviewers(self, role=None): + qry = PullRequestReviewers.query()\ + .filter(PullRequestReviewers.pull_request_id == self.pull_request_id) + if role: + qry = qry.filter(PullRequestReviewers.role == role) + + return qry.all() + + @property + def reviewers_count(self): + qry = PullRequestReviewers.query()\ + .filter(PullRequestReviewers.pull_request_id == self.pull_request_id)\ + .filter(PullRequestReviewers.role == PullRequestReviewers.ROLE_REVIEWER) + return qry.count() + + @property + def observers_count(self): + qry = PullRequestReviewers.query()\ + .filter(PullRequestReviewers.pull_request_id == self.pull_request_id)\ + .filter(PullRequestReviewers.role == PullRequestReviewers.ROLE_OBSERVER) + return qry.count() + + def observers(self): + qry = PullRequestReviewers.query()\ + .filter(PullRequestReviewers.pull_request_id == self.pull_request_id)\ + .filter(PullRequestReviewers.role == PullRequestReviewers.ROLE_OBSERVER)\ + .all() + + for entry in qry: + yield entry, entry.user + @property def workspace_id(self): from rhodecode.model.pull_request import PullRequestModel @@ -4512,6 +4529,9 @@ class PullRequestVersion(Base, _PullRequ @property def reviewers(self): return self.pull_request.reviewers + @property + def reviewers(self): + return self.pull_request.reviewers @property def versions(self): @@ -4530,6 +4550,9 @@ class PullRequestVersion(Base, _PullRequ def reviewers_statuses(self): return self.pull_request.reviewers_statuses() + def observers(self): + return self.pull_request.observers() + class PullRequestReviewers(Base, BaseModel): __tablename__ = 'pull_request_reviewers' @@ -4538,6 +4561,7 @@ class PullRequestReviewers(Base, BaseMod ) ROLE_REVIEWER = u'reviewer' ROLE_OBSERVER = u'observer' + ROLES = [ROLE_REVIEWER, ROLE_OBSERVER] @hybrid_property def reasons(self): @@ -4589,6 +4613,15 @@ class PullRequestReviewers(Base, BaseMod return user_group_data + @classmethod + def get_pull_request_reviewers(cls, pull_request_id, role=None): + qry = PullRequestReviewers.query()\ + .filter(PullRequestReviewers.pull_request_id == pull_request_id) + if role: + qry = qry.filter(PullRequestReviewers.role == role) + + return qry.all() + def __unicode__(self): return u"<%s('id:%s')>" % (self.__class__.__name__, self.pull_requests_reviewers_id) @@ -4954,16 +4987,21 @@ class RepoReviewRuleUser(Base, BaseModel __table_args__ = ( base_table_args ) + ROLE_REVIEWER = u'reviewer' + ROLE_OBSERVER = u'observer' + ROLES = [ROLE_REVIEWER, ROLE_OBSERVER] repo_review_rule_user_id = Column('repo_review_rule_user_id', Integer(), primary_key=True) repo_review_rule_id = Column("repo_review_rule_id", Integer(), ForeignKey('repo_review_rules.repo_review_rule_id')) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False) mandatory = Column("mandatory", Boolean(), nullable=False, default=False) + role = Column('role', Unicode(255), nullable=True, default=ROLE_REVIEWER) user = relationship('User') def rule_data(self): return { - 'mandatory': self.mandatory + 'mandatory': self.mandatory, + 'role': self.role, } @@ -4974,17 +5012,22 @@ class RepoReviewRuleUserGroup(Base, Base ) VOTE_RULE_ALL = -1 + ROLE_REVIEWER = u'reviewer' + ROLE_OBSERVER = u'observer' + ROLES = [ROLE_REVIEWER, ROLE_OBSERVER] repo_review_rule_users_group_id = Column('repo_review_rule_users_group_id', Integer(), primary_key=True) repo_review_rule_id = Column("repo_review_rule_id", Integer(), ForeignKey('repo_review_rules.repo_review_rule_id')) - users_group_id = Column("users_group_id", Integer(),ForeignKey('users_groups.users_group_id'), nullable=False) + users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False) mandatory = Column("mandatory", Boolean(), nullable=False, default=False) + role = Column('role', Unicode(255), nullable=True, default=ROLE_REVIEWER) vote_rule = Column("vote_rule", Integer(), nullable=True, default=VOTE_RULE_ALL) users_group = relationship('UserGroup') def rule_data(self): return { 'mandatory': self.mandatory, + 'role': self.role, 'vote_rule': self.vote_rule } diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py --- a/rhodecode/model/forms.py +++ b/rhodecode/model/forms.py @@ -601,6 +601,14 @@ def PullRequestForm(localizer, repo_id): reasons = All() rules = All(v.UniqueList(localizer, convert=int)()) mandatory = v.StringBoolean() + role = v.String(if_missing='reviewer') + + class ObserverForm(formencode.Schema): + user_id = v.Int(not_empty=True) + reasons = All() + rules = All(v.UniqueList(localizer, convert=int)()) + mandatory = v.StringBoolean() + role = v.String(if_missing='observer') class _PullRequestForm(formencode.Schema): allow_extra_fields = True @@ -614,6 +622,7 @@ def PullRequestForm(localizer, repo_id): revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(), v.UniqueList(localizer)(not_empty=True)) review_members = formencode.ForEach(ReviewerForm()) + observer_members = formencode.ForEach(ObserverForm()) pullrequest_title = v.UnicodeString(strip=True, required=True, min=1, max=255) pullrequest_desc = v.UnicodeString(strip=True, required=False) description_renderer = v.UnicodeString(strip=True, required=False) 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 @@ -154,28 +154,56 @@ def get_diff_info( commits = [] if get_commit_authors: - commits = target_scm.compare( + log.debug('Obtaining commit authors from set of commits') + _compare_data = target_scm.compare( target_ref, source_ref, source_scm, merge=True, - pre_load=["author"]) + pre_load=["author", "date", "message"] + ) - for commit in commits: - user = User.get_from_cs_author(commit.author) + for commit in _compare_data: + # NOTE(marcink): we serialize here, so we don't produce more vcsserver calls on data returned + # at this function which is later called via JSON serialization + serialized_commit = dict( + author=commit.author, + date=commit.date, + message=commit.message, + commit_id=commit.raw_id, + raw_id=commit.raw_id + ) + commits.append(serialized_commit) + user = User.get_from_cs_author(serialized_commit['author']) if user and user not in commit_authors: commit_authors.append(user) # lines if get_authors: + log.debug('Calculating authors of changed files') target_commit = source_repo.get_commit(ancestor_id) for fname, lines in changed_lines.items(): + try: - node = target_commit.get_node(fname) + node = target_commit.get_node(fname, pre_load=["is_binary"]) except Exception: + log.exception("Failed to load node with path %s", fname) continue if not isinstance(node, FileNode): continue + # NOTE(marcink): for binary node we don't do annotation, just use last author + if node.is_binary: + author = node.last_commit.author + email = node.last_commit.author_email + + user = User.get_from_cs_author(author) + if user: + user_counts[user.user_id] = user_counts.get(user.user_id, 0) + 1 + author_counts[author] = author_counts.get(author, 0) + 1 + email_counts[email] = email_counts.get(email, 0) + 1 + + continue + for annotation in node.annotate: line_no, commit_id, get_commit_func, line_text = annotation if line_no in lines: @@ -190,6 +218,8 @@ def get_diff_info( author_counts[author] = author_counts.get(author, 0) + 1 email_counts[email] = email_counts.get(email, 0) + 1 + log.debug('Default reviewers processing finished') + return { 'commits': commits, 'files': all_files_changes, @@ -260,10 +290,16 @@ class PullRequestModel(BaseModel): _perms = ('repository.admin',) return self._check_perms(_perms, pull_request, user) or owner + def is_user_reviewer(self, pull_request, user): + return user.user_id in [ + x.user_id for x in + pull_request.get_pull_request_reviewers(PullRequestReviewers.ROLE_REVIEWER) + if x.user + ] + def check_user_change_status(self, pull_request, user, api=False): - reviewer = user.user_id in [x.user_id for x in - pull_request.reviewers] - return self.check_user_update(pull_request, user, api) or reviewer + return self.check_user_update(pull_request, user, api) \ + or self.is_user_reviewer(pull_request, user) def check_user_comment(self, pull_request, user): owner = user.user_id == pull_request.user_id @@ -575,7 +611,7 @@ class PullRequestModel(BaseModel): pull_request_display_obj, at_version def create(self, created_by, source_repo, source_ref, target_repo, - target_ref, revisions, reviewers, title, description=None, + target_ref, revisions, reviewers, observers, title, description=None, common_ancestor_id=None, description_renderer=None, reviewer_data=None, translator=None, auth_user=None): @@ -606,7 +642,7 @@ class PullRequestModel(BaseModel): reviewer_ids = set() # members / reviewers for reviewer_object in reviewers: - user_id, reasons, mandatory, rules = reviewer_object + user_id, reasons, mandatory, role, rules = reviewer_object user = self._get_user(user_id) # skip duplicates @@ -620,6 +656,7 @@ class PullRequestModel(BaseModel): reviewer.pull_request = pull_request reviewer.reasons = reasons reviewer.mandatory = mandatory + reviewer.role = role # NOTE(marcink): pick only first rule for now rule_id = list(rules)[0] if rules else None @@ -653,6 +690,33 @@ class PullRequestModel(BaseModel): Session().add(reviewer) Session().flush() + for observer_object in observers: + user_id, reasons, mandatory, role, rules = observer_object + user = self._get_user(user_id) + + # skip duplicates from reviewers + if user.user_id in reviewer_ids: + continue + + #reviewer_ids.add(user.user_id) + + observer = PullRequestReviewers() + observer.user = user + observer.pull_request = pull_request + observer.reasons = reasons + observer.mandatory = mandatory + observer.role = role + + # NOTE(marcink): pick only first rule for now + rule_id = list(rules)[0] if rules else None + rule = RepoReviewRule.get(rule_id) if rule_id else None + if rule: + # TODO(marcink): do we need this for observers ?? + pass + + Session().add(observer) + Session().flush() + # Set approval status to "Under Review" for all commits which are # part of this pull request. ChangesetStatusModel().set_status( @@ -678,7 +742,7 @@ class PullRequestModel(BaseModel): MergeCheck.validate( pull_request, auth_user=auth_user, translator=translator) - self.notify_reviewers(pull_request, reviewer_ids) + self.notify_reviewers(pull_request, reviewer_ids, created_by_user) self.trigger_pull_request_hook(pull_request, created_by_user, 'create') creation_data = pull_request.get_api_data(with_merge_state=False) @@ -1204,23 +1268,25 @@ class PullRequestModel(BaseModel): :param pull_request: the pr to update :param reviewer_data: list of tuples - [(user, ['reason1', 'reason2'], mandatory_flag, [rules])] + [(user, ['reason1', 'reason2'], mandatory_flag, role, [rules])] + :param user: current use who triggers this action """ + pull_request = self.__get_pull_request(pull_request) if pull_request.is_closed(): raise ValueError('This pull request is closed') reviewers = {} - for user_id, reasons, mandatory, rules in reviewer_data: + for user_id, reasons, mandatory, role, rules in reviewer_data: if isinstance(user_id, (int, compat.string_types)): user_id = self._get_user(user_id).user_id reviewers[user_id] = { - 'reasons': reasons, 'mandatory': mandatory} + 'reasons': reasons, 'mandatory': mandatory, 'role': role} reviewers_ids = set(reviewers.keys()) - current_reviewers = PullRequestReviewers.query()\ - .filter(PullRequestReviewers.pull_request == - pull_request).all() + current_reviewers = PullRequestReviewers.get_pull_request_reviewers( + pull_request.pull_request_id, role=PullRequestReviewers.ROLE_REVIEWER) + current_reviewers_ids = set([x.user.user_id for x in current_reviewers]) ids_to_add = reviewers_ids.difference(current_reviewers_ids) @@ -1241,16 +1307,19 @@ class PullRequestModel(BaseModel): reviewer.reasons = reviewers[uid]['reasons'] # NOTE(marcink): mandatory shouldn't be changed now # reviewer.mandatory = reviewers[uid]['reasons'] + # NOTE(marcink): role should be hardcoded, so we won't edit it. + reviewer.role = PullRequestReviewers.ROLE_REVIEWER Session().add(reviewer) added_audit_reviewers.append(reviewer.get_dict()) for uid in ids_to_remove: changed = True - # NOTE(marcink): we fetch "ALL" reviewers using .all(). This is an edge case - # that prevents and fixes cases that we added the same reviewer twice. + # NOTE(marcink): we fetch "ALL" reviewers objects using .all(). + # This is an edge case that handles previous state of having the same reviewer twice. # this CAN happen due to the lack of DB checks reviewers = PullRequestReviewers.query()\ .filter(PullRequestReviewers.user_id == uid, + PullRequestReviewers.role == PullRequestReviewers.ROLE_REVIEWER, PullRequestReviewers.pull_request == pull_request)\ .all() @@ -1273,7 +1342,90 @@ class PullRequestModel(BaseModel): 'repo.pull_request.reviewer.delete', {'old_data': user_data}, user, pull_request) - self.notify_reviewers(pull_request, ids_to_add) + self.notify_reviewers(pull_request, ids_to_add, user) + return ids_to_add, ids_to_remove + + def update_observers(self, pull_request, observer_data, user): + """ + Update the observers in the pull request + + :param pull_request: the pr to update + :param observer_data: list of tuples + [(user, ['reason1', 'reason2'], mandatory_flag, role, [rules])] + :param user: current use who triggers this action + """ + pull_request = self.__get_pull_request(pull_request) + if pull_request.is_closed(): + raise ValueError('This pull request is closed') + + observers = {} + for user_id, reasons, mandatory, role, rules in observer_data: + if isinstance(user_id, (int, compat.string_types)): + user_id = self._get_user(user_id).user_id + observers[user_id] = { + 'reasons': reasons, 'observers': mandatory, 'role': role} + + observers_ids = set(observers.keys()) + current_observers = PullRequestReviewers.get_pull_request_reviewers( + pull_request.pull_request_id, role=PullRequestReviewers.ROLE_OBSERVER) + + current_observers_ids = set([x.user.user_id for x in current_observers]) + + ids_to_add = observers_ids.difference(current_observers_ids) + ids_to_remove = current_observers_ids.difference(observers_ids) + + log.debug("Adding %s observer", ids_to_add) + log.debug("Removing %s observer", ids_to_remove) + changed = False + added_audit_observers = [] + removed_audit_observers = [] + + for uid in ids_to_add: + changed = True + _usr = self._get_user(uid) + observer = PullRequestReviewers() + observer.user = _usr + observer.pull_request = pull_request + observer.reasons = observers[uid]['reasons'] + # NOTE(marcink): mandatory shouldn't be changed now + # observer.mandatory = observer[uid]['reasons'] + + # NOTE(marcink): role should be hardcoded, so we won't edit it. + observer.role = PullRequestReviewers.ROLE_OBSERVER + Session().add(observer) + added_audit_observers.append(observer.get_dict()) + + for uid in ids_to_remove: + changed = True + # NOTE(marcink): we fetch "ALL" reviewers objects using .all(). + # This is an edge case that handles previous state of having the same reviewer twice. + # this CAN happen due to the lack of DB checks + observers = PullRequestReviewers.query()\ + .filter(PullRequestReviewers.user_id == uid, + PullRequestReviewers.role == PullRequestReviewers.ROLE_OBSERVER, + PullRequestReviewers.pull_request == pull_request)\ + .all() + + for obj in observers: + added_audit_observers.append(obj.get_dict()) + Session().delete(obj) + + if changed: + Session().expire_all() + pull_request.updated_on = datetime.datetime.now() + Session().add(pull_request) + + # finally store audit logs + for user_data in added_audit_observers: + self._log_audit_action( + 'repo.pull_request.observer.add', {'data': user_data}, + user, pull_request) + for user_data in removed_audit_observers: + self._log_audit_action( + 'repo.pull_request.observer.delete', {'old_data': user_data}, + user, pull_request) + + self.notify_observers(pull_request, ids_to_add, user) return ids_to_add, ids_to_remove def get_url(self, pull_request, request=None, permalink=False): @@ -1301,16 +1453,16 @@ class PullRequestModel(BaseModel): pr_url = urllib.unquote(self.get_url(pull_request, request=request)) return safe_unicode('{pr_url}/repository'.format(pr_url=pr_url)) - def notify_reviewers(self, pull_request, reviewers_ids): - # notification to reviewers - if not reviewers_ids: + def _notify_reviewers(self, pull_request, user_ids, role, user): + # notification to reviewers/observers + if not user_ids: return - log.debug('Notify following reviewers about pull-request %s', reviewers_ids) + log.debug('Notify following %s users about pull-request %s', role, user_ids) pull_request_obj = pull_request # get the current participants of this pull request - recipients = reviewers_ids + recipients = user_ids notification_type = EmailNotificationModel.TYPE_PULL_REQUEST pr_source_repo = pull_request_obj.source_repo @@ -1332,8 +1484,10 @@ class PullRequestModel(BaseModel): (x.raw_id, x.message) for x in map(pr_source_repo.get_commit, pull_request.revisions)] + current_rhodecode_user = user kwargs = { - 'user': pull_request.author, + 'user': current_rhodecode_user, + 'pull_request_author': pull_request.author, 'pull_request': pull_request_obj, 'pull_request_commits': pull_request_commits, @@ -1345,6 +1499,7 @@ class PullRequestModel(BaseModel): 'pull_request_url': pr_url, 'thread_ids': [pr_url], + 'user_role': role } # pre-generate the subject for notification itself @@ -1353,7 +1508,7 @@ class PullRequestModel(BaseModel): # create notification objects, and emails NotificationModel().create( - created_by=pull_request.author, + created_by=current_rhodecode_user, notification_subject=subject, notification_body=body_plaintext, notification_type=notification_type, @@ -1361,11 +1516,19 @@ class PullRequestModel(BaseModel): email_kwargs=kwargs, ) + def notify_reviewers(self, pull_request, reviewers_ids, user): + return self._notify_reviewers(pull_request, reviewers_ids, + PullRequestReviewers.ROLE_REVIEWER, user) + + def notify_observers(self, pull_request, observers_ids, user): + return self._notify_reviewers(pull_request, observers_ids, + PullRequestReviewers.ROLE_OBSERVER, user) + def notify_users(self, pull_request, updating_user, ancestor_commit_id, commit_changes, file_changes): updating_user_id = updating_user.user_id - reviewers = set([x.user.user_id for x in pull_request.reviewers]) + reviewers = set([x.user.user_id for x in pull_request.get_pull_request_reviewers()]) # NOTE(marcink): send notification to all other users except to # person who updated the PR recipients = reviewers.difference(set([updating_user_id])) @@ -1874,11 +2037,13 @@ class PullRequestModel(BaseModel): try: from rc_reviewers.utils import get_default_reviewers_data from rc_reviewers.utils import validate_default_reviewers + from rc_reviewers.utils import validate_observers except ImportError: from rhodecode.apps.repository.utils import get_default_reviewers_data from rhodecode.apps.repository.utils import validate_default_reviewers + from rhodecode.apps.repository.utils import validate_observers - return get_default_reviewers_data, validate_default_reviewers + return get_default_reviewers_data, validate_default_reviewers, validate_observers class MergeCheck(object): diff --git a/rhodecode/model/user.py b/rhodecode/model/user.py --- a/rhodecode/model/user.py +++ b/rhodecode/model/user.py @@ -42,7 +42,7 @@ from rhodecode.lib.exceptions import ( from rhodecode.lib.caching_query import FromCache from rhodecode.model import BaseModel from rhodecode.model.db import ( - _hash_key, true, false, or_, joinedload, User, UserToPerm, + _hash_key, func, true, false, or_, joinedload, User, UserToPerm, UserEmailMap, UserIpMap, UserLog) from rhodecode.model.meta import Session from rhodecode.model.auth_token import AuthTokenModel @@ -96,7 +96,11 @@ class UserModel(BaseModel): User.username.ilike(ilike_expression) ) ) + # sort by len to have top most matches first + query = query.order_by(func.length(User.username))\ + .order_by(User.username) query = query.limit(limit) + users = query.all() _users = [ diff --git a/rhodecode/model/validation_schema/schemas/reviewer_schema.py b/rhodecode/model/validation_schema/schemas/reviewer_schema.py --- a/rhodecode/model/validation_schema/schemas/reviewer_schema.py +++ b/rhodecode/model/validation_schema/schemas/reviewer_schema.py @@ -21,12 +21,17 @@ import colander from rhodecode.model.validation_schema import validators, preparers, types +DEFAULT_ROLE = 'reviewer' +VALID_ROLES = ['reviewer', 'observer'] + class ReviewerSchema(colander.MappingSchema): username = colander.SchemaNode(types.StrOrIntType()) reasons = colander.SchemaNode(colander.List(), missing=['no reason specified']) mandatory = colander.SchemaNode(colander.Boolean(), missing=False) rules = colander.SchemaNode(colander.List(), missing=[]) + role = colander.SchemaNode(colander.String(), missing=DEFAULT_ROLE, + validator=colander.OneOf(VALID_ROLES)) class ReviewerListSchema(colander.SequenceSchema): diff --git a/rhodecode/public/502.html b/rhodecode/public/502.html --- a/rhodecode/public/502.html +++ b/rhodecode/public/502.html @@ -97,6 +97,7 @@
  • The server is being restarted.
  • The server is overloaded.
  • The link may be incorrect.
  • +
  • Reload page
  • diff --git a/rhodecode/public/css/main.less b/rhodecode/public/css/main.less --- a/rhodecode/public/css/main.less +++ b/rhodecode/public/css/main.less @@ -374,9 +374,6 @@ ul.auth_plugins { background-color: @grey6; } - .td-status { - padding-left: .5em; - } .log-container .truncate { height: 2.75em; white-space: pre-line; @@ -384,6 +381,10 @@ ul.auth_plugins { table.rctable .user { padding-left: 0; } + .td-status { + padding: 0 0px 0px 10px; + width: 15px; + } table.rctable { td.td-description, .rc-user { @@ -494,7 +495,8 @@ ul.auth_plugins { padding-top: 10px; } -#add_reviewer_input { +#add_reviewer_input, +#add_observer_input { padding-top: 10px } @@ -1700,8 +1702,33 @@ table.group_members { } .reviewer_ac .ac-input { + width: 98%; + margin-bottom: 1em; +} + +.observer_ac .ac-input { + width: 98%; + margin-bottom: 1em; +} + +.rule-table { width: 100%; - margin-bottom: 1em; +} + +.rule-table td { + +} + +.rule-table .td-role { + width: 100px +} + +.rule-table .td-mandatory { + width: 100px +} + +.rule-table .td-group-votes { + width: 150px } .compare_view_commits tr{ @@ -2635,6 +2662,7 @@ h3.files_location{ li { list-style-type: none } + } .grid-filter-box-icon { diff --git a/rhodecode/public/css/summary.less b/rhodecode/public/css/summary.less --- a/rhodecode/public/css/summary.less +++ b/rhodecode/public/css/summary.less @@ -477,23 +477,3 @@ } } - -.rctable.repo_summary { - border: 1px solid #eaeaea; - border-radius: 2px; - border-collapse: inherit; - border-bottom: 0; - - th { - background: @grey7; - border-bottom: 0; - } - - td { - border-color: #eaeaea; - } - - td.td-status { - padding: 0 0 0 10px; - } -} diff --git a/rhodecode/public/css/tables.less b/rhodecode/public/css/tables.less --- a/rhodecode/public/css/tables.less +++ b/rhodecode/public/css/tables.less @@ -4,6 +4,25 @@ // see style guide documentation for guidelines. // TABLES +table.rctable.table-bordered { + border: 1px solid #eaeaea; + border-radius: 2px; + border-collapse: inherit; + border-bottom: 0; + + th { + background: @grey7; + border-bottom: 0; + } + + td { + border-color: #eaeaea; + } + + td.td-status { + padding: 0 0 0 10px; + } +} .rctable, table.rctable, @@ -306,12 +325,14 @@ table.dataTable { } } } + .rctable.audit-log { td { vertical-align: top; } } + // TRUNCATING // TODO: lisaq: should this possibly be moved out of tables.less? // for truncated text @@ -426,15 +447,6 @@ table.keyboard-mappings { } } -// Pull Request List Table -#pull_request_list_table.dataTable { - - //TODO: lisa: This needs to be removed once the description is adjusted - // for using an expand_commit button (see issue 765) - td { - vertical-align: middle; - } -} // Settings (no border) table.rctable.dl-settings { @@ -484,9 +496,6 @@ table.trending_language_tbl { // Changesets #changesets.rctable { - th { - padding: 0 1em 0.65em 0; - } // td must be fixed height for graph td { diff --git a/rhodecode/public/css/type.less b/rhodecode/public/css/type.less --- a/rhodecode/public/css/type.less +++ b/rhodecode/public/css/type.less @@ -344,6 +344,10 @@ mark, width: 200px; } + #obj_count { + line-height: 34px; + } + } #readme .title { diff --git a/rhodecode/public/js/rhodecode/i18n/be.js b/rhodecode/public/js/rhodecode/i18n/be.js --- a/rhodecode/public/js/rhodecode/i18n/be.js +++ b/rhodecode/public/js/rhodecode/i18n/be.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Add another comment', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Delete', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Stop following this repository', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Submitting...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/de.js b/rhodecode/public/js/rhodecode/i18n/de.js --- a/rhodecode/public/js/rhodecode/i18n/de.js +++ b/rhodecode/public/js/rhodecode/i18n/de.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Add another comment', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Löschen', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Stop following this repository', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Submitting...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/en.js b/rhodecode/public/js/rhodecode/i18n/en.js --- a/rhodecode/public/js/rhodecode/i18n/en.js +++ b/rhodecode/public/js/rhodecode/i18n/en.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Add another comment', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Delete', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Stop following this repository', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Submitting...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/es.js b/rhodecode/public/js/rhodecode/i18n/es.js --- a/rhodecode/public/js/rhodecode/i18n/es.js +++ b/rhodecode/public/js/rhodecode/i18n/es.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Add another comment', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Delete', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Stop following this repository', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Submitting...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/fr.js b/rhodecode/public/js/rhodecode/i18n/fr.js --- a/rhodecode/public/js/rhodecode/i18n/fr.js +++ b/rhodecode/public/js/rhodecode/i18n/fr.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Add another comment', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Supprimer', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Arrêter de suivre ce dépôt', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Envoi…', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/it.js b/rhodecode/public/js/rhodecode/i18n/it.js --- a/rhodecode/public/js/rhodecode/i18n/it.js +++ b/rhodecode/public/js/rhodecode/i18n/it.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Aggiungi un altro commento', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Elimina', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'Nessun risultato', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Smetti di seguire il repository', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Inoltro...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'Al momento non ci sono richieste di PULL che richiedono il tuo intervento', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/ja.js b/rhodecode/public/js/rhodecode/i18n/ja.js --- a/rhodecode/public/js/rhodecode/i18n/ja.js +++ b/rhodecode/public/js/rhodecode/i18n/ja.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': '別のコメントを追加', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': '選択したステータス ({0}) を元にコメントが自動的に設定されます...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': '削除', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'まだリポジトリグループがありません。', 'No repository groups present.': 'No repository groups present.', 'No results': '結果がありません', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'まだタグがありません。', 'No user groups available yet.': 'まだユーザーグループがありません。', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'このリポジトリのフォローをやめる', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': '送信中...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/js_translations.js b/rhodecode/public/js/rhodecode/i18n/js_translations.js --- a/rhodecode/public/js/rhodecode/i18n/js_translations.js +++ b/rhodecode/public/js/rhodecode/i18n/js_translations.js @@ -1,5 +1,7 @@ // AUTO GENERATED FILE FOR Babel JS-GETTEXT EXTRACTORS, DO NOT CHANGE _gettext('(from usergroup {0})'); +_gettext(', and {0} file changed.'); +_gettext(', and {0} files changed.'); _gettext('{0} file changed, '); _gettext('{0} files changed, '); _gettext('Add another comment'); @@ -21,6 +23,8 @@ _gettext('Comment body was not changed.'); _gettext('Comment text will be set automatically based on currently selected status ({0}) ...'); _gettext('Commit Authors are not allowed to be a reviewer.'); +_gettext('Compare summary: {0} commit'); +_gettext('Compare summary: {0} commits'); _gettext('Context file: '); _gettext('Delete'); _gettext('Delete this comment?'); @@ -58,6 +62,7 @@ _gettext('No repository groups available yet.'); _gettext('No repository groups present.'); _gettext('No results'); +_gettext('No review rules set.'); _gettext('No ssh keys available yet.'); _gettext('No tags available yet.'); _gettext('No user groups available yet.'); @@ -95,11 +100,13 @@ _gettext('Stop following this repository'); _gettext('Stopped watching this repository'); _gettext('Submitting...'); +_gettext('Switch target repository with the source.'); _gettext('Switch to chat'); _gettext('Switch to comment'); _gettext('TODO comment'); _gettext('TODO from comment {0} was fixed.'); _gettext('There are currently no open pull requests requiring your participation.'); +_gettext('There are no commits to merge.'); _gettext('There is a later version of file tree available. Click {0} to create a file at the latest tree.'); _gettext('There is an existing path `{0}` at this commit.'); _gettext('This pull requests will consist of {0} commit.'); diff --git a/rhodecode/public/js/rhodecode/i18n/pl.js b/rhodecode/public/js/rhodecode/i18n/pl.js --- a/rhodecode/public/js/rhodecode/i18n/pl.js +++ b/rhodecode/public/js/rhodecode/i18n/pl.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Dodaj kolejny komentarz', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Usuń', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Zakończyć obserwację tego repozytorium', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Przesyłanie...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/pt.js b/rhodecode/public/js/rhodecode/i18n/pt.js --- a/rhodecode/public/js/rhodecode/i18n/pt.js +++ b/rhodecode/public/js/rhodecode/i18n/pt.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Adicionar outro comentário', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Excluir', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Parar de seguir este repositório', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Enviando...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/ru.js b/rhodecode/public/js/rhodecode/i18n/ru.js --- a/rhodecode/public/js/rhodecode/i18n/ru.js +++ b/rhodecode/public/js/rhodecode/i18n/ru.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Добавить другой комментарий', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': 'Удалить', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': 'Отменить наблюдение за репозиторием', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': 'Применение...', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/rhodecode/i18n/zh.js b/rhodecode/public/js/rhodecode/i18n/zh.js --- a/rhodecode/public/js/rhodecode/i18n/zh.js +++ b/rhodecode/public/js/rhodecode/i18n/zh.js @@ -6,6 +6,8 @@ //JS translations map var _TM = { '(from usergroup {0})': '(from usergroup {0})', + ', and {0} file changed.': ', and {0} file changed.', + ', and {0} files changed.': ', and {0} files changed.', '{0} file changed, ': '{0} file changed, ', '{0} files changed, ': '{0} files changed, ', 'Add another comment': 'Add another comment', @@ -27,6 +29,8 @@ var _TM = { 'Comment body was not changed.': 'Comment body was not changed.', 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', + 'Compare summary: {0} commit': 'Compare summary: {0} commit', + 'Compare summary: {0} commits': 'Compare summary: {0} commits', 'Context file: ': 'Context file: ', 'Delete': '删除', 'Delete this comment?': 'Delete this comment?', @@ -64,6 +68,7 @@ var _TM = { 'No repository groups available yet.': 'No repository groups available yet.', 'No repository groups present.': 'No repository groups present.', 'No results': 'No results', + 'No review rules set.': 'No review rules set.', 'No ssh keys available yet.': 'No ssh keys available yet.', 'No tags available yet.': 'No tags available yet.', 'No user groups available yet.': 'No user groups available yet.', @@ -101,11 +106,13 @@ var _TM = { 'Stop following this repository': '停止关注该版本库', 'Stopped watching this repository': 'Stopped watching this repository', 'Submitting...': '提交中……', + 'Switch target repository with the source.': 'Switch target repository with the source.', 'Switch to chat': 'Switch to chat', 'Switch to comment': 'Switch to comment', 'TODO comment': 'TODO comment', 'TODO from comment {0} was fixed.': 'TODO from comment {0} was fixed.', 'There are currently no open pull requests requiring your participation.': 'There are currently no open pull requests requiring your participation.', + 'There are no commits to merge.': 'There are no commits to merge.', 'There is a later version of file tree available. Click {0} to create a file at the latest tree.': 'There is a later version of file tree available. Click {0} to create a file at the latest tree.', 'There is an existing path `{0}` at this commit.': 'There is an existing path `{0}` at this commit.', 'This pull requests will consist of {0} commit.': 'This pull requests will consist of {0} commit.', diff --git a/rhodecode/public/js/src/rhodecode/changelog.js b/rhodecode/public/js/src/rhodecode/changelog.js --- a/rhodecode/public/js/src/rhodecode/changelog.js +++ b/rhodecode/public/js/src/rhodecode/changelog.js @@ -75,8 +75,8 @@ var CommitsController = function () { height: height, x_step: x_step, y_step: 42, - dotRadius: 3.5, - lineWidth: 2.5 + dotRadius: 3.8, + lineWidth: 2.8 }; var prevCommitsData = this.$graphCanvas.data('commits') || []; @@ -98,11 +98,12 @@ var CommitsController = function () { this.setLabelText(edgeData); - var padding = 90; + // main padding from top, aligns the first dot graph + var padding = 100; if (prev_link) { padding += 34; + } - } $('#graph_nodes').css({'padding-top': padding}); $.each($('.message.truncate'), function(idx, value) { diff --git a/rhodecode/public/js/src/rhodecode/pullrequests.js b/rhodecode/public/js/src/rhodecode/pullrequests.js --- a/rhodecode/public/js/src/rhodecode/pullrequests.js +++ b/rhodecode/public/js/src/rhodecode/pullrequests.js @@ -94,21 +94,26 @@ var getTitleAndDescription = function(so }; -ReviewersController = function () { +window.ReviewersController = function () { var self = this; + this.$loadingIndicator = $('.calculate-reviewers'); this.$reviewRulesContainer = $('#review_rules'); this.$rulesList = this.$reviewRulesContainer.find('.pr-reviewer-rules'); this.$userRule = $('.pr-user-rule-container'); - this.forbidReviewUsers = undefined; this.$reviewMembers = $('#review_members'); + this.$observerMembers = $('#observer_members'); + this.currentRequest = null; this.diffData = null; this.enabledRules = []; + // sync with db.py entries + this.ROLE_REVIEWER = 'reviewer'; + this.ROLE_OBSERVER = 'observer' //dummy handler, we might register our own later - this.diffDataHandler = function(data){}; + this.diffDataHandler = function (data) {}; - this.defaultForbidReviewUsers = function () { + this.defaultForbidUsers = function () { return [ { 'username': 'default', @@ -117,6 +122,9 @@ ReviewersController = function () { ]; }; + // init default forbidden users + this.forbidUsers = this.defaultForbidUsers(); + this.hideReviewRules = function () { self.$reviewRulesContainer.hide(); $(self.$userRule.selector).hide(); @@ -133,11 +141,40 @@ ReviewersController = function () { return '
    - {0}
    '.format(ruleText) }; + this.increaseCounter = function(role) { + if (role === self.ROLE_REVIEWER) { + var $elem = $('#reviewers-cnt') + var cnt = parseInt($elem.data('count') || 0) + cnt +=1 + $elem.html(cnt); + $elem.data('count', cnt); + } + else if (role === self.ROLE_OBSERVER) { + var $elem = $('#observers-cnt'); + var cnt = parseInt($elem.data('count') || 0) + cnt +=1 + $elem.html(cnt); + $elem.data('count', cnt); + } + } + + this.resetCounter = function () { + var $elem = $('#reviewers-cnt'); + + $elem.data('count', 0); + $elem.html(0); + + var $elem = $('#observers-cnt'); + + $elem.data('count', 0); + $elem.html(0); + } + this.loadReviewRules = function (data) { self.diffData = data; // reset forbidden Users - this.forbidReviewUsers = self.defaultForbidReviewUsers(); + this.forbidUsers = self.defaultForbidUsers(); // reset state of review rules self.$rulesList.html(''); @@ -148,7 +185,7 @@ ReviewersController = function () { self.addRule( _gettext('All reviewers must vote.')) ); - return self.forbidReviewUsers + return self.forbidUsers } if (data.rules.voting !== undefined) { @@ -195,7 +232,7 @@ ReviewersController = function () { } if (data.rules.forbid_author_to_review) { - self.forbidReviewUsers.push(data.rules_data.pr_author); + self.forbidUsers.push(data.rules_data.pr_author); self.$rulesList.append( self.addRule( _gettext('Author is not allowed to be a reviewer.')) @@ -206,9 +243,8 @@ ReviewersController = function () { if (data.rules_data.forbidden_users) { $.each(data.rules_data.forbidden_users, function (index, member_data) { - self.forbidReviewUsers.push(member_data) + self.forbidUsers.push(member_data) }); - } self.$rulesList.append( @@ -223,9 +259,31 @@ ReviewersController = function () { _gettext('No review rules set.')) } - return self.forbidReviewUsers + return self.forbidUsers }; + this.emptyTables = function () { + self.emptyReviewersTable(); + self.emptyObserversTable(); + + // Also reset counters. + self.resetCounter(); + } + + this.emptyReviewersTable = function (withText) { + self.$reviewMembers.empty(); + if (withText !== undefined) { + self.$reviewMembers.html(withText) + } + }; + + this.emptyObserversTable = function (withText) { + self.$observerMembers.empty(); + if (withText !== undefined) { + self.$observerMembers.html(withText) + } + } + this.loadDefaultReviewers = function (sourceRepo, sourceRef, targetRepo, targetRef) { if (self.currentRequest) { @@ -233,19 +291,21 @@ ReviewersController = function () { self.currentRequest.abort(); } - $('.calculate-reviewers').show(); - // reset reviewer members - self.$reviewMembers.empty(); + self.$loadingIndicator.show(); + + // reset reviewer/observe members + self.emptyTables(); prButtonLock(true, null, 'reviewers'); $('#user').hide(); // hide user autocomplete before load + $('#observer').hide(); //hide observer autocomplete before load // lock PR button, so we cannot send PR before it's calculated prButtonLock(true, _gettext('Loading diff ...'), 'compare'); if (sourceRef.length !== 3 || targetRef.length !== 3) { // don't load defaults in case we're missing some refs... - $('.calculate-reviewers').hide(); + self.$loadingIndicator.hide(); return } @@ -253,9 +313,13 @@ ReviewersController = function () { { 'repo_name': templateContext.repo_name, 'source_repo': sourceRepo, + 'source_ref_type': sourceRef[0], + 'source_ref_name': sourceRef[1], 'source_ref': sourceRef[2], 'target_repo': targetRepo, - 'target_ref': targetRef[2] + 'target_ref': targetRef[2], + 'target_ref_type': sourceRef[0], + 'target_ref_name': sourceRef[1] }); self.currentRequest = $.ajax({ @@ -268,15 +332,23 @@ ReviewersController = function () { // review rules self.loadReviewRules(data); - self.handleDiffData(data["diff_info"]); + var diffHandled = self.handleDiffData(data["diff_info"]); + if (diffHandled === false) { + return + } for (var i = 0; i < data.reviewers.length; i++) { var reviewer = data.reviewers[i]; - self.addReviewMember(reviewer, reviewer.reasons, reviewer.mandatory); + // load reviewer rules from the repo data + self.addMember(reviewer, reviewer.reasons, reviewer.mandatory, reviewer.role); } - $('.calculate-reviewers').hide(); + + + self.$loadingIndicator.hide(); prButtonLock(false, null, 'reviewers'); - $('#user').show(); // show user autocomplete after load + + $('#user').show(); // show user autocomplete before load + $('#observer').show(); // show observer autocomplete before load var commitElements = data["diff_info"]['commits']; @@ -292,7 +364,7 @@ ReviewersController = function () { }, error: function (jqXHR, textStatus, errorThrown) { - var prefix = "Loading diff and reviewers failed\n" + var prefix = "Loading diff and reviewers/observers failed\n" var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix); ajaxErrorSwal(message); } @@ -301,7 +373,7 @@ ReviewersController = function () { }; // check those, refactor - this.removeReviewMember = function (reviewer_id, mark_delete) { + this.removeMember = function (reviewer_id, mark_delete) { var reviewer = $('#reviewer_{0}'.format(reviewer_id)); if (typeof (mark_delete) === undefined) { @@ -312,6 +384,7 @@ ReviewersController = function () { if (reviewer) { // now delete the input $('#reviewer_{0} input'.format(reviewer_id)).remove(); + $('#reviewer_{0}_rules input'.format(reviewer_id)).remove(); // mark as to-delete var obj = $('#reviewer_{0}_name'.format(reviewer_id)); obj.addClass('to-delete'); @@ -322,27 +395,26 @@ ReviewersController = function () { } }; - this.reviewMemberEntry = function () { + this.addMember = function (reviewer_obj, reasons, mandatory, role) { - }; - - this.addReviewMember = function (reviewer_obj, reasons, mandatory) { var id = reviewer_obj.user_id; var username = reviewer_obj.username; - var reasons = reasons || []; - var mandatory = mandatory || false; + reasons = reasons || []; + mandatory = mandatory || false; + role = role || self.ROLE_REVIEWER - // register IDS to check if we don't have this ID already in + // register current set IDS to check if we don't have this ID already in + // and prevent duplicates var currentIds = []; - $.each(self.$reviewMembers.find('.reviewer_entry'), function (index, value) { + $.each($('.reviewer_entry'), function (index, value) { currentIds.push($(value).data('reviewerUserId')) }) var userAllowedReview = function (userId) { var allowed = true; - $.each(self.forbidReviewUsers, function (index, member_data) { + $.each(self.forbidUsers, function (index, member_data) { if (parseInt(userId) === member_data['user_id']) { allowed = false; return false // breaks the loop @@ -352,6 +424,7 @@ ReviewersController = function () { }; var userAllowed = userAllowedReview(id); + if (!userAllowed) { alert(_gettext('User `{0}` not allowed to be a reviewer').format(username)); } else { @@ -359,11 +432,13 @@ ReviewersController = function () { var alreadyReviewer = currentIds.indexOf(id) != -1; if (alreadyReviewer) { - alert(_gettext('User `{0}` already in reviewers').format(username)); + alert(_gettext('User `{0}` already in reviewers/observers').format(username)); } else { + var reviewerEntry = renderTemplate('reviewMemberEntry', { 'member': reviewer_obj, 'mandatory': mandatory, + 'role': role, 'reasons': reasons, 'allowed_to_update': true, 'review_status': 'not_reviewed', @@ -372,20 +447,36 @@ ReviewersController = function () { 'create': true, 'rule_show': true, }) - $(self.$reviewMembers.selector).append(reviewerEntry); + + if (role === self.ROLE_REVIEWER) { + $(self.$reviewMembers.selector).append(reviewerEntry); + self.increaseCounter(self.ROLE_REVIEWER); + $('#reviewer-empty-msg').remove() + } + else if (role === self.ROLE_OBSERVER) { + $(self.$observerMembers.selector).append(reviewerEntry); + self.increaseCounter(self.ROLE_OBSERVER); + $('#observer-empty-msg').remove(); + } + tooltipActivate(); } } }; - this.updateReviewers = function (repo_name, pull_request_id) { - var postData = $('#reviewers input').serialize(); - _updatePullRequest(repo_name, pull_request_id, postData); + this.updateReviewers = function (repo_name, pull_request_id, role) { + if (role === 'reviewer') { + var postData = $('#reviewers input').serialize(); + _updatePullRequest(repo_name, pull_request_id, postData); + } else if (role === 'observer') { + var postData = $('#observers input').serialize(); + _updatePullRequest(repo_name, pull_request_id, postData); + } }; this.handleDiffData = function (data) { - self.diffDataHandler(data) + return self.diffDataHandler(data) } }; @@ -449,35 +540,26 @@ var editPullRequest = function(repo_name /** - * Reviewer autocomplete + * autocomplete handler for reviewers/observers */ -var ReviewerAutoComplete = function(inputId) { - $(inputId).autocomplete({ - serviceUrl: pyroutes.url('user_autocomplete_data'), - minChars:2, - maxHeight:400, - deferRequestBy: 300, //miliseconds - showNoSuggestionNotice: true, - tabDisabled: true, - autoSelectFirst: true, - params: { user_id: templateContext.rhodecode_user.user_id, user_groups:true, user_groups_expand:true, skip_default_user:true }, - formatResult: autocompleteFormatResult, - lookupFilter: autocompleteFilterResult, - onSelect: function(element, data) { +var autoCompleteHandler = function (inputId, controller, role) { + + return function (element, data) { var mandatory = false; - var reasons = [_gettext('added manually by "{0}"').format(templateContext.rhodecode_user.username)]; + var reasons = [_gettext('added manually by "{0}"').format( + templateContext.rhodecode_user.username)]; // add whole user groups if (data.value_type == 'user_group') { reasons.push(_gettext('member of "{0}"').format(data.value_display)); - $.each(data.members, function(index, member_data) { + $.each(data.members, function (index, member_data) { var reviewer = member_data; reviewer['user_id'] = member_data['id']; reviewer['gravatar_link'] = member_data['icon_link']; reviewer['user_link'] = member_data['profile_link']; reviewer['rules'] = []; - reviewersController.addReviewMember(reviewer, reasons, mandatory); + controller.addMember(reviewer, reasons, mandatory, role); }) } // add single user @@ -487,14 +569,71 @@ var ReviewerAutoComplete = function(inpu reviewer['gravatar_link'] = data['icon_link']; reviewer['user_link'] = data['profile_link']; reviewer['rules'] = []; - reviewersController.addReviewMember(reviewer, reasons, mandatory); + controller.addMember(reviewer, reasons, mandatory, role); } - $(inputId).val(''); + $(inputId).val(''); } - }); +} + +/** + * Reviewer autocomplete + */ +var ReviewerAutoComplete = function (inputId, controller) { + var self = this; + self.controller = controller; + self.inputId = inputId; + var handler = autoCompleteHandler(inputId, controller, controller.ROLE_REVIEWER); + + $(inputId).autocomplete({ + serviceUrl: pyroutes.url('user_autocomplete_data'), + minChars: 2, + maxHeight: 400, + deferRequestBy: 300, //miliseconds + showNoSuggestionNotice: true, + tabDisabled: true, + autoSelectFirst: true, + params: { + user_id: templateContext.rhodecode_user.user_id, + user_groups: true, + user_groups_expand: true, + skip_default_user: true + }, + formatResult: autocompleteFormatResult, + lookupFilter: autocompleteFilterResult, + onSelect: handler + }); }; +/** + * Observers autocomplete + */ +var ObserverAutoComplete = function(inputId, controller) { + var self = this; + self.controller = controller; + self.inputId = inputId; + var handler = autoCompleteHandler(inputId, controller, controller.ROLE_OBSERVER); + + $(inputId).autocomplete({ + serviceUrl: pyroutes.url('user_autocomplete_data'), + minChars: 2, + maxHeight: 400, + deferRequestBy: 300, //miliseconds + showNoSuggestionNotice: true, + tabDisabled: true, + autoSelectFirst: true, + params: { + user_id: templateContext.rhodecode_user.user_id, + user_groups: true, + user_groups_expand: true, + skip_default_user: true + }, + formatResult: autocompleteFormatResult, + lookupFilter: autocompleteFilterResult, + onSelect: handler + }); +} + window.VersionController = function () { var self = this; @@ -504,7 +643,7 @@ window.VersionController = function () { this.adjustRadioSelectors = function (curNode) { var getVal = function (item) { - if (item == 'latest') { + if (item === 'latest') { return Number.MAX_SAFE_INTEGER } else { @@ -663,6 +802,7 @@ window.UpdatePrController = function () }; }; + /** * Reviewer display panel */ @@ -673,6 +813,7 @@ window.ReviewersPanel = { removeButtons: null, reviewRules: null, setReviewers: null, + controller: null, setSelectors: function () { var self = this; @@ -682,17 +823,18 @@ window.ReviewersPanel = { self.removeButtons = $('.reviewer_member_remove,.reviewer_member_mandatory_remove'); }, - init: function (reviewRules, setReviewers) { + init: function (controller, reviewRules, setReviewers) { var self = this; self.setSelectors(); - this.reviewRules = reviewRules; - this.setReviewers = setReviewers; + self.controller = controller; + self.reviewRules = reviewRules; + self.setReviewers = setReviewers; - this.editButton.on('click', function (e) { + self.editButton.on('click', function (e) { self.edit(); }); - this.closeButton.on('click', function (e) { + self.closeButton.on('click', function (e) { self.close(); self.renderReviewers(); }); @@ -702,26 +844,134 @@ window.ReviewersPanel = { }, renderReviewers: function () { + var self = this; - $('#review_members').html('') - $.each(this.setReviewers.reviewers, function (key, val) { + if (self.setReviewers.reviewers === undefined) { + return + } + if (self.setReviewers.reviewers.length === 0) { + self.controller.emptyReviewersTable('No reviewers'); + return + } + + self.controller.emptyReviewersTable(); + + $.each(self.setReviewers.reviewers, function (key, val) { + var member = val; + if (member.role === self.controller.ROLE_REVIEWER) { + var entry = renderTemplate('reviewMemberEntry', { + 'member': member, + 'mandatory': member.mandatory, + 'role': member.role, + 'reasons': member.reasons, + 'allowed_to_update': member.allowed_to_update, + 'review_status': member.review_status, + 'review_status_label': member.review_status_label, + 'user_group': member.user_group, + 'create': false + }); + + $(self.controller.$reviewMembers.selector).append(entry) + } + }); + + tooltipActivate(); + }, + + edit: function (event) { + var self = this; + self.editButton.hide(); + self.closeButton.show(); + self.addButton.show(); + $(self.removeButtons.selector).css('visibility', 'visible'); + // review rules + self.controller.loadReviewRules(this.reviewRules); + }, + + close: function (event) { + var self = this; + this.editButton.show(); + this.closeButton.hide(); + this.addButton.hide(); + $(this.removeButtons.selector).css('visibility', 'hidden'); + // hide review rules + self.controller.hideReviewRules(); + } +}; - var entry = renderTemplate('reviewMemberEntry', { - 'member': member, - 'mandatory': member.mandatory, - 'reasons': member.reasons, - 'allowed_to_update': member.allowed_to_update, - 'review_status': member.review_status, - 'review_status_label': member.review_status_label, - 'user_group': member.user_group, - 'create': false - }); +/** + * Reviewer display panel + */ +window.ObserversPanel = { + editButton: null, + closeButton: null, + addButton: null, + removeButtons: null, + reviewRules: null, + setReviewers: null, + controller: null, + + setSelectors: function () { + var self = this; + self.editButton = $('#open_edit_observers'); + self.closeButton =$('#close_edit_observers'); + self.addButton = $('#add_observer'); + self.removeButtons = $('.observer_member_remove,.observer_member_mandatory_remove'); + }, + + init: function (controller, reviewRules, setReviewers) { + var self = this; + self.setSelectors(); + + self.controller = controller; + self.reviewRules = reviewRules; + self.setReviewers = setReviewers; + + self.editButton.on('click', function (e) { + self.edit(); + }); + self.closeButton.on('click', function (e) { + self.close(); + self.renderObservers(); + }); - $('#review_members').append(entry) + self.renderObservers(); + + }, + + renderObservers: function () { + var self = this; + if (self.setReviewers.observers === undefined) { + return + } + if (self.setReviewers.observers.length === 0) { + self.controller.emptyObserversTable('No observers'); + return + } + + self.controller.emptyObserversTable(); + + $.each(self.setReviewers.observers, function (key, val) { + var member = val; + if (member.role === self.controller.ROLE_OBSERVER) { + var entry = renderTemplate('reviewMemberEntry', { + 'member': member, + 'mandatory': member.mandatory, + 'role': member.role, + 'reasons': member.reasons, + 'allowed_to_update': member.allowed_to_update, + 'review_status': member.review_status, + 'review_status_label': member.review_status_label, + 'user_group': member.user_group, + 'create': false + }); + + $(self.controller.$observerMembers.selector).append(entry) + } }); + tooltipActivate(); - }, edit: function (event) { @@ -729,8 +979,6 @@ window.ReviewersPanel = { this.closeButton.show(); this.addButton.show(); $(this.removeButtons.selector).css('visibility', 'visible'); - // review rules - reviewersController.loadReviewRules(this.reviewRules); }, close: function (event) { @@ -738,12 +986,56 @@ window.ReviewersPanel = { this.closeButton.hide(); this.addButton.hide(); $(this.removeButtons.selector).css('visibility', 'hidden'); - // hide review rules - reviewersController.hideReviewRules() + } + +}; + +window.PRDetails = { + editButton: null, + closeButton: null, + deleteButton: null, + viewFields: null, + editFields: null, + + setSelectors: function () { + var self = this; + self.editButton = $('#open_edit_pullrequest') + self.closeButton = $('#close_edit_pullrequest') + self.deleteButton = $('#delete_pullrequest') + self.viewFields = $('#pr-desc, #pr-title') + self.editFields = $('#pr-desc-edit, #pr-title-edit, .pr-save') + }, + + init: function () { + var self = this; + self.setSelectors(); + self.editButton.on('click', function (e) { + self.edit(); + }); + self.closeButton.on('click', function (e) { + self.view(); + }); + }, + + edit: function (event) { + var cmInstance = $('#pr-description-input').get(0).MarkupForm.cm; + this.viewFields.hide(); + this.editButton.hide(); + this.deleteButton.hide(); + this.closeButton.show(); + this.editFields.show(); + cmInstance.refresh(); + }, + + view: function (event) { + this.editButton.show(); + this.deleteButton.show(); + this.editFields.hide(); + this.closeButton.hide(); + this.viewFields.show(); } }; - /** * OnLine presence using channelstream */ @@ -813,29 +1105,29 @@ window.refreshComments = function (versi $.each($('.comment'), function (idx, element) { currentIDs.push($(element).data('commentId')); }); - var data = {"comments[]": currentIDs}; + var data = {"comments": currentIDs}; var $targetElem = $('.comments-content-table'); $targetElem.css('opacity', 0.3); - $targetElem.load( - loadUrl, data, function (responseText, textStatus, jqXHR) { - if (jqXHR.status !== 200) { - return false; - } - var $counterElem = $('#comments-count'); - var newCount = $(responseText).data('counter'); - if (newCount !== undefined) { - var callback = function () { - $counterElem.animate({'opacity': 1.00}, 200) - $counterElem.html(newCount); - }; - $counterElem.animate({'opacity': 0.15}, 200, callback); - } - $targetElem.css('opacity', 1); - tooltipActivate(); + var success = function (data) { + var $counterElem = $('#comments-count'); + var newCount = $(data).data('counter'); + if (newCount !== undefined) { + var callback = function () { + $counterElem.animate({'opacity': 1.00}, 200) + $counterElem.html(newCount); + }; + $counterElem.animate({'opacity': 0.15}, 200, callback); } - ); + + $targetElem.css('opacity', 1); + $targetElem.html(data); + tooltipActivate(); + } + + ajaxPOST(loadUrl, data, success, null, {}) + } window.refreshTODOs = function (version) { @@ -858,28 +1150,28 @@ window.refreshTODOs = function (version) currentIDs.push($(element).data('commentId')); }); - var data = {"comments[]": currentIDs}; + var data = {"comments": currentIDs}; var $targetElem = $('.todos-content-table'); $targetElem.css('opacity', 0.3); - $targetElem.load( - loadUrl, data, function (responseText, textStatus, jqXHR) { - if (jqXHR.status !== 200) { - return false; - } - var $counterElem = $('#todos-count') - var newCount = $(responseText).data('counter'); - if (newCount !== undefined) { - var callback = function () { - $counterElem.animate({'opacity': 1.00}, 200) - $counterElem.html(newCount); - }; - $counterElem.animate({'opacity': 0.15}, 200, callback); - } - $targetElem.css('opacity', 1); - tooltipActivate(); + var success = function (data) { + var $counterElem = $('#todos-count') + var newCount = $(data).data('counter'); + if (newCount !== undefined) { + var callback = function () { + $counterElem.animate({'opacity': 1.00}, 200) + $counterElem.html(newCount); + }; + $counterElem.animate({'opacity': 0.15}, 200, callback); } - ); + + $targetElem.css('opacity', 1); + $targetElem.html(data); + tooltipActivate(); + } + + ajaxPOST(loadUrl, data, success, null, {}) + } window.refreshAllComments = function (version) { @@ -888,3 +1180,12 @@ window.refreshAllComments = function (ve refreshComments(version); refreshTODOs(version); }; + +window.sidebarComment = function (commentId) { + var jsonData = $('#commentHovercard{0}'.format(commentId)).data('commentJsonB64'); + if (!jsonData) { + return 'Failed to load comment {0}'.format(commentId) + } + var funcData = JSON.parse(atob(jsonData)); + return renderTemplate('sideBarCommentHovercard', funcData) +}; diff --git a/rhodecode/public/js/src/rhodecode/utils/ajax.js b/rhodecode/public/js/src/rhodecode/utils/ajax.js --- a/rhodecode/public/js/src/rhodecode/utils/ajax.js +++ b/rhodecode/public/js/src/rhodecode/utils/ajax.js @@ -57,15 +57,18 @@ var ajaxGET = function (url, success, fa return request; }; -var ajaxPOST = function (url, postData, success, failure) { - var sUrl = url; - var postData = toQueryString(postData); - var request = $.ajax({ +var ajaxPOST = function (url, postData, success, failure, options) { + + var ajaxSettings = $.extend({ type: 'POST', - url: sUrl, - data: postData, + url: url, + data: toQueryString(postData), headers: {'X-PARTIAL-XHR': true} - }) + }, options); + + var request = $.ajax( + ajaxSettings + ) .done(function (data) { success(data); }) @@ -126,7 +129,8 @@ function formatErrorMessage(jqXHR, textS } else if (errorThrown === 'abort') { return (prefix + 'Ajax request aborted.'); } else { - return (prefix + 'Uncaught Error.\n' + jqXHR.responseText); + var errInfo = 'Uncaught Error. code: {0}\n'.format(jqXHR.status) + return (prefix + errInfo + jqXHR.responseText); } } diff --git a/rhodecode/templates/admin/my_account/my_account_pullrequests.mako b/rhodecode/templates/admin/my_account/my_account_pullrequests.mako --- a/rhodecode/templates/admin/my_account/my_account_pullrequests.mako +++ b/rhodecode/templates/admin/my_account/my_account_pullrequests.mako @@ -33,7 +33,7 @@

    ${_('Pull Requests You Participate In')}

    -
    +
    @@ -58,16 +58,10 @@ dom: 'rtp', pageLength: ${c.visual.dashboard_items}, - order: [[2, "desc"]], + order: [[1, "desc"]], columns: [ { data: { - "_": "target_repo", - "sort": "target_repo" - }, title: "${_('Target Repo')}", className: "td-targetrepo", orderable: false - }, - { - data: { "_": "status", "sort": "status" }, title: "", className: "td-status", orderable: false @@ -101,7 +95,13 @@ "_": "updated_on", "sort": "updated_on_raw" }, title: "${_('Last Update')}", className: "td-time" - } + }, + { + data: { + "_": "target_repo", + "sort": "target_repo" + }, title: "${_('Target Repo')}", className: "td-targetrepo", orderable: false + }, ], language: { paginate: DEFAULT_GRID_PAGINATION, diff --git a/rhodecode/templates/base/base.mako b/rhodecode/templates/base/base.mako --- a/rhodecode/templates/base/base.mako +++ b/rhodecode/templates/base/base.mako @@ -785,15 +785,15 @@ - Prefix query to allow special search: - user:admin, to search for usernames, always global + user:admin, to search for usernames, always global - user_group:devops, to search for user groups, always global + user_group:devops, to search for user groups, always global - pr:303, to search for pull request number, title, or description, always global + pr:303, to search for pull request number, title, or description, always global - commit:efced4, to search for commits, scoped to repositories or groups + commit:efced4, to search for commits, scoped to repositories or groups - file:models.py, to search for file paths, scoped to repositories or groups + file:models.py, to search for file paths, scoped to repositories or groups % if c.template_context['search_context']['repo_id']: For advanced full text search visit: repository search diff --git a/rhodecode/templates/base/issue_tracker_settings.mako b/rhodecode/templates/base/issue_tracker_settings.mako --- a/rhodecode/templates/base/issue_tracker_settings.mako +++ b/rhodecode/templates/base/issue_tracker_settings.mako @@ -16,8 +16,8 @@ examples = [ ), ( - 'Redmine', - '(^#|\s#)(?P\d+)', + 'Tickets with #123 (Redmine etc)', + '(?\d+)', 'https://myissueserver.com/${repo}/issue/${issue_id}', '' ), @@ -38,14 +38,15 @@ examples = [ ( 'JIRA - All tickets', - '(^|\s\w+-\d+)', - 'https://myjira.com/browse/${id}', + # official JIRA ticket pattern + '(?[A-Z]{1,6}-(?:[1-9][0-9]{0,7}))', + 'https://myjira.com/browse/${issue_id}', '' ), ( - 'JIRA - Project (JRA)', - '(?:(^|\s)(?P(?:JRA-|JRA-)(?:\d+)))', + 'JIRA - Single project (JRA-XXXXXXXX)', + '(?JRA-(?:[1-9][0-9]{0,7}))', 'https://myjira.com/${issue_id}', '' ), @@ -275,13 +276,19 @@ examples = [