Show More
The requested changes are too big and content was truncated. Show full diff
@@ -0,0 +1,60 b'' | |||||
|
1 | |RCE| 4.18.1 |RNS| | |||
|
2 | ------------------ | |||
|
3 | ||||
|
4 | Release Date | |||
|
5 | ^^^^^^^^^^^^ | |||
|
6 | ||||
|
7 | - 2020-01-20 | |||
|
8 | ||||
|
9 | ||||
|
10 | New Features | |||
|
11 | ^^^^^^^^^^^^ | |||
|
12 | ||||
|
13 | ||||
|
14 | ||||
|
15 | General | |||
|
16 | ^^^^^^^ | |||
|
17 | ||||
|
18 | - API: invalidate license cache on set_license_key call. | |||
|
19 | - API: add send_email flag for comments api to allow commenting without email notification. | |||
|
20 | - API: added pull requests versions into returned API data. | |||
|
21 | - Dashboard: fixed jumping of text in grid loading by new loading indicator. | |||
|
22 | - Installation: add few extra defaults that makes RhodeCode nicer out of the box. | |||
|
23 | - Pull Requests: small code cleanup to define other type of merge username. | |||
|
24 | RC_MERGE_USER_NAME_ATTR env variable defines what should be used from user as merge username. | |||
|
25 | - Gists: cleanup UI and make the gist access id use monospace according to the new UI. | |||
|
26 | ||||
|
27 | ||||
|
28 | Security | |||
|
29 | ^^^^^^^^ | |||
|
30 | ||||
|
31 | - Repository permission: properly flush permission caches on set private mode of repository. | |||
|
32 | Otherwise we get cached values still in place until it expires. | |||
|
33 | - Repository permission: add set/un-set of private repository from permissions page. | |||
|
34 | - Permissions: flush all user permissions in case of default user permission changes. | |||
|
35 | ||||
|
36 | ||||
|
37 | Performance | |||
|
38 | ^^^^^^^^^^^ | |||
|
39 | ||||
|
40 | - Caches: used more efficient way of fetching all users for permissions invalidation. | |||
|
41 | - Issue trackers: optimized performance of fetching issue tracker patterns. | |||
|
42 | ||||
|
43 | ||||
|
44 | Fixes | |||
|
45 | ^^^^^ | |||
|
46 | ||||
|
47 | - SSH: fixed SSH problems with EE edition. | |||
|
48 | - Branch permissions: remove emtpy tooltips on branch permission entries. | |||
|
49 | - Core: fixed cython compat inspect that caused some API calls to not work correctly in EE release. | |||
|
50 | - Audit logger: use copy of params we later modify to prevent from modification by the store | |||
|
51 | function of parameters that we only use for reading. | |||
|
52 | - Users: fixed wrong mention of readme in user description help block. | |||
|
53 | - Issue trackers: fixed wrong examples in patterns. | |||
|
54 | - Issue trackers: fixed missing option to get back to inherited settings. | |||
|
55 | ||||
|
56 | ||||
|
57 | Upgrade notes | |||
|
58 | ^^^^^^^^^^^^^ | |||
|
59 | ||||
|
60 | - Scheduled release addressing problems in 4.18.X releases. |
@@ -0,0 +1,49 b'' | |||||
|
1 | |RCE| 4.18.2 |RNS| | |||
|
2 | ------------------ | |||
|
3 | ||||
|
4 | Release Date | |||
|
5 | ^^^^^^^^^^^^ | |||
|
6 | ||||
|
7 | - 2020-01-28 | |||
|
8 | ||||
|
9 | ||||
|
10 | New Features | |||
|
11 | ^^^^^^^^^^^^ | |||
|
12 | ||||
|
13 | ||||
|
14 | ||||
|
15 | General | |||
|
16 | ^^^^^^^ | |||
|
17 | ||||
|
18 | - Permissions: add better help text about default permissions, and correlation with anonymous access enabled. | |||
|
19 | - Mentions: markdown renderer now wraps username in hovercard logic allowing checking the mentioned user. | |||
|
20 | - Documentation: added note about hard restart due to celery update. | |||
|
21 | - Maintenance: run rebuildfncache for Mercurial in maintenance command. | |||
|
22 | ||||
|
23 | ||||
|
24 | Security | |||
|
25 | ^^^^^^^^ | |||
|
26 | ||||
|
27 | ||||
|
28 | ||||
|
29 | Performance | |||
|
30 | ^^^^^^^^^^^ | |||
|
31 | ||||
|
32 | - Authentication: cache plugins for auth and their settings in the auth_registry for single request. | |||
|
33 | This heavily influences SVN performance on multiple-file commits. | |||
|
34 | ||||
|
35 | ||||
|
36 | Fixes | |||
|
37 | ^^^^^ | |||
|
38 | ||||
|
39 | - Descriptions: fixed rendering problem with certain meta-tags in repo description. | |||
|
40 | - Emails: fixed fonts rendering problems in Outlook. | |||
|
41 | - Emails: fixed bug in test email sending. | |||
|
42 | - Summary: fixed styling of readme indicator. | |||
|
43 | - Flash: fixed display problem with flash messages on error pages. | |||
|
44 | ||||
|
45 | ||||
|
46 | Upgrade notes | |||
|
47 | ^^^^^^^^^^^^^ | |||
|
48 | ||||
|
49 | - Scheduled release addressing problems in 4.18.X releases. |
@@ -0,0 +1,64 b'' | |||||
|
1 | |RCE| 4.18.3 |RNS| | |||
|
2 | ------------------ | |||
|
3 | ||||
|
4 | Release Date | |||
|
5 | ^^^^^^^^^^^^ | |||
|
6 | ||||
|
7 | - 2020-03-24 | |||
|
8 | ||||
|
9 | ||||
|
10 | New Features | |||
|
11 | ^^^^^^^^^^^^ | |||
|
12 | ||||
|
13 | - LDAP: added nested user groups sync which was planned in 4.18.X but didn't | |||
|
14 | make it to the release. New option for sync is available in the LDAP configuration. | |||
|
15 | ||||
|
16 | ||||
|
17 | General | |||
|
18 | ^^^^^^^ | |||
|
19 | ||||
|
20 | - API: added branch permissions functions. | |||
|
21 | - Pull requests: added creating indicator to let users know they should wait until PR is creating. | |||
|
22 | - Pull requests: allow super-admins to force change state of locked PRs. | |||
|
23 | - Users/User groups: in edit mode we now show the actual name of what we're editing. | |||
|
24 | - SSH: allow generation of legacy SSH keys for older systems and Windows users. | |||
|
25 | - File store: don't response with cookie data on file-store download response. | |||
|
26 | - File store: use our own logic for setting content-type. This solves a problem | |||
|
27 | when previously used resolver set different content-type+content-encoding which | |||
|
28 | is an incorrect behaviour. | |||
|
29 | - My Account: show info about password usage for external accounts e.g github/google etc | |||
|
30 | We now recommend using auth-tokens instead of actual passwords. | |||
|
31 | - Repositories: in description field we now show mention of metatags only if they | |||
|
32 | are enabled. | |||
|
33 | ||||
|
34 | ||||
|
35 | Security | |||
|
36 | ^^^^^^^^ | |||
|
37 | ||||
|
38 | - Remote sync: don't expose credentials in displayed URLs. | |||
|
39 | Remote links url had visible credentials displayed in the link. | |||
|
40 | This was used for web-view and not needed anymore. | |||
|
41 | ||||
|
42 | ||||
|
43 | Performance | |||
|
44 | ^^^^^^^^^^^ | |||
|
45 | ||||
|
46 | - Full text search: significantly improved GIT commit indexing performance by reducing | |||
|
47 | number of calls to the vcsserver. | |||
|
48 | ||||
|
49 | ||||
|
50 | Fixes | |||
|
51 | ^^^^^ | |||
|
52 | ||||
|
53 | - Mercurial: fixed cases of lookup of branches that are exactly 20 character long. | |||
|
54 | - SVN: allow legacy (pre SVN 1.7) extraction of post commit data. | |||
|
55 | - GIT: use non-unicode author extraction as it's returned as bytes from backend, and | |||
|
56 | we can get an unicode errors while there's some non-ascii characters. | |||
|
57 | - GIT: use safe configparser for git submodules to prevent from errors on submodules with % sign. | |||
|
58 | - System info: fixed UI problem with new version update info screen. | |||
|
59 | ||||
|
60 | ||||
|
61 | Upgrade notes | |||
|
62 | ^^^^^^^^^^^^^ | |||
|
63 | ||||
|
64 | - Scheduled release addressing problems in 4.18.X releases. |
@@ -58,3 +58,7 b' ad5bd0c4bd322fdbd04bb825a3d027e08f7a3901' | |||||
58 | 037f5794b55a6236d68f6485a485372dde6566e0 v4.17.3 |
|
58 | 037f5794b55a6236d68f6485a485372dde6566e0 v4.17.3 | |
59 | 83bc3100cfd6094c1d04f475ddb299b7dc3d0b33 v4.17.4 |
|
59 | 83bc3100cfd6094c1d04f475ddb299b7dc3d0b33 v4.17.4 | |
60 | e3de8c95baf8cc9109ca56aee8193a2cb6a54c8a v4.17.4 |
|
60 | e3de8c95baf8cc9109ca56aee8193a2cb6a54c8a v4.17.4 | |
|
61 | f37a3126570477543507f0bc9d245ce75546181a v4.18.0 | |||
|
62 | 71d8791463e87b64c1a18475de330ee600d37561 v4.18.1 | |||
|
63 | 4bd6b75dac1d25c64885d4d49385e5533f21c525 v4.18.2 | |||
|
64 | 12ed92fe57f2e9fc7b71dc0b65e26c2da5c7085f v4.18.3 |
@@ -57,5 +57,5 b' Each lines should represent a single nam' | |||||
57 | Run this line from CLI to execute the code from the `repo_delete_task.py` file and |
|
57 | Run this line from CLI to execute the code from the `repo_delete_task.py` file and | |
58 | exit the ishell after the execution:: |
|
58 | exit the ishell after the execution:: | |
59 |
|
59 | |||
60 |
echo "%run repo_delete_task.py" | rccontrol ishell |
|
60 | echo "%run repo_delete_task.py" | rccontrol ishell enterprise-1 | |
61 |
|
61 |
@@ -124,6 +124,7 b' 1. To configure Apache, create and edit ' | |||||
124 | LogLevel info |
|
124 | LogLevel info | |
125 | # allows custom host names, prevents 400 errors on checkout |
|
125 | # allows custom host names, prevents 400 errors on checkout | |
126 | HttpProtocolOptions Unsafe |
|
126 | HttpProtocolOptions Unsafe | |
|
127 | # Most likely this will be: /home/user/.rccontrol/enterprise-1/mod_dav_svn.conf | |||
127 | Include /home/user/.rccontrol/enterprise-1/mod_dav_svn.conf |
|
128 | Include /home/user/.rccontrol/enterprise-1/mod_dav_svn.conf | |
128 | </VirtualHost> |
|
129 | </VirtualHost> | |
129 |
|
130 |
@@ -48,7 +48,7 b' uses, or if required it can be a differe' | |||||
48 |
|
48 | |||
49 |
|
49 | |||
50 |
|
50 | |||
51 | To switch to reds-based user sessions uncomment the following section in |
|
51 | To switch to redis-based user sessions uncomment the following section in | |
52 | your :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file. |
|
52 | your :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file. | |
53 |
|
53 | |||
54 | .. code-block:: ini |
|
54 | .. code-block:: ini |
@@ -33,6 +33,15 b' 2. Run the |RCC| installer and accept th' | |||||
33 | Do you accept the RhodeCode Control license? |
|
33 | Do you accept the RhodeCode Control license? | |
34 | Press [Y] to accept license and [V] to view license text: y |
|
34 | Press [Y] to accept license and [V] to view license text: y | |
35 |
|
35 | |||
|
36 | ||||
|
37 | .. important:: | |||
|
38 | ||||
|
39 | We recommend running RhodeCode as a non-root user, such as `rhodecode`; | |||
|
40 | this user must have a proper home directory. | |||
|
41 | Either log in as that user to install the software, or do it as root | |||
|
42 | with `sudo -i -u rhodecode ./RhodeCode-installer-linux-*` | |||
|
43 | ||||
|
44 | ||||
36 | 3. Install a VCS Server, and configure it to start at boot. |
|
45 | 3. Install a VCS Server, and configure it to start at boot. | |
37 |
|
46 | |||
38 | .. code-block:: bash |
|
47 | .. code-block:: bash |
@@ -193,6 +193,10 b' Fixes' | |||||
193 | Upgrade notes |
|
193 | Upgrade notes | |
194 | ^^^^^^^^^^^^^ |
|
194 | ^^^^^^^^^^^^^ | |
195 |
|
195 | |||
|
196 | - Major Celery Version upgrade. The 4.18.X release includes a major Celery version. | |||
|
197 | It's recommended to run `rccontrol self-stop && rccontrol self-init` after the | |||
|
198 | upgrade to ensure celery workers are restarted and updated. | |||
|
199 | ||||
196 | - New Automation task. We've changed the logic for updating latest change inside repository group. |
|
200 | - New Automation task. We've changed the logic for updating latest change inside repository group. | |
197 | New logic includes scanning for changes in all nested objects. Since this is a heavy task |
|
201 | New logic includes scanning for changes in all nested objects. Since this is a heavy task | |
198 | a new dedicated scheduler task has been created to update it automatically on a scheduled base. |
|
202 | a new dedicated scheduler task has been created to update it automatically on a scheduled base. | |
@@ -218,6 +222,11 b' Upgrade notes' | |||||
218 | Please review vcsserver.ini settings under: |
|
222 | Please review vcsserver.ini settings under: | |
219 | `rc_cache.repo_object.backend = dogpile.cache.rc.redis_msgpack` |
|
223 | `rc_cache.repo_object.backend = dogpile.cache.rc.redis_msgpack` | |
220 |
|
224 | |||
|
225 | - Gunicorn configuration now moved to .ini files. | |||
|
226 | Upgrading to 4.18.X will overwrite the gunicorn_conf.py file. If there are any custom changes in that file | |||
|
227 | they will be lost. Recommended way to configure gunicorn is now via the .ini files. Please check `rhodecode.template.ini` file | |||
|
228 | for example gunicorn configuration. | |||
|
229 | ||||
221 | - New memory monitoring for Gunicorn workers. Starting from 4.18 release a option was added |
|
230 | - New memory monitoring for Gunicorn workers. Starting from 4.18 release a option was added | |
222 | to limit the maximum amount of memory used by a worker. |
|
231 | to limit the maximum amount of memory used by a worker. | |
223 | Please review new settings in `[server:main]` section for memory management in both |
|
232 | Please review new settings in `[server:main]` section for memory management in both |
@@ -9,6 +9,9 b' Release Notes' | |||||
9 | .. toctree:: |
|
9 | .. toctree:: | |
10 | :maxdepth: 1 |
|
10 | :maxdepth: 1 | |
11 |
|
11 | |||
|
12 | release-notes-4.18.3.rst | |||
|
13 | release-notes-4.18.2.rst | |||
|
14 | release-notes-4.18.1.rst | |||
12 | release-notes-4.18.0.rst |
|
15 | release-notes-4.18.0.rst | |
13 | release-notes-4.17.4.rst |
|
16 | release-notes-4.17.4.rst | |
14 | release-notes-4.17.3.rst |
|
17 | release-notes-4.17.3.rst |
@@ -18,7 +18,6 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 | import inspect |
|
|||
22 | import itertools |
|
21 | import itertools | |
23 | import logging |
|
22 | import logging | |
24 | import sys |
|
23 | import sys | |
@@ -186,10 +185,12 b' def request_view(request):' | |||||
186 | Main request handling method. It handles all logic to call a specific |
|
185 | Main request handling method. It handles all logic to call a specific | |
187 | exposed method |
|
186 | exposed method | |
188 | """ |
|
187 | """ | |
|
188 | # cython compatible inspect | |||
|
189 | from rhodecode.config.patches import inspect_getargspec | |||
|
190 | inspect = inspect_getargspec() | |||
189 |
|
191 | |||
190 | # check if we can find this session using api_key, get_by_auth_token |
|
192 | # check if we can find this session using api_key, get_by_auth_token | |
191 | # search not expired tokens only |
|
193 | # search not expired tokens only | |
192 |
|
||||
193 | try: |
|
194 | try: | |
194 | api_user = User.get_by_auth_token(request.rpc_api_key) |
|
195 | api_user = User.get_by_auth_token(request.rpc_api_key) | |
195 |
|
196 |
@@ -56,5 +56,6 b' class TestGetMethod(object):' | |||||
56 | 'request': '<RequiredType>', |
|
56 | 'request': '<RequiredType>', | |
57 | 'resolves_comment_id': '<Optional:None>', |
|
57 | 'resolves_comment_id': '<Optional:None>', | |
58 | 'status': '<Optional:None>', |
|
58 | 'status': '<Optional:None>', | |
59 |
'userid': '<Optional:<OptionalAttr:apiuser>>' |
|
59 | 'userid': '<Optional:<OptionalAttr:apiuser>>', | |
|
60 | 'send_email': '<Optional:True>'}] | |||
60 | assert_ok(id_, expected, given=response.body) |
|
61 | assert_ok(id_, expected, given=response.body) |
@@ -66,7 +66,7 b' class TestGrantUserGroupPermission(objec' | |||||
66 | perm=perm) |
|
66 | perm=perm) | |
67 | response = api_call(self.app, params) |
|
67 | response = api_call(self.app, params) | |
68 |
|
68 | |||
69 | expected = 'permission `%s` does not exist' % (perm,) |
|
69 | expected = 'permission `%s` does not exist.' % (perm,) | |
70 | assert_error(id_, expected, given=response.body) |
|
70 | assert_error(id_, expected, given=response.body) | |
71 |
|
71 | |||
72 | @mock.patch.object(RepoModel, 'grant_user_group_permission', crash) |
|
72 | @mock.patch.object(RepoModel, 'grant_user_group_permission', crash) |
@@ -132,8 +132,7 b' class TestGrantUserGroupPermissionFromRe' | |||||
132 | RepoGroupModel().revoke_user_group_permission( |
|
132 | RepoGroupModel().revoke_user_group_permission( | |
133 | repo_group.group_id, user_group.users_group_id) |
|
133 | repo_group.group_id, user_group.users_group_id) | |
134 | else: |
|
134 | else: | |
135 | expected = 'repository group `%s` does not exist' % ( |
|
135 | expected = 'repository group `%s` does not exist' % (repo_group.name,) | |
136 | repo_group.name,) |
|
|||
137 | assert_error(id_, expected, given=response.body) |
|
136 | assert_error(id_, expected, given=response.body) | |
138 |
|
137 | |||
139 | def test_api_grant_user_group_permission_to_repo_group_wrong_permission( |
|
138 | def test_api_grant_user_group_permission_to_repo_group_wrong_permission( | |
@@ -149,7 +148,7 b' class TestGrantUserGroupPermissionFromRe' | |||||
149 | perm=perm) |
|
148 | perm=perm) | |
150 | response = api_call(self.app, params) |
|
149 | response = api_call(self.app, params) | |
151 |
|
150 | |||
152 | expected = 'permission `%s` does not exist' % (perm,) |
|
151 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) | |
153 | assert_error(id_, expected, given=response.body) |
|
152 | assert_error(id_, expected, given=response.body) | |
154 |
|
153 | |||
155 | @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', crash) |
|
154 | @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', crash) |
@@ -65,7 +65,7 b' class TestGrantUserPermission(object):' | |||||
65 | perm=perm) |
|
65 | perm=perm) | |
66 | response = api_call(self.app, params) |
|
66 | response = api_call(self.app, params) | |
67 |
|
67 | |||
68 | expected = 'permission `%s` does not exist' % (perm,) |
|
68 | expected = 'permission `%s` does not exist.' % (perm,) | |
69 | assert_error(id_, expected, given=response.body) |
|
69 | assert_error(id_, expected, given=response.body) | |
70 |
|
70 | |||
71 | @mock.patch.object(RepoModel, 'grant_user_permission', crash) |
|
71 | @mock.patch.object(RepoModel, 'grant_user_permission', crash) |
@@ -132,7 +132,7 b' class TestGrantUserPermissionFromRepoGro' | |||||
132 | perm=perm) |
|
132 | perm=perm) | |
133 | response = api_call(self.app, params) |
|
133 | response = api_call(self.app, params) | |
134 |
|
134 | |||
135 | expected = 'permission `%s` does not exist' % (perm,) |
|
135 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) | |
136 | assert_error(id_, expected, given=response.body) |
|
136 | assert_error(id_, expected, given=response.body) | |
137 |
|
137 | |||
138 | @mock.patch.object(RepoGroupModel, 'grant_user_permission', crash) |
|
138 | @mock.patch.object(RepoGroupModel, 'grant_user_permission', crash) |
@@ -130,7 +130,7 b' class TestGrantUserPermissionFromUserGro' | |||||
130 | perm=perm) |
|
130 | perm=perm) | |
131 | response = api_call(self.app, params) |
|
131 | response = api_call(self.app, params) | |
132 |
|
132 | |||
133 | expected = 'permission `%s` does not exist' % perm |
|
133 | expected = 'permission `%s` does not exist. Permission should start with prefix: `usergroup.`' % perm | |
134 | assert_error(id_, expected, given=response.body) |
|
134 | assert_error(id_, expected, given=response.body) | |
135 |
|
135 | |||
136 | def test_api_grant_user_permission_to_user_group_exception_when_adding( |
|
136 | def test_api_grant_user_permission_to_user_group_exception_when_adding( |
@@ -308,7 +308,11 b' def get_perm_or_error(permid, prefix=Non' | |||||
308 |
|
308 | |||
309 | perm = PermissionModel.cls.get_by_key(permid) |
|
309 | perm = PermissionModel.cls.get_by_key(permid) | |
310 | if perm is None: |
|
310 | if perm is None: | |
311 |
|
|
311 | msg = 'permission `{}` does not exist.'.format(permid) | |
|
312 | if prefix: | |||
|
313 | msg += ' Permission should start with prefix: `{}`'.format(prefix) | |||
|
314 | raise JSONRPCError(msg) | |||
|
315 | ||||
312 | if prefix: |
|
316 | if prefix: | |
313 | if not perm.permission_name.startswith(prefix): |
|
317 | if not perm.permission_name.startswith(prefix): | |
314 | raise JSONRPCError('permission `%s` is invalid, ' |
|
318 | raise JSONRPCError('permission `%s` is invalid, ' | |
@@ -351,12 +355,12 b' def get_pull_request_or_error(pullreques' | |||||
351 | def build_commit_data(commit, detail_level): |
|
355 | def build_commit_data(commit, detail_level): | |
352 | parsed_diff = [] |
|
356 | parsed_diff = [] | |
353 | if detail_level == 'extended': |
|
357 | if detail_level == 'extended': | |
354 | for f in commit.added: |
|
358 | for f_path in commit.added_paths: | |
355 |
parsed_diff.append(_get_commit_dict(filename=f |
|
359 | parsed_diff.append(_get_commit_dict(filename=f_path, op='A')) | |
356 | for f in commit.changed: |
|
360 | for f_path in commit.changed_paths: | |
357 |
parsed_diff.append(_get_commit_dict(filename=f |
|
361 | parsed_diff.append(_get_commit_dict(filename=f_path, op='M')) | |
358 | for f in commit.removed: |
|
362 | for f_path in commit.removed_paths: | |
359 |
parsed_diff.append(_get_commit_dict(filename=f |
|
363 | parsed_diff.append(_get_commit_dict(filename=f_path, op='D')) | |
360 |
|
364 | |||
361 | elif detail_level == 'full': |
|
365 | elif detail_level == 'full': | |
362 | from rhodecode.lib.diffs import DiffProcessor |
|
366 | from rhodecode.lib.diffs import DiffProcessor |
@@ -73,6 +73,7 b' def get_pull_request(request, apiuser, p' | |||||
73 | "status" : "<status>", |
|
73 | "status" : "<status>", | |
74 | "created_on": "<date_time_created>", |
|
74 | "created_on": "<date_time_created>", | |
75 | "updated_on": "<date_time_updated>", |
|
75 | "updated_on": "<date_time_updated>", | |
|
76 | "versions": "<number_or_versions_of_pr>", | |||
76 | "commit_ids": [ |
|
77 | "commit_ids": [ | |
77 | ... |
|
78 | ... | |
78 | "<commit_id>", |
|
79 | "<commit_id>", | |
@@ -452,7 +453,7 b' def comment_pull_request(' | |||||
452 | message=Optional(None), commit_id=Optional(None), status=Optional(None), |
|
453 | message=Optional(None), commit_id=Optional(None), status=Optional(None), | |
453 | comment_type=Optional(ChangesetComment.COMMENT_TYPE_NOTE), |
|
454 | comment_type=Optional(ChangesetComment.COMMENT_TYPE_NOTE), | |
454 | resolves_comment_id=Optional(None), extra_recipients=Optional([]), |
|
455 | resolves_comment_id=Optional(None), extra_recipients=Optional([]), | |
455 | userid=Optional(OAttr('apiuser'))): |
|
456 | userid=Optional(OAttr('apiuser')), send_email=Optional(True)): | |
456 | """ |
|
457 | """ | |
457 | Comment on the pull request specified with the `pullrequestid`, |
|
458 | Comment on the pull request specified with the `pullrequestid`, | |
458 | in the |repo| specified by the `repoid`, and optionally change the |
|
459 | in the |repo| specified by the `repoid`, and optionally change the | |
@@ -483,6 +484,8 b' def comment_pull_request(' | |||||
483 | :type extra_recipients: Optional(list) |
|
484 | :type extra_recipients: Optional(list) | |
484 | :param userid: Comment on the pull request as this user |
|
485 | :param userid: Comment on the pull request as this user | |
485 | :type userid: Optional(str or int) |
|
486 | :type userid: Optional(str or int) | |
|
487 | :param send_email: Define if this comment should also send email notification | |||
|
488 | :type send_email: Optional(bool) | |||
486 |
|
489 | |||
487 | Example output: |
|
490 | Example output: | |
488 |
|
491 | |||
@@ -527,6 +530,7 b' def comment_pull_request(' | |||||
527 | comment_type = Optional.extract(comment_type) |
|
530 | comment_type = Optional.extract(comment_type) | |
528 | resolves_comment_id = Optional.extract(resolves_comment_id) |
|
531 | resolves_comment_id = Optional.extract(resolves_comment_id) | |
529 | extra_recipients = Optional.extract(extra_recipients) |
|
532 | extra_recipients = Optional.extract(extra_recipients) | |
|
533 | send_email = Optional.extract(send_email, binary=True) | |||
530 |
|
534 | |||
531 | if not message and not status: |
|
535 | if not message and not status: | |
532 | raise JSONRPCError( |
|
536 | raise JSONRPCError( | |
@@ -587,7 +591,8 b' def comment_pull_request(' | |||||
587 | comment_type=comment_type, |
|
591 | comment_type=comment_type, | |
588 | resolves_comment_id=resolves_comment_id, |
|
592 | resolves_comment_id=resolves_comment_id, | |
589 | auth_user=auth_user, |
|
593 | auth_user=auth_user, | |
590 | extra_recipients=extra_recipients |
|
594 | extra_recipients=extra_recipients, | |
|
595 | send_email=send_email | |||
591 | ) |
|
596 | ) | |
592 |
|
597 | |||
593 | if allowed_to_change_status and status: |
|
598 | if allowed_to_change_status and status: |
@@ -1551,7 +1551,7 b' def comment_commit(' | |||||
1551 | request, apiuser, repoid, commit_id, message, status=Optional(None), |
|
1551 | request, apiuser, repoid, commit_id, message, status=Optional(None), | |
1552 | comment_type=Optional(ChangesetComment.COMMENT_TYPE_NOTE), |
|
1552 | comment_type=Optional(ChangesetComment.COMMENT_TYPE_NOTE), | |
1553 | resolves_comment_id=Optional(None), extra_recipients=Optional([]), |
|
1553 | resolves_comment_id=Optional(None), extra_recipients=Optional([]), | |
1554 | userid=Optional(OAttr('apiuser'))): |
|
1554 | userid=Optional(OAttr('apiuser')), send_email=Optional(True)): | |
1555 | """ |
|
1555 | """ | |
1556 | Set a commit comment, and optionally change the status of the commit. |
|
1556 | Set a commit comment, and optionally change the status of the commit. | |
1557 |
|
1557 | |||
@@ -1575,6 +1575,8 b' def comment_commit(' | |||||
1575 | :type extra_recipients: Optional(list) |
|
1575 | :type extra_recipients: Optional(list) | |
1576 | :param userid: Set the user name of the comment creator. |
|
1576 | :param userid: Set the user name of the comment creator. | |
1577 | :type userid: Optional(str or int) |
|
1577 | :type userid: Optional(str or int) | |
|
1578 | :param send_email: Define if this comment should also send email notification | |||
|
1579 | :type send_email: Optional(bool) | |||
1578 |
|
1580 | |||
1579 | Example error output: |
|
1581 | Example error output: | |
1580 |
|
1582 | |||
@@ -1610,6 +1612,7 b' def comment_commit(' | |||||
1610 | comment_type = Optional.extract(comment_type) |
|
1612 | comment_type = Optional.extract(comment_type) | |
1611 | resolves_comment_id = Optional.extract(resolves_comment_id) |
|
1613 | resolves_comment_id = Optional.extract(resolves_comment_id) | |
1612 | extra_recipients = Optional.extract(extra_recipients) |
|
1614 | extra_recipients = Optional.extract(extra_recipients) | |
|
1615 | send_email = Optional.extract(send_email, binary=True) | |||
1613 |
|
1616 | |||
1614 | allowed_statuses = [x[0] for x in ChangesetStatus.STATUSES] |
|
1617 | allowed_statuses = [x[0] for x in ChangesetStatus.STATUSES] | |
1615 | if status and status not in allowed_statuses: |
|
1618 | if status and status not in allowed_statuses: | |
@@ -1639,7 +1642,8 b' def comment_commit(' | |||||
1639 | comment_type=comment_type, |
|
1642 | comment_type=comment_type, | |
1640 | resolves_comment_id=resolves_comment_id, |
|
1643 | resolves_comment_id=resolves_comment_id, | |
1641 | auth_user=apiuser, |
|
1644 | auth_user=apiuser, | |
1642 | extra_recipients=extra_recipients |
|
1645 | extra_recipients=extra_recipients, | |
|
1646 | send_email=send_email | |||
1643 | ) |
|
1647 | ) | |
1644 | if status: |
|
1648 | if status: | |
1645 | # also do a status change |
|
1649 | # also do a status change |
@@ -18,7 +18,6 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 | import inspect |
|
|||
22 | import logging |
|
21 | import logging | |
23 | import itertools |
|
22 | import itertools | |
24 | import base64 |
|
23 | import base64 | |
@@ -334,6 +333,9 b' def get_method(request, apiuser, pattern' | |||||
334 | ] |
|
333 | ] | |
335 | error : null |
|
334 | error : null | |
336 | """ |
|
335 | """ | |
|
336 | from rhodecode.config.patches import inspect_getargspec | |||
|
337 | inspect = inspect_getargspec() | |||
|
338 | ||||
337 | if not has_superadmin_permission(apiuser): |
|
339 | if not has_superadmin_permission(apiuser): | |
338 | raise JSONRPCForbidden() |
|
340 | raise JSONRPCForbidden() | |
339 |
|
341 |
@@ -37,7 +37,7 b' from rhodecode.model import user_group' | |||||
37 | from rhodecode.model import user |
|
37 | from rhodecode.model import user | |
38 | from rhodecode.model.db import User |
|
38 | from rhodecode.model.db import User | |
39 | from rhodecode.model.scm import ScmModel |
|
39 | from rhodecode.model.scm import ScmModel | |
40 | from rhodecode.model.settings import VcsSettingsModel |
|
40 | from rhodecode.model.settings import VcsSettingsModel, IssueTrackerSettingsModel | |
41 | from rhodecode.model.repo import ReadmeFinder |
|
41 | from rhodecode.model.repo import ReadmeFinder | |
42 |
|
42 | |||
43 | log = logging.getLogger(__name__) |
|
43 | log = logging.getLogger(__name__) | |
@@ -226,6 +226,7 b' class RepoAppView(BaseAppView):' | |||||
226 | self.db_repo_name = self.db_repo.repo_name |
|
226 | self.db_repo_name = self.db_repo.repo_name | |
227 | self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo) |
|
227 | self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo) | |
228 | self.db_repo_artifacts = ScmModel().get_artifacts(self.db_repo) |
|
228 | self.db_repo_artifacts = ScmModel().get_artifacts(self.db_repo) | |
|
229 | self.db_repo_patterns = IssueTrackerSettingsModel(repo=self.db_repo) | |||
229 |
|
230 | |||
230 | def _handle_missing_requirements(self, error): |
|
231 | def _handle_missing_requirements(self, error): | |
231 | log.error( |
|
232 | log.error( |
@@ -573,7 +573,7 b' class AdminSettingsView(BaseAppView):' | |||||
573 |
|
573 | |||
574 | email_kwargs = { |
|
574 | email_kwargs = { | |
575 | 'date': datetime.datetime.now(), |
|
575 | 'date': datetime.datetime.now(), | |
576 |
'user': |
|
576 | 'user': self._rhodecode_db_user | |
577 | } |
|
577 | } | |
578 |
|
578 | |||
579 | (subject, headers, email_body, |
|
579 | (subject, headers, email_body, |
@@ -872,7 +872,10 b' class UsersView(UserAppView):' | |||||
872 |
|
872 | |||
873 | c.active = 'ssh_keys_generate' |
|
873 | c.active = 'ssh_keys_generate' | |
874 | comment = 'RhodeCode-SSH {}'.format(c.user.email or '') |
|
874 | comment = 'RhodeCode-SSH {}'.format(c.user.email or '') | |
875 | c.private, c.public = SshKeyModel().generate_keypair(comment=comment) |
|
875 | private_format = self.request.GET.get('private_format') \ | |
|
876 | or SshKeyModel.DEFAULT_PRIVATE_KEY_FORMAT | |||
|
877 | c.private, c.public = SshKeyModel().generate_keypair( | |||
|
878 | comment=comment, private_format=private_format) | |||
876 |
|
879 | |||
877 | return self._get_template_context(c) |
|
880 | return self._get_template_context(c) | |
878 |
|
881 |
@@ -33,6 +33,7 b' from rhodecode.lib import audit_logger' | |||||
33 | from rhodecode.lib.auth import ( |
|
33 | from rhodecode.lib.auth import ( | |
34 | CSRFRequired, NotAnonymous, HasRepoPermissionAny, HasRepoGroupPermissionAny, |
|
34 | CSRFRequired, NotAnonymous, HasRepoPermissionAny, HasRepoGroupPermissionAny, | |
35 | LoginRequired) |
|
35 | LoginRequired) | |
|
36 | from rhodecode.lib.vcs.conf.mtypes import get_mimetypes_db | |||
36 | from rhodecode.model.db import Session, FileStore, UserApiKeys |
|
37 | from rhodecode.model.db import Session, FileStore, UserApiKeys | |
37 |
|
38 | |||
38 | log = logging.getLogger(__name__) |
|
39 | log = logging.getLogger(__name__) | |
@@ -46,6 +47,15 b' class FileStoreView(BaseAppView):' | |||||
46 | self.storage = utils.get_file_storage(self.request.registry.settings) |
|
47 | self.storage = utils.get_file_storage(self.request.registry.settings) | |
47 | return c |
|
48 | return c | |
48 |
|
49 | |||
|
50 | def _guess_type(self, file_name): | |||
|
51 | """ | |||
|
52 | Our own type guesser for mimetypes using the rich DB | |||
|
53 | """ | |||
|
54 | if not hasattr(self, 'db'): | |||
|
55 | self.db = get_mimetypes_db() | |||
|
56 | _content_type, _encoding = self.db.guess_type(file_name, strict=False) | |||
|
57 | return _content_type, _encoding | |||
|
58 | ||||
49 | def _serve_file(self, file_uid): |
|
59 | def _serve_file(self, file_uid): | |
50 |
|
60 | |||
51 | if not self.storage.exists(file_uid): |
|
61 | if not self.storage.exists(file_uid): | |
@@ -92,7 +102,18 b' class FileStoreView(BaseAppView):' | |||||
92 | FileStore.bump_access_counter(file_uid) |
|
102 | FileStore.bump_access_counter(file_uid) | |
93 |
|
103 | |||
94 | file_path = self.storage.store_path(file_uid) |
|
104 | file_path = self.storage.store_path(file_uid) | |
95 | return FileResponse(file_path) |
|
105 | content_type = 'application/octet-stream' | |
|
106 | content_encoding = None | |||
|
107 | ||||
|
108 | _content_type, _encoding = self._guess_type(file_path) | |||
|
109 | if _content_type: | |||
|
110 | content_type = _content_type | |||
|
111 | ||||
|
112 | # For file store we don't submit any session data, this logic tells the | |||
|
113 | # Session lib to skip it | |||
|
114 | setattr(self.request, '_file_response', True) | |||
|
115 | return FileResponse(file_path, request=self.request, | |||
|
116 | content_type=content_type, content_encoding=content_encoding) | |||
96 |
|
117 | |||
97 | @LoginRequired() |
|
118 | @LoginRequired() | |
98 | @NotAnonymous() |
|
119 | @NotAnonymous() |
@@ -105,11 +105,11 b' class TestGistsController(TestController' | |||||
105 | g4 = create_gist('gist4', gist_type='private').gist_access_id |
|
105 | g4 = create_gist('gist4', gist_type='private').gist_access_id | |
106 | response = self.app.get(route_path('gists_show')) |
|
106 | response = self.app.get(route_path('gists_show')) | |
107 |
|
107 | |||
108 |
response.mustcontain( |
|
108 | response.mustcontain(g1.gist_access_id) | |
109 |
response.mustcontain( |
|
109 | response.mustcontain(g2.gist_access_id) | |
110 |
response.mustcontain( |
|
110 | response.mustcontain(g3.gist_access_id) | |
111 | response.mustcontain('gist3-desc') |
|
111 | response.mustcontain('gist3-desc') | |
112 |
response.mustcontain(no=[ |
|
112 | response.mustcontain(no=[g4]) | |
113 |
|
113 | |||
114 | # Expiration information should be visible |
|
114 | # Expiration information should be visible | |
115 | expires_tag = '%s' % h.age_component( |
|
115 | expires_tag = '%s' % h.age_component( | |
@@ -122,7 +122,7 b' class TestGistsController(TestController' | |||||
122 | response = self.app.get(route_path('gists_show', params=dict(private=1))) |
|
122 | response = self.app.get(route_path('gists_show', params=dict(private=1))) | |
123 |
|
123 | |||
124 | # and privates |
|
124 | # and privates | |
125 |
response.mustcontain( |
|
125 | response.mustcontain(gist.gist_access_id) | |
126 |
|
126 | |||
127 | def test_index_show_all(self, create_gist): |
|
127 | def test_index_show_all(self, create_gist): | |
128 | self.log_user() |
|
128 | self.log_user() | |
@@ -136,7 +136,7 b' class TestGistsController(TestController' | |||||
136 | assert len(GistModel.get_all()) == 4 |
|
136 | assert len(GistModel.get_all()) == 4 | |
137 | # and privates |
|
137 | # and privates | |
138 | for gist in GistModel.get_all(): |
|
138 | for gist in GistModel.get_all(): | |
139 |
response.mustcontain( |
|
139 | response.mustcontain(gist.gist_access_id) | |
140 |
|
140 | |||
141 | def test_index_show_all_hidden_from_regular(self, create_gist): |
|
141 | def test_index_show_all_hidden_from_regular(self, create_gist): | |
142 | self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
142 | self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
@@ -150,7 +150,7 b' class TestGistsController(TestController' | |||||
150 | # since we don't have access to private in this view, we |
|
150 | # since we don't have access to private in this view, we | |
151 | # should see nothing |
|
151 | # should see nothing | |
152 | for gist in GistModel.get_all(): |
|
152 | for gist in GistModel.get_all(): | |
153 |
response.mustcontain(no=[ |
|
153 | response.mustcontain(no=[gist.gist_access_id]) | |
154 |
|
154 | |||
155 | def test_create(self): |
|
155 | def test_create(self): | |
156 | self.log_user() |
|
156 | self.log_user() |
@@ -33,7 +33,7 b' def assert_and_get_main_filter_content(r' | |||||
33 | if data_item['type'] == 'search': |
|
33 | if data_item['type'] == 'search': | |
34 | display_val = data_item['value_display'] |
|
34 | display_val = data_item['value_display'] | |
35 | if data_item['id'] == -1: |
|
35 | if data_item['id'] == -1: | |
36 | assert 'File search for:' in display_val, display_val |
|
36 | assert 'File content search for:' in display_val, display_val | |
37 | elif data_item['id'] == -2: |
|
37 | elif data_item['id'] == -2: | |
38 | assert 'Commit search for:' in display_val, display_val |
|
38 | assert 'Commit search for:' in display_val, display_val | |
39 | else: |
|
39 | else: |
@@ -453,7 +453,7 b' class HomeView(BaseAppView, DataGridAppV' | |||||
453 | qry = query |
|
453 | qry = query | |
454 | return {'q': qry, 'type': 'content'} |
|
454 | return {'q': qry, 'type': 'content'} | |
455 |
|
455 | |||
456 | label = u'File search for `{}`'.format(h.escape(query)) |
|
456 | label = u'File content search for `{}`'.format(h.escape(query)) | |
457 | file_qry = { |
|
457 | file_qry = { | |
458 | 'id': -10, |
|
458 | 'id': -10, | |
459 | 'value': query, |
|
459 | 'value': query, | |
@@ -497,7 +497,7 b' class HomeView(BaseAppView, DataGridAppV' | |||||
497 | qry = query |
|
497 | qry = query | |
498 | return {'q': qry, 'type': 'content'} |
|
498 | return {'q': qry, 'type': 'content'} | |
499 |
|
499 | |||
500 | label = u'File search for `{}`'.format(query) |
|
500 | label = u'File content search for `{}`'.format(query) | |
501 | file_qry = { |
|
501 | file_qry = { | |
502 | 'id': -30, |
|
502 | 'id': -30, | |
503 | 'value': query, |
|
503 | 'value': query, | |
@@ -541,7 +541,7 b' class HomeView(BaseAppView, DataGridAppV' | |||||
541 | { |
|
541 | { | |
542 | 'id': -1, |
|
542 | 'id': -1, | |
543 | 'value': query, |
|
543 | 'value': query, | |
544 | 'value_display': u'File search for: `{}`'.format(query), |
|
544 | 'value_display': u'File content search for: `{}`'.format(query), | |
545 | 'value_icon': '<i class="icon-code"></i>', |
|
545 | 'value_icon': '<i class="icon-code"></i>', | |
546 | 'type': 'search', |
|
546 | 'type': 'search', | |
547 | 'subtype': 'global', |
|
547 | 'subtype': 'global', |
@@ -26,6 +26,10 b' def includeme(config):' | |||||
26 | pattern='/_hovercard/user/{user_id}') |
|
26 | pattern='/_hovercard/user/{user_id}') | |
27 |
|
27 | |||
28 | config.add_route( |
|
28 | config.add_route( | |
|
29 | name='hovercard_username', | |||
|
30 | pattern='/_hovercard/username/{username}') | |||
|
31 | ||||
|
32 | config.add_route( | |||
29 | name='hovercard_user_group', |
|
33 | name='hovercard_user_group', | |
30 | pattern='/_hovercard/user_group/{user_group_id}') |
|
34 | pattern='/_hovercard/user_group/{user_group_id}') | |
31 |
|
35 |
@@ -65,6 +65,19 b' class HoverCardsView(BaseAppView):' | |||||
65 |
|
65 | |||
66 | @LoginRequired() |
|
66 | @LoginRequired() | |
67 | @view_config( |
|
67 | @view_config( | |
|
68 | route_name='hovercard_username', request_method='GET', xhr=True, | |||
|
69 | renderer='rhodecode:templates/hovercards/hovercard_user.mako') | |||
|
70 | def hovercard_username(self): | |||
|
71 | c = self.load_default_context() | |||
|
72 | username = self.request.matchdict['username'] | |||
|
73 | c.user = User.get_by_username(username) | |||
|
74 | if not c.user: | |||
|
75 | raise HTTPNotFound() | |||
|
76 | ||||
|
77 | return self._get_template_context(c) | |||
|
78 | ||||
|
79 | @LoginRequired() | |||
|
80 | @view_config( | |||
68 | route_name='hovercard_user_group', request_method='GET', xhr=True, |
|
81 | route_name='hovercard_user_group', request_method='GET', xhr=True, | |
69 | renderer='rhodecode:templates/hovercards/hovercard_user_group.mako') |
|
82 | renderer='rhodecode:templates/hovercards/hovercard_user_group.mako') | |
70 | def hovercard_user_group(self): |
|
83 | def hovercard_user_group(self): |
@@ -108,7 +108,8 b' class TestLoginController(object):' | |||||
108 |
|
108 | |||
109 | def test_login_regular_forbidden_when_super_admin_restriction(self): |
|
109 | def test_login_regular_forbidden_when_super_admin_restriction(self): | |
110 | from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin |
|
110 | from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin | |
111 | with fixture.auth_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN): |
|
111 | with fixture.auth_restriction(self.app._pyramid_registry, | |
|
112 | RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN): | |||
112 | response = self.app.post(route_path('login'), |
|
113 | response = self.app.post(route_path('login'), | |
113 | {'username': 'test_regular', |
|
114 | {'username': 'test_regular', | |
114 | 'password': 'test12'}) |
|
115 | 'password': 'test12'}) | |
@@ -118,7 +119,8 b' class TestLoginController(object):' | |||||
118 |
|
119 | |||
119 | def test_login_regular_forbidden_when_scope_restriction(self): |
|
120 | def test_login_regular_forbidden_when_scope_restriction(self): | |
120 | from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin |
|
121 | from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin | |
121 | with fixture.scope_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS): |
|
122 | with fixture.scope_restriction(self.app._pyramid_registry, | |
|
123 | RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS): | |||
122 | response = self.app.post(route_path('login'), |
|
124 | response = self.app.post(route_path('login'), | |
123 | {'username': 'test_regular', |
|
125 | {'username': 'test_regular', | |
124 | 'password': 'test12'}) |
|
126 | 'password': 'test12'}) |
@@ -76,6 +76,7 b' class MyAccountView(BaseAppView, DataGri' | |||||
76 | def my_account_profile(self): |
|
76 | def my_account_profile(self): | |
77 | c = self.load_default_context() |
|
77 | c = self.load_default_context() | |
78 | c.active = 'profile' |
|
78 | c.active = 'profile' | |
|
79 | c.extern_type = c.user.extern_type | |||
79 | return self._get_template_context(c) |
|
80 | return self._get_template_context(c) | |
80 |
|
81 | |||
81 | @LoginRequired() |
|
82 | @LoginRequired() |
@@ -72,8 +72,11 b' class MyAccountSshKeysView(BaseAppView, ' | |||||
72 |
|
72 | |||
73 | c.active = 'ssh_keys_generate' |
|
73 | c.active = 'ssh_keys_generate' | |
74 | if c.ssh_key_generator_enabled: |
|
74 | if c.ssh_key_generator_enabled: | |
|
75 | private_format = self.request.GET.get('private_format') \ | |||
|
76 | or SshKeyModel.DEFAULT_PRIVATE_KEY_FORMAT | |||
75 | comment = 'RhodeCode-SSH {}'.format(c.user.email or '') |
|
77 | comment = 'RhodeCode-SSH {}'.format(c.user.email or '') | |
76 |
c.private, c.public = SshKeyModel().generate_keypair( |
|
78 | c.private, c.public = SshKeyModel().generate_keypair( | |
|
79 | comment=comment, private_format=private_format) | |||
77 | c.target_form_url = h.route_path( |
|
80 | c.target_form_url = h.route_path( | |
78 | 'my_account_ssh_keys', _query=dict(default_key=c.public)) |
|
81 | 'my_account_ssh_keys', _query=dict(default_key=c.public)) | |
79 | return self._get_template_context(c) |
|
82 | return self._get_template_context(c) |
@@ -28,6 +28,7 b' from rhodecode.lib import helpers as h' | |||||
28 | from rhodecode.lib import audit_logger |
|
28 | from rhodecode.lib import audit_logger | |
29 | from rhodecode.lib.auth import ( |
|
29 | from rhodecode.lib.auth import ( | |
30 | LoginRequired, HasRepoGroupPermissionAnyDecorator, CSRFRequired) |
|
30 | LoginRequired, HasRepoGroupPermissionAnyDecorator, CSRFRequired) | |
|
31 | from rhodecode.model.db import User | |||
31 | from rhodecode.model.permission import PermissionModel |
|
32 | from rhodecode.model.permission import PermissionModel | |
32 | from rhodecode.model.repo_group import RepoGroupModel |
|
33 | from rhodecode.model.repo_group import RepoGroupModel | |
33 | from rhodecode.model.forms import RepoGroupPermsForm |
|
34 | from rhodecode.model.forms import RepoGroupPermsForm | |
@@ -96,7 +97,13 b' class RepoGroupPermissionsView(RepoGroup' | |||||
96 |
|
97 | |||
97 | Session().commit() |
|
98 | Session().commit() | |
98 | h.flash(_('Repository Group permissions updated'), category='success') |
|
99 | h.flash(_('Repository Group permissions updated'), category='success') | |
99 | PermissionModel().flush_user_permission_caches(changes) |
|
100 | ||
|
101 | affected_user_ids = None | |||
|
102 | if changes.get('default_user_changed', False): | |||
|
103 | # if we change the default user, we need to flush everyone permissions | |||
|
104 | affected_user_ids = User.get_all_user_ids() | |||
|
105 | PermissionModel().flush_user_permission_caches( | |||
|
106 | changes, affected_user_ids=affected_user_ids) | |||
100 |
|
107 | |||
101 | raise HTTPFound( |
|
108 | raise HTTPFound( | |
102 | h.route_path('edit_repo_group_perms', |
|
109 | h.route_path('edit_repo_group_perms', |
@@ -28,6 +28,8 b' from rhodecode.lib import helpers as h' | |||||
28 | from rhodecode.lib import audit_logger |
|
28 | from rhodecode.lib import audit_logger | |
29 | from rhodecode.lib.auth import ( |
|
29 | from rhodecode.lib.auth import ( | |
30 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) |
|
30 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) | |
|
31 | from rhodecode.lib.utils2 import str2bool | |||
|
32 | from rhodecode.model.db import User | |||
31 | from rhodecode.model.forms import RepoPermsForm |
|
33 | from rhodecode.model.forms import RepoPermsForm | |
32 | from rhodecode.model.meta import Session |
|
34 | from rhodecode.model.meta import Session | |
33 | from rhodecode.model.permission import PermissionModel |
|
35 | from rhodecode.model.permission import PermissionModel | |
@@ -89,7 +91,12 b' class RepoSettingsPermissionsView(RepoAp' | |||||
89 | Session().commit() |
|
91 | Session().commit() | |
90 | h.flash(_('Repository access permissions updated'), category='success') |
|
92 | h.flash(_('Repository access permissions updated'), category='success') | |
91 |
|
93 | |||
92 | PermissionModel().flush_user_permission_caches(changes) |
|
94 | affected_user_ids = None | |
|
95 | if changes.get('default_user_changed', False): | |||
|
96 | # if we change the default user, we need to flush everyone permissions | |||
|
97 | affected_user_ids = User.get_all_user_ids() | |||
|
98 | PermissionModel().flush_user_permission_caches( | |||
|
99 | changes, affected_user_ids=affected_user_ids) | |||
93 |
|
100 | |||
94 | raise HTTPFound( |
|
101 | raise HTTPFound( | |
95 | h.route_path('edit_repo_perms', repo_name=self.db_repo_name)) |
|
102 | h.route_path('edit_repo_perms', repo_name=self.db_repo_name)) | |
@@ -104,9 +111,11 b' class RepoSettingsPermissionsView(RepoAp' | |||||
104 | _ = self.request.translate |
|
111 | _ = self.request.translate | |
105 | self.load_default_context() |
|
112 | self.load_default_context() | |
106 |
|
113 | |||
|
114 | private_flag = str2bool(self.request.POST.get('private')) | |||
|
115 | ||||
107 | try: |
|
116 | try: | |
108 | RepoModel().update( |
|
117 | RepoModel().update( | |
109 |
self.db_repo, **{'repo_private': |
|
118 | self.db_repo, **{'repo_private': private_flag, 'repo_name': self.db_repo_name}) | |
110 | Session().commit() |
|
119 | Session().commit() | |
111 |
|
120 | |||
112 | h.flash(_('Repository `{}` private mode set successfully').format(self.db_repo_name), |
|
121 | h.flash(_('Repository `{}` private mode set successfully').format(self.db_repo_name), | |
@@ -116,7 +125,11 b' class RepoSettingsPermissionsView(RepoAp' | |||||
116 | h.flash(_('Error occurred during update of repository {}').format( |
|
125 | h.flash(_('Error occurred during update of repository {}').format( | |
117 | self.db_repo_name), category='error') |
|
126 | self.db_repo_name), category='error') | |
118 |
|
127 | |||
|
128 | # NOTE(dan): we change repo private mode we need to notify all USERS | |||
|
129 | affected_user_ids = User.get_all_user_ids() | |||
|
130 | PermissionModel().trigger_permission_flush(affected_user_ids) | |||
|
131 | ||||
119 | return { |
|
132 | return { | |
120 | 'redirect_url': h.route_path('edit_repo_perms', repo_name=self.db_repo_name), |
|
133 | 'redirect_url': h.route_path('edit_repo_perms', repo_name=self.db_repo_name), | |
121 |
'private': |
|
134 | 'private': private_flag | |
122 | } |
|
135 | } |
@@ -275,6 +275,20 b' class RepoPullRequestsView(RepoAppView, ' | |||||
275 |
|
275 | |||
276 | c.state_progressing = pull_request.is_state_changing() |
|
276 | c.state_progressing = pull_request.is_state_changing() | |
277 |
|
277 | |||
|
278 | _new_state = { | |||
|
279 | 'created': PullRequest.STATE_CREATED, | |||
|
280 | }.get(self.request.GET.get('force_state')) | |||
|
281 | if c.is_super_admin and _new_state: | |||
|
282 | with pull_request.set_state(PullRequest.STATE_UPDATING, final_state=_new_state): | |||
|
283 | h.flash( | |||
|
284 | _('Pull Request state was force changed to `{}`').format(_new_state), | |||
|
285 | category='success') | |||
|
286 | Session().commit() | |||
|
287 | ||||
|
288 | raise HTTPFound(h.route_path( | |||
|
289 | 'pullrequest_show', repo_name=self.db_repo_name, | |||
|
290 | pull_request_id=pull_request_id)) | |||
|
291 | ||||
278 | version = self.request.GET.get('version') |
|
292 | version = self.request.GET.get('version') | |
279 | from_version = self.request.GET.get('from_version') or version |
|
293 | from_version = self.request.GET.get('from_version') or version | |
280 | merge_checks = self.request.GET.get('merge_checks') |
|
294 | merge_checks = self.request.GET.get('merge_checks') |
@@ -31,7 +31,7 b' from rhodecode.lib.auth import (' | |||||
31 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) |
|
31 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) | |
32 | from rhodecode.model.forms import IssueTrackerPatternsForm |
|
32 | from rhodecode.model.forms import IssueTrackerPatternsForm | |
33 | from rhodecode.model.meta import Session |
|
33 | from rhodecode.model.meta import Session | |
34 |
from rhodecode.model.settings import |
|
34 | from rhodecode.model.settings import SettingsModel | |
35 |
|
35 | |||
36 | log = logging.getLogger(__name__) |
|
36 | log = logging.getLogger(__name__) | |
37 |
|
37 | |||
@@ -53,7 +53,7 b' class RepoSettingsIssueTrackersView(Repo' | |||||
53 | c.active = 'issuetracker' |
|
53 | c.active = 'issuetracker' | |
54 | c.data = 'data' |
|
54 | c.data = 'data' | |
55 |
|
55 | |||
56 |
c.settings_model = |
|
56 | c.settings_model = self.db_repo_patterns | |
57 | c.global_patterns = c.settings_model.get_global_settings() |
|
57 | c.global_patterns = c.settings_model.get_global_settings() | |
58 | c.repo_patterns = c.settings_model.get_repo_settings() |
|
58 | c.repo_patterns = c.settings_model.get_repo_settings() | |
59 |
|
59 | |||
@@ -79,7 +79,7 b' class RepoSettingsIssueTrackersView(Repo' | |||||
79 | def repo_issuetracker_delete(self): |
|
79 | def repo_issuetracker_delete(self): | |
80 | _ = self.request.translate |
|
80 | _ = self.request.translate | |
81 | uid = self.request.POST.get('uid') |
|
81 | uid = self.request.POST.get('uid') | |
82 |
repo_settings = |
|
82 | repo_settings = self.db_repo_patterns | |
83 | try: |
|
83 | try: | |
84 | repo_settings.delete_entries(uid) |
|
84 | repo_settings.delete_entries(uid) | |
85 | except Exception: |
|
85 | except Exception: | |
@@ -113,7 +113,7 b' class RepoSettingsIssueTrackersView(Repo' | |||||
113 | def repo_issuetracker_update(self): |
|
113 | def repo_issuetracker_update(self): | |
114 | _ = self.request.translate |
|
114 | _ = self.request.translate | |
115 | # Save inheritance |
|
115 | # Save inheritance | |
116 |
repo_settings = |
|
116 | repo_settings = self.db_repo_patterns | |
117 | inherited = ( |
|
117 | inherited = ( | |
118 | self.request.POST.get('inherit_global_issuetracker') == "inherited") |
|
118 | self.request.POST.get('inherit_global_issuetracker') == "inherited") | |
119 | repo_settings.inherit_global_settings = inherited |
|
119 | repo_settings.inherit_global_settings = inherited |
@@ -24,6 +24,7 b'' | |||||
24 | # LogLevel info |
|
24 | # LogLevel info | |
25 | # # allows custom host names, prevents 400 errors on checkout |
|
25 | # # allows custom host names, prevents 400 errors on checkout | |
26 | # HttpProtocolOptions Unsafe |
|
26 | # HttpProtocolOptions Unsafe | |
|
27 | # # Most likely this will be: /home/user/.rccontrol/enterprise-1/mod_dav_svn.conf | |||
27 | # Include /path/to/generated/mod_dav_svn.conf |
|
28 | # Include /path/to/generated/mod_dav_svn.conf | |
28 | # </VirtualHost> |
|
29 | # </VirtualHost> | |
29 | # |
|
30 | # |
@@ -150,6 +150,7 b' class RhodeCodeAuthPluginBase(object):' | |||||
150 |
|
150 | |||
151 | def __init__(self, plugin_id): |
|
151 | def __init__(self, plugin_id): | |
152 | self._plugin_id = plugin_id |
|
152 | self._plugin_id = plugin_id | |
|
153 | self._settings = {} | |||
153 |
|
154 | |||
154 | def __str__(self): |
|
155 | def __str__(self): | |
155 | return self.get_id() |
|
156 | return self.get_id() | |
@@ -226,17 +227,26 b' class RhodeCodeAuthPluginBase(object):' | |||||
226 | """ |
|
227 | """ | |
227 | return AuthnPluginSettingsSchemaBase() |
|
228 | return AuthnPluginSettingsSchemaBase() | |
228 |
|
229 | |||
229 |
def |
|
230 | def _propagate_settings(self, raw_settings): | |
230 | """ |
|
|||
231 | Returns the plugin settings as dictionary. |
|
|||
232 | """ |
|
|||
233 | settings = {} |
|
231 | settings = {} | |
234 | raw_settings = SettingsModel().get_all_settings() |
|
|||
235 | for node in self.get_settings_schema(): |
|
232 | for node in self.get_settings_schema(): | |
236 | settings[node.name] = self.get_setting_by_name( |
|
233 | settings[node.name] = self.get_setting_by_name( | |
237 | node.name, plugin_cached_settings=raw_settings) |
|
234 | node.name, plugin_cached_settings=raw_settings) | |
238 | return settings |
|
235 | return settings | |
239 |
|
236 | |||
|
237 | def get_settings(self, use_cache=True): | |||
|
238 | """ | |||
|
239 | Returns the plugin settings as dictionary. | |||
|
240 | """ | |||
|
241 | if self._settings != {} and use_cache: | |||
|
242 | return self._settings | |||
|
243 | ||||
|
244 | raw_settings = SettingsModel().get_all_settings() | |||
|
245 | settings = self._propagate_settings(raw_settings) | |||
|
246 | ||||
|
247 | self._settings = settings | |||
|
248 | return self._settings | |||
|
249 | ||||
240 | def get_setting_by_name(self, name, default=None, plugin_cached_settings=None): |
|
250 | def get_setting_by_name(self, name, default=None, plugin_cached_settings=None): | |
241 | """ |
|
251 | """ | |
242 | Returns a plugin setting by name. |
|
252 | Returns a plugin setting by name. | |
@@ -594,19 +604,19 b' class AuthLdapBase(object):' | |||||
594 | if not full_resolve: |
|
604 | if not full_resolve: | |
595 | return '{}:{}'.format(host, port) |
|
605 | return '{}:{}'.format(host, port) | |
596 |
|
606 | |||
597 | log.debug('LDAP: Resolving IP for LDAP host %s', host) |
|
607 | log.debug('LDAP: Resolving IP for LDAP host `%s`', host) | |
598 | try: |
|
608 | try: | |
599 | ip = socket.gethostbyname(host) |
|
609 | ip = socket.gethostbyname(host) | |
600 |
log.debug('Got LDAP |
|
610 | log.debug('LDAP: Got LDAP host `%s` ip %s', host, ip) | |
601 | except Exception: |
|
611 | except Exception: | |
602 | raise LdapConnectionError( |
|
612 | raise LdapConnectionError('Failed to resolve host: `{}`'.format(host)) | |
603 | 'Failed to resolve host: `{}`'.format(host)) |
|
|||
604 |
|
613 | |||
605 | log.debug('LDAP: Checking if IP %s is accessible', ip) |
|
614 | log.debug('LDAP: Checking if IP %s is accessible', ip) | |
606 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
|
615 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
607 | try: |
|
616 | try: | |
608 | s.connect((ip, int(port))) |
|
617 | s.connect((ip, int(port))) | |
609 | s.shutdown(socket.SHUT_RD) |
|
618 | s.shutdown(socket.SHUT_RD) | |
|
619 | log.debug('LDAP: connection to %s successful', ip) | |||
610 | except Exception: |
|
620 | except Exception: | |
611 | raise LdapConnectionError( |
|
621 | raise LdapConnectionError( | |
612 | 'Failed to connect to host: `{}:{}`'.format(host, port)) |
|
622 | 'Failed to connect to host: `{}:{}`'.format(host, port)) | |
@@ -667,7 +677,7 b' def loadplugin(plugin_id):' | |||||
667 |
|
677 | |||
668 | def get_authn_registry(registry=None): |
|
678 | def get_authn_registry(registry=None): | |
669 | registry = registry or get_current_registry() |
|
679 | registry = registry or get_current_registry() | |
670 |
authn_registry = registry. |
|
680 | authn_registry = registry.queryUtility(IAuthnPluginRegistry) | |
671 | return authn_registry |
|
681 | return authn_registry | |
672 |
|
682 | |||
673 |
|
683 | |||
@@ -690,6 +700,7 b' def authenticate(username, password, env' | |||||
690 | headers_only = environ and not (username and password) |
|
700 | headers_only = environ and not (username and password) | |
691 |
|
701 | |||
692 | authn_registry = get_authn_registry(registry) |
|
702 | authn_registry = get_authn_registry(registry) | |
|
703 | ||||
693 | plugins_to_check = authn_registry.get_plugins_for_authentication() |
|
704 | plugins_to_check = authn_registry.get_plugins_for_authentication() | |
694 | log.debug('Starting ordered authentication chain using %s plugins', |
|
705 | log.debug('Starting ordered authentication chain using %s plugins', | |
695 | [x.name for x in plugins_to_check]) |
|
706 | [x.name for x in plugins_to_check]) |
@@ -145,16 +145,16 b' class AuthLdap(AuthLdapBase):' | |||||
145 | log.debug('Trying simple_bind with password and given login DN: %r', |
|
145 | log.debug('Trying simple_bind with password and given login DN: %r', | |
146 | self.LDAP_BIND_DN) |
|
146 | self.LDAP_BIND_DN) | |
147 | ldap_conn.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS) |
|
147 | ldap_conn.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS) | |
148 |
|
148 | log.debug('simple_bind successful') | ||
149 | return ldap_conn |
|
149 | return ldap_conn | |
150 |
|
150 | |||
151 | def fetch_attrs_from_simple_bind(self, server, dn, username, password): |
|
151 | def fetch_attrs_from_simple_bind(self, server, dn, username, password): | |
152 | try: |
|
152 | try: | |
153 | log.debug('Trying simple bind with %r', dn) |
|
153 | log.debug('Trying simple bind with %r', dn) | |
154 | server.simple_bind_s(dn, safe_str(password)) |
|
154 | server.simple_bind_s(dn, safe_str(password)) | |
155 |
|
|
155 | _dn, attrs = server.search_ext_s( | |
156 | dn, ldap.SCOPE_BASE, '(objectClass=*)', )[0] |
|
156 | dn, ldap.SCOPE_BASE, '(objectClass=*)', )[0] | |
157 | _, attrs = user |
|
157 | ||
158 | return attrs |
|
158 | return attrs | |
159 |
|
159 | |||
160 | except ldap.INVALID_CREDENTIALS: |
|
160 | except ldap.INVALID_CREDENTIALS: | |
@@ -206,7 +206,7 b' class AuthLdap(AuthLdapBase):' | |||||
206 | break |
|
206 | break | |
207 | else: |
|
207 | else: | |
208 | raise LdapPasswordError( |
|
208 | raise LdapPasswordError( | |
209 | 'Failed to authenticate user `{}`' |
|
209 | 'Failed to authenticate user `{}` ' | |
210 | 'with given password'.format(username)) |
|
210 | 'with given password'.format(username)) | |
211 |
|
211 | |||
212 | except ldap.NO_SUCH_OBJECT: |
|
212 | except ldap.NO_SUCH_OBJECT: | |
@@ -249,7 +249,7 b' class LdapSettingsSchema(AuthnPluginSett' | |||||
249 | colander.Int(), |
|
249 | colander.Int(), | |
250 | default=389, |
|
250 | default=389, | |
251 | description=_('Custom port that the LDAP server is listening on. ' |
|
251 | description=_('Custom port that the LDAP server is listening on. ' | |
252 | 'Default value is: 389, use 689 for LDAPS(SSL)'), |
|
252 | 'Default value is: 389, use 689 for LDAPS (SSL)'), | |
253 | preparer=strip_whitespace, |
|
253 | preparer=strip_whitespace, | |
254 | title=_('Port'), |
|
254 | title=_('Port'), | |
255 | validator=colander.Range(min=0, max=65536), |
|
255 | validator=colander.Range(min=0, max=65536), | |
@@ -272,7 +272,7 b' class LdapSettingsSchema(AuthnPluginSett' | |||||
272 | 'uid=root,cn=users,dc=mydomain,dc=com, or admin@mydomain.com'), |
|
272 | 'uid=root,cn=users,dc=mydomain,dc=com, or admin@mydomain.com'), | |
273 | missing='', |
|
273 | missing='', | |
274 | preparer=strip_whitespace, |
|
274 | preparer=strip_whitespace, | |
275 |
title=_(' |
|
275 | title=_('Bind account'), | |
276 | widget='string') |
|
276 | widget='string') | |
277 | dn_pass = colander.SchemaNode( |
|
277 | dn_pass = colander.SchemaNode( | |
278 | colander.String(), |
|
278 | colander.String(), | |
@@ -280,7 +280,7 b' class LdapSettingsSchema(AuthnPluginSett' | |||||
280 | description=_('Password to authenticate for given user DN.'), |
|
280 | description=_('Password to authenticate for given user DN.'), | |
281 | missing='', |
|
281 | missing='', | |
282 | preparer=strip_whitespace, |
|
282 | preparer=strip_whitespace, | |
283 |
title=_(' |
|
283 | title=_('Bind account password'), | |
284 | widget='password') |
|
284 | widget='password') | |
285 | tls_kind = colander.SchemaNode( |
|
285 | tls_kind = colander.SchemaNode( | |
286 | colander.String(), |
|
286 | colander.String(), | |
@@ -318,7 +318,7 b' class LdapSettingsSchema(AuthnPluginSett' | |||||
318 | colander.String(), |
|
318 | colander.String(), | |
319 | default='', |
|
319 | default='', | |
320 | description=_('Base DN to search. Dynamic bind is supported. Add `$login` marker ' |
|
320 | description=_('Base DN to search. Dynamic bind is supported. Add `$login` marker ' | |
321 |
'in it to be replaced with current user |
|
321 | 'in it to be replaced with current user username \n' | |
322 | '(e.g., dc=mydomain,dc=com, or ou=Users,dc=mydomain,dc=com)'), |
|
322 | '(e.g., dc=mydomain,dc=com, or ou=Users,dc=mydomain,dc=com)'), | |
323 | missing='', |
|
323 | missing='', | |
324 | preparer=strip_whitespace, |
|
324 | preparer=strip_whitespace, |
@@ -38,6 +38,7 b' class AuthenticationPluginRegistry(objec' | |||||
38 |
|
38 | |||
39 | def __init__(self, settings): |
|
39 | def __init__(self, settings): | |
40 | self._plugins = {} |
|
40 | self._plugins = {} | |
|
41 | self._plugins_for_auth = None | |||
41 | self._fallback_plugin = settings.get(self.fallback_plugin_key, None) |
|
42 | self._fallback_plugin = settings.get(self.fallback_plugin_key, None) | |
42 |
|
43 | |||
43 | def add_authn_plugin(self, config, plugin): |
|
44 | def add_authn_plugin(self, config, plugin): | |
@@ -63,6 +64,10 b' class AuthenticationPluginRegistry(objec' | |||||
63 | if plugin.uid == plugin_uid: |
|
64 | if plugin.uid == plugin_uid: | |
64 | return plugin |
|
65 | return plugin | |
65 |
|
66 | |||
|
67 | def invalidate_plugins_for_auth(self): | |||
|
68 | log.debug('Invalidating cached plugins for authentication') | |||
|
69 | self._plugins_for_auth = None | |||
|
70 | ||||
66 | def get_plugins_for_authentication(self): |
|
71 | def get_plugins_for_authentication(self): | |
67 | """ |
|
72 | """ | |
68 | Returns a list of plugins which should be consulted when authenticating |
|
73 | Returns a list of plugins which should be consulted when authenticating | |
@@ -70,6 +75,9 b' class AuthenticationPluginRegistry(objec' | |||||
70 | Additionally it includes the fallback plugin from the INI file, if |
|
75 | Additionally it includes the fallback plugin from the INI file, if | |
71 | `rhodecode.auth_plugin_fallback` is set to a plugin ID. |
|
76 | `rhodecode.auth_plugin_fallback` is set to a plugin ID. | |
72 | """ |
|
77 | """ | |
|
78 | if self._plugins_for_auth is not None: | |||
|
79 | return self._plugins_for_auth | |||
|
80 | ||||
73 | plugins = [] |
|
81 | plugins = [] | |
74 |
|
82 | |||
75 | # Add all enabled and active plugins to the list. We iterate over the |
|
83 | # Add all enabled and active plugins to the list. We iterate over the | |
@@ -80,6 +88,9 b' class AuthenticationPluginRegistry(objec' | |||||
80 | plugin = self.get_plugin(plugin_id) |
|
88 | plugin = self.get_plugin(plugin_id) | |
81 | if plugin is not None and plugin.is_active( |
|
89 | if plugin is not None and plugin.is_active( | |
82 | plugin_cached_settings=raw_settings): |
|
90 | plugin_cached_settings=raw_settings): | |
|
91 | ||||
|
92 | # inject settings into plugin, we can re-use the DB fetched settings here | |||
|
93 | plugin._settings = plugin._propagate_settings(raw_settings) | |||
83 | plugins.append(plugin) |
|
94 | plugins.append(plugin) | |
84 |
|
95 | |||
85 | # Add the fallback plugin from ini file. |
|
96 | # Add the fallback plugin from ini file. | |
@@ -89,6 +100,8 b' class AuthenticationPluginRegistry(objec' | |||||
89 | self._fallback_plugin) |
|
100 | self._fallback_plugin) | |
90 | plugin = self.get_plugin(self._fallback_plugin) |
|
101 | plugin = self.get_plugin(self._fallback_plugin) | |
91 | if plugin is not None and plugin not in plugins: |
|
102 | if plugin is not None and plugin not in plugins: | |
|
103 | plugin._settings = plugin._propagate_settings(raw_settings) | |||
92 | plugins.append(plugin) |
|
104 | plugins.append(plugin) | |
93 |
|
105 | |||
94 | return plugins |
|
106 | self._plugins_for_auth = plugins | |
|
107 | return self._plugins_for_auth |
@@ -99,11 +99,12 b' class AuthnPluginViewBase(BaseAppView):' | |||||
99 | for name, value in valid_data.items(): |
|
99 | for name, value in valid_data.items(): | |
100 | self.plugin.create_or_update_setting(name, value) |
|
100 | self.plugin.create_or_update_setting(name, value) | |
101 | Session().commit() |
|
101 | Session().commit() | |
|
102 | SettingsModel().invalidate_settings_cache() | |||
102 |
|
103 | |||
103 | # Display success message and redirect. |
|
104 | # Display success message and redirect. | |
104 | h.flash(_('Auth settings updated successfully.'), category='success') |
|
105 | h.flash(_('Auth settings updated successfully.'), category='success') | |
105 | redirect_to = self.request.resource_path( |
|
106 | redirect_to = self.request.resource_path(self.context, route_name='auth_home') | |
106 | self.context, route_name='auth_home') |
|
107 | ||
107 | return HTTPFound(redirect_to) |
|
108 | return HTTPFound(redirect_to) | |
108 |
|
109 | |||
109 |
|
110 | |||
@@ -159,7 +160,7 b' class AuthSettingsView(BaseAppView):' | |||||
159 | 'auth_plugins', plugins) |
|
160 | 'auth_plugins', plugins) | |
160 | Session().add(setting) |
|
161 | Session().add(setting) | |
161 | Session().commit() |
|
162 | Session().commit() | |
162 |
|
163 | SettingsModel().invalidate_settings_cache() | ||
163 | h.flash(_('Auth settings updated successfully.'), category='success') |
|
164 | h.flash(_('Auth settings updated successfully.'), category='success') | |
164 | except formencode.Invalid as errors: |
|
165 | except formencode.Invalid as errors: | |
165 | e = errors.error_dict or {} |
|
166 | e = errors.error_dict or {} | |
@@ -174,6 +175,6 b' class AuthSettingsView(BaseAppView):' | |||||
174 | h.flash(_('Error occurred during update of auth settings.'), |
|
175 | h.flash(_('Error occurred during update of auth settings.'), | |
175 | category='error') |
|
176 | category='error') | |
176 |
|
177 | |||
177 | redirect_to = self.request.resource_path( |
|
178 | redirect_to = self.request.resource_path(self.context, route_name='auth_home') | |
178 | self.context, route_name='auth_home') |
|
179 | ||
179 | return HTTPFound(redirect_to) |
|
180 | return HTTPFound(redirect_to) |
@@ -95,3 +95,5 b' def inspect_getargspec():' | |||||
95 | return inspect.ArgSpec(args, varargs, varkw, func.func_defaults) |
|
95 | return inspect.ArgSpec(args, varargs, varkw, func.func_defaults) | |
96 |
|
96 | |||
97 | inspect.getargspec = custom_getargspec |
|
97 | inspect.getargspec = custom_getargspec | |
|
98 | ||||
|
99 | return inspect |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
@@ -151,20 +151,22 b' def _store_log(action_name, action_data,' | |||||
151 |
|
151 | |||
152 |
|
152 | |||
153 | def store_web(*args, **kwargs): |
|
153 | def store_web(*args, **kwargs): | |
154 |
|
|
154 | action_data = {} | |
155 |
|
|
155 | org_action_data = kwargs.pop('action_data', {}) | |
156 |
|
|
156 | action_data.update(org_action_data) | |
157 |
|
|
157 | action_data['source'] = SOURCE_WEB | |
158 | }) |
|
158 | kwargs['action_data'] = action_data | |
|
159 | ||||
159 | return store(*args, **kwargs) |
|
160 | return store(*args, **kwargs) | |
160 |
|
161 | |||
161 |
|
162 | |||
162 | def store_api(*args, **kwargs): |
|
163 | def store_api(*args, **kwargs): | |
163 |
|
|
164 | action_data = {} | |
164 |
|
|
165 | org_action_data = kwargs.pop('action_data', {}) | |
165 |
|
|
166 | action_data.update(org_action_data) | |
166 |
|
|
167 | action_data['source'] = SOURCE_API | |
167 | }) |
|
168 | kwargs['action_data'] = action_data | |
|
169 | ||||
168 | return store(*args, **kwargs) |
|
170 | return store(*args, **kwargs) | |
169 |
|
171 | |||
170 |
|
172 |
@@ -24,7 +24,6 b' authentication and permission libraries' | |||||
24 |
|
24 | |||
25 | import os |
|
25 | import os | |
26 | import time |
|
26 | import time | |
27 | import inspect |
|
|||
28 | import collections |
|
27 | import collections | |
29 | import fnmatch |
|
28 | import fnmatch | |
30 | import hashlib |
|
29 | import hashlib | |
@@ -2013,6 +2012,7 b' class PermsFunction(object):' | |||||
2013 | self.user_group_name = None |
|
2012 | self.user_group_name = None | |
2014 |
|
2013 | |||
2015 | def __bool__(self): |
|
2014 | def __bool__(self): | |
|
2015 | import inspect | |||
2016 | frame = inspect.currentframe() |
|
2016 | frame = inspect.currentframe() | |
2017 | stack_trace = traceback.format_stack(frame) |
|
2017 | stack_trace = traceback.format_stack(frame) | |
2018 | log.error('Checking bool value on a class instance of perm ' |
|
2018 | log.error('Checking bool value on a class instance of perm ' |
@@ -211,8 +211,9 b' def vcs_operation_context(' | |||||
211 | class BasicAuth(AuthBasicAuthenticator): |
|
211 | class BasicAuth(AuthBasicAuthenticator): | |
212 |
|
212 | |||
213 | def __init__(self, realm, authfunc, registry, auth_http_code=None, |
|
213 | def __init__(self, realm, authfunc, registry, auth_http_code=None, | |
214 | initial_call_detection=False, acl_repo_name=None): |
|
214 | initial_call_detection=False, acl_repo_name=None, rc_realm=''): | |
215 | self.realm = realm |
|
215 | self.realm = realm | |
|
216 | self.rc_realm = rc_realm | |||
216 | self.initial_call = initial_call_detection |
|
217 | self.initial_call = initial_call_detection | |
217 | self.authfunc = authfunc |
|
218 | self.authfunc = authfunc | |
218 | self.registry = registry |
|
219 | self.registry = registry | |
@@ -227,7 +228,7 b' class BasicAuth(AuthBasicAuthenticator):' | |||||
227 | return HTTPForbidden |
|
228 | return HTTPForbidden | |
228 |
|
229 | |||
229 | def get_rc_realm(self): |
|
230 | def get_rc_realm(self): | |
230 |
return safe_str(self.r |
|
231 | return safe_str(self.rc_realm) | |
231 |
|
232 | |||
232 | def build_authentication(self): |
|
233 | def build_authentication(self): | |
233 | head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm) |
|
234 | head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm) | |
@@ -288,7 +289,7 b' def attach_context_attributes(context, r' | |||||
288 | """ |
|
289 | """ | |
289 | config = request.registry.settings |
|
290 | config = request.registry.settings | |
290 |
|
291 | |||
291 | rc_config = SettingsModel().get_all_settings(cache=True) |
|
292 | rc_config = SettingsModel().get_all_settings(cache=True, from_request=False) | |
292 | context.rc_config = rc_config |
|
293 | context.rc_config = rc_config | |
293 | context.rhodecode_version = rhodecode.__version__ |
|
294 | context.rhodecode_version = rhodecode.__version__ | |
294 | context.rhodecode_edition = config.get('rhodecode.edition') |
|
295 | context.rhodecode_edition = config.get('rhodecode.edition') |
@@ -66,11 +66,12 b' markdown_tags = [' | |||||
66 | markdown_attrs = { |
|
66 | markdown_attrs = { | |
67 | "*": ["class", "style", "align"], |
|
67 | "*": ["class", "style", "align"], | |
68 | "img": ["src", "alt", "title"], |
|
68 | "img": ["src", "alt", "title"], | |
69 | "a": ["href", "alt", "title", "name"], |
|
69 | "a": ["href", "alt", "title", "name", "data-hovercard-alt", "data-hovercard-url"], | |
70 | "abbr": ["title"], |
|
70 | "abbr": ["title"], | |
71 | "acronym": ["title"], |
|
71 | "acronym": ["title"], | |
72 | "pre": ["lang"], |
|
72 | "pre": ["lang"], | |
73 | "input": ["type", "disabled", "checked"] |
|
73 | "input": ["type", "disabled", "checked"], | |
|
74 | "strong": ["title", "data-hovercard-alt", "data-hovercard-url"], | |||
74 | } |
|
75 | } | |
75 |
|
76 | |||
76 | standard_styles = [ |
|
77 | standard_styles = [ |
@@ -421,9 +421,20 b' class DbManage(object):' | |||||
421 |
|
421 | |||
422 | :param skip_existing: |
|
422 | :param skip_existing: | |
423 | """ |
|
423 | """ | |
|
424 | defaults = [ | |||
|
425 | ('auth_plugins', | |||
|
426 | 'egg:rhodecode-enterprise-ce#token,egg:rhodecode-enterprise-ce#rhodecode', | |||
|
427 | 'list'), | |||
424 |
|
428 | |||
425 | for k, v, t in [('auth_plugins', 'egg:rhodecode-enterprise-ce#rhodecode', 'list'), |
|
429 | ('auth_authtoken_enabled', | |
426 | ('auth_rhodecode_enabled', 'True', 'bool')]: |
|
430 | 'True', | |
|
431 | 'bool'), | |||
|
432 | ||||
|
433 | ('auth_rhodecode_enabled', | |||
|
434 | 'True', | |||
|
435 | 'bool'), | |||
|
436 | ] | |||
|
437 | for k, v, t in defaults: | |||
427 | if (skip_existing and |
|
438 | if (skip_existing and | |
428 | SettingsModel().get_setting_by_name(k) is not None): |
|
439 | SettingsModel().get_setting_by_name(k) is not None): | |
429 | log.debug('Skipping option %s', k) |
|
440 | log.debug('Skipping option %s', k) | |
@@ -568,19 +579,32 b' class DbManage(object):' | |||||
568 | ('title', '', 'unicode'), |
|
579 | ('title', '', 'unicode'), | |
569 | ('pre_code', '', 'unicode'), |
|
580 | ('pre_code', '', 'unicode'), | |
570 | ('post_code', '', 'unicode'), |
|
581 | ('post_code', '', 'unicode'), | |
|
582 | ||||
|
583 | # Visual | |||
571 | ('show_public_icon', True, 'bool'), |
|
584 | ('show_public_icon', True, 'bool'), | |
572 | ('show_private_icon', True, 'bool'), |
|
585 | ('show_private_icon', True, 'bool'), | |
573 | ('stylify_metatags', False, 'bool'), |
|
586 | ('stylify_metatags', False, 'bool'), | |
574 | ('dashboard_items', 100, 'int'), |
|
587 | ('dashboard_items', 100, 'int'), | |
575 | ('admin_grid_items', 25, 'int'), |
|
588 | ('admin_grid_items', 25, 'int'), | |
|
589 | ||||
|
590 | ('markup_renderer', 'markdown', 'unicode'), | |||
|
591 | ||||
576 | ('show_version', True, 'bool'), |
|
592 | ('show_version', True, 'bool'), | |
|
593 | ('show_revision_number', True, 'bool'), | |||
|
594 | ('show_sha_length', 12, 'int'), | |||
|
595 | ||||
577 | ('use_gravatar', False, 'bool'), |
|
596 | ('use_gravatar', False, 'bool'), | |
578 | ('gravatar_url', User.DEFAULT_GRAVATAR_URL, 'unicode'), |
|
597 | ('gravatar_url', User.DEFAULT_GRAVATAR_URL, 'unicode'), | |
|
598 | ||||
579 | ('clone_uri_tmpl', Repository.DEFAULT_CLONE_URI, 'unicode'), |
|
599 | ('clone_uri_tmpl', Repository.DEFAULT_CLONE_URI, 'unicode'), | |
|
600 | ('clone_uri_ssh_tmpl', Repository.DEFAULT_CLONE_URI_SSH, 'unicode'), | |||
580 | ('support_url', '', 'unicode'), |
|
601 | ('support_url', '', 'unicode'), | |
581 | ('update_url', RhodeCodeSetting.DEFAULT_UPDATE_URL, 'unicode'), |
|
602 | ('update_url', RhodeCodeSetting.DEFAULT_UPDATE_URL, 'unicode'), | |
582 | ('show_revision_number', True, 'bool'), |
|
603 | ||
583 | ('show_sha_length', 12, 'int'), |
|
604 | # VCS Settings | |
|
605 | ('pr_merge_enabled', True, 'bool'), | |||
|
606 | ('use_outdated_comments', True, 'bool'), | |||
|
607 | ('diff_cache', True, 'bool'), | |||
584 | ] |
|
608 | ] | |
585 |
|
609 | |||
586 | for key, val, type_ in settings: |
|
610 | for key, val, type_ in settings: |
@@ -598,9 +598,10 b' class _Message(object):' | |||||
598 | * ``category``: the category specified when the message was created. |
|
598 | * ``category``: the category specified when the message was created. | |
599 | """ |
|
599 | """ | |
600 |
|
600 | |||
601 | def __init__(self, category, message): |
|
601 | def __init__(self, category, message, sub_data=None): | |
602 | self.category = category |
|
602 | self.category = category | |
603 | self.message = message |
|
603 | self.message = message | |
|
604 | self.sub_data = sub_data or {} | |||
604 |
|
605 | |||
605 | def __str__(self): |
|
606 | def __str__(self): | |
606 | return self.message |
|
607 | return self.message | |
@@ -663,7 +664,17 b' class Flash(object):' | |||||
663 | # of strings. |
|
664 | # of strings. | |
664 | for cat in self.categories: |
|
665 | for cat in self.categories: | |
665 | for msg in session.pop_flash(queue=cat): |
|
666 | for msg in session.pop_flash(queue=cat): | |
666 | messages.append(_Message(cat, msg)) |
|
667 | sub_data = {} | |
|
668 | if hasattr(msg, 'rsplit'): | |||
|
669 | flash_data = msg.rsplit('|DELIM|', 1) | |||
|
670 | org_message = flash_data[0] | |||
|
671 | if len(flash_data) > 1: | |||
|
672 | sub_data = json.loads(flash_data[1]) | |||
|
673 | else: | |||
|
674 | org_message = msg | |||
|
675 | ||||
|
676 | messages.append(_Message(cat, org_message, sub_data=sub_data)) | |||
|
677 | ||||
667 | # Map messages from the default queue to the 'notice' category. |
|
678 | # Map messages from the default queue to the 'notice' category. | |
668 | for msg in session.pop_flash(): |
|
679 | for msg in session.pop_flash(): | |
669 | messages.append(_Message('notice', msg)) |
|
680 | messages.append(_Message('notice', msg)) | |
@@ -673,25 +684,16 b' class Flash(object):' | |||||
673 |
|
684 | |||
674 | def json_alerts(self, session=None, request=None): |
|
685 | def json_alerts(self, session=None, request=None): | |
675 | payloads = [] |
|
686 | payloads = [] | |
676 | messages = flash.pop_messages(session=session, request=request) |
|
687 | messages = flash.pop_messages(session=session, request=request) or [] | |
677 |
|
|
688 | for message in messages: | |
678 | for message in messages: |
|
689 | payloads.append({ | |
679 |
|
|
690 | 'message': { | |
680 |
|
|
691 | 'message': u'{}'.format(message.message), | |
681 | flash_data = message.message.rsplit('|DELIM|', 1) |
|
692 | 'level': message.category, | |
682 | org_message = flash_data[0] |
|
693 | 'force': True, | |
683 |
|
|
694 | 'subdata': message.sub_data | |
684 | subdata = json.loads(flash_data[1]) |
|
695 | } | |
685 |
|
|
696 | }) | |
686 | org_message = message.message |
|
|||
687 | payloads.append({ |
|
|||
688 | 'message': { |
|
|||
689 | 'message': u'{}'.format(org_message), |
|
|||
690 | 'level': message.category, |
|
|||
691 | 'force': True, |
|
|||
692 | 'subdata': subdata |
|
|||
693 | } |
|
|||
694 | }) |
|
|||
695 | return json.dumps(payloads) |
|
697 | return json.dumps(payloads) | |
696 |
|
698 | |||
697 | def __call__(self, message, category=None, ignore_duplicate=True, |
|
699 | def __call__(self, message, category=None, ignore_duplicate=True, | |
@@ -1514,6 +1516,9 b' def get_active_pattern_entries(repo_name' | |||||
1514 | return active_entries |
|
1516 | return active_entries | |
1515 |
|
1517 | |||
1516 |
|
1518 | |||
|
1519 | pr_pattern_re = re.compile(r'(?:(?:^!)|(?: !))(\d+)') | |||
|
1520 | ||||
|
1521 | ||||
1517 | def process_patterns(text_string, repo_name, link_format='html', active_entries=None): |
|
1522 | def process_patterns(text_string, repo_name, link_format='html', active_entries=None): | |
1518 |
|
1523 | |||
1519 | allowed_formats = ['html', 'rst', 'markdown', |
|
1524 | allowed_formats = ['html', 'rst', 'markdown', | |
@@ -1522,7 +1527,10 b' def process_patterns(text_string, repo_n' | |||||
1522 | raise ValueError('Link format can be only one of:{} got {}'.format( |
|
1527 | raise ValueError('Link format can be only one of:{} got {}'.format( | |
1523 | allowed_formats, link_format)) |
|
1528 | allowed_formats, link_format)) | |
1524 |
|
1529 | |||
1525 | active_entries = active_entries or get_active_pattern_entries(repo_name) |
|
1530 | if active_entries is None: | |
|
1531 | log.debug('Fetch active patterns for repo: %s', repo_name) | |||
|
1532 | active_entries = get_active_pattern_entries(repo_name) | |||
|
1533 | ||||
1526 | issues_data = [] |
|
1534 | issues_data = [] | |
1527 | new_text = text_string |
|
1535 | new_text = text_string | |
1528 |
|
1536 | |||
@@ -1537,11 +1545,14 b' def process_patterns(text_string, repo_n' | |||||
1537 | log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s', |
|
1545 | log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s', | |
1538 | uid, entry['pat'], entry['url'], entry['pref']) |
|
1546 | uid, entry['pat'], entry['url'], entry['pref']) | |
1539 |
|
1547 | |||
1540 | try: |
|
1548 | if entry.get('pat_compiled'): | |
1541 |
pattern = |
|
1549 | pattern = entry['pat_compiled'] | |
1542 | except re.error: |
|
1550 | else: | |
1543 | log.exception('issue tracker pattern: `%s` failed to compile', entry['pat']) |
|
1551 | try: | |
1544 | continue |
|
1552 | pattern = re.compile(r'%s' % entry['pat']) | |
|
1553 | except re.error: | |||
|
1554 | log.exception('issue tracker pattern: `%s` failed to compile', entry['pat']) | |||
|
1555 | continue | |||
1545 |
|
1556 | |||
1546 | data_func = partial( |
|
1557 | data_func = partial( | |
1547 | _process_url_func, repo_name=repo_name, entry=entry, uid=uid, |
|
1558 | _process_url_func, repo_name=repo_name, entry=entry, uid=uid, | |
@@ -1569,7 +1580,7 b' def process_patterns(text_string, repo_n' | |||||
1569 | pr_url_func = partial( |
|
1580 | pr_url_func = partial( | |
1570 | _process_url_func, repo_name=repo_name, entry=pr_entry, uid=None, |
|
1581 | _process_url_func, repo_name=repo_name, entry=pr_entry, uid=None, | |
1571 | link_format=link_format+'+hovercard') |
|
1582 | link_format=link_format+'+hovercard') | |
1572 |
new_text = |
|
1583 | new_text = pr_pattern_re.sub(pr_url_func, new_text) | |
1573 | log.debug('processed !pr pattern') |
|
1584 | log.debug('processed !pr pattern') | |
1574 |
|
1585 | |||
1575 | return new_text, issues_data |
|
1586 | return new_text, issues_data | |
@@ -1580,6 +1591,7 b' def urlify_commit_message(commit_text, r' | |||||
1580 | Parses given text message and makes proper links. |
|
1591 | Parses given text message and makes proper links. | |
1581 | issues are linked to given issue-server, and rest is a commit link |
|
1592 | issues are linked to given issue-server, and rest is a commit link | |
1582 | """ |
|
1593 | """ | |
|
1594 | ||||
1583 | def escaper(_text): |
|
1595 | def escaper(_text): | |
1584 | return _text.replace('<', '<').replace('>', '>') |
|
1596 | return _text.replace('<', '<').replace('>', '>') | |
1585 |
|
1597 | |||
@@ -1636,7 +1648,7 b' def renderer_from_filename(filename, exc' | |||||
1636 |
|
1648 | |||
1637 |
|
1649 | |||
1638 | def render(source, renderer='rst', mentions=False, relative_urls=None, |
|
1650 | def render(source, renderer='rst', mentions=False, relative_urls=None, | |
1639 | repo_name=None): |
|
1651 | repo_name=None, active_pattern_entries=None): | |
1640 |
|
1652 | |||
1641 | def maybe_convert_relative_links(html_source): |
|
1653 | def maybe_convert_relative_links(html_source): | |
1642 | if relative_urls: |
|
1654 | if relative_urls: | |
@@ -1651,7 +1663,8 b" def render(source, renderer='rst', menti" | |||||
1651 | if repo_name: |
|
1663 | if repo_name: | |
1652 | # process patterns on comments if we pass in repo name |
|
1664 | # process patterns on comments if we pass in repo name | |
1653 | source, issues = process_patterns( |
|
1665 | source, issues = process_patterns( | |
1654 |
source, repo_name, link_format='rst' |
|
1666 | source, repo_name, link_format='rst', | |
|
1667 | active_entries=active_pattern_entries) | |||
1655 |
|
1668 | |||
1656 | return literal( |
|
1669 | return literal( | |
1657 | '<div class="rst-block">%s</div>' % |
|
1670 | '<div class="rst-block">%s</div>' % | |
@@ -1662,7 +1675,8 b" def render(source, renderer='rst', menti" | |||||
1662 | if repo_name: |
|
1675 | if repo_name: | |
1663 | # process patterns on comments if we pass in repo name |
|
1676 | # process patterns on comments if we pass in repo name | |
1664 | source, issues = process_patterns( |
|
1677 | source, issues = process_patterns( | |
1665 |
source, repo_name, link_format='markdown' |
|
1678 | source, repo_name, link_format='markdown', | |
|
1679 | active_entries=active_pattern_entries) | |||
1666 |
|
1680 | |||
1667 | return literal( |
|
1681 | return literal( | |
1668 | '<div class="markdown-block">%s</div>' % |
|
1682 | '<div class="markdown-block">%s</div>' % |
@@ -47,6 +47,14 b' log = logging.getLogger(__name__)' | |||||
47 | # default renderer used to generate automated comments |
|
47 | # default renderer used to generate automated comments | |
48 | DEFAULT_COMMENTS_RENDERER = 'rst' |
|
48 | DEFAULT_COMMENTS_RENDERER = 'rst' | |
49 |
|
49 | |||
|
50 | try: | |||
|
51 | from lxml.html import fromstring | |||
|
52 | from lxml.html import tostring | |||
|
53 | except ImportError: | |||
|
54 | log.exception('Failed to import lxml') | |||
|
55 | fromstring = None | |||
|
56 | tostring = None | |||
|
57 | ||||
50 |
|
58 | |||
51 | class CustomHTMLTranslator(writers.html4css1.HTMLTranslator): |
|
59 | class CustomHTMLTranslator(writers.html4css1.HTMLTranslator): | |
52 | """ |
|
60 | """ | |
@@ -81,11 +89,7 b' def relative_links(html_source, server_p' | |||||
81 | if not html_source: |
|
89 | if not html_source: | |
82 | return html_source |
|
90 | return html_source | |
83 |
|
91 | |||
84 | try: |
|
92 | if not fromstring and tostring: | |
85 | from lxml.html import fromstring |
|
|||
86 | from lxml.html import tostring |
|
|||
87 | except ImportError: |
|
|||
88 | log.exception('Failed to import lxml') |
|
|||
89 | return html_source |
|
93 | return html_source | |
90 |
|
94 | |||
91 | try: |
|
95 | try: | |
@@ -210,6 +214,8 b' class MarkupRenderer(object):' | |||||
210 | URL_PAT = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]' |
|
214 | URL_PAT = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]' | |
211 | r'|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)') |
|
215 | r'|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)') | |
212 |
|
216 | |||
|
217 | MENTION_PAT = re.compile(MENTIONS_REGEX) | |||
|
218 | ||||
213 | extensions = ['markdown.extensions.codehilite', 'markdown.extensions.extra', |
|
219 | extensions = ['markdown.extensions.codehilite', 'markdown.extensions.extra', | |
214 | 'markdown.extensions.def_list', 'markdown.extensions.sane_lists'] |
|
220 | 'markdown.extensions.def_list', 'markdown.extensions.sane_lists'] | |
215 |
|
221 | |||
@@ -348,6 +354,26 b' class MarkupRenderer(object):' | |||||
348 | return cls.URL_PAT.sub(url_func, text) |
|
354 | return cls.URL_PAT.sub(url_func, text) | |
349 |
|
355 | |||
350 | @classmethod |
|
356 | @classmethod | |
|
357 | def convert_mentions(cls, text, mode): | |||
|
358 | mention_pat = cls.MENTION_PAT | |||
|
359 | ||||
|
360 | def wrapp(match_obj): | |||
|
361 | uname = match_obj.groups()[0] | |||
|
362 | hovercard_url = "pyroutes.url('hovercard_username', {'username': '%s'});" % uname | |||
|
363 | ||||
|
364 | if mode == 'markdown': | |||
|
365 | tmpl = '<strong class="tooltip-hovercard" data-hovercard-alt="{uname}" data-hovercard-url="{hovercard_url}">@{uname}</strong>' | |||
|
366 | elif mode == 'rst': | |||
|
367 | tmpl = ' **@{uname}** ' | |||
|
368 | else: | |||
|
369 | raise ValueError('mode must be rst or markdown') | |||
|
370 | ||||
|
371 | return tmpl.format(**{'uname': uname, | |||
|
372 | 'hovercard_url': hovercard_url}) | |||
|
373 | ||||
|
374 | return mention_pat.sub(wrapp, text).strip() | |||
|
375 | ||||
|
376 | @classmethod | |||
351 | def plain(cls, source, universal_newline=True, leading_newline=True): |
|
377 | def plain(cls, source, universal_newline=True, leading_newline=True): | |
352 | source = safe_unicode(source) |
|
378 | source = safe_unicode(source) | |
353 | if universal_newline: |
|
379 | if universal_newline: | |
@@ -378,12 +404,7 b' class MarkupRenderer(object):' | |||||
378 | cls.extensions, cls.output_format) |
|
404 | cls.extensions, cls.output_format) | |
379 |
|
405 | |||
380 | if mentions: |
|
406 | if mentions: | |
381 | mention_pat = re.compile(MENTIONS_REGEX) |
|
407 | mention_hl = cls.convert_mentions(source, mode='markdown') | |
382 |
|
||||
383 | def wrapp(match_obj): |
|
|||
384 | uname = match_obj.groups()[0] |
|
|||
385 | return ' **@%(uname)s** ' % {'uname': uname} |
|
|||
386 | mention_hl = mention_pat.sub(wrapp, source).strip() |
|
|||
387 | # we extracted mentions render with this using Mentions false |
|
408 | # we extracted mentions render with this using Mentions false | |
388 | return cls.markdown(mention_hl, safe=safe, flavored=flavored, |
|
409 | return cls.markdown(mention_hl, safe=safe, flavored=flavored, | |
389 | mentions=False) |
|
410 | mentions=False) | |
@@ -409,12 +430,7 b' class MarkupRenderer(object):' | |||||
409 | @classmethod |
|
430 | @classmethod | |
410 | def rst(cls, source, safe=True, mentions=False, clean_html=False): |
|
431 | def rst(cls, source, safe=True, mentions=False, clean_html=False): | |
411 | if mentions: |
|
432 | if mentions: | |
412 | mention_pat = re.compile(MENTIONS_REGEX) |
|
433 | mention_hl = cls.convert_mentions(source, mode='rst') | |
413 |
|
||||
414 | def wrapp(match_obj): |
|
|||
415 | uname = match_obj.groups()[0] |
|
|||
416 | return ' **@%(uname)s** ' % {'uname': uname} |
|
|||
417 | mention_hl = mention_pat.sub(wrapp, source).strip() |
|
|||
418 | # we extracted mentions render with this using Mentions false |
|
434 | # we extracted mentions render with this using Mentions false | |
419 | return cls.rst(mention_hl, safe=safe, mentions=False) |
|
435 | return cls.rst(mention_hl, safe=safe, mentions=False) | |
420 |
|
436 | |||
@@ -443,7 +459,7 b' class MarkupRenderer(object):' | |||||
443 | except Exception: |
|
459 | except Exception: | |
444 | log.exception('Error when rendering RST') |
|
460 | log.exception('Error when rendering RST') | |
445 | if safe: |
|
461 | if safe: | |
446 |
log.debug('Fallback |
|
462 | log.debug('Fallback to render in plain mode') | |
447 | return cls.plain(source) |
|
463 | return cls.plain(source) | |
448 | else: |
|
464 | else: | |
449 | raise |
|
465 | raise |
@@ -133,15 +133,16 b' class SimpleVCS(object):' | |||||
133 | self.config = config |
|
133 | self.config = config | |
134 | # re-populated by specialized middleware |
|
134 | # re-populated by specialized middleware | |
135 | self.repo_vcs_config = base.Config() |
|
135 | self.repo_vcs_config = base.Config() | |
136 | self.rhodecode_settings = SettingsModel().get_all_settings(cache=True) |
|
|||
137 |
|
136 | |||
138 | registry.rhodecode_settings = self.rhodecode_settings |
|
137 | rc_settings = SettingsModel().get_all_settings(cache=True, from_request=False) | |
|
138 | realm = rc_settings.get('rhodecode_realm') or 'RhodeCode AUTH' | |||
|
139 | ||||
139 | # authenticate this VCS request using authfunc |
|
140 | # authenticate this VCS request using authfunc | |
140 | auth_ret_code_detection = \ |
|
141 | auth_ret_code_detection = \ | |
141 | str2bool(self.config.get('auth_ret_code_detection', False)) |
|
142 | str2bool(self.config.get('auth_ret_code_detection', False)) | |
142 | self.authenticate = BasicAuth( |
|
143 | self.authenticate = BasicAuth( | |
143 | '', authenticate, registry, config.get('auth_ret_code'), |
|
144 | '', authenticate, registry, config.get('auth_ret_code'), | |
144 | auth_ret_code_detection) |
|
145 | auth_ret_code_detection, rc_realm=realm) | |
145 | self.ip_addr = '0.0.0.0' |
|
146 | self.ip_addr = '0.0.0.0' | |
146 |
|
147 | |||
147 | @LazyProperty |
|
148 | @LazyProperty |
@@ -32,10 +32,14 b' def BeakerSessionFactoryConfig(**options' | |||||
32 |
|
32 | |||
33 | def session_callback(request, response): |
|
33 | def session_callback(request, response): | |
34 | exception = getattr(request, 'exception', None) |
|
34 | exception = getattr(request, 'exception', None) | |
35 | if (exception is None or self._cookie_on_exception) and self.accessed(): |
|
35 | file_response = getattr(request, '_file_response', None) | |
|
36 | ||||
|
37 | if file_response is None \ | |||
|
38 | and (exception is None or self._cookie_on_exception) \ | |||
|
39 | and self.accessed(): | |||
36 | self.persist() |
|
40 | self.persist() | |
37 | headers = self.__dict__['_headers'] |
|
41 | headers = self.__dict__['_headers'] | |
38 |
if headers |
|
42 | if headers.get('set_cookie') and headers.get('cookie_out'): | |
39 | response.headerlist.append(('Set-Cookie', headers['cookie_out'])) |
|
43 | response.headerlist.append(('Set-Cookie', headers['cookie_out'])) | |
40 | request.add_response_callback(session_callback) |
|
44 | request.add_response_callback(session_callback) | |
41 |
|
45 |
@@ -148,6 +148,15 b' class HGUpdateCaches(MaintenanceTask):' | |||||
148 | return res |
|
148 | return res | |
149 |
|
149 | |||
150 |
|
150 | |||
|
151 | class HGRebuildFnCaches(MaintenanceTask): | |||
|
152 | human_name = 'HG rebuild fn caches' | |||
|
153 | ||||
|
154 | def run(self): | |||
|
155 | instance = self.db_repo.scm_instance() | |||
|
156 | res = instance.hg_rebuild_fn_cache() | |||
|
157 | return res | |||
|
158 | ||||
|
159 | ||||
151 | class SVNVerify(MaintenanceTask): |
|
160 | class SVNVerify(MaintenanceTask): | |
152 | human_name = 'SVN Verify repo' |
|
161 | human_name = 'SVN Verify repo' | |
153 |
|
162 | |||
@@ -162,7 +171,7 b' class RepoMaintenance(object):' | |||||
162 | Performs maintenance of repository based on it's type |
|
171 | Performs maintenance of repository based on it's type | |
163 | """ |
|
172 | """ | |
164 | tasks = { |
|
173 | tasks = { | |
165 | 'hg': [HGVerify, HGUpdateCaches], |
|
174 | 'hg': [HGVerify, HGUpdateCaches, HGRebuildFnCaches], | |
166 | 'git': [GitFSCK, GitGC, GitRepack], |
|
175 | 'git': [GitFSCK, GitGC, GitRepack], | |
167 | 'svn': [SVNVerify], |
|
176 | 'svn': [SVNVerify], | |
168 | } |
|
177 | } |
@@ -432,8 +432,11 b' class GitCommit(base.BaseCommit):' | |||||
432 | """ |
|
432 | """ | |
433 | if not self.parents: |
|
433 | if not self.parents: | |
434 | return list(self._get_file_nodes()) |
|
434 | return list(self._get_file_nodes()) | |
435 | return AddedFileNodesGenerator( |
|
435 | return AddedFileNodesGenerator(self.added_paths, self) | |
436 | [n for n in self._get_paths_for_status('added')], self) |
|
436 | ||
|
437 | @LazyProperty | |||
|
438 | def added_paths(self): | |||
|
439 | return [n for n in self._get_paths_for_status('added')] | |||
437 |
|
440 | |||
438 | @LazyProperty |
|
441 | @LazyProperty | |
439 | def changed(self): |
|
442 | def changed(self): | |
@@ -442,8 +445,11 b' class GitCommit(base.BaseCommit):' | |||||
442 | """ |
|
445 | """ | |
443 | if not self.parents: |
|
446 | if not self.parents: | |
444 | return [] |
|
447 | return [] | |
445 | return ChangedFileNodesGenerator( |
|
448 | return ChangedFileNodesGenerator(self.changed_paths, self) | |
446 | [n for n in self._get_paths_for_status('modified')], self) |
|
449 | ||
|
450 | @LazyProperty | |||
|
451 | def changed_paths(self): | |||
|
452 | return [n for n in self._get_paths_for_status('modified')] | |||
447 |
|
453 | |||
448 | @LazyProperty |
|
454 | @LazyProperty | |
449 | def removed(self): |
|
455 | def removed(self): | |
@@ -452,8 +458,11 b' class GitCommit(base.BaseCommit):' | |||||
452 | """ |
|
458 | """ | |
453 | if not self.parents: |
|
459 | if not self.parents: | |
454 | return [] |
|
460 | return [] | |
455 | return RemovedFileNodesGenerator( |
|
461 | return RemovedFileNodesGenerator(self.removed_paths, self) | |
456 | [n for n in self._get_paths_for_status('deleted')], self) |
|
462 | ||
|
463 | @LazyProperty | |||
|
464 | def removed_paths(self): | |||
|
465 | return [n for n in self._get_paths_for_status('deleted')] | |||
457 |
|
466 | |||
458 | def _get_submodule_url(self, submodule_path): |
|
467 | def _get_submodule_url(self, submodule_path): | |
459 | git_modules_path = '.gitmodules' |
|
468 | git_modules_path = '.gitmodules' | |
@@ -472,7 +481,7 b' class GitCommit(base.BaseCommit):' | |||||
472 | for line in _content.splitlines(): |
|
481 | for line in _content.splitlines(): | |
473 | yield line |
|
482 | yield line | |
474 |
|
483 | |||
475 | parser = configparser.ConfigParser() |
|
484 | parser = configparser.RawConfigParser() | |
476 | parser.read_file(iter_content(submodules_node.content)) |
|
485 | parser.read_file(iter_content(submodules_node.content)) | |
477 |
|
486 | |||
478 | for section in parser.sections(): |
|
487 | for section in parser.sections(): |
@@ -372,18 +372,30 b' class MercurialCommit(base.BaseCommit):' | |||||
372 | """ |
|
372 | """ | |
373 | Returns list of added ``FileNode`` objects. |
|
373 | Returns list of added ``FileNode`` objects. | |
374 | """ |
|
374 | """ | |
375 |
return AddedFileNodesGenerator( |
|
375 | return AddedFileNodesGenerator(self.added_paths, self) | |
|
376 | ||||
|
377 | @LazyProperty | |||
|
378 | def added_paths(self): | |||
|
379 | return [n for n in self.status[1]] | |||
376 |
|
380 | |||
377 | @property |
|
381 | @property | |
378 | def changed(self): |
|
382 | def changed(self): | |
379 | """ |
|
383 | """ | |
380 | Returns list of modified ``FileNode`` objects. |
|
384 | Returns list of modified ``FileNode`` objects. | |
381 | """ |
|
385 | """ | |
382 |
return ChangedFileNodesGenerator( |
|
386 | return ChangedFileNodesGenerator(self.changed_paths, self) | |
|
387 | ||||
|
388 | @LazyProperty | |||
|
389 | def changed_paths(self): | |||
|
390 | return [n for n in self.status[0]] | |||
383 |
|
391 | |||
384 | @property |
|
392 | @property | |
385 | def removed(self): |
|
393 | def removed(self): | |
386 | """ |
|
394 | """ | |
387 | Returns list of removed ``FileNode`` objects. |
|
395 | Returns list of removed ``FileNode`` objects. | |
388 | """ |
|
396 | """ | |
389 |
return RemovedFileNodesGenerator( |
|
397 | return RemovedFileNodesGenerator(self.removed_paths, self) | |
|
398 | ||||
|
399 | @LazyProperty | |||
|
400 | def removed_paths(self): | |||
|
401 | return [n for n in self.status[2]] |
@@ -290,6 +290,12 b' class MercurialRepository(BaseRepository' | |||||
290 | self._remote.invalidate_vcs_cache() |
|
290 | self._remote.invalidate_vcs_cache() | |
291 | return update_cache |
|
291 | return update_cache | |
292 |
|
292 | |||
|
293 | def hg_rebuild_fn_cache(self): | |||
|
294 | update_cache = self._remote.hg_rebuild_fn_cache() | |||
|
295 | ||||
|
296 | self._remote.invalidate_vcs_cache() | |||
|
297 | return update_cache | |||
|
298 | ||||
293 | def get_common_ancestor(self, commit_id1, commit_id2, repo2): |
|
299 | def get_common_ancestor(self, commit_id1, commit_id2, repo2): | |
294 | if commit_id1 == commit_id2: |
|
300 | if commit_id1 == commit_id2: | |
295 | return commit_id1 |
|
301 | return commit_id1 |
@@ -218,18 +218,27 b' class SubversionCommit(base.BaseCommit):' | |||||
218 |
|
218 | |||
219 | @property |
|
219 | @property | |
220 | def added(self): |
|
220 | def added(self): | |
221 | return nodes.AddedFileNodesGenerator( |
|
221 | return nodes.AddedFileNodesGenerator(self.added_paths, self) | |
222 | self._changes_cache['added'], self) |
|
222 | ||
|
223 | @LazyProperty | |||
|
224 | def added_paths(self): | |||
|
225 | return [n for n in self._changes_cache['added']] | |||
223 |
|
226 | |||
224 | @property |
|
227 | @property | |
225 | def changed(self): |
|
228 | def changed(self): | |
226 | return nodes.ChangedFileNodesGenerator( |
|
229 | return nodes.ChangedFileNodesGenerator(self.changed_paths, self) | |
227 | self._changes_cache['changed'], self) |
|
230 | ||
|
231 | @LazyProperty | |||
|
232 | def changed_paths(self): | |||
|
233 | return [n for n in self._changes_cache['changed']] | |||
228 |
|
234 | |||
229 | @property |
|
235 | @property | |
230 | def removed(self): |
|
236 | def removed(self): | |
231 | return nodes.RemovedFileNodesGenerator( |
|
237 | return nodes.RemovedFileNodesGenerator(self.removed_paths, self) | |
232 | self._changes_cache['removed'], self) |
|
238 | ||
|
239 | @LazyProperty | |||
|
240 | def removed_paths(self): | |||
|
241 | return [n for n in self._changes_cache['removed']] | |||
233 |
|
242 | |||
234 |
|
243 | |||
235 | def _date_from_svn_properties(properties): |
|
244 | def _date_from_svn_properties(properties): |
@@ -18,6 +18,19 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
|
21 | DEFAULTS = { | |||
|
22 | 'encodings_map': {'.gz': 'gzip', | |||
|
23 | '.Z': 'compress', | |||
|
24 | '.bz2': 'bzip2', | |||
|
25 | '.xz': 'xz'}, | |||
|
26 | 'suffix_map': {'.svgz': '.svg.gz', | |||
|
27 | '.tgz': '.tar.gz', | |||
|
28 | '.taz': '.tar.gz', | |||
|
29 | '.tz': '.tar.gz', | |||
|
30 | '.tbz2': '.tar.bz2', | |||
|
31 | '.txz': '.tar.xz'}, | |||
|
32 | } | |||
|
33 | ||||
21 | TYPES_MAP = [ |
|
34 | TYPES_MAP = [ | |
22 | {'.jpg': 'image/jpg', |
|
35 | {'.jpg': 'image/jpg', | |
23 | '.mid': 'audio/midi', |
|
36 | '.mid': 'audio/midi', | |
@@ -1203,4 +1216,6 b' def get_mimetypes_db(extra_types=None):' | |||||
1203 | types_map[1].update(extra_types) |
|
1216 | types_map[1].update(extra_types) | |
1204 | db = mimetypes.MimeTypes() |
|
1217 | db = mimetypes.MimeTypes() | |
1205 | db.types_map = types_map |
|
1218 | db.types_map = types_map | |
|
1219 | db.encodings_map.update(DEFAULTS['encodings_map']) | |||
|
1220 | db.suffix_map.update(DEFAULTS['suffix_map']) | |||
1206 | return db |
|
1221 | return db |
@@ -1025,6 +1025,17 b' class User(Base, BaseModel):' | |||||
1025 | return qry.all() |
|
1025 | return qry.all() | |
1026 |
|
1026 | |||
1027 | @classmethod |
|
1027 | @classmethod | |
|
1028 | def get_all_user_ids(cls, only_active=True): | |||
|
1029 | """ | |||
|
1030 | Returns all users IDs | |||
|
1031 | """ | |||
|
1032 | qry = Session().query(User.user_id) | |||
|
1033 | ||||
|
1034 | if only_active: | |||
|
1035 | qry = qry.filter(User.active == true()) | |||
|
1036 | return [x.user_id for x in qry] | |||
|
1037 | ||||
|
1038 | @classmethod | |||
1028 | def get_default_user(cls, cache=False, refresh=False): |
|
1039 | def get_default_user(cls, cache=False, refresh=False): | |
1029 | user = User.get_by_username(User.DEFAULT_USER, cache=cache) |
|
1040 | user = User.get_by_username(User.DEFAULT_USER, cache=cache) | |
1030 | if user is None: |
|
1041 | if user is None: | |
@@ -3890,8 +3901,8 b' class _SetState(object):' | |||||
3890 | self._current_state = None |
|
3901 | self._current_state = None | |
3891 |
|
3902 | |||
3892 | def __enter__(self): |
|
3903 | def __enter__(self): | |
3893 | log.debug('StateLock: entering set state context, setting state to: `%s`', |
|
3904 | log.debug('StateLock: entering set state context of pr %s, setting state to: `%s`', | |
3894 | self._pr_state) |
|
3905 | self._pr, self._pr_state) | |
3895 | self.set_pr_state(self._pr_state) |
|
3906 | self.set_pr_state(self._pr_state) | |
3896 | return self |
|
3907 | return self | |
3897 |
|
3908 | |||
@@ -3901,8 +3912,9 b' class _SetState(object):' | |||||
3901 | return None |
|
3912 | return None | |
3902 |
|
3913 | |||
3903 | self.set_pr_state(self._org_state) |
|
3914 | self.set_pr_state(self._org_state) | |
3904 | log.debug('StateLock: exiting set state context, setting state to: `%s`', |
|
3915 | log.debug('StateLock: exiting set state context of pr %s, setting state to: `%s`', | |
3905 | self._org_state) |
|
3916 | self._pr, self._org_state) | |
|
3917 | ||||
3906 | @property |
|
3918 | @property | |
3907 | def state(self): |
|
3919 | def state(self): | |
3908 | return self._current_state |
|
3920 | return self._current_state | |
@@ -4285,6 +4297,7 b' class PullRequest(Base, _PullRequestBase' | |||||
4285 | def __json__(self): |
|
4297 | def __json__(self): | |
4286 | return { |
|
4298 | return { | |
4287 | 'revisions': self.revisions, |
|
4299 | 'revisions': self.revisions, | |
|
4300 | 'versions': self.versions_count | |||
4288 | } |
|
4301 | } | |
4289 |
|
4302 | |||
4290 | def calculated_review_status(self): |
|
4303 | def calculated_review_status(self): | |
@@ -4307,6 +4320,14 b' class PullRequest(Base, _PullRequestBase' | |||||
4307 | vcs_obj = self.target_repo.scm_instance() |
|
4320 | vcs_obj = self.target_repo.scm_instance() | |
4308 | return vcs_obj.get_shadow_instance(shadow_repository_path) |
|
4321 | return vcs_obj.get_shadow_instance(shadow_repository_path) | |
4309 |
|
4322 | |||
|
4323 | @property | |||
|
4324 | def versions_count(self): | |||
|
4325 | """ | |||
|
4326 | return number of versions this PR have, e.g a PR that once been | |||
|
4327 | updated will have 2 versions | |||
|
4328 | """ | |||
|
4329 | return self.versions.count() + 1 | |||
|
4330 | ||||
4310 |
|
4331 | |||
4311 | class PullRequestVersion(Base, _PullRequestBase): |
|
4332 | class PullRequestVersion(Base, _PullRequestBase): | |
4312 | __tablename__ = 'pull_request_versions' |
|
4333 | __tablename__ = 'pull_request_versions' |
@@ -21,8 +21,7 b'' | |||||
21 | """ |
|
21 | """ | |
22 | permissions model for RhodeCode |
|
22 | permissions model for RhodeCode | |
23 | """ |
|
23 | """ | |
24 |
|
24 | import collections | ||
25 |
|
||||
26 | import logging |
|
25 | import logging | |
27 | import traceback |
|
26 | import traceback | |
28 |
|
27 | |||
@@ -557,6 +556,27 b' class PermissionModel(BaseModel):' | |||||
557 | self.sa.rollback() |
|
556 | self.sa.rollback() | |
558 | raise |
|
557 | raise | |
559 |
|
558 | |||
|
559 | def get_users_with_repo_write(self, db_repo): | |||
|
560 | write_plus = ['repository.write', 'repository.admin'] | |||
|
561 | default_user_id = User.get_default_user().user_id | |||
|
562 | user_write_permissions = collections.OrderedDict() | |||
|
563 | ||||
|
564 | # write+ and DEFAULT user for inheritance | |||
|
565 | for perm in db_repo.permissions(): | |||
|
566 | if perm.permission in write_plus or perm.user_id == default_user_id: | |||
|
567 | user_write_permissions[perm.user_id] = perm | |||
|
568 | return user_write_permissions | |||
|
569 | ||||
|
570 | def get_user_groups_with_repo_write(self, db_repo): | |||
|
571 | write_plus = ['repository.write', 'repository.admin'] | |||
|
572 | user_group_write_permissions = collections.OrderedDict() | |||
|
573 | ||||
|
574 | # write+ and DEFAULT user for inheritance | |||
|
575 | for p in db_repo.permission_user_groups(): | |||
|
576 | if p.permission in write_plus: | |||
|
577 | user_group_write_permissions[p.users_group_id] = p | |||
|
578 | return user_group_write_permissions | |||
|
579 | ||||
560 | def trigger_permission_flush(self, affected_user_ids): |
|
580 | def trigger_permission_flush(self, affected_user_ids): | |
561 | events.trigger(events.UserPermissionsChange(affected_user_ids)) |
|
581 | events.trigger(events.UserPermissionsChange(affected_user_ids)) | |
562 |
|
582 |
@@ -26,6 +26,8 b' pull request model for RhodeCode' | |||||
26 |
|
26 | |||
27 | import json |
|
27 | import json | |
28 | import logging |
|
28 | import logging | |
|
29 | import os | |||
|
30 | ||||
29 | import datetime |
|
31 | import datetime | |
30 | import urllib |
|
32 | import urllib | |
31 | import collections |
|
33 | import collections | |
@@ -632,6 +634,7 b' class PullRequestModel(BaseModel):' | |||||
632 | repo_id = pull_request.target_repo.repo_id |
|
634 | repo_id = pull_request.target_repo.repo_id | |
633 | use_rebase = self._use_rebase_for_merging(pull_request) |
|
635 | use_rebase = self._use_rebase_for_merging(pull_request) | |
634 | close_branch = self._close_branch_before_merging(pull_request) |
|
636 | close_branch = self._close_branch_before_merging(pull_request) | |
|
637 | user_name = self._user_name_for_merging(pull_request, user) | |||
635 |
|
638 | |||
636 | target_ref = self._refresh_reference( |
|
639 | target_ref = self._refresh_reference( | |
637 | pull_request.target_ref_parts, target_vcs) |
|
640 | pull_request.target_ref_parts, target_vcs) | |
@@ -647,7 +650,6 b' class PullRequestModel(BaseModel):' | |||||
647 | target_vcs.config.set( |
|
650 | target_vcs.config.set( | |
648 | 'rhodecode', 'RC_SCM_DATA', json.dumps(extras)) |
|
651 | 'rhodecode', 'RC_SCM_DATA', json.dumps(extras)) | |
649 |
|
652 | |||
650 | user_name = user.short_contact |
|
|||
651 | merge_state = target_vcs.merge( |
|
653 | merge_state = target_vcs.merge( | |
652 | repo_id, workspace_id, target_ref, source_vcs, |
|
654 | repo_id, workspace_id, target_ref, source_vcs, | |
653 | pull_request.source_ref_parts, |
|
655 | pull_request.source_ref_parts, | |
@@ -1664,6 +1666,16 b' class PullRequestModel(BaseModel):' | |||||
1664 |
|
1666 | |||
1665 | return False |
|
1667 | return False | |
1666 |
|
1668 | |||
|
1669 | def _user_name_for_merging(self, pull_request, user): | |||
|
1670 | env_user_name_attr = os.environ.get('RC_MERGE_USER_NAME_ATTR', '') | |||
|
1671 | if env_user_name_attr and hasattr(user, env_user_name_attr): | |||
|
1672 | user_name_attr = env_user_name_attr | |||
|
1673 | else: | |||
|
1674 | user_name_attr = 'short_contact' | |||
|
1675 | ||||
|
1676 | user_name = getattr(user, user_name_attr) | |||
|
1677 | return user_name | |||
|
1678 | ||||
1667 | def _close_branch_before_merging(self, pull_request): |
|
1679 | def _close_branch_before_merging(self, pull_request): | |
1668 | repo_type = pull_request.target_repo.repo_type |
|
1680 | repo_type = pull_request.target_repo.repo_type | |
1669 | if repo_type == 'hg': |
|
1681 | if repo_type == 'hg': |
@@ -38,8 +38,7 b' from rhodecode.lib.user_log_filter impor' | |||||
38 | from rhodecode.lib.utils import make_db_config |
|
38 | from rhodecode.lib.utils import make_db_config | |
39 | from rhodecode.lib.utils2 import ( |
|
39 | from rhodecode.lib.utils2 import ( | |
40 | safe_str, safe_unicode, remove_prefix, obfuscate_url_pw, |
|
40 | safe_str, safe_unicode, remove_prefix, obfuscate_url_pw, | |
41 |
get_current_rhodecode_user, safe_int, |
|
41 | get_current_rhodecode_user, safe_int, action_logger_generic) | |
42 | action_logger_generic) |
|
|||
43 | from rhodecode.lib.vcs.backends import get_backend |
|
42 | from rhodecode.lib.vcs.backends import get_backend | |
44 | from rhodecode.model import BaseModel |
|
43 | from rhodecode.model import BaseModel | |
45 | from rhodecode.model.db import ( |
|
44 | from rhodecode.model.db import ( | |
@@ -199,9 +198,11 b' class RepoModel(BaseModel):' | |||||
199 |
|
198 | |||
200 | def get_repos_as_dict(self, repo_list=None, admin=False, |
|
199 | def get_repos_as_dict(self, repo_list=None, admin=False, | |
201 | super_user_actions=False, short_name=None): |
|
200 | super_user_actions=False, short_name=None): | |
|
201 | ||||
202 | _render = get_current_request().get_partial_renderer( |
|
202 | _render = get_current_request().get_partial_renderer( | |
203 | 'rhodecode:templates/data_table/_dt_elements.mako') |
|
203 | 'rhodecode:templates/data_table/_dt_elements.mako') | |
204 | c = _render.get_call_context() |
|
204 | c = _render.get_call_context() | |
|
205 | h = _render.get_helpers() | |||
205 |
|
206 | |||
206 | def quick_menu(repo_name): |
|
207 | def quick_menu(repo_name): | |
207 | return _render('quick_menu', repo_name) |
|
208 | return _render('quick_menu', repo_name) | |
@@ -258,7 +259,7 b' class RepoModel(BaseModel):' | |||||
258 | "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state, |
|
259 | "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state, | |
259 | repo.private, repo.archived, repo.fork), |
|
260 | repo.private, repo.archived, repo.fork), | |
260 |
|
261 | |||
261 | "desc": desc(repo.description), |
|
262 | "desc": desc(h.escape(repo.description)), | |
262 |
|
263 | |||
263 | "last_change": last_change(repo.updated_on), |
|
264 | "last_change": last_change(repo.updated_on), | |
264 |
|
265 | |||
@@ -619,13 +620,26 b' class RepoModel(BaseModel):' | |||||
619 | changes = { |
|
620 | changes = { | |
620 | 'added': [], |
|
621 | 'added': [], | |
621 | 'updated': [], |
|
622 | 'updated': [], | |
622 | 'deleted': [] |
|
623 | 'deleted': [], | |
|
624 | 'default_user_changed': None | |||
623 | } |
|
625 | } | |
|
626 | ||||
|
627 | repo = self._get_repo(repo) | |||
|
628 | ||||
624 | # update permissions |
|
629 | # update permissions | |
625 | for member_id, perm, member_type in perm_updates: |
|
630 | for member_id, perm, member_type in perm_updates: | |
626 | member_id = int(member_id) |
|
631 | member_id = int(member_id) | |
627 | if member_type == 'user': |
|
632 | if member_type == 'user': | |
628 | member_name = User.get(member_id).username |
|
633 | member_name = User.get(member_id).username | |
|
634 | if member_name == User.DEFAULT_USER: | |||
|
635 | # NOTE(dan): detect if we changed permissions for default user | |||
|
636 | perm_obj = self.sa.query(UserRepoToPerm) \ | |||
|
637 | .filter(UserRepoToPerm.user_id == member_id) \ | |||
|
638 | .filter(UserRepoToPerm.repository == repo) \ | |||
|
639 | .scalar() | |||
|
640 | if perm_obj and perm_obj.permission.permission_name != perm: | |||
|
641 | changes['default_user_changed'] = True | |||
|
642 | ||||
629 | # this updates also current one if found |
|
643 | # this updates also current one if found | |
630 | self.grant_user_permission( |
|
644 | self.grant_user_permission( | |
631 | repo=repo, user=member_id, perm=perm) |
|
645 | repo=repo, user=member_id, perm=perm) |
@@ -41,7 +41,7 b' from rhodecode.model.db import (_hash_ke' | |||||
41 | UserGroup, Repository) |
|
41 | UserGroup, Repository) | |
42 | from rhodecode.model.settings import VcsSettingsModel, SettingsModel |
|
42 | from rhodecode.model.settings import VcsSettingsModel, SettingsModel | |
43 | from rhodecode.lib.caching_query import FromCache |
|
43 | from rhodecode.lib.caching_query import FromCache | |
44 |
from rhodecode.lib.utils2 import action_logger_generic |
|
44 | from rhodecode.lib.utils2 import action_logger_generic | |
45 |
|
45 | |||
46 | log = logging.getLogger(__name__) |
|
46 | log = logging.getLogger(__name__) | |
47 |
|
47 | |||
@@ -353,7 +353,8 b' class RepoGroupModel(BaseModel):' | |||||
353 | changes = { |
|
353 | changes = { | |
354 | 'added': [], |
|
354 | 'added': [], | |
355 | 'updated': [], |
|
355 | 'updated': [], | |
356 | 'deleted': [] |
|
356 | 'deleted': [], | |
|
357 | 'default_user_changed': None | |||
357 | } |
|
358 | } | |
358 |
|
359 | |||
359 | def _set_perm_user(obj, user, perm): |
|
360 | def _set_perm_user(obj, user, perm): | |
@@ -430,6 +431,15 b' class RepoGroupModel(BaseModel):' | |||||
430 | member_id = int(member_id) |
|
431 | member_id = int(member_id) | |
431 | if member_type == 'user': |
|
432 | if member_type == 'user': | |
432 | member_name = User.get(member_id).username |
|
433 | member_name = User.get(member_id).username | |
|
434 | if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER: | |||
|
435 | # NOTE(dan): detect if we changed permissions for default user | |||
|
436 | perm_obj = self.sa.query(UserRepoGroupToPerm) \ | |||
|
437 | .filter(UserRepoGroupToPerm.user_id == member_id) \ | |||
|
438 | .filter(UserRepoGroupToPerm.group == repo_group) \ | |||
|
439 | .scalar() | |||
|
440 | if perm_obj and perm_obj.permission.permission_name != perm: | |||
|
441 | changes['default_user_changed'] = True | |||
|
442 | ||||
433 | # this updates also current one if found |
|
443 | # this updates also current one if found | |
434 | _set_perm_user(obj, user=member_id, perm=perm) |
|
444 | _set_perm_user(obj, user=member_id, perm=perm) | |
435 | elif member_type == 'user_group': |
|
445 | elif member_type == 'user_group': | |
@@ -698,8 +708,6 b' class RepoGroupModel(BaseModel):' | |||||
698 | for repo_group in repo_groups: |
|
708 | for repo_group in repo_groups: | |
699 | repo_group.update_commit_cache() |
|
709 | repo_group.update_commit_cache() | |
700 |
|
710 | |||
701 |
|
||||
702 |
|
||||
703 | def get_repo_groups_as_dict(self, repo_group_list=None, admin=False, |
|
711 | def get_repo_groups_as_dict(self, repo_group_list=None, admin=False, | |
704 | super_user_actions=False): |
|
712 | super_user_actions=False): | |
705 |
|
713 | |||
@@ -753,7 +761,7 b' class RepoGroupModel(BaseModel):' | |||||
753 | "last_changeset": "", |
|
761 | "last_changeset": "", | |
754 | "last_changeset_raw": "", |
|
762 | "last_changeset_raw": "", | |
755 |
|
763 | |||
756 | "desc": desc(group.group_description, group.personal), |
|
764 | "desc": desc(h.escape(group.group_description), group.personal), | |
757 | "top_level_repos": 0, |
|
765 | "top_level_repos": 0, | |
758 | "owner": user_profile(group.User.username) |
|
766 | "owner": user_profile(group.User.username) | |
759 | } |
|
767 | } |
@@ -21,9 +21,11 b'' | |||||
21 | import os |
|
21 | import os | |
22 | import hashlib |
|
22 | import hashlib | |
23 | import logging |
|
23 | import logging | |
|
24 | import re | |||
24 | from collections import namedtuple |
|
25 | from collections import namedtuple | |
25 | from functools import wraps |
|
26 | from functools import wraps | |
26 | import bleach |
|
27 | import bleach | |
|
28 | from pyramid.threadlocal import get_current_request, get_current_registry | |||
27 |
|
29 | |||
28 | from rhodecode.lib import rc_cache |
|
30 | from rhodecode.lib import rc_cache | |
29 | from rhodecode.lib.utils2 import ( |
|
31 | from rhodecode.lib.utils2 import ( | |
@@ -210,7 +212,23 b' class SettingsModel(BaseModel):' | |||||
210 | invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE |
|
212 | invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE | |
211 | CacheKey.set_invalidate(invalidation_namespace) |
|
213 | CacheKey.set_invalidate(invalidation_namespace) | |
212 |
|
214 | |||
213 | def get_all_settings(self, cache=False): |
|
215 | def get_all_settings(self, cache=False, from_request=True): | |
|
216 | from rhodecode.authentication.base import get_authn_registry | |||
|
217 | ||||
|
218 | # defines if we use GLOBAL, or PER_REPO | |||
|
219 | repo = self._get_repo(self.repo) if self.repo else None | |||
|
220 | key = "settings_repo.{}".format(repo.repo_id) if repo else "settings_app" | |||
|
221 | ||||
|
222 | # initially try the requests context, this is the fastest | |||
|
223 | # we only fetch global config | |||
|
224 | if from_request: | |||
|
225 | request = get_current_request() | |||
|
226 | ||||
|
227 | if request and not repo and hasattr(request, 'call_context') and hasattr(request.call_context, 'rc_config'): | |||
|
228 | rc_config = request.call_context.rc_config | |||
|
229 | if rc_config: | |||
|
230 | return rc_config | |||
|
231 | ||||
214 | region = rc_cache.get_or_create_region('sql_cache_short') |
|
232 | region = rc_cache.get_or_create_region('sql_cache_short') | |
215 | invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE |
|
233 | invalidation_namespace = CacheKey.SETTINGS_INVALIDATION_NAMESPACE | |
216 |
|
234 | |||
@@ -226,9 +244,6 b' class SettingsModel(BaseModel):' | |||||
226 | } |
|
244 | } | |
227 | return settings |
|
245 | return settings | |
228 |
|
246 | |||
229 | repo = self._get_repo(self.repo) if self.repo else None |
|
|||
230 | key = "settings_repo.{}".format(repo.repo_id) if repo else "settings_app" |
|
|||
231 |
|
||||
232 | inv_context_manager = rc_cache.InvalidationContext( |
|
247 | inv_context_manager = rc_cache.InvalidationContext( | |
233 | uid='cache_settings', invalidation_namespace=invalidation_namespace) |
|
248 | uid='cache_settings', invalidation_namespace=invalidation_namespace) | |
234 | with inv_context_manager as invalidation_context: |
|
249 | with inv_context_manager as invalidation_context: | |
@@ -240,6 +255,11 b' class SettingsModel(BaseModel):' | |||||
240 | # are anyway very short lived and it's a safest way. |
|
255 | # are anyway very short lived and it's a safest way. | |
241 | region = rc_cache.get_or_create_region('sql_cache_short') |
|
256 | region = rc_cache.get_or_create_region('sql_cache_short') | |
242 | region.invalidate() |
|
257 | region.invalidate() | |
|
258 | registry = get_current_registry() | |||
|
259 | if registry: | |||
|
260 | authn_registry = get_authn_registry(registry) | |||
|
261 | if authn_registry: | |||
|
262 | authn_registry.invalidate_plugins_for_auth() | |||
243 |
|
263 | |||
244 | result = _get_all_settings('rhodecode_settings', key) |
|
264 | result = _get_all_settings('rhodecode_settings', key) | |
245 | log.debug('Fetching app settings for key: %s took: %.4fs', key, |
|
265 | log.debug('Fetching app settings for key: %s took: %.4fs', key, | |
@@ -360,9 +380,15 b' class IssueTrackerSettingsModel(object):' | |||||
360 | for uid in issuetracker_entries: |
|
380 | for uid in issuetracker_entries: | |
361 | url_data = qs.get(self._get_keyname('url', uid, 'rhodecode_')) |
|
381 | url_data = qs.get(self._get_keyname('url', uid, 'rhodecode_')) | |
362 |
|
382 | |||
|
383 | pat = qs.get(self._get_keyname('pat', uid, 'rhodecode_')) | |||
|
384 | try: | |||
|
385 | pat_compiled = re.compile(r'%s' % pat) | |||
|
386 | except re.error: | |||
|
387 | pat_compiled = None | |||
|
388 | ||||
363 | issuetracker_entries[uid] = AttributeDict({ |
|
389 | issuetracker_entries[uid] = AttributeDict({ | |
364 |
'pat': |
|
390 | 'pat': pat, | |
365 | self._get_keyname('pat', uid, 'rhodecode_')), |
|
391 | 'pat_compiled': pat_compiled, | |
366 | 'url': url_cleaner( |
|
392 | 'url': url_cleaner( | |
367 | qs.get(self._get_keyname('url', uid, 'rhodecode_')) or ''), |
|
393 | qs.get(self._get_keyname('url', uid, 'rhodecode_')) or ''), | |
368 | 'pref': bleach.clean( |
|
394 | 'pref': bleach.clean( |
@@ -38,6 +38,7 b' log = logging.getLogger(__name__)' | |||||
38 |
|
38 | |||
39 | class SshKeyModel(BaseModel): |
|
39 | class SshKeyModel(BaseModel): | |
40 | cls = UserSshKeys |
|
40 | cls = UserSshKeys | |
|
41 | DEFAULT_PRIVATE_KEY_FORMAT = 'pkcs8' | |||
41 |
|
42 | |||
42 | def parse_key(self, key_data): |
|
43 | def parse_key(self, key_data): | |
43 | """ |
|
44 | """ | |
@@ -66,16 +67,23 b' class SshKeyModel(BaseModel):' | |||||
66 | log.error("Key Parse error: %s", err) |
|
67 | log.error("Key Parse error: %s", err) | |
67 | raise |
|
68 | raise | |
68 |
|
69 | |||
69 | def generate_keypair(self, comment=None): |
|
70 | def generate_keypair(self, comment=None, private_format=DEFAULT_PRIVATE_KEY_FORMAT): | |
70 |
|
71 | |||
71 | key = rsa.generate_private_key( |
|
72 | key = rsa.generate_private_key( | |
72 | backend=crypto_default_backend(), |
|
73 | backend=crypto_default_backend(), | |
73 | public_exponent=65537, |
|
74 | public_exponent=65537, | |
74 | key_size=2048 |
|
75 | key_size=2048 | |
75 | ) |
|
76 | ) | |
|
77 | if private_format == self.DEFAULT_PRIVATE_KEY_FORMAT: | |||
|
78 | private_format = crypto_serialization.PrivateFormat.PKCS8 | |||
|
79 | else: | |||
|
80 | # legacy format that can be used by older systems, use if pkcs8 have | |||
|
81 | # problems | |||
|
82 | private_format = crypto_serialization.PrivateFormat.TraditionalOpenSSL | |||
|
83 | ||||
76 | private_key = key.private_bytes( |
|
84 | private_key = key.private_bytes( | |
77 | crypto_serialization.Encoding.PEM, |
|
85 | crypto_serialization.Encoding.PEM, | |
78 |
|
|
86 | private_format, | |
79 | crypto_serialization.NoEncryption()) |
|
87 | crypto_serialization.NoEncryption()) | |
80 | public_key = key.public_key().public_bytes( |
|
88 | public_key = key.public_key().public_bytes( | |
81 | crypto_serialization.Encoding.OpenSSH, |
|
89 | crypto_serialization.Encoding.OpenSSH, |
@@ -134,14 +134,11 b' div.markdown-block h2 {' | |||||
134 | div.markdown-block h1 { |
|
134 | div.markdown-block h1 { | |
135 | font-size: 32px; |
|
135 | font-size: 32px; | |
136 | margin: 15px 0 15px 0 !important; |
|
136 | margin: 15px 0 15px 0 !important; | |
137 | padding-bottom: 5px !important; |
|
|||
138 | } |
|
137 | } | |
139 |
|
138 | |||
140 | div.markdown-block h2 { |
|
139 | div.markdown-block h2 { | |
141 | font-size: 24px !important; |
|
140 | font-size: 24px !important; | |
142 | margin: 34px 0 10px 0 !important; |
|
141 | margin: 34px 0 10px 0 !important; | |
143 | padding-top: 15px !important; |
|
|||
144 | padding-bottom: 8px !important; |
|
|||
145 | } |
|
142 | } | |
146 |
|
143 | |||
147 | div.markdown-block h3 { |
|
144 | div.markdown-block h3 { | |
@@ -174,6 +171,21 b' div.markdown-block hr {' | |||||
174 | margin-bottom: 13px; |
|
171 | margin-bottom: 13px; | |
175 | } |
|
172 | } | |
176 |
|
173 | |||
|
174 | div.markdown-block blockquote { | |||
|
175 | color: #424242 !important; | |||
|
176 | padding: 8px 21px; | |||
|
177 | margin: 12px 0; | |||
|
178 | border-left: 4px solid @grey6; | |||
|
179 | } | |||
|
180 | ||||
|
181 | div.markdown-block blockquote p { | |||
|
182 | color: #424242 !important; | |||
|
183 | padding: 0 !important; | |||
|
184 | margin: 0 !important; | |||
|
185 | line-height: 1.5; | |||
|
186 | } | |||
|
187 | ||||
|
188 | ||||
177 | div.markdown-block ol, |
|
189 | div.markdown-block ol, | |
178 | div.markdown-block ul, |
|
190 | div.markdown-block ul, | |
179 | div.markdown-block p, |
|
191 | div.markdown-block p, | |
@@ -181,13 +193,11 b' div.markdown-block blockquote,' | |||||
181 | div.markdown-block dl, |
|
193 | div.markdown-block dl, | |
182 | div.markdown-block li, |
|
194 | div.markdown-block li, | |
183 | div.markdown-block table { |
|
195 | div.markdown-block table { | |
184 | margin: 3px 0px 13px 0px !important; |
|
|||
185 | color: #424242 !important; |
|
196 | color: #424242 !important; | |
186 | font-size: 13px !important; |
|
197 | font-size: 13px !important; | |
187 | font-family: @text-regular; |
|
198 | font-family: @text-regular; | |
188 | font-weight: normal !important; |
|
199 | font-weight: normal !important; | |
189 | overflow: visible !important; |
|
200 | overflow: visible !important; | |
190 | line-height: 140% !important; |
|
|||
191 | } |
|
201 | } | |
192 |
|
202 | |||
193 | div.markdown-block pre { |
|
203 | div.markdown-block pre { | |
@@ -245,14 +255,6 b' div.markdown-block ol li {' | |||||
245 | list-style: decimal !important; |
|
255 | list-style: decimal !important; | |
246 | } |
|
256 | } | |
247 |
|
257 | |||
248 | /* |
|
|||
249 | div.markdown-block a, |
|
|||
250 | div.markdown-block a:visited { |
|
|||
251 | color: #4183C4 !important; |
|
|||
252 | background-color: inherit; |
|
|||
253 | text-decoration: none; |
|
|||
254 | } |
|
|||
255 | */ |
|
|||
256 |
|
258 | |||
257 | div.markdown-block #message { |
|
259 | div.markdown-block #message { | |
258 | .border-radius(@border-radius); |
|
260 | .border-radius(@border-radius); |
@@ -87,6 +87,10 b' body {' | |||||
87 | border-left: @border-thickness solid @border-default-color; |
|
87 | border-left: @border-thickness solid @border-default-color; | |
88 | } |
|
88 | } | |
89 |
|
89 | |||
|
90 | .cursor-pointer { | |||
|
91 | cursor: pointer; | |||
|
92 | } | |||
|
93 | ||||
90 | input + .action-link, .action-link.first{ |
|
94 | input + .action-link, .action-link.first{ | |
91 | border-left: none; |
|
95 | border-left: none; | |
92 | } |
|
96 | } |
@@ -3,9 +3,13 b'' | |||||
3 | .readme-title { |
|
3 | .readme-title { | |
4 | border: 1px solid @grey6; |
|
4 | border: 1px solid @grey6; | |
5 | padding: 10px 5px; |
|
5 | padding: 10px 5px; | |
6 | font-weight: 600; |
|
|||
7 | margin-top: 30px; |
|
6 | margin-top: 30px; | |
8 | margin-bottom: -1px; |
|
7 | margin-bottom: -1px; | |
|
8 | ||||
|
9 | a { | |||
|
10 | font-weight: 600; | |||
|
11 | font-size: 13px | |||
|
12 | } | |||
9 | } |
|
13 | } | |
10 |
|
14 | |||
11 | div.readme_box { |
|
15 | div.readme_box { | |
@@ -34,14 +38,11 b' div.readme_box h2 {' | |||||
34 | div.readme_box h1 { |
|
38 | div.readme_box h1 { | |
35 | font-size: 32px; |
|
39 | font-size: 32px; | |
36 | margin: 15px 0 15px 0 !important; |
|
40 | margin: 15px 0 15px 0 !important; | |
37 | padding-bottom: 5px !important; |
|
|||
38 | } |
|
41 | } | |
39 |
|
42 | |||
40 | div.readme_box h2 { |
|
43 | div.readme_box h2 { | |
41 | font-size: 24px !important; |
|
44 | font-size: 24px !important; | |
42 | margin: 34px 0 10px 0 !important; |
|
45 | margin: 34px 0 10px 0 !important; | |
43 | padding-top: 15px !important; |
|
|||
44 | padding-bottom: 8px !important; |
|
|||
45 | } |
|
46 | } | |
46 |
|
47 | |||
47 | div.readme_box h3 { |
|
48 | div.readme_box h3 { | |
@@ -74,6 +75,20 b' div.readme_box hr {' | |||||
74 | margin-bottom: 13px; |
|
75 | margin-bottom: 13px; | |
75 | } |
|
76 | } | |
76 |
|
77 | |||
|
78 | div.readme_box blockquote { | |||
|
79 | color: #424242 !important; | |||
|
80 | padding: 8px 21px; | |||
|
81 | margin: 12px 0; | |||
|
82 | border-left: 4px solid @grey6; | |||
|
83 | } | |||
|
84 | ||||
|
85 | div.readme_box blockquote p { | |||
|
86 | color: #424242 !important; | |||
|
87 | padding: 0 !important; | |||
|
88 | margin: 0 !important; | |||
|
89 | line-height: 1.5; | |||
|
90 | } | |||
|
91 | ||||
77 | div.readme_box ol, |
|
92 | div.readme_box ol, | |
78 | div.readme_box ul, |
|
93 | div.readme_box ul, | |
79 | div.readme_box p, |
|
94 | div.readme_box p, | |
@@ -81,13 +96,11 b' div.readme_box blockquote,' | |||||
81 | div.readme_box dl, |
|
96 | div.readme_box dl, | |
82 | div.readme_box li, |
|
97 | div.readme_box li, | |
83 | div.readme_box table { |
|
98 | div.readme_box table { | |
84 | margin: 3px 0px 13px 0px !important; |
|
|||
85 | color: #424242 !important; |
|
99 | color: #424242 !important; | |
86 | font-size: 13px !important; |
|
100 | font-size: 13px !important; | |
87 | font-family: @text-regular; |
|
101 | font-family: @text-regular; | |
88 | font-weight: normal !important; |
|
102 | font-weight: normal !important; | |
89 | overflow: visible !important; |
|
103 | overflow: visible !important; | |
90 | line-height: 140% !important; |
|
|||
91 | } |
|
104 | } | |
92 |
|
105 | |||
93 | div.readme_box pre { |
|
106 | div.readme_box pre { |
@@ -373,6 +373,17 b' table#repo_list_table {' | |||||
373 | min-width: 600px; |
|
373 | min-width: 600px; | |
374 | } |
|
374 | } | |
375 |
|
375 | |||
|
376 | #no_grid_data { | |||
|
377 | text-align: center; | |||
|
378 | } | |||
|
379 | ||||
|
380 | #grid_data_loading { | |||
|
381 | text-align: center; | |||
|
382 | font-weight: 600; | |||
|
383 | font-size: 16px; | |||
|
384 | padding: 80px 20px; | |||
|
385 | } | |||
|
386 | ||||
376 | // Keyboard mappings |
|
387 | // Keyboard mappings | |
377 | table.keyboard-mappings { |
|
388 | table.keyboard-mappings { | |
378 | th { |
|
389 | th { | |
@@ -538,5 +549,12 b' table.compare_view_commits {' | |||||
538 | img{ |
|
549 | img{ | |
539 | vertical-align: middle; |
|
550 | vertical-align: middle; | |
540 | } |
|
551 | } | |
|
552 | ||||
|
553 | &.td-expire { | |||
|
554 | width: 200px; | |||
|
555 | } | |||
|
556 | &.td-gist-type { | |||
|
557 | width: 100px; | |||
|
558 | } | |||
541 | } |
|
559 | } | |
542 | } |
|
560 | } |
@@ -593,7 +593,7 b' address {' | |||||
593 | } |
|
593 | } | |
594 |
|
594 | |||
595 | .help-block-inline { |
|
595 | .help-block-inline { | |
596 | margin: 0; |
|
596 | margin: 0 !important; | |
597 | } |
|
597 | } | |
598 |
|
598 | |||
599 | // help block text |
|
599 | // help block text |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Follow', |
|
33 | 'Follow': 'Follow', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'Lifetime', |
|
41 | 'Lifetime': 'Lifetime', | |
33 | 'Loading ...': 'Loading ...', |
|
42 | 'Loading ...': 'Loading ...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'No matching files', |
|
51 | 'No matching files': 'No matching files', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Follow', |
|
33 | 'Follow': 'Follow', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'Lebensdauer', |
|
41 | 'Lifetime': 'Lebensdauer', | |
33 | 'Loading ...': 'Loading ...', |
|
42 | 'Loading ...': 'Loading ...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'No matching files', |
|
51 | 'No matching files': 'No matching files', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Follow', |
|
33 | 'Follow': 'Follow', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'Lifetime', |
|
41 | 'Lifetime': 'Lifetime', | |
33 | 'Loading ...': 'Loading ...', |
|
42 | 'Loading ...': 'Loading ...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'No matching files', |
|
51 | 'No matching files': 'No matching files', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Follow', |
|
33 | 'Follow': 'Follow', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'De por vida', |
|
41 | 'Lifetime': 'De por vida', | |
33 | 'Loading ...': 'Loading ...', |
|
42 | 'Loading ...': 'Loading ...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'No matching files', |
|
51 | 'No matching files': 'No matching files', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Follow', |
|
33 | 'Follow': 'Follow', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'Durée de vie', |
|
41 | 'Lifetime': 'Durée de vie', | |
33 | 'Loading ...': 'Loading ...', |
|
42 | 'Loading ...': 'Loading ...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'No matching files', |
|
51 | 'No matching files': 'No matching files', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} mois', |
|
139 | '{0} months': '{0} mois', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Segui', |
|
33 | 'Follow': 'Segui', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'a vita', |
|
41 | 'Lifetime': 'a vita', | |
33 | 'Loading ...': 'Caricamento ...', |
|
42 | 'Loading ...': 'Caricamento ...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'Nessuna corrispondenza tra i file', |
|
51 | 'No matching files': 'Nessuna corrispondenza tra i file', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'Nessun risultato', |
|
57 | 'No results': 'Nessun risultato', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': '選択したステータス ({0}) を元にコメントが自動的に設定されます...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': '選択したステータス ({0}) を元にコメントが自動的に設定されます...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'フォロー', |
|
33 | 'Follow': 'フォロー', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': '有効期間', |
|
41 | 'Lifetime': '有効期間', | |
33 | 'Loading ...': '読み込み中...', |
|
42 | 'Loading ...': '読み込み中...', | |
34 | 'Loading failed': '読み込み失敗', |
|
43 | 'Loading failed': '読み込み失敗', | |
35 | 'Loading more results...': '結果を読み込み中...', |
|
44 | 'Loading more results...': '結果を読み込み中...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'まだブックマークがありません。', |
|
46 | 'No bookmarks available yet.': 'まだブックマークがありません。', | |
37 | 'No branches available yet.': 'まだブランチがありません。', |
|
47 | 'No branches available yet.': 'まだブランチがありません。', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'マッチするファイルはありません', |
|
51 | 'No matching files': 'マッチするファイルはありません', | |
42 | 'No pull requests available yet.': 'まだプルリクエストがありません。', |
|
52 | 'No pull requests available yet.': 'まだプルリクエストがありません。', | |
43 | 'No repositories available yet.': 'まだリポジトリがありません。', |
|
53 | 'No repositories available yet.': 'まだリポジトリがありません。', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'まだリポジトリグループがありません。', |
|
55 | 'No repository groups available yet.': 'まだリポジトリグループがありません。', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': '結果がありません', |
|
57 | 'No results': '結果がありません', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'まだタグがありません。', |
|
59 | 'No tags available yet.': 'まだタグがありません。', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} 分', |
|
137 | '{0} min': '{0} 分', | |
126 | '{0} month': '{0} ヶ月', |
|
138 | '{0} month': '{0} ヶ月', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} 件の結果があります。矢印キーの上下で選択できます。', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} 件の結果があります。矢印キーの上下で選択できます。', | |
133 | '{0} sec': '{0} 秒', |
|
147 | '{0} sec': '{0} 秒', |
@@ -5,28 +5,38 b'' | |||||
5 | _gettext('All Authors'); |
|
5 | _gettext('All Authors'); | |
6 | _gettext('All individual reviewers must vote.'); |
|
6 | _gettext('All individual reviewers must vote.'); | |
7 | _gettext('All reviewers must vote.'); |
|
7 | _gettext('All reviewers must vote.'); | |
|
8 | _gettext('Are you sure to close this pull request without merging?'); | |||
8 | _gettext('At least {0} reviewer must vote.'); |
|
9 | _gettext('At least {0} reviewer must vote.'); | |
9 | _gettext('At least {0} reviewers must vote.'); |
|
10 | _gettext('At least {0} reviewers must vote.'); | |
10 | _gettext('Author is not allowed to be a reviewer.'); |
|
11 | _gettext('Author is not allowed to be a reviewer.'); | |
11 | _gettext('Changed files'); |
|
12 | _gettext('Changed files'); | |
12 | _gettext('Close'); |
|
13 | _gettext('Close'); | |
|
14 | _gettext('Collapse all files'); | |||
|
15 | _gettext('Collapse {0} commit'); | |||
|
16 | _gettext('Collapse {0} commits'); | |||
13 | _gettext('Comment text will be set automatically based on currently selected status ({0}) ...'); |
|
17 | _gettext('Comment text will be set automatically based on currently selected status ({0}) ...'); | |
14 | _gettext('Commit Authors are not allowed to be a reviewer.'); |
|
18 | _gettext('Commit Authors are not allowed to be a reviewer.'); | |
15 | _gettext('Context file: '); |
|
19 | _gettext('Context file: '); | |
16 | _gettext('Delete this comment?'); |
|
20 | _gettext('Delete this comment?'); | |
17 | _gettext('Diff to Commit '); |
|
21 | _gettext('Diff to Commit '); | |
|
22 | _gettext('Expand all files'); | |||
|
23 | _gettext('Expand {0} commit'); | |||
|
24 | _gettext('Expand {0} commits'); | |||
18 | _gettext('Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.'); |
|
25 | _gettext('Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.'); | |
19 | _gettext('Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.'); |
|
26 | _gettext('Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.'); | |
20 | _gettext('Follow'); |
|
27 | _gettext('Follow'); | |
|
28 | _gettext('Force updating...'); | |||
21 | _gettext('Hide full context diff'); |
|
29 | _gettext('Hide full context diff'); | |
22 | _gettext('Hide whitespace changes'); |
|
30 | _gettext('Hide whitespace changes'); | |
23 | _gettext('Invite reviewers to this discussion'); |
|
31 | _gettext('Invite reviewers to this discussion'); | |
24 | _gettext('Leave a comment on line {0}.'); |
|
32 | _gettext('Leave a comment on line {0}.'); | |
25 | _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}'); |
|
33 | _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}'); | |
|
34 | _gettext('Leave a resolution comment, or click resolve button to resolve TODO comment #{0}'); | |||
26 | _gettext('Lifetime'); |
|
35 | _gettext('Lifetime'); | |
27 | _gettext('Loading ...'); |
|
36 | _gettext('Loading ...'); | |
28 | _gettext('Loading failed'); |
|
37 | _gettext('Loading failed'); | |
29 | _gettext('Loading more results...'); |
|
38 | _gettext('Loading more results...'); | |
|
39 | _gettext('Loading...'); | |||
30 | _gettext('No bookmarks available yet.'); |
|
40 | _gettext('No bookmarks available yet.'); | |
31 | _gettext('No branches available yet.'); |
|
41 | _gettext('No branches available yet.'); | |
32 | _gettext('No forks available yet.'); |
|
42 | _gettext('No forks available yet.'); | |
@@ -35,7 +45,9 b'' | |||||
35 | _gettext('No matching files'); |
|
45 | _gettext('No matching files'); | |
36 | _gettext('No pull requests available yet.'); |
|
46 | _gettext('No pull requests available yet.'); | |
37 | _gettext('No repositories available yet.'); |
|
47 | _gettext('No repositories available yet.'); | |
|
48 | _gettext('No repositories present.'); | |||
38 | _gettext('No repository groups available yet.'); |
|
49 | _gettext('No repository groups available yet.'); | |
|
50 | _gettext('No repository groups present.'); | |||
39 | _gettext('No results'); |
|
51 | _gettext('No results'); | |
40 | _gettext('No ssh keys available yet.'); |
|
52 | _gettext('No ssh keys available yet.'); | |
41 | _gettext('No tags available yet.'); |
|
53 | _gettext('No tags available yet.'); | |
@@ -119,9 +131,11 b'' | |||||
119 | _gettext('{0} min'); |
|
131 | _gettext('{0} min'); | |
120 | _gettext('{0} month'); |
|
132 | _gettext('{0} month'); | |
121 | _gettext('{0} months'); |
|
133 | _gettext('{0} months'); | |
|
134 | _gettext('{0} of {1} repositories'); | |||
122 | _gettext('{0} of {1} repository groups'); |
|
135 | _gettext('{0} of {1} repository groups'); | |
123 | _gettext('{0} out of {1} ssh keys'); |
|
136 | _gettext('{0} out of {1} ssh keys'); | |
124 | _gettext('{0} out of {1} users'); |
|
137 | _gettext('{0} out of {1} users'); | |
|
138 | _gettext('{0} repositories'); | |||
125 | _gettext('{0} repository groups'); |
|
139 | _gettext('{0} repository groups'); | |
126 | _gettext('{0} results are available, use up and down arrow keys to navigate.'); |
|
140 | _gettext('{0} results are available, use up and down arrow keys to navigate.'); | |
127 | _gettext('{0} sec'); |
|
141 | _gettext('{0} sec'); |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Zamknij', |
|
19 | 'Close': 'Zamknij', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Obserwuj', |
|
33 | 'Follow': 'Obserwuj', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'Czas życia', |
|
41 | 'Lifetime': 'Czas życia', | |
33 | 'Loading ...': 'Ładuję...', |
|
42 | 'Loading ...': 'Ładuję...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'Nie ma plików pasujących', |
|
51 | 'No matching files': 'Nie ma plików pasujących', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Seguir', |
|
33 | 'Follow': 'Seguir', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'Tempo de Vida', |
|
41 | 'Lifetime': 'Tempo de Vida', | |
33 | 'Loading ...': 'Carregando...', |
|
42 | 'Loading ...': 'Carregando...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'Nenhum arquivo encontrado', |
|
51 | 'No matching files': 'Nenhum arquivo encontrado', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Наблюдать', |
|
33 | 'Follow': 'Наблюдать', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': 'Срок', |
|
41 | 'Lifetime': 'Срок', | |
33 | 'Loading ...': 'Загрузка...', |
|
42 | 'Loading ...': 'Загрузка...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'Нет совпадений', |
|
51 | 'No matching files': 'Нет совпадений', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -11,28 +11,38 b' var _TM = {' | |||||
11 | 'All Authors': 'All Authors', |
|
11 | 'All Authors': 'All Authors', | |
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', |
|
12 | 'All individual reviewers must vote.': 'All individual reviewers must vote.', | |
13 | 'All reviewers must vote.': 'All reviewers must vote.', |
|
13 | 'All reviewers must vote.': 'All reviewers must vote.', | |
|
14 | 'Are you sure to close this pull request without merging?': 'Are you sure to close this pull request without merging?', | |||
14 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', |
|
15 | 'At least {0} reviewer must vote.': 'At least {0} reviewer must vote.', | |
15 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', |
|
16 | 'At least {0} reviewers must vote.': 'At least {0} reviewers must vote.', | |
16 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', |
|
17 | 'Author is not allowed to be a reviewer.': 'Author is not allowed to be a reviewer.', | |
17 | 'Changed files': 'Changed files', |
|
18 | 'Changed files': 'Changed files', | |
18 | 'Close': 'Close', |
|
19 | 'Close': 'Close', | |
|
20 | 'Collapse all files': 'Collapse all files', | |||
|
21 | 'Collapse {0} commit': 'Collapse {0} commit', | |||
|
22 | 'Collapse {0} commits': 'Collapse {0} commits', | |||
19 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', |
|
23 | 'Comment text will be set automatically based on currently selected status ({0}) ...': 'Comment text will be set automatically based on currently selected status ({0}) ...', | |
20 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', |
|
24 | 'Commit Authors are not allowed to be a reviewer.': 'Commit Authors are not allowed to be a reviewer.', | |
21 | 'Context file: ': 'Context file: ', |
|
25 | 'Context file: ': 'Context file: ', | |
22 | 'Delete this comment?': 'Delete this comment?', |
|
26 | 'Delete this comment?': 'Delete this comment?', | |
23 | 'Diff to Commit ': 'Diff to Commit ', |
|
27 | 'Diff to Commit ': 'Diff to Commit ', | |
|
28 | 'Expand all files': 'Expand all files', | |||
|
29 | 'Expand {0} commit': 'Expand {0} commit', | |||
|
30 | 'Expand {0} commits': 'Expand {0} commits', | |||
24 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', |
|
31 | 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.': 'Fetching repository state failed. Error code: {0} {1}. Try <a href="{2}">refreshing</a> this page.', | |
25 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', |
|
32 | 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.': 'Fetching repository state failed. Error code: {0} {1}. Try refreshing this page.', | |
26 | 'Follow': 'Follow', |
|
33 | 'Follow': 'Follow', | |
|
34 | 'Force updating...': 'Force updating...', | |||
27 | 'Hide full context diff': 'Hide full context diff', |
|
35 | 'Hide full context diff': 'Hide full context diff', | |
28 | 'Hide whitespace changes': 'Hide whitespace changes', |
|
36 | 'Hide whitespace changes': 'Hide whitespace changes', | |
29 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', |
|
37 | 'Invite reviewers to this discussion': 'Invite reviewers to this discussion', | |
30 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', |
|
38 | 'Leave a comment on line {0}.': 'Leave a comment on line {0}.', | |
31 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', |
|
39 | 'Leave a comment, or click resolve button to resolve TODO comment #{0}': 'Leave a comment, or click resolve button to resolve TODO comment #{0}', | |
|
40 | 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}': 'Leave a resolution comment, or click resolve button to resolve TODO comment #{0}', | |||
32 | 'Lifetime': '终身', |
|
41 | 'Lifetime': '终身', | |
33 | 'Loading ...': 'Loading ...', |
|
42 | 'Loading ...': 'Loading ...', | |
34 | 'Loading failed': 'Loading failed', |
|
43 | 'Loading failed': 'Loading failed', | |
35 | 'Loading more results...': 'Loading more results...', |
|
44 | 'Loading more results...': 'Loading more results...', | |
|
45 | 'Loading...': 'Loading...', | |||
36 | 'No bookmarks available yet.': 'No bookmarks available yet.', |
|
46 | 'No bookmarks available yet.': 'No bookmarks available yet.', | |
37 | 'No branches available yet.': 'No branches available yet.', |
|
47 | 'No branches available yet.': 'No branches available yet.', | |
38 | 'No forks available yet.': 'No forks available yet.', |
|
48 | 'No forks available yet.': 'No forks available yet.', | |
@@ -41,7 +51,9 b' var _TM = {' | |||||
41 | 'No matching files': 'No matching files', |
|
51 | 'No matching files': 'No matching files', | |
42 | 'No pull requests available yet.': 'No pull requests available yet.', |
|
52 | 'No pull requests available yet.': 'No pull requests available yet.', | |
43 | 'No repositories available yet.': 'No repositories available yet.', |
|
53 | 'No repositories available yet.': 'No repositories available yet.', | |
|
54 | 'No repositories present.': 'No repositories present.', | |||
44 | 'No repository groups available yet.': 'No repository groups available yet.', |
|
55 | 'No repository groups available yet.': 'No repository groups available yet.', | |
|
56 | 'No repository groups present.': 'No repository groups present.', | |||
45 | 'No results': 'No results', |
|
57 | 'No results': 'No results', | |
46 | 'No ssh keys available yet.': 'No ssh keys available yet.', |
|
58 | 'No ssh keys available yet.': 'No ssh keys available yet.', | |
47 | 'No tags available yet.': 'No tags available yet.', |
|
59 | 'No tags available yet.': 'No tags available yet.', | |
@@ -125,9 +137,11 b' var _TM = {' | |||||
125 | '{0} min': '{0} min', |
|
137 | '{0} min': '{0} min', | |
126 | '{0} month': '{0} month', |
|
138 | '{0} month': '{0} month', | |
127 | '{0} months': '{0} months', |
|
139 | '{0} months': '{0} months', | |
|
140 | '{0} of {1} repositories': '{0} of {1} repositories', | |||
128 | '{0} of {1} repository groups': '{0} of {1} repository groups', |
|
141 | '{0} of {1} repository groups': '{0} of {1} repository groups', | |
129 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', |
|
142 | '{0} out of {1} ssh keys': '{0} out of {1} ssh keys', | |
130 | '{0} out of {1} users': '{0} out of {1} users', |
|
143 | '{0} out of {1} users': '{0} out of {1} users', | |
|
144 | '{0} repositories': '{0} repositories', | |||
131 | '{0} repository groups': '{0} repository groups', |
|
145 | '{0} repository groups': '{0} repository groups', | |
132 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', |
|
146 | '{0} results are available, use up and down arrow keys to navigate.': '{0} results are available, use up and down arrow keys to navigate.', | |
133 | '{0} sec': '{0} sec', |
|
147 | '{0} sec': '{0} sec', |
@@ -31,6 +31,7 b' function registerRCRoutes() {' | |||||
31 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); |
|
31 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); | |
32 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); |
|
32 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); | |
33 | pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']); |
|
33 | pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']); | |
|
34 | pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']); | |||
34 | pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']); |
|
35 | pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']); | |
35 | pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']); |
|
36 | pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']); | |
36 | pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']); |
|
37 | pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']); |
@@ -299,6 +299,10 b' var tooltipActivate = function () {' | |||||
299 | var altHovercard =$origin.data('hovercardAlt'); |
|
299 | var altHovercard =$origin.data('hovercardAlt'); | |
300 |
|
300 | |||
301 | if (hovercardUrl !== undefined && hovercardUrl !== "") { |
|
301 | if (hovercardUrl !== undefined && hovercardUrl !== "") { | |
|
302 | if (hovercardUrl.substr(0,12) === 'pyroutes.url'){ | |||
|
303 | hovercardUrl = eval(hovercardUrl) | |||
|
304 | } | |||
|
305 | ||||
302 | var loaded = loadHoverCard(hovercardUrl, altHovercard, function (data) { |
|
306 | var loaded = loadHoverCard(hovercardUrl, altHovercard, function (data) { | |
303 | instance.content(data); |
|
307 | instance.content(data); | |
304 | }) |
|
308 | }) |
@@ -102,7 +102,7 b'' | |||||
102 | { data: {"_": "author", |
|
102 | { data: {"_": "author", | |
103 | "sort": "author_raw"}, title: "${_("Author")}", width: "250px", className: "td-user" }, |
|
103 | "sort": "author_raw"}, title: "${_("Author")}", width: "250px", className: "td-user" }, | |
104 | { data: {"_": "type", |
|
104 | { data: {"_": "type", | |
105 |
"sort": "type"}, title: "${_("Type")}", width: " |
|
105 | "sort": "type"}, title: "${_("Type")}", width: "100px", className: "td-gist-type" }, | |
106 | { data: {"_": "access_id", |
|
106 | { data: {"_": "access_id", | |
107 | "sort": "access_id"}, title: "${_("Name")}", width:"150px", className: "td-componentname" }, |
|
107 | "sort": "access_id"}, title: "${_("Name")}", width:"150px", className: "td-componentname" }, | |
108 | { data: {"_": "description", |
|
108 | { data: {"_": "description", | |
@@ -110,7 +110,7 b'' | |||||
110 | { data: {"_": "created_on", |
|
110 | { data: {"_": "created_on", | |
111 | "sort": "created_on_raw"}, title: "${_("Created on")}", className: "td-time" }, |
|
111 | "sort": "created_on_raw"}, title: "${_("Created on")}", className: "td-time" }, | |
112 | { data: {"_": "expires", |
|
112 | { data: {"_": "expires", | |
113 | "sort": "expires"}, title: "${_("Expires")}", className: "td-exp" } |
|
113 | "sort": "expires"}, title: "${_("Expires")}", width: "200px", className: "td-expire" } | |
114 | ], |
|
114 | ], | |
115 | language: { |
|
115 | language: { | |
116 | paginate: DEFAULT_GRID_PAGINATION, |
|
116 | paginate: DEFAULT_GRID_PAGINATION, |
@@ -71,7 +71,7 b'' | |||||
71 | <div class="input"> |
|
71 | <div class="input"> | |
72 | ${h.text('description', class_='medium', placeholder=_('Description'))} |
|
72 | ${h.text('description', class_='medium', placeholder=_('Description'))} | |
73 | ${h.hidden('lifetime')} |
|
73 | ${h.hidden('lifetime')} | |
74 | ${h.select('role', '', c.role_options)} |
|
74 | ${h.select('role', request.GET.get('token_role', ''), c.role_options)} | |
75 |
|
75 | |||
76 | % if c.allow_scoped_tokens: |
|
76 | % if c.allow_scoped_tokens: | |
77 | ${h.hidden('scope_repo_id')} |
|
77 | ${h.hidden('scope_repo_id')} |
@@ -4,7 +4,9 b'' | |||||
4 |
|
4 | |||
5 | % if c.extern_type != 'rhodecode': |
|
5 | % if c.extern_type != 'rhodecode': | |
6 | <p>${_('Your user account details are managed by an external source. Details cannot be managed here.')} |
|
6 | <p>${_('Your user account details are managed by an external source. Details cannot be managed here.')} | |
7 | <br/>${_('Source type')}: <strong>${c.extern_type}</strong> |
|
7 | <br/>${_('For VCS access please generate')} | |
|
8 | <a href="${h.route_path('my_account_auth_tokens', _query={'token_role':'token_role_vcs'})}">Authentication Token</a> or <a href="${h.route_path('my_account_ssh_keys_generate')}">SSH Key</a>. | |||
|
9 | <br/>${_('Source type')}: <strong>${c.extern_type}</strong> | |||
8 | </p> |
|
10 | </p> | |
9 | % else: |
|
11 | % else: | |
10 | ${c.form.render() | n} |
|
12 | ${c.form.render() | n} |
@@ -8,6 +8,17 b'' | |||||
8 | </div> |
|
8 | </div> | |
9 |
|
9 | |||
10 | <div class="panel-body fields"> |
|
10 | <div class="panel-body fields"> | |
|
11 | %if c.extern_type != 'rhodecode': | |||
|
12 | <% readonly = "readonly" %> | |||
|
13 | <% disabled = " disabled" %> | |||
|
14 | <div class="alert-warning" style="margin:0px 0px 20px 0px; padding: 10px"> | |||
|
15 | <strong>${_('This user was created from external source (%s). Editing some of the settings is limited.' % c.extern_type)}</strong> | |||
|
16 | </div> | |||
|
17 | <div style="margin:-10px 0px 20px 0px;"> | |||
|
18 | ${_('For VCS access please generate')} | |||
|
19 | <a href="${h.route_path('my_account_auth_tokens', _query={'token_role':'token_role_vcs'})}">Authentication Token</a> or <a href="${h.route_path('my_account_ssh_keys_generate')}">SSH Key</a>. | |||
|
20 | </div> | |||
|
21 | %endif | |||
11 | <div class="field"> |
|
22 | <div class="field"> | |
12 | <div class="label"> |
|
23 | <div class="label"> | |
13 | ${_('Photo')}: |
|
24 | ${_('Photo')}: |
@@ -11,13 +11,19 b'' | |||||
11 |
|
11 | |||
12 | %if c.extern_type != 'rhodecode': |
|
12 | %if c.extern_type != 'rhodecode': | |
13 | <% readonly = "readonly" %> |
|
13 | <% readonly = "readonly" %> | |
14 | <% disabled = "disabled" %> |
|
14 | <% disabled = " disabled" %> | |
|
15 | <div class="alert-warning" style="margin:0px 0px 20px 0px; padding: 10px"> | |||
|
16 | <strong>${_('This user was created from external source (%s). Editing some of the settings is limited.' % c.extern_type)}</strong> | |||
|
17 | </div> | |||
|
18 | <div style="margin:-10px 0px 20px 0px;"> | |||
|
19 | ${_('For VCS access please generate')} | |||
|
20 | <a href="${h.route_path('my_account_auth_tokens', _query={'token_role':'token_role_vcs'})}">Authentication Token</a> or <a href="${h.route_path('my_account_ssh_keys_generate')}">SSH Key</a>. | |||
|
21 | </div> | |||
|
22 | %endif | |||
|
23 | ||||
|
24 | %if c.extern_type != 'rhodecode': | |||
15 | <div class="infoform"> |
|
25 | <div class="infoform"> | |
16 | <div class="fields"> |
|
26 | <div class="fields"> | |
17 | <p>${_('Your user account details are managed by an external source. Details cannot be managed here.')} |
|
|||
18 | <br/>${_('Source type')}: <strong>${c.extern_type}</strong> |
|
|||
19 | </p> |
|
|||
20 |
|
||||
21 | <div class="field"> |
|
27 | <div class="field"> | |
22 | <div class="label"> |
|
28 | <div class="label"> | |
23 | <label for="username">${_('Username')}:</label> |
|
29 | <label for="username">${_('Username')}:</label> |
@@ -55,7 +55,13 b'' | |||||
55 | <div class="textarea editor"> |
|
55 | <div class="textarea editor"> | |
56 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} |
|
56 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} | |
57 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> |
|
57 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> | |
58 | <span class="help-block">${_('Plain text format with support of {metatags}').format(metatags=metatags_url)|n}</span> |
|
58 | <span class="help-block"> | |
|
59 | % if c.visual.stylify_metatags: | |||
|
60 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} | |||
|
61 | % else: | |||
|
62 | ${_('Plain text format.')} | |||
|
63 | % endif | |||
|
64 | </span> | |||
59 | <span id="meta-tags-desc" style="display: none"> |
|
65 | <span id="meta-tags-desc" style="display: none"> | |
60 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
66 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
61 | ${dt.metatags_help()} |
|
67 | ${dt.metatags_help()} |
@@ -28,7 +28,7 b'' | |||||
28 | <div class="sidebar"> |
|
28 | <div class="sidebar"> | |
29 | <ul class="nav nav-pills nav-stacked"> |
|
29 | <ul class="nav nav-pills nav-stacked"> | |
30 | <li class="${h.is_active('settings', c.active)}"><a href="${h.route_path('edit_repo_group', repo_group_name=c.repo_group.group_name)}">${_('Settings')}</a></li> |
|
30 | <li class="${h.is_active('settings', c.active)}"><a href="${h.route_path('edit_repo_group', repo_group_name=c.repo_group.group_name)}">${_('Settings')}</a></li> | |
31 | <li class="${h.is_active('permissions', c.active)}"><a href="${h.route_path('edit_repo_group_perms', repo_group_name=c.repo_group.group_name)}">${_('Permissions')}</a></li> |
|
31 | <li class="${h.is_active('permissions', c.active)}"><a href="${h.route_path('edit_repo_group_perms', repo_group_name=c.repo_group.group_name)}">${_('Access Permissions')}</a></li> | |
32 | <li class="${h.is_active('advanced', c.active)}"><a href="${h.route_path('edit_repo_group_advanced', repo_group_name=c.repo_group.group_name)}">${_('Advanced')}</a></li> |
|
32 | <li class="${h.is_active('advanced', c.active)}"><a href="${h.route_path('edit_repo_group_advanced', repo_group_name=c.repo_group.group_name)}">${_('Advanced')}</a></li> | |
33 | <li class="${h.is_active('integrations', c.active)}"><a href="${h.route_path('repo_group_integrations_home', repo_group_name=c.repo_group.group_name)}">${_('Integrations')}</a></li> |
|
33 | <li class="${h.is_active('integrations', c.active)}"><a href="${h.route_path('repo_group_integrations_home', repo_group_name=c.repo_group.group_name)}">${_('Integrations')}</a></li> | |
34 | </ul> |
|
34 | </ul> |
@@ -61,7 +61,12 b'' | |||||
61 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} |
|
61 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} | |
62 | <span class="user"> |
|
62 | <span class="user"> | |
63 | % if _user.username == h.DEFAULT_USER: |
|
63 | % if _user.username == h.DEFAULT_USER: | |
64 | ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span> |
|
64 | ${h.DEFAULT_USER} | |
|
65 | % if _user.active: | |||
|
66 | <span class="user-perm-help-text"> - ${_('permission for other logged in and anonymous users')}</span> | |||
|
67 | % else: | |||
|
68 | <span class="user-perm-help-text"> - ${_('permission for other logged in users')}</span> | |||
|
69 | % endif | |||
65 | % else: |
|
70 | % else: | |
66 | ${h.link_to_user(_user.username)} |
|
71 | ${h.link_to_user(_user.username)} | |
67 | %if getattr(_user, 'duplicate_perm', None): |
|
72 | %if getattr(_user, 'duplicate_perm', None): | |
@@ -104,7 +109,12 b'' | |||||
104 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} |
|
109 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} | |
105 | <span class="user"> |
|
110 | <span class="user"> | |
106 | % if _user.username == h.DEFAULT_USER: |
|
111 | % if _user.username == h.DEFAULT_USER: | |
107 | ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span> |
|
112 | ${h.DEFAULT_USER} | |
|
113 | % if _user.active: | |||
|
114 | <span class="user-perm-help-text"> - ${_('permission for other logged in and anonymous users')}</span> | |||
|
115 | % else: | |||
|
116 | <span class="user-perm-help-text"> - ${_('permission for other logged in users')}</span> | |||
|
117 | % endif | |||
108 | % else: |
|
118 | % else: | |
109 | ${h.link_to_user(_user.username)} |
|
119 | ${h.link_to_user(_user.username)} | |
110 | %if getattr(_user, 'duplicate_perm', None): |
|
120 | %if getattr(_user, 'duplicate_perm', None): |
@@ -59,7 +59,13 b'' | |||||
59 | ${c.form.render_error(request, c.form['repo_group_description'])|n} |
|
59 | ${c.form.render_error(request, c.form['repo_group_description'])|n} | |
60 |
|
60 | |||
61 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> |
|
61 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> | |
62 | <span class="help-block">${_('Plain text format with support of {metatags}').format(metatags=metatags_url)|n}</span> |
|
62 | <span class="help-block"> | |
|
63 | % if c.visual.stylify_metatags: | |||
|
64 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} | |||
|
65 | % else: | |||
|
66 | ${_('Plain text format.')} | |||
|
67 | % endif | |||
|
68 | </span> | |||
63 | <span id="meta-tags-desc" style="display: none"> |
|
69 | <span id="meta-tags-desc" style="display: none"> | |
64 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
70 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
65 | ${dt.metatags_help()} |
|
71 | ${dt.metatags_help()} |
@@ -68,7 +68,14 b'' | |||||
68 | <div class="textarea editor"> |
|
68 | <div class="textarea editor"> | |
69 | ${h.textarea('repo_description',cols=23,rows=5,class_="medium")} |
|
69 | ${h.textarea('repo_description',cols=23,rows=5,class_="medium")} | |
70 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> |
|
70 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> | |
71 | <span class="help-block">${_('Plain text format with support of {metatags}. Add a README file for longer descriptions').format(metatags=metatags_url)|n}</span> |
|
71 | <span class="help-block"> | |
|
72 | % if c.visual.stylify_metatags: | |||
|
73 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} | |||
|
74 | % else: | |||
|
75 | ${_('Plain text format.')} | |||
|
76 | % endif | |||
|
77 | ${_('Add a README file for longer descriptions')} | |||
|
78 | </span> | |||
72 | <span id="meta-tags-desc" style="display: none"> |
|
79 | <span id="meta-tags-desc" style="display: none"> | |
73 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
80 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
74 | ${dt.metatags_help()} |
|
81 | ${dt.metatags_help()} |
@@ -23,43 +23,48 b'' | |||||
23 | <div class="panel-heading"> |
|
23 | <div class="panel-heading"> | |
24 | <h3 class="panel-title">${_('Inherited Issue Tracker Patterns')}</h3> |
|
24 | <h3 class="panel-title">${_('Inherited Issue Tracker Patterns')}</h3> | |
25 | </div> |
|
25 | </div> | |
|
26 | ||||
26 | <div class="panel-body"> |
|
27 | <div class="panel-body"> | |
27 |
|
|
28 | <table class="rctable issuetracker readonly"> | |
28 | <tr> |
|
29 | <tr> | |
29 | <th>${_('Description')}</th> |
|
30 | <th>${_('Description')}</th> | |
30 | <th>${_('Pattern')}</th> |
|
31 | <th>${_('Pattern')}</th> | |
31 | <th>${_('Url')}</th> |
|
32 | <th>${_('Url')}</th> | |
32 | <th>${_('Prefix')}</th> |
|
33 | <th>${_('Prefix')}</th> | |
33 |
<th |
|
34 | <th></th> | |
34 | </tr> |
|
35 | </tr> | |
35 | %for uid, entry in c.global_patterns.items(): |
|
|||
36 | <tr id="${uid}"> |
|
|||
37 | <td class="td-description issuetracker_desc"> |
|
|||
38 | <span class="entry"> |
|
|||
39 | ${entry.desc} |
|
|||
40 | </span> |
|
|||
41 | </td> |
|
|||
42 | <td class="td-regex issuetracker_pat"> |
|
|||
43 | <span class="entry"> |
|
|||
44 | ${entry.pat} |
|
|||
45 | </span> |
|
|||
46 | </td> |
|
|||
47 | <td class="td-url issuetracker_url"> |
|
|||
48 | <span class="entry"> |
|
|||
49 | ${entry.url} |
|
|||
50 | </span> |
|
|||
51 | </td> |
|
|||
52 | <td class="td-prefix issuetracker_pref"> |
|
|||
53 | <span class="entry"> |
|
|||
54 | ${entry.pref} |
|
|||
55 | </span> |
|
|||
56 | </td> |
|
|||
57 | <td class="td-action"> |
|
|||
58 | </td> |
|
|||
59 | </tr> |
|
|||
60 | %endfor |
|
|||
61 |
|
36 | |||
62 | </table> |
|
37 | % for uid, entry in c.global_patterns.items(): | |
|
38 | <tr id="${uid}"> | |||
|
39 | <td class="td-description issuetracker_desc"> | |||
|
40 | <span class="entry"> | |||
|
41 | ${entry.desc} | |||
|
42 | </span> | |||
|
43 | </td> | |||
|
44 | <td class="td-regex issuetracker_pat"> | |||
|
45 | <span class="entry"> | |||
|
46 | ${entry.pat} | |||
|
47 | </span> | |||
|
48 | </td> | |||
|
49 | <td class="td-url issuetracker_url"> | |||
|
50 | <span class="entry"> | |||
|
51 | ${entry.url} | |||
|
52 | </span> | |||
|
53 | </td> | |||
|
54 | <td class="td-prefix issuetracker_pref"> | |||
|
55 | <span class="entry"> | |||
|
56 | ${entry.pref} | |||
|
57 | </span> | |||
|
58 | </td> | |||
|
59 | <td class="td-action"> | |||
|
60 | </td> | |||
|
61 | </tr> | |||
|
62 | % endfor | |||
|
63 | ||||
|
64 | </table> | |||
|
65 | <div class="buttons"> | |||
|
66 | <button type="submit" class="btn btn-primary save-inheritance" id="save">${_('Save')}</button> | |||
|
67 | </div> | |||
63 | </div> |
|
68 | </div> | |
64 | </div> |
|
69 | </div> | |
65 | </div> |
|
70 | </div> | |
@@ -77,7 +82,6 b'' | |||||
77 | )} |
|
82 | )} | |
78 | <div class="buttons"> |
|
83 | <div class="buttons"> | |
79 | <button type="submit" class="btn btn-primary save-inheritance" id="save">${_('Save')}</button> |
|
84 | <button type="submit" class="btn btn-primary save-inheritance" id="save">${_('Save')}</button> | |
80 | <button type="reset" class="btn reset-inheritance">${_('Reset')}</button> |
|
|||
81 | </div> |
|
85 | </div> | |
82 | </div> |
|
86 | </div> | |
83 | </div> |
|
87 | </div> |
@@ -58,7 +58,11 b'' | |||||
58 | <td class="private_repo_msg"> |
|
58 | <td class="private_repo_msg"> | |
59 | ${base.gravatar(h.DEFAULT_USER_EMAIL, 16)} |
|
59 | ${base.gravatar(h.DEFAULT_USER_EMAIL, 16)} | |
60 | ${h.DEFAULT_USER} - ${_('only users/user groups explicitly added here will have access')}</td> |
|
60 | ${h.DEFAULT_USER} - ${_('only users/user groups explicitly added here will have access')}</td> | |
61 |
<td |
|
61 | <td class="td-action"> | |
|
62 | <span class="tooltip btn btn-link btn-default" onclick="setPrivateRepo(false); return false" title="${_('Private repositories are only visible to people explicitly added as collaborators. Default permissions wont apply')}"> | |||
|
63 | ${_('un-set private mode')} | |||
|
64 | </span> | |||
|
65 | </td> | |||
62 | <td class="quick_repo_menu"> |
|
66 | <td class="quick_repo_menu"> | |
63 | % if c.rhodecode_user.is_admin: |
|
67 | % if c.rhodecode_user.is_admin: | |
64 | <i class="icon-more"></i> |
|
68 | <i class="icon-more"></i> | |
@@ -83,7 +87,12 b'' | |||||
83 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} |
|
87 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} | |
84 | <span class="user"> |
|
88 | <span class="user"> | |
85 | % if _user.username == h.DEFAULT_USER: |
|
89 | % if _user.username == h.DEFAULT_USER: | |
86 | ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span> |
|
90 | ${h.DEFAULT_USER} | |
|
91 | % if _user.active: | |||
|
92 | <span class="user-perm-help-text"> - ${_('permission for other logged in and anonymous users')}</span> | |||
|
93 | % else: | |||
|
94 | <span class="user-perm-help-text"> - ${_('permission for other logged in users')}</span> | |||
|
95 | % endif | |||
87 | % else: |
|
96 | % else: | |
88 | ${h.link_to_user(_user.username)} |
|
97 | ${h.link_to_user(_user.username)} | |
89 | %if getattr(_user, 'duplicate_perm', None): |
|
98 | %if getattr(_user, 'duplicate_perm', None): | |
@@ -106,7 +115,7 b'' | |||||
106 | ${_('Remove')} |
|
115 | ${_('Remove')} | |
107 | </span> |
|
116 | </span> | |
108 | %elif _user.username == h.DEFAULT_USER: |
|
117 | %elif _user.username == h.DEFAULT_USER: | |
109 |
<span class="tooltip btn btn-link btn-default" onclick=" |
|
118 | <span class="tooltip btn btn-link btn-default" onclick="setPrivateRepo(true); return false" title="${_('Private repositories are only visible to people explicitly added as collaborators. Default permissions wont apply')}"> | |
110 | ${_('set private mode')} |
|
119 | ${_('set private mode')} | |
111 | </span> |
|
120 | </span> | |
112 | %endif |
|
121 | %endif | |
@@ -204,9 +213,10 b'' | |||||
204 | }); |
|
213 | }); | |
205 | quick_repo_menu(); |
|
214 | quick_repo_menu(); | |
206 |
|
215 | |||
207 |
var |
|
216 | var setPrivateRepo = function (private) { | |
208 | var postData = { |
|
217 | var postData = { | |
209 | 'csrf_token': CSRF_TOKEN |
|
218 | 'csrf_token': CSRF_TOKEN, | |
|
219 | 'private': private | |||
210 | }; |
|
220 | }; | |
211 |
|
221 | |||
212 | var success = function(o) { |
|
222 | var success = function(o) { |
@@ -174,7 +174,14 b'' | |||||
174 | ${c.form.render_error(request, c.form['repo_description'])|n} |
|
174 | ${c.form.render_error(request, c.form['repo_description'])|n} | |
175 |
|
175 | |||
176 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> |
|
176 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> | |
177 | <span class="help-block">${_('Plain text format with support of {metatags}. Add a README file for longer descriptions').format(metatags=metatags_url)|n}</span> |
|
177 | <span class="help-block"> | |
|
178 | % if c.visual.stylify_metatags: | |||
|
179 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} | |||
|
180 | % else: | |||
|
181 | ${_('Plain text format.')} | |||
|
182 | % endif | |||
|
183 | ${_('Add a README file for longer descriptions')} | |||
|
184 | </span> | |||
178 | <span id="meta-tags-desc" style="display: none"> |
|
185 | <span id="meta-tags-desc" style="display: none"> | |
179 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
186 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
180 | ${dt.metatags_help()} |
|
187 | ${dt.metatags_help()} |
@@ -1,5 +1,5 b'' | |||||
1 |
|
1 | |||
2 |
<div id="update_notice" style="display: none; margin: |
|
2 | <div id="update_notice" style="display: none; margin: 0px 0px 30px 0px"> | |
3 | <div>${_('Checking for updates...')}</div> |
|
3 | <div>${_('Checking for updates...')}</div> | |
4 | </div> |
|
4 | </div> | |
5 |
|
5 |
@@ -18,7 +18,11 b'' | |||||
18 |
|
18 | |||
19 | <div class="panel panel-default"> |
|
19 | <div class="panel panel-default"> | |
20 | <div class="panel-heading"> |
|
20 | <div class="panel-heading"> | |
21 | <h3 class="panel-title">${_('User Group: %s') % c.user_group.users_group_name}</h3> |
|
21 | <h3 class="panel-title"> | |
|
22 | <i class="icon-user-group" title="${_('User group')}"></i> | |||
|
23 | ${h.link_to_group(c.user_group.users_group_name)} | |||
|
24 | - ${_('Advanced')} | |||
|
25 | </h3> | |||
22 | </div> |
|
26 | </div> | |
23 | <div class="panel-body"> |
|
27 | <div class="panel-body"> | |
24 | ${base.dt_info_panel(elems)} |
|
28 | ${base.dt_info_panel(elems)} |
@@ -2,7 +2,11 b'' | |||||
2 |
|
2 | |||
3 | <div class="panel panel-default"> |
|
3 | <div class="panel panel-default"> | |
4 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
5 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | <i class="icon-user-group" title="${_('User group')}"></i> | |||
|
7 | ${h.link_to_group(c.user_group.users_group_name)} | |||
|
8 | - ${_('Access Permissions')} | |||
|
9 | </h3> | |||
6 | </div> |
|
10 | </div> | |
7 | <div class="panel-body"> |
|
11 | <div class="panel-body"> | |
8 | ${h.secure_form(h.route_path('edit_user_group_perms_update', user_group_id=c.user_group.users_group_id), request=request)} |
|
12 | ${h.secure_form(h.route_path('edit_user_group_perms_update', user_group_id=c.user_group.users_group_id), request=request)} | |
@@ -63,7 +67,12 b'' | |||||
63 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} |
|
67 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} | |
64 | <span class="user"> |
|
68 | <span class="user"> | |
65 | % if _user.username == h.DEFAULT_USER: |
|
69 | % if _user.username == h.DEFAULT_USER: | |
66 | ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span> |
|
70 | ${h.DEFAULT_USER} | |
|
71 | % if _user.active: | |||
|
72 | <span class="user-perm-help-text"> - ${_('permission for other logged in and anonymous users')}</span> | |||
|
73 | % else: | |||
|
74 | <span class="user-perm-help-text"> - ${_('permission for other logged in users')}</span> | |||
|
75 | % endif | |||
67 | % else: |
|
76 | % else: | |
68 | ${h.link_to_user(_user.username)} |
|
77 | ${h.link_to_user(_user.username)} | |
69 | %if getattr(_user, 'duplicate_perm', None): |
|
78 | %if getattr(_user, 'duplicate_perm', None): | |
@@ -106,7 +115,12 b'' | |||||
106 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} |
|
115 | ${base.gravatar(_user.email, 16, user=_user, tooltip=True)} | |
107 | <span class="user"> |
|
116 | <span class="user"> | |
108 | % if _user.username == h.DEFAULT_USER: |
|
117 | % if _user.username == h.DEFAULT_USER: | |
109 | ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span> |
|
118 | ${h.DEFAULT_USER} | |
|
119 | % if _user.active: | |||
|
120 | <span class="user-perm-help-text"> - ${_('permission for other logged in and anonymous users')}</span> | |||
|
121 | % else: | |||
|
122 | <span class="user-perm-help-text"> - ${_('permission for other logged in users')}</span> | |||
|
123 | % endif | |||
110 | % else: |
|
124 | % else: | |
111 | ${h.link_to_user(_user.username)} |
|
125 | ${h.link_to_user(_user.username)} | |
112 | %if getattr(_user, 'duplicate_perm', None): |
|
126 | %if getattr(_user, 'duplicate_perm', None): |
@@ -3,7 +3,11 b'' | |||||
3 |
|
3 | |||
4 | <div class="panel panel-default"> |
|
4 | <div class="panel panel-default"> | |
5 | <div class="panel-heading"> |
|
5 | <div class="panel-heading"> | |
6 | <h3 class="panel-title">${_('User Group: %s') % c.user_group.users_group_name}</h3> |
|
6 | <h3 class="panel-title"> | |
|
7 | <i class="icon-user-group" title="${_('User group')}"></i> | |||
|
8 | ${h.link_to_group(c.user_group.users_group_name)} | |||
|
9 | - ${_('Settings')} | |||
|
10 | </h3> | |||
7 | </div> |
|
11 | </div> | |
8 | <div class="panel-body"> |
|
12 | <div class="panel-body"> | |
9 | ${h.secure_form(h.route_path('user_groups_update', user_group_id=c.user_group.users_group_id), id='edit_user_group', request=request)} |
|
13 | ${h.secure_form(h.route_path('user_groups_update', user_group_id=c.user_group.users_group_id), id='edit_user_group', request=request)} |
@@ -25,7 +25,10 b'' | |||||
25 |
|
25 | |||
26 | <div class="panel panel-default"> |
|
26 | <div class="panel panel-default"> | |
27 | <div class="panel-heading"> |
|
27 | <div class="panel-heading"> | |
28 | <h3 class="panel-title">${_('User: {}').format(c.user.username)}</h3> |
|
28 | <h3 class="panel-title"> | |
|
29 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
30 | - ${_('Access Permissions')} | |||
|
31 | </h3> | |||
29 | </div> |
|
32 | </div> | |
30 | <div class="panel-body"> |
|
33 | <div class="panel-body"> | |
31 | <table class="rctable"> |
|
34 | <table class="rctable"> |
@@ -4,8 +4,10 b'' | |||||
4 |
|
4 | |||
5 | <div class="panel panel-default"> |
|
5 | <div class="panel panel-default"> | |
6 | <div class="panel-heading"> |
|
6 | <div class="panel-heading"> | |
7 |
<h3 class="panel-title"> |
|
7 | <h3 class="panel-title"> | |
8 | ${_ungettext('%s entry', '%s entries', c.audit_logs.item_count) % (c.audit_logs.item_count)} |
|
8 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |
|
9 | - ${_('Audit Logs')} | |||
|
10 | (${_ungettext('%s entry', '%s entries', c.audit_logs.item_count) % (c.audit_logs.item_count)}) | |||
9 | </h3> |
|
11 | </h3> | |
10 | <a href="${h.route_path('edit_user_audit_logs_download', user_id=c.user.user_id)}" class="panel-edit">${_('Download as JSON')}</a> |
|
12 | <a href="${h.route_path('edit_user_audit_logs_download', user_id=c.user.user_id)}" class="panel-edit">${_('Download as JSON')}</a> | |
11 | </div> |
|
13 | </div> |
@@ -1,6 +1,11 b'' | |||||
|
1 | <%namespace name="base" file="/base/base.mako"/> | |||
|
2 | ||||
1 | <div class="panel panel-default"> |
|
3 | <div class="panel panel-default"> | |
2 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
3 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
7 | - ${_('Authentication Tokens')} | |||
|
8 | </h3> | |||
4 | </div> |
|
9 | </div> | |
5 | <div class="panel-body"> |
|
10 | <div class="panel-body"> | |
6 | <div class="apikeys_wrap"> |
|
11 | <div class="apikeys_wrap"> |
@@ -2,7 +2,10 b'' | |||||
2 |
|
2 | |||
3 | <div class="panel panel-default"> |
|
3 | <div class="panel panel-default"> | |
4 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
5 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
7 | - ${_('Caches')} | |||
|
8 | </h3> | |||
6 | </div> |
|
9 | </div> | |
7 | <div class="panel-body"> |
|
10 | <div class="panel-body"> | |
8 | <p> |
|
11 | <p> |
@@ -2,7 +2,10 b'' | |||||
2 |
|
2 | |||
3 | <div class="panel panel-default"> |
|
3 | <div class="panel panel-default"> | |
4 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
5 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
7 | - ${_('Additional Email Addresses')} | |||
|
8 | </h3> | |||
6 | </div> |
|
9 | </div> | |
7 | <div class="panel-body"> |
|
10 | <div class="panel-body"> | |
8 | <div class="emails_wrap"> |
|
11 | <div class="emails_wrap"> |
@@ -1,9 +1,12 b'' | |||||
1 | ## -*- coding: utf-8 -*- |
|
1 | ## -*- coding: utf-8 -*- | |
2 |
|
2 | <%namespace name="base" file="/base/base.mako"/> | ||
3 |
|
3 | |||
4 | <div class="panel panel-default"> |
|
4 | <div class="panel panel-default"> | |
5 | <div class="panel-heading"> |
|
5 | <div class="panel-heading"> | |
6 |
<h3 class="panel-title"> |
|
6 | <h3 class="panel-title"> | |
|
7 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
8 | - ${_('User groups administration')} | |||
|
9 | </h3> | |||
7 | </div> |
|
10 | </div> | |
8 | <div class="panel-body"> |
|
11 | <div class="panel-body"> | |
9 | <div class="fields"> |
|
12 | <div class="fields"> |
@@ -1,6 +1,11 b'' | |||||
|
1 | <%namespace name="base" file="/base/base.mako"/> | |||
|
2 | ||||
1 | <div class="panel panel-default"> |
|
3 | <div class="panel panel-default"> | |
2 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
3 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
7 | - ${_('Custom IP Whitelist')} | |||
|
8 | </h3> | |||
4 | </div> |
|
9 | </div> | |
5 | <div class="panel-body"> |
|
10 | <div class="panel-body"> | |
6 | <div class="ips_wrap"> |
|
11 | <div class="ips_wrap"> |
@@ -2,7 +2,10 b'' | |||||
2 |
|
2 | |||
3 | <div class="panel panel-default user-profile"> |
|
3 | <div class="panel panel-default user-profile"> | |
4 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
5 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
7 | - ${_('User Profile')} | |||
|
8 | </h3> | |||
6 | </div> |
|
9 | </div> | |
7 | <div class="panel-body"> |
|
10 | <div class="panel-body"> | |
8 | <div class="user-profile-content"> |
|
11 | <div class="user-profile-content"> | |
@@ -73,7 +76,13 b'' | |||||
73 | <div class="input textarea editor"> |
|
76 | <div class="input textarea editor"> | |
74 | ${h.textarea('description', rows=10, class_="medium")} |
|
77 | ${h.textarea('description', rows=10, class_="medium")} | |
75 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> |
|
78 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> | |
76 | <span class="help-block">${_('Plain text format with support of {metatags}. Add a README file for longer descriptions').format(metatags=metatags_url)|n}</span> |
|
79 | <span class="help-block"> | |
|
80 | % if c.visual.stylify_metatags: | |||
|
81 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} | |||
|
82 | % else: | |||
|
83 | ${_('Plain text format.')} | |||
|
84 | % endif | |||
|
85 | </span> | |||
77 | <span id="meta-tags-desc" style="display: none"> |
|
86 | <span id="meta-tags-desc" style="display: none"> | |
78 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
87 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
79 | ${dt.metatags_help()} |
|
88 | ${dt.metatags_help()} |
@@ -1,6 +1,11 b'' | |||||
|
1 | <%namespace name="base" file="/base/base.mako"/> | |||
|
2 | ||||
1 | <div class="panel panel-default"> |
|
3 | <div class="panel panel-default"> | |
2 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
3 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
7 | - ${_('SSH Keys')} | |||
|
8 | </h3> | |||
4 | </div> |
|
9 | </div> | |
5 | <div class="panel-body"> |
|
10 | <div class="panel-body"> | |
6 | <div class="sshkeys_wrap"> |
|
11 | <div class="sshkeys_wrap"> |
@@ -1,11 +1,16 b'' | |||||
|
1 | <%namespace name="base" file="/base/base.mako"/> | |||
|
2 | ||||
1 | <div class="panel panel-default"> |
|
3 | <div class="panel panel-default"> | |
2 | <div class="panel-heading"> |
|
4 | <div class="panel-heading"> | |
3 |
<h3 class="panel-title"> |
|
5 | <h3 class="panel-title"> | |
|
6 | ${base.gravatar_with_user(c.user.username, 16, tooltip=False, _class='pull-left')} | |||
|
7 | - ${_('New SSH Key generation')} | |||
|
8 | </h3> | |||
4 | </div> |
|
9 | </div> | |
5 | <div class="panel-body"> |
|
10 | <div class="panel-body"> | |
6 | %if c.ssh_enabled and c.ssh_key_generator_enabled: |
|
11 | %if c.ssh_enabled and c.ssh_key_generator_enabled: | |
7 | <p> |
|
12 | <p> | |
8 | ${_('Below is a 2048 bit generated SSH RSA key.')}<br/> |
|
13 | ${_('Below is a 2048 bit generated SSH RSA key.')}<br/>${_('If you use older systems please try to generate a')} <a href="${h.current_route_path(request, private_format='legacy')}">${_('legacy format')}</a> ssh key.<br/> | |
9 | ${_('If You wish to use it to access RhodeCode via the SSH please save the private key and click `Use this generated key` at the bottom.')} |
|
14 | ${_('If You wish to use it to access RhodeCode via the SSH please save the private key and click `Use this generated key` at the bottom.')} | |
10 | </p> |
|
15 | </p> | |
11 | <h4>${_('Private key')}</h4> |
|
16 | <h4>${_('Private key')}</h4> |
@@ -230,13 +230,13 b'' | |||||
230 | </%def> |
|
230 | </%def> | |
231 |
|
231 | |||
232 |
|
232 | |||
233 | <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False)"> |
|
233 | <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False, _class='rc-user')"> | |
234 | <% |
|
234 | <% | |
235 | email = h.email_or_none(contact) |
|
235 | email = h.email_or_none(contact) | |
236 | rc_user = h.discover_user(contact) |
|
236 | rc_user = h.discover_user(contact) | |
237 | %> |
|
237 | %> | |
238 |
|
238 | |||
239 |
<div class=" |
|
239 | <div class="${_class}"> | |
240 | ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)} |
|
240 | ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)} | |
241 | <span class="${('user user-disabled' if show_disabled else 'user')}"> ${h.link_to_user(rc_user or contact)}</span> |
|
241 | <span class="${('user user-disabled' if show_disabled else 'user')}"> ${h.link_to_user(rc_user or contact)}</span> | |
242 | </div> |
|
242 | </div> | |
@@ -405,10 +405,6 b'' | |||||
405 | %endif |
|
405 | %endif | |
406 | %endif |
|
406 | %endif | |
407 | </ul> |
|
407 | </ul> | |
408 | % else: |
|
|||
409 | <a class="menulink disabled"> |
|
|||
410 | <div class="menulabel">${_('Options')}<div class="show_more"></div></div> |
|
|||
411 | </a> |
|
|||
412 | % endif |
|
408 | % endif | |
413 | </li> |
|
409 | </li> | |
414 |
|
410 |
@@ -59,14 +59,14 b' examples = [' | |||||
59 |
|
59 | |||
60 | ( |
|
60 | ( | |
61 | 'Pivotal Tracker', |
|
61 | 'Pivotal Tracker', | |
62 | '(?:pivot-)(?<project_id>\d+)-(?<story>\d+)', |
|
62 | '(?:pivot-)(?P<project_id>\d+)-(?P<story>\d+)', | |
63 | 'https://www.pivotaltracker.com/s/projects/${project_id}/stories/${story}', |
|
63 | 'https://www.pivotaltracker.com/s/projects/${project_id}/stories/${story}', | |
64 | 'PIV-', |
|
64 | 'PIV-', | |
65 | ), |
|
65 | ), | |
66 |
|
66 | |||
67 | ( |
|
67 | ( | |
68 | 'Trello', |
|
68 | 'Trello', | |
69 | '(?:trello-)(?<card_id>[a-zA-Z0-9]+)', |
|
69 | '(?:trello-)(?P<card_id>[a-zA-Z0-9]+)', | |
70 | 'https://trello.com/example.com/${card_id}', |
|
70 | 'https://trello.com/example.com/${card_id}', | |
71 | 'TRELLO-', |
|
71 | 'TRELLO-', | |
72 | ), |
|
72 | ), |
@@ -5,7 +5,7 b'' | |||||
5 | ## |
|
5 | ## | |
6 | <%namespace name="base" file="/base/base.mako"/> |
|
6 | <%namespace name="base" file="/base/base.mako"/> | |
7 |
|
7 | |||
8 | <%def name="comment_block(comment, inline=False)"> |
|
8 | <%def name="comment_block(comment, inline=False, active_pattern_entries=None)"> | |
9 | <% pr_index_ver = comment.get_index_version(getattr(c, 'versions', [])) %> |
|
9 | <% pr_index_ver = comment.get_index_version(getattr(c, 'versions', [])) %> | |
10 | <% latest_ver = len(getattr(c, 'versions', [])) %> |
|
10 | <% latest_ver = len(getattr(c, 'versions', [])) %> | |
11 | % if inline: |
|
11 | % if inline: | |
@@ -156,7 +156,7 b'' | |||||
156 | </div> |
|
156 | </div> | |
157 | </div> |
|
157 | </div> | |
158 | <div class="text"> |
|
158 | <div class="text"> | |
159 | ${h.render(comment.text, renderer=comment.renderer, mentions=True, repo_name=getattr(c, 'repo_name', None))} |
|
159 | ${h.render(comment.text, renderer=comment.renderer, mentions=True, repo_name=getattr(c, 'repo_name', None), active_pattern_entries=active_pattern_entries)} | |
160 | </div> |
|
160 | </div> | |
161 |
|
161 | |||
162 | </div> |
|
162 | </div> | |
@@ -164,13 +164,17 b'' | |||||
164 |
|
164 | |||
165 | ## generate main comments |
|
165 | ## generate main comments | |
166 | <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)"> |
|
166 | <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)"> | |
|
167 | <% | |||
|
168 | active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None)) | |||
|
169 | %> | |||
|
170 | ||||
167 | <div class="general-comments" id="comments"> |
|
171 | <div class="general-comments" id="comments"> | |
168 | %for comment in comments: |
|
172 | %for comment in comments: | |
169 | <div id="comment-tr-${comment.comment_id}"> |
|
173 | <div id="comment-tr-${comment.comment_id}"> | |
170 | ## only render comments that are not from pull request, or from |
|
174 | ## only render comments that are not from pull request, or from | |
171 | ## pull request and a status change |
|
175 | ## pull request and a status change | |
172 | %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request: |
|
176 | %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request: | |
173 | ${comment_block(comment)} |
|
177 | ${comment_block(comment, active_pattern_entries=active_pattern_entries)} | |
174 | %endif |
|
178 | %endif | |
175 | </div> |
|
179 | </div> | |
176 | %endfor |
|
180 | %endfor |
@@ -60,12 +60,16 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
60 | <% |
|
60 | <% | |
61 | diffset_container_id = h.md5(diffset.target_ref) |
|
61 | diffset_container_id = h.md5(diffset.target_ref) | |
62 | collapse_all = len(diffset.files) > collapse_when_files_over |
|
62 | collapse_all = len(diffset.files) > collapse_when_files_over | |
|
63 | active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None)) | |||
63 | %> |
|
64 | %> | |
64 |
|
65 | |||
65 | %if use_comments: |
|
66 | %if use_comments: | |
|
67 | ||||
|
68 | ## Template for injecting comments | |||
66 | <div id="cb-comments-inline-container-template" class="js-template"> |
|
69 | <div id="cb-comments-inline-container-template" class="js-template"> | |
67 |
${inline_comments_container([] |
|
70 | ${inline_comments_container([])} | |
68 | </div> |
|
71 | </div> | |
|
72 | ||||
69 | <div class="js-template" id="cb-comment-inline-form-template"> |
|
73 | <div class="js-template" id="cb-comment-inline-form-template"> | |
70 | <div class="comment-inline-form ac"> |
|
74 | <div class="comment-inline-form ac"> | |
71 |
|
75 | |||
@@ -259,7 +263,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
259 | ## new/deleted/empty content case |
|
263 | ## new/deleted/empty content case | |
260 | % if not filediff.hunks: |
|
264 | % if not filediff.hunks: | |
261 | ## Comment container, on "fakes" hunk that contains all data to render comments |
|
265 | ## Comment container, on "fakes" hunk that contains all data to render comments | |
262 | ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments)} |
|
266 | ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], filediff.hunk_ops, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} | |
263 | % endif |
|
267 | % endif | |
264 |
|
268 | |||
265 | %if filediff.limited_diff: |
|
269 | %if filediff.limited_diff: | |
@@ -299,7 +303,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
299 | ${hunk.section_header} |
|
303 | ${hunk.section_header} | |
300 | </td> |
|
304 | </td> | |
301 | </tr> |
|
305 | </tr> | |
302 | ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments)} |
|
306 | ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} | |
303 | % endfor |
|
307 | % endfor | |
304 |
|
308 | |||
305 | <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %> |
|
309 | <% unmatched_comments = (inline_comments or {}).get(filediff.patch['filename'], {}) %> | |
@@ -323,7 +327,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
323 | <td class="cb-lineno cb-context"></td> |
|
327 | <td class="cb-lineno cb-context"></td> | |
324 | <td class="cb-lineno cb-context"></td> |
|
328 | <td class="cb-lineno cb-context"></td> | |
325 | <td class="cb-content cb-context"> |
|
329 | <td class="cb-content cb-context"> | |
326 |
${inline_comments_container(comments, |
|
330 | ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)} | |
327 | </td> |
|
331 | </td> | |
328 | </tr> |
|
332 | </tr> | |
329 | %elif c.user_session_attrs["diffmode"] == 'sideside': |
|
333 | %elif c.user_session_attrs["diffmode"] == 'sideside': | |
@@ -348,7 +352,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
348 | <td class="cb-lineno cb-context"></td> |
|
352 | <td class="cb-lineno cb-context"></td> | |
349 | <td class="cb-content cb-context"> |
|
353 | <td class="cb-content cb-context"> | |
350 | % if lineno.startswith('o'): |
|
354 | % if lineno.startswith('o'): | |
351 |
${inline_comments_container(comments, |
|
355 | ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)} | |
352 | % endif |
|
356 | % endif | |
353 | </td> |
|
357 | </td> | |
354 |
|
358 | |||
@@ -356,7 +360,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
356 | <td class="cb-lineno cb-context"></td> |
|
360 | <td class="cb-lineno cb-context"></td> | |
357 | <td class="cb-content cb-context"> |
|
361 | <td class="cb-content cb-context"> | |
358 | % if lineno.startswith('n'): |
|
362 | % if lineno.startswith('n'): | |
359 |
${inline_comments_container(comments, |
|
363 | ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)} | |
360 | % endif |
|
364 | % endif | |
361 | </td> |
|
365 | </td> | |
362 | </tr> |
|
366 | </tr> | |
@@ -415,7 +419,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
415 | <td class="cb-lineno cb-context"></td> |
|
419 | <td class="cb-lineno cb-context"></td> | |
416 | <td class="cb-lineno cb-context"></td> |
|
420 | <td class="cb-lineno cb-context"></td> | |
417 | <td class="cb-content cb-context"> |
|
421 | <td class="cb-content cb-context"> | |
418 |
${inline_comments_container(comments_dict['comments'], |
|
422 | ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)} | |
419 | </td> |
|
423 | </td> | |
420 | </tr> |
|
424 | </tr> | |
421 | %elif c.user_session_attrs["diffmode"] == 'sideside': |
|
425 | %elif c.user_session_attrs["diffmode"] == 'sideside': | |
@@ -427,7 +431,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
427 | <td class="cb-data cb-context"></td> |
|
431 | <td class="cb-data cb-context"></td> | |
428 | <td class="cb-lineno cb-context"></td> |
|
432 | <td class="cb-lineno cb-context"></td> | |
429 | <td class="cb-content cb-context"> |
|
433 | <td class="cb-content cb-context"> | |
430 |
${inline_comments_container(comments_dict['comments'], |
|
434 | ${inline_comments_container(comments_dict['comments'], active_pattern_entries=active_pattern_entries)} | |
431 | </td> |
|
435 | </td> | |
432 | </tr> |
|
436 | </tr> | |
433 | %endif |
|
437 | %endif | |
@@ -584,10 +588,11 b' from rhodecode.lib.diffs import NEW_FILE' | |||||
584 | </%def> |
|
588 | </%def> | |
585 |
|
589 | |||
586 |
|
590 | |||
587 |
<%def name="inline_comments_container(comments, |
|
591 | <%def name="inline_comments_container(comments, active_pattern_entries=None)"> | |
|
592 | ||||
588 | <div class="inline-comments"> |
|
593 | <div class="inline-comments"> | |
589 | %for comment in comments: |
|
594 | %for comment in comments: | |
590 | ${commentblock.comment_block(comment, inline=True)} |
|
595 | ${commentblock.comment_block(comment, inline=True, active_pattern_entries=active_pattern_entries)} | |
591 | %endfor |
|
596 | %endfor | |
592 | % if comments and comments[-1].outdated: |
|
597 | % if comments and comments[-1].outdated: | |
593 | <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}"> |
|
598 | <span class="btn btn-secondary cb-comment-add-button comment-outdated}" style="display: none;}"> | |
@@ -619,7 +624,7 b' def get_comments_for(diff_type, comments' | |||||
619 | return data |
|
624 | return data | |
620 | %> |
|
625 | %> | |
621 |
|
626 | |||
622 | <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None)"> |
|
627 | <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)"> | |
623 | %for i, line in enumerate(hunk.sideside): |
|
628 | %for i, line in enumerate(hunk.sideside): | |
624 | <% |
|
629 | <% | |
625 | old_line_anchor, new_line_anchor = None, None |
|
630 | old_line_anchor, new_line_anchor = None, None | |
@@ -669,7 +674,7 b' def get_comments_for(diff_type, comments' | |||||
669 | <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span> |
|
674 | <span class="cb-code"><span class="cb-action ${action_class(line.original.action)}"></span>${line.original.content or '' | n}</span> | |
670 |
|
675 | |||
671 | %if use_comments and line.original.lineno and line_old_comments: |
|
676 | %if use_comments and line.original.lineno and line_old_comments: | |
672 |
${inline_comments_container(line_old_comments, |
|
677 | ${inline_comments_container(line_old_comments, active_pattern_entries=active_pattern_entries)} | |
673 | %endif |
|
678 | %endif | |
674 |
|
679 | |||
675 | </td> |
|
680 | </td> | |
@@ -711,7 +716,7 b' def get_comments_for(diff_type, comments' | |||||
711 | %endif |
|
716 | %endif | |
712 | <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span> |
|
717 | <span class="cb-code"><span class="cb-action ${action_class(line.modified.action)}"></span>${line.modified.content or '' | n}</span> | |
713 | %if use_comments and line.modified.lineno and line_new_comments: |
|
718 | %if use_comments and line.modified.lineno and line_new_comments: | |
714 |
${inline_comments_container(line_new_comments, |
|
719 | ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)} | |
715 | %endif |
|
720 | %endif | |
716 | </td> |
|
721 | </td> | |
717 | </tr> |
|
722 | </tr> | |
@@ -719,7 +724,7 b' def get_comments_for(diff_type, comments' | |||||
719 | </%def> |
|
724 | </%def> | |
720 |
|
725 | |||
721 |
|
726 | |||
722 | <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None)"> |
|
727 | <%def name="render_hunk_lines_unified(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)"> | |
723 | %for old_line_no, new_line_no, action, content, comments_args in hunk.unified: |
|
728 | %for old_line_no, new_line_no, action, content, comments_args in hunk.unified: | |
724 |
|
729 | |||
725 | <% |
|
730 | <% | |
@@ -777,7 +782,7 b' def get_comments_for(diff_type, comments' | |||||
777 | %endif |
|
782 | %endif | |
778 | <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span> |
|
783 | <span class="cb-code"><span class="cb-action ${action_class(action)}"></span> ${content or '' | n}</span> | |
779 | %if use_comments and comments: |
|
784 | %if use_comments and comments: | |
780 |
${inline_comments_container(comments, |
|
785 | ${inline_comments_container(comments, active_pattern_entries=active_pattern_entries)} | |
781 | %endif |
|
786 | %endif | |
782 | </td> |
|
787 | </td> | |
783 | </tr> |
|
788 | </tr> | |
@@ -785,11 +790,11 b' def get_comments_for(diff_type, comments' | |||||
785 | </%def> |
|
790 | </%def> | |
786 |
|
791 | |||
787 |
|
792 | |||
788 | <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments)"> |
|
793 | <%def name="render_hunk_lines(filediff, diff_mode, hunk, use_comments, inline_comments, active_pattern_entries)"> | |
789 | % if diff_mode == 'unified': |
|
794 | % if diff_mode == 'unified': | |
790 | ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments)} |
|
795 | ${render_hunk_lines_unified(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} | |
791 | % elif diff_mode == 'sideside': |
|
796 | % elif diff_mode == 'sideside': | |
792 | ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments)} |
|
797 | ${render_hunk_lines_sideside(filediff, hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} | |
793 | % else: |
|
798 | % else: | |
794 | <tr class="cb-line"> |
|
799 | <tr class="cb-line"> | |
795 | <td>unknown diff mode</td> |
|
800 | <td>unknown diff mode</td> |
@@ -310,9 +310,9 b'' | |||||
310 |
|
310 | |||
311 | <%def name="gist_access_id(gist_access_id, full_contact)"> |
|
311 | <%def name="gist_access_id(gist_access_id, full_contact)"> | |
312 | <div> |
|
312 | <div> | |
313 |
< |
|
313 | <code> | |
314 |
<a href="${h.route_path('gist_show', gist_id=gist_access_id)}"> |
|
314 | <a href="${h.route_path('gist_show', gist_id=gist_access_id)}">${gist_access_id}</a> | |
315 |
</ |
|
315 | </code> | |
316 | </div> |
|
316 | </div> | |
317 | </%def> |
|
317 | </%def> | |
318 |
|
318 |
@@ -21,7 +21,7 b'' | |||||
21 | <ul> |
|
21 | <ul> | |
22 | % for elem in sorted(c.email_types.keys()): |
|
22 | % for elem in sorted(c.email_types.keys()): | |
23 | <li> |
|
23 | <li> | |
24 | <a href="${request.route_path('debug_style_email', email_id=elem, _query={'user':c.rhodecode_user.username})}">${elem}</a> |
|
24 | <a href="${request.route_path('debug_style_email', email_id=elem, _query={'user':c.rhodecode_user.username, 'email': ''})}">${elem}</a> | |
25 | | |
|
25 | | | |
26 | <a href="${request.route_path('debug_style_email_plain_rendered', email_id=elem, _query={'user':c.rhodecode_user.username})}">plain rendered</a> |
|
26 | <a href="${request.route_path('debug_style_email_plain_rendered', email_id=elem, _query={'user':c.rhodecode_user.username})}">plain rendered</a> | |
27 | </li> |
|
27 | </li> |
@@ -63,8 +63,8 b" css_style = ';'.join([" | |||||
63 |
|
63 | |||
64 | ## Constants |
|
64 | ## Constants | |
65 | <% |
|
65 | <% | |
66 |
text_regular = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif |
|
66 | text_regular = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', Helvetica, sans-serif" | |
67 |
text_monospace = "'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace |
|
67 | text_monospace = "'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace" | |
68 |
|
68 | |||
69 | %> |
|
69 | %> | |
70 |
|
70 | |||
@@ -100,7 +100,7 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
100 | -ms-text-size-adjust: 100%; |
|
100 | -ms-text-size-adjust: 100%; | |
101 | margin: 0; |
|
101 | margin: 0; | |
102 | padding: 0; |
|
102 | padding: 0; | |
103 | font-family: ${text_regular|n} |
|
103 | font-family: ${text_regular|n}; | |
104 | } |
|
104 | } | |
105 |
|
105 | |||
106 | /* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/ |
|
106 | /* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/ | |
@@ -184,6 +184,13 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
184 | mso-table-rspace: 0pt; |
|
184 | mso-table-rspace: 0pt; | |
185 | } |
|
185 | } | |
186 |
|
186 | |||
|
187 | table tr { | |||
|
188 | display: table-row; | |||
|
189 | vertical-align: inherit; | |||
|
190 | border-color: inherit; | |||
|
191 | border-spacing: 0 3px; | |||
|
192 | } | |||
|
193 | ||||
187 | table td { |
|
194 | table td { | |
188 | padding: .65em 1em .65em 0; |
|
195 | padding: .65em 1em .65em 0; | |
189 | border-collapse: collapse; |
|
196 | border-collapse: collapse; | |
@@ -202,6 +209,10 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
202 | outline: 1px solid #979797 |
|
209 | outline: 1px solid #979797 | |
203 | } |
|
210 | } | |
204 |
|
211 | |||
|
212 | code { | |||
|
213 | font-family: ${text_monospace|n}; | |||
|
214 | } | |||
|
215 | ||||
205 | @media only screen and (-webkit-min-device-pixel-ratio: 2) { |
|
216 | @media only screen and (-webkit-min-device-pixel-ratio: 2) { | |
206 | /* Put your iPhone 4g styles in here */ |
|
217 | /* Put your iPhone 4g styles in here */ | |
207 | } |
|
218 | } | |
@@ -283,7 +294,7 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
283 | margin: 3px 0 13px 0 !important; |
|
294 | margin: 3px 0 13px 0 !important; | |
284 | color: #424242 !important; |
|
295 | color: #424242 !important; | |
285 | font-size: 13px !important; |
|
296 | font-size: 13px !important; | |
286 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; |
|
297 | font-family: ${text_regular|n}; | |
287 | font-weight: normal !important; |
|
298 | font-weight: normal !important; | |
288 | overflow: visible !important; |
|
299 | overflow: visible !important; | |
289 | line-height: 140% !important |
|
300 | line-height: 140% !important | |
@@ -361,7 +372,7 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
361 | } |
|
372 | } | |
362 |
|
373 | |||
363 | div.markdown-block code, div.markdown-block pre, div.markdown-block #ws, div.markdown-block #message { |
|
374 | div.markdown-block code, div.markdown-block pre, div.markdown-block #ws, div.markdown-block #message { | |
364 | font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'DejaVu Sans Mono', 'Ubuntu Mono', 'Courier New', 'andale mono', 'lucida console', monospace; |
|
375 | font-family: ${text_monospace|n}; | |
365 | font-size: 11px; |
|
376 | font-size: 11px; | |
366 | -webkit-border-radius: 2px; |
|
377 | -webkit-border-radius: 2px; | |
367 | -moz-border-radius: 2px; |
|
378 | -moz-border-radius: 2px; | |
@@ -490,8 +501,10 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
490 | <![endif]--> |
|
501 | <![endif]--> | |
491 | </head> |
|
502 | </head> | |
492 | <body> |
|
503 | <body> | |
|
504 | ||||
|
505 | <div> | |||
493 | <!-- Wrapper/Container Table: Use a wrapper table to control the width and the background color consistently of your email. Use this approach instead of setting attributes on the body tag. --> |
|
506 | <!-- Wrapper/Container Table: Use a wrapper table to control the width and the background color consistently of your email. Use this approach instead of setting attributes on the body tag. --> | |
494 |
<table cellpadding="0" cellspacing="0" border="0" id="backgroundTable" align="left" style="margin:1%;width:97%;padding:0;font-family: |
|
507 | <table cellpadding="0" cellspacing="0" border="0" id="backgroundTable" align="left" style="margin:1%;width:97%;padding:0;font-family:${text_regular|n};font-weight:100;border:1px solid #dbd9da"> | |
495 | <tr> |
|
508 | <tr> | |
496 | <td valign="top" style="padding:0;"> |
|
509 | <td valign="top" style="padding:0;"> | |
497 | <table cellpadding="0" cellspacing="0" border="0" align="left" width="100%"> |
|
510 | <table cellpadding="0" cellspacing="0" border="0" align="left" width="100%"> | |
@@ -513,11 +526,13 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
513 | </tr> |
|
526 | </tr> | |
514 | </table> |
|
527 | </table> | |
515 | <!-- End of wrapper table --> |
|
528 | <!-- End of wrapper table --> | |
|
529 | </div> | |||
516 |
|
530 | |||
517 | <div style="clear: both"></div> |
|
531 | <div style="width:100%; clear: both; height: 1px"> </div> | |
518 | <div style="margin-left:1%;font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace}"> |
|
532 | ||
|
533 | <div style="margin-left:1%;font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace};"> | |||
519 | ${_('This is a notification from RhodeCode.')} |
|
534 | ${_('This is a notification from RhodeCode.')} | |
520 | <a style="font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace}" href="${instance_url}"> |
|
535 | <a style="font-weight:100;font-size:11px;color:#666666;text-decoration:none;font-family:${text_monospace};" href="${instance_url}"> | |
521 | ${instance_url} |
|
536 | ${instance_url} | |
522 | </a> |
|
537 | </a> | |
523 | </div> |
|
538 | </div> |
@@ -58,7 +58,14 b'' | |||||
58 | <div class="textarea editor"> |
|
58 | <div class="textarea editor"> | |
59 | ${h.textarea('description',cols=23,rows=5,class_="medium")} |
|
59 | ${h.textarea('description',cols=23,rows=5,class_="medium")} | |
60 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> |
|
60 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> | |
61 | <span class="help-block">${_('Plain text format with support of {metatags}. Add a README file for longer descriptions').format(metatags=metatags_url)|n}</span> |
|
61 | <span class="help-block"> | |
|
62 | % if c.visual.stylify_metatags: | |||
|
63 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} | |||
|
64 | % else: | |||
|
65 | ${_('Plain text format.')} | |||
|
66 | % endif | |||
|
67 | ${_('Add a README file for longer descriptions')} | |||
|
68 | </span> | |||
62 | <span id="meta-tags-desc" style="display: none"> |
|
69 | <span id="meta-tags-desc" style="display: none"> | |
63 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
70 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
64 | ${dt.metatags_help()} |
|
71 | ${dt.metatags_help()} |
@@ -14,32 +14,50 b'' | |||||
14 | <div class="title"> |
|
14 | <div class="title"> | |
15 |
|
15 | |||
16 | </div> |
|
16 | </div> | |
|
17 | ||||
17 | <!-- end box / title --> |
|
18 | <!-- end box / title --> | |
18 | <div id="no_grid_data" class="table" style="display: none"> |
|
19 | <div id="no_grid_data" class="table" style="display: none"> | |
19 | <h2 class="no-object-border"> |
|
20 | <h2> | |
20 | ${_('No repositories or repositories groups exists here.')} |
|
21 | ${_('No repositories or repositories groups exists here.')} | |
21 | </h2> |
|
22 | </h2> | |
22 | </div> |
|
23 | </div> | |
23 |
|
24 | |||
|
25 | <div id="grid_data_loading" class="table" style="display: none"> | |||
|
26 | <i class="icon-spin animate-spin"></i> | |||
|
27 | ${_('loading...')} | |||
|
28 | </div> | |||
|
29 | ||||
24 | <div class="table"> |
|
30 | <div class="table"> | |
25 | <div id="groups_list_wrap" style="min-height: 200px;"> |
|
31 | <div id="groups_list_wrap" style="min-height: 200px;display: none"> | |
26 | <table id="group_list_table" class="display" style="width: 100%;"></table> |
|
32 | <table id="group_list_table" class="display" style="width: 100%;"></table> | |
27 | </div> |
|
33 | </div> | |
28 | </div> |
|
34 | </div> | |
29 |
|
35 | |||
30 | <div class="table"> |
|
36 | <div class="table"> | |
31 | <div id="repos_list_wrap" style="min-height: 200px;"> |
|
37 | <div id="repos_list_wrap" style="min-height: 200px;display: none"> | |
32 | <table id="repo_list_table" class="display" style="width: 100%;"></table> |
|
38 | <table id="repo_list_table" class="display" style="width: 100%;"></table> | |
33 | </div> |
|
39 | </div> | |
34 | </div> |
|
40 | </div> | |
35 |
|
41 | |||
36 | </div> |
|
42 | </div> | |
|
43 | ||||
37 | <script> |
|
44 | <script> | |
38 | $(document).ready(function () { |
|
45 | $(document).ready(function () { | |
|
46 | var noRepoData = null; | |||
|
47 | var noGroupData = null; | |||
|
48 | var $gridDataLoading = $('#grid_data_loading'); | |||
39 |
|
49 | |||
40 | // repo group list |
|
50 | // global show loading of hidden grids | |
|
51 | $(document).on('preInit.dt', function (e, settings) { | |||
|
52 | $gridDataLoading.show(); | |||
|
53 | }); | |||
|
54 | ||||
|
55 | ## repo group list | |||
41 | var $groupListTable = $('#group_list_table'); |
|
56 | var $groupListTable = $('#group_list_table'); | |
42 |
|
57 | |||
|
58 | $groupListTable.on('xhr.dt', function (e, settings, json, xhr) { | |||
|
59 | $gridDataLoading.hide(); | |||
|
60 | }); | |||
43 | $groupListTable.DataTable({ |
|
61 | $groupListTable.DataTable({ | |
44 | processing: true, |
|
62 | processing: true, | |
45 | serverSide: true, |
|
63 | serverSide: true, | |
@@ -97,11 +115,12 b'' | |||||
97 | emptyTable: _gettext("No repository groups present.") |
|
115 | emptyTable: _gettext("No repository groups present.") | |
98 | }, |
|
116 | }, | |
99 | "drawCallback": function (settings, json) { |
|
117 | "drawCallback": function (settings, json) { | |
|
118 | ||||
100 | // hide grid if it's empty |
|
119 | // hide grid if it's empty | |
101 | if (settings.fnRecordsDisplay() === 0) { |
|
120 | if (settings.fnRecordsDisplay() === 0) { | |
102 |
|
|
121 | noGroupData = true; | |
103 | // both hidden, show no-data |
|
122 | // both hidden, show no-data | |
104 |
if ( |
|
123 | if (noRepoData === true) { | |
105 | $('#no_grid_data').show(); |
|
124 | $('#no_grid_data').show(); | |
106 | } |
|
125 | } | |
107 | } else { |
|
126 | } else { | |
@@ -119,18 +138,13 b'' | |||||
119 | }, |
|
138 | }, | |
120 | }); |
|
139 | }); | |
121 |
|
140 | |||
122 | $groupListTable.on('xhr.dt', function (e, settings, json, xhr) { |
|
|||
123 | $groupListTable.css('opacity', 1); |
|
|||
124 | }); |
|
|||
125 |
|
141 | |||
126 | $groupListTable.on('preXhr.dt', function (e, settings, data) { |
|
142 | ## repo list | |
127 | $groupListTable.css('opacity', 0.3); |
|
|||
128 | }); |
|
|||
129 |
|
||||
130 |
|
||||
131 | ## // repo list |
|
|||
132 | var $repoListTable = $('#repo_list_table'); |
|
143 | var $repoListTable = $('#repo_list_table'); | |
133 |
|
144 | |||
|
145 | $repoListTable.on('xhr.dt', function (e, settings, json, xhr) { | |||
|
146 | $gridDataLoading.hide(); | |||
|
147 | }); | |||
134 | $repoListTable.DataTable({ |
|
148 | $repoListTable.DataTable({ | |
135 | processing: true, |
|
149 | processing: true, | |
136 | serverSide: true, |
|
150 | serverSide: true, | |
@@ -188,11 +202,13 b'' | |||||
188 | emptyTable: _gettext("No repositories present.") |
|
202 | emptyTable: _gettext("No repositories present.") | |
189 | }, |
|
203 | }, | |
190 | "drawCallback": function (settings, json) { |
|
204 | "drawCallback": function (settings, json) { | |
|
205 | ||||
191 | // hide grid if it's empty |
|
206 | // hide grid if it's empty | |
192 | if (settings.fnRecordsDisplay() == 0) { |
|
207 | if (settings.fnRecordsDisplay() == 0) { | |
193 |
|
|
208 | noRepoData = true; | |
|
209 | ||||
194 | // both hidden, show no-data |
|
210 | // both hidden, show no-data | |
195 |
if ( |
|
211 | if (noGroupData === true) { | |
196 | $('#no_grid_data').show() |
|
212 | $('#no_grid_data').show() | |
197 | } |
|
213 | } | |
198 | } else { |
|
214 | } else { | |
@@ -210,14 +226,6 b'' | |||||
210 | }, |
|
226 | }, | |
211 | }); |
|
227 | }); | |
212 |
|
228 | |||
213 | $repoListTable.on('xhr.dt', function (e, settings, json, xhr) { |
|
|||
214 | $repoListTable.css('opacity', 1); |
|
|||
215 | }); |
|
|||
216 |
|
||||
217 | $repoListTable.on('preXhr.dt', function (e, settings, data) { |
|
|||
218 | $repoListTable.css('opacity', 0.3); |
|
|||
219 | }); |
|
|||
220 |
|
||||
221 | }); |
|
229 | }); | |
222 | </script> |
|
230 | </script> | |
223 | </%def> |
|
231 | </%def> |
@@ -514,6 +514,7 b'' | |||||
514 | // Flush changes into textarea |
|
514 | // Flush changes into textarea | |
515 | codeMirrorInstance.save(); |
|
515 | codeMirrorInstance.save(); | |
516 | prButtonLock(true, null, 'all'); |
|
516 | prButtonLock(true, null, 'all'); | |
|
517 | $pullRequestSubmit.val(_gettext('Please wait creating pull request...')); | |||
517 | }); |
|
518 | }); | |
518 |
|
519 | |||
519 | prButtonLock(true, "${_('Please select source and target')}", 'all'); |
|
520 | prButtonLock(true, "${_('Please select source and target')}", 'all'); |
@@ -438,6 +438,11 b'' | |||||
438 |
|
438 | |||
439 | <h2 style="text-align: center"> |
|
439 | <h2 style="text-align: center"> | |
440 | ${_('Cannot show diff when pull request state is changing. Current progress state')}: <span class="tag tag-merge-state-${c.pull_request.state}">${c.pull_request.state}</span> |
|
440 | ${_('Cannot show diff when pull request state is changing. Current progress state')}: <span class="tag tag-merge-state-${c.pull_request.state}">${c.pull_request.state}</span> | |
|
441 | ||||
|
442 | % if c.is_super_admin: | |||
|
443 | <br/> | |||
|
444 | If you think this is an error try <a href="${h.current_route_path(request, force_state='created')}">forced state reset</a> to <span class="tag tag-merge-state-created">created</span> state. | |||
|
445 | % endif | |||
441 | </h2> |
|
446 | </h2> | |
442 |
|
447 | |||
443 | % else: |
|
448 | % else: |
@@ -29,6 +29,7 b' import shutil' | |||||
29 |
|
29 | |||
30 | import configobj |
|
30 | import configobj | |
31 |
|
31 | |||
|
32 | from rhodecode.model.settings import SettingsModel | |||
32 | from rhodecode.tests import * |
|
33 | from rhodecode.tests import * | |
33 | from rhodecode.model.db import Repository, User, RepoGroup, UserGroup, Gist, UserEmailMap |
|
34 | from rhodecode.model.db import Repository, User, RepoGroup, UserGroup, Gist, UserEmailMap | |
34 | from rhodecode.model.meta import Session |
|
35 | from rhodecode.model.meta import Session | |
@@ -122,7 +123,7 b' class Fixture(object):' | |||||
122 |
|
123 | |||
123 | return context() |
|
124 | return context() | |
124 |
|
125 | |||
125 | def auth_restriction(self, auth_restriction): |
|
126 | def auth_restriction(self, registry, auth_restriction): | |
126 | """ |
|
127 | """ | |
127 | Context process for changing the builtin rhodecode plugin auth restrictions. |
|
128 | Context process for changing the builtin rhodecode plugin auth restrictions. | |
128 | Use like: |
|
129 | Use like: | |
@@ -135,26 +136,26 b' class Fixture(object):' | |||||
135 |
|
136 | |||
136 | class context(object): |
|
137 | class context(object): | |
137 | def _get_pluing(self): |
|
138 | def _get_pluing(self): | |
138 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format( |
|
139 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid) | |
139 | RhodeCodeAuthPlugin.uid) |
|
|||
140 | plugin = RhodeCodeAuthPlugin(plugin_id) |
|
140 | plugin = RhodeCodeAuthPlugin(plugin_id) | |
141 | return plugin |
|
141 | return plugin | |
142 |
|
142 | |||
143 | def __enter__(self): |
|
143 | def __enter__(self): | |
144 | plugin = self._get_pluing() |
|
144 | plugin = self._get_pluing() | |
145 | plugin.create_or_update_setting( |
|
145 | plugin.create_or_update_setting('auth_restriction', auth_restriction) | |
146 | 'auth_restriction', auth_restriction) |
|
|||
147 | Session().commit() |
|
146 | Session().commit() | |
|
147 | SettingsModel().invalidate_settings_cache() | |||
148 |
|
148 | |||
149 | def __exit__(self, exc_type, exc_val, exc_tb): |
|
149 | def __exit__(self, exc_type, exc_val, exc_tb): | |
150 | plugin = self._get_pluing() |
|
150 | plugin = self._get_pluing() | |
151 | plugin.create_or_update_setting( |
|
151 | plugin.create_or_update_setting( | |
152 | 'auth_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE) |
|
152 | 'auth_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE) | |
153 | Session().commit() |
|
153 | Session().commit() | |
|
154 | SettingsModel().invalidate_settings_cache() | |||
154 |
|
155 | |||
155 | return context() |
|
156 | return context() | |
156 |
|
157 | |||
157 | def scope_restriction(self, scope_restriction): |
|
158 | def scope_restriction(self, registry, scope_restriction): | |
158 | """ |
|
159 | """ | |
159 | Context process for changing the builtin rhodecode plugin scope restrictions. |
|
160 | Context process for changing the builtin rhodecode plugin scope restrictions. | |
160 | Use like: |
|
161 | Use like: | |
@@ -167,22 +168,22 b' class Fixture(object):' | |||||
167 |
|
168 | |||
168 | class context(object): |
|
169 | class context(object): | |
169 | def _get_pluing(self): |
|
170 | def _get_pluing(self): | |
170 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format( |
|
171 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid) | |
171 | RhodeCodeAuthPlugin.uid) |
|
|||
172 | plugin = RhodeCodeAuthPlugin(plugin_id) |
|
172 | plugin = RhodeCodeAuthPlugin(plugin_id) | |
173 | return plugin |
|
173 | return plugin | |
174 |
|
174 | |||
175 | def __enter__(self): |
|
175 | def __enter__(self): | |
176 | plugin = self._get_pluing() |
|
176 | plugin = self._get_pluing() | |
177 | plugin.create_or_update_setting( |
|
177 | plugin.create_or_update_setting('scope_restriction', scope_restriction) | |
178 | 'scope_restriction', scope_restriction) |
|
|||
179 | Session().commit() |
|
178 | Session().commit() | |
|
179 | SettingsModel().invalidate_settings_cache() | |||
180 |
|
180 | |||
181 | def __exit__(self, exc_type, exc_val, exc_tb): |
|
181 | def __exit__(self, exc_type, exc_val, exc_tb): | |
182 | plugin = self._get_pluing() |
|
182 | plugin = self._get_pluing() | |
183 | plugin.create_or_update_setting( |
|
183 | plugin.create_or_update_setting( | |
184 | 'scope_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL) |
|
184 | 'scope_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL) | |
185 | Session().commit() |
|
185 | Session().commit() | |
|
186 | SettingsModel().invalidate_settings_cache() | |||
186 |
|
187 | |||
187 | return context() |
|
188 | return context() | |
188 |
|
189 |
@@ -43,6 +43,9 b' class TestIssueTrackerSettingsModel(obje' | |||||
43 | settings_mock.return_value = input_settings |
|
43 | settings_mock.return_value = input_settings | |
44 | result = model.get_global_settings(cache=True) |
|
44 | result = model.get_global_settings(cache=True) | |
45 | get_settings.assert_called_once_with(cache=True) |
|
45 | get_settings.assert_called_once_with(cache=True) | |
|
46 | for k, v in result.items(): | |||
|
47 | v.pop('pat_compiled', None) | |||
|
48 | ||||
46 | assert expected_result == result |
|
49 | assert expected_result == result | |
47 |
|
50 | |||
48 | def test_get_repo_settings_raise_exception_when_repo_is_not_set(self): |
|
51 | def test_get_repo_settings_raise_exception_when_repo_is_not_set(self): | |
@@ -68,6 +71,8 b' class TestIssueTrackerSettingsModel(obje' | |||||
68 | settings_mock.return_value = input_settings |
|
71 | settings_mock.return_value = input_settings | |
69 | result = model.get_repo_settings(cache=True) |
|
72 | result = model.get_repo_settings(cache=True) | |
70 | get_settings.assert_called_once_with(cache=True) |
|
73 | get_settings.assert_called_once_with(cache=True) | |
|
74 | for k, v in result.items(): | |||
|
75 | v.pop('pat_compiled', None) | |||
71 | assert expected_result == result |
|
76 | assert expected_result == result | |
72 |
|
77 | |||
73 | @pytest.mark.parametrize("inherit_settings, method", [ |
|
78 | @pytest.mark.parametrize("inherit_settings, method", [ |
@@ -209,6 +209,8 b' def enable_auth_plugins(request, baseapp' | |||||
209 | Session().add(setting) |
|
209 | Session().add(setting) | |
210 | Session().commit() |
|
210 | Session().commit() | |
211 |
|
211 | |||
|
212 | SettingsModel().invalidate_settings_cache() | |||
|
213 | ||||
212 | def cleanup(): |
|
214 | def cleanup(): | |
213 | _enable_plugins(['egg:rhodecode-enterprise-ce#rhodecode']) |
|
215 | _enable_plugins(['egg:rhodecode-enterprise-ce#rhodecode']) | |
214 |
|
216 |
General Comments 0
You need to be logged in to leave comments.
Login now