##// END OF EJS Templates
release: Merge default into stable for release preparation
marcink -
r3497:d3230053 merge stable
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,42 b''
1 .. _restore-deleted-repositories:
2
3 Restoring Deleted Repositories
4 ==============================
5
6 By default when repository or whole repository group is deleted an archived copy
7 of filesystem repositories are kept. You can see them as special entries in the
8 repository storage such as::
9
10 drwxrwxr-x 3 rcdev rcdev 4096 Dec 4 2017 rm__20171204_105727_400795__ce-import
11 drwxrwxr-x 6 rcdev rcdev 4096 Nov 21 2017 rm__20180221_152430_675047__svn-repo
12 drwxr-xr-x 7 rcdev rcdev 4096 Mar 28 2018 rm__20180328_143124_617576__test-git
13 drwxr-xr-x 7 rcdev rcdev 4096 Mar 28 2018 rm__20180328_144954_317729__test-git-install-hooks
14
15
16 Data from those repositories can be restored by simply removing the
17 `rm_YYYYDDMM_HHMMSS_DDDDDD__` prefix and additionally only in case of Mercurial
18 repositories remove the `.hg` store prefix.::
19
20 rm__.hg => .hg
21
22
23 For Git or SVN repositories this operation is not required.
24
25 After removing the prefix repository can be brought by opening
26 :menuselection:`Admin --> Settings --> Remap and Rescan` and running `Rescan Filesystem`
27
28 This will create a new DB entry restoring the data previously removed.
29 To restore OLD database entries this should be done by restoring from a Database backup.
30
31 RhodeCode also keeps the repository group structure, this is marked by entries that
32 in addition have GROUP in the prefix, eg::
33
34 drwxr-xr-x 2 rcdev rcdev 4096 Jan 18 16:13 rm__20181130_120650_977082_GROUP_Test1
35 drwxr-xr-x 2 rcdev rcdev 4096 Jan 18 16:13 rm__20181130_120659_922952_GROUP_Docs
36
37
38
39 .. note::
40
41 RhodeCode Tools have a special cleanup tool for the archived repositories. Please
42 see :ref:`clean-up-cmds`
@@ -0,0 +1,37 b''
1 .. _store-methods-ref:
2
3 store methods
4 =============
5
6 file_store_add (EE only)
7 ------------------------
8
9 .. py:function:: file_store_add(apiuser, filename, content)
10
11 Upload API for the file_store
12
13 Example usage from CLI::
14 rhodecode-api --instance-name=enterprise-1 upload_file "{"content": "$(cat image.jpg | base64)", "filename":"image.jpg"}"
15
16 This command takes the following options:
17
18 :param apiuser: This is filled automatically from the |authtoken|.
19 :type apiuser: AuthUser
20 :param filename: name of the file uploaded
21 :type filename: str
22 :param content: base64 encoded content of the uploaded file
23 :type content: str
24
25 Example output:
26
27 .. code-block:: bash
28
29 id : <id_given_in_input>
30 result: {
31 "access_path": "/_file_store/download/84d156f7-8323-4ad3-9fce-4a8e88e1deaf-0.jpg",
32 "access_path_fqn": "http://server.domain.com/_file_store/download/84d156f7-8323-4ad3-9fce-4a8e88e1deaf-0.jpg",
33 "store_fid": "84d156f7-8323-4ad3-9fce-4a8e88e1deaf-0.jpg"
34 }
35 error : null
36
37
@@ -0,0 +1,88 b''
1 .. _auth-saml-bulk-enroll-users-ref:
2
3
4 Bulk enroll multiple existing users
5 -----------------------------------
6
7
8 RhodeCode Supports standard SAML 2.0 SSO for the web-application part.
9 Below is an example how to enroll list of all or some users to use SAML authentication.
10 This method simply enables SAML authentication for many users at once.
11
12
13 From the server RhodeCode Enterprise is running run ishell on the instance which we
14 want to apply the SAML migration::
15
16 rccontrol ishell enterprise-1
17
18 Follow these steps to enable SAML authentication for multiple users.
19
20
21 1) Create a user_id => attribute mapping
22
23
24 `saml2user` is a mapping of external ID from SAML provider such as OneLogin, DuoSecurity, Google.
25 This mapping consists of local rhodecode user_id mapped to set of required attributes needed to bind SAML
26 account to internal rhodecode user.
27 For example, 123 is local rhodecode user_id, and '48253211' is OneLogin ID.
28 For other providers you'd have to figure out what would be the user-id, sometimes it's the email, i.e for Google
29 The most important this id needs to be unique for each user.
30
31 .. code-block:: python
32
33 In [1]: saml2user = {
34 ...: # OneLogin, uses externalID available to read from in the UI
35 ...: 123: {'id: '48253211'},
36 ...: # for Google/DuoSecurity email is also an option for unique ID
37 ...: 124: {'id: 'email@domain.com'},
38 ...: }
39
40
41 2) Import the plugin you want to run migration for.
42
43 From available options pick only one and run the `import` statement
44
45 .. code-block:: python
46
47 # for Duo Security
48 In [2]: from rc_auth_plugins.auth_duo_security import RhodeCodeAuthPlugin
49 # for OneLogin
50 In [2]: from rc_auth_plugins.auth_onelogin import RhodeCodeAuthPlugin
51 # generic SAML plugin
52 In [2]: from rc_auth_plugins.auth_saml import RhodeCodeAuthPlugin
53
54 3) Run the migration based on saml2user mapping.
55
56 Enter in the ishell prompt
57
58 .. code-block:: python
59
60 In [3]: for user in User.get_all():
61 ...: existing_identity = ExternalIdentity().query().filter(ExternalIdentity.local_user_id == user.user_id).scalar()
62 ...: attrs = saml2user.get(user.user_id)
63 ...: provider = RhodeCodeAuthPlugin.uid
64 ...: if existing_identity:
65 ...: print('Identity for user `{}` already exists, skipping'.format(user.username))
66 ...: continue
67 ...: if attrs:
68 ...: external_id = attrs['id']
69 ...: new_external_identity = ExternalIdentity()
70 ...: new_external_identity.external_id = external_id
71 ...: new_external_identity.external_username = '{}-saml-{}'.format(user.username, user.user_id)
72 ...: new_external_identity.provider_name = provider
73 ...: new_external_identity.local_user_id = user_id
74 ...: new_external_identity.access_token = ''
75 ...: new_external_identity.token_secret = ''
76 ...: new_external_identity.alt_token = ''
77 ...: Session().add(ex_identity)
78 ...: Session().commit()
79 ...: print('Set user `{}` external identity bound to ExternalID:{}'.format(user.username, external_id))
80
81 .. note::
82
83 saml2user can be really big and hard to maintain in ishell. It's also possible
84 to load it as a JSON file prepared before and stored on disk. To do so run::
85
86 import json
87 saml2user = json.loads(open('/path/to/saml2user.json','rb').read())
88
@@ -0,0 +1,148 b''
1 |RCE| 4.16.0 |RNS|
2 ------------------
3
4 Release Date
5 ^^^^^^^^^^^^
6
7 - 2019-02-15
8
9
10 New Features
11 ^^^^^^^^^^^^
12
13
14 - Full-text search: added support for ElasticSearch 6.X (ES6)
15 - Full-text search: Expose a quick way to search within repository groups using ES6.
16 - Full-text search: Add quick links to broaden/narrow search scope to repositories or
17 repository groups from global search.
18 - Full-text search: ES6 backend adds new highlighter, and search markers for better UX when searching.
19 - Full-text search: ES6 backend has enabled advanced `query string syntax`
20 adding more search and filtering capabilities.
21 - Full-text search: ES6 engine will now show added information where available such as line numbers file size.
22 - Files: added option to use highlight marker to show keywords inside file source. This
23 is used now for ES6 backend extended highlighting capabilities
24 - Artifacts (beta): EE edition exposes new feature called storage_api this allows storing
25 binary files outside of Version Control System, but in the scope of a repository or group.
26 This will soon become an Artifacts functionality available in EE edition.
27 - Authentication: introduced `User restriction` and `Scope restriction` for RhodeCode authentication plugins.
28 Admins can limit usage of RhodeCode plugins to super-admins user types, and usage in Web, or VCS protocol only.
29 This is mostly to help to migrate users to SAML, keeping the super-admins to manage instances via local-logins,
30 and secondly to force usage of AuthenticationTokens instead of re-using same credentials for
31 WEB and VCS authentication.
32 - API: added basic upload API for the storage_api. It's possible to store files using internal
33 API. This is a start for attachments upload in RhodeCode.
34 - API: added store_exception_api for remote exception storage. This is used by a new
35 indexer that will report any problems back into the RhodeCode instance in case of indexing problems.
36 - API: added function to fetch comments for a repository.
37 - Quick search: improve the styling of search input and results.
38 - Pull requests: allowed to select all forks and parent forks of target repository in creation UI.
39 This is a common workflow supported by GitHub etc.
40
41
42 General
43 ^^^^^^^
44
45 - Users/Repositories/Repository groups: expose IDs of those objects in advanced views.
46 Useful for API calls or usage in ishell.
47 - UI: moved repo group select next to the name as it's very relevant to each other.
48 - Pull requests: increase the stability of concurrent pull requests created.
49 - Pull requests: introduced operation state for pull requests to prevent from
50 locks during merge/update operations in concurrent busy environments.
51 - Pull requests: ensure that merge response provide more details about failed operations.
52 - UI / Files: expose downloads options onto files view similar as in summary page.
53 - Repositories: show hooks version and update link in the advanced section of repository page.
54 - Events: trigger 'review_status_change' in all cases when reviewers are changed
55 influencing review status.
56 - Files: display submodules in a sorted way, equal to how Directories are sorted.
57 - API: fetching all pull-requests now sorts the results and exposed a flag to show/hide
58 the merge result state for faster result fetching.
59 - API: merge_pull_request expose detailed merge message in the merge operation
60 next to numeric merge response code.
61 - API: added possibility to specify owner to create_pull_request API.
62 - SSH: Added ability to disable server-side SSH key generation to enforce users
63 generated SSH keys only outside of the server.
64 - Integrations: allow PUT method for WebHook integration.
65 - Dependencies: bumped git to 2.19.2 release.
66 - Dependencies: dropped pygments-markdown-lexer as it's natively supported by pygments now.
67 - Dependencies: bumped pyramid to 1.10.1
68 - Dependencies: bumped pastedeploy to 2.0.1
69 - Dependencies: bumped pastescript to 3.0.0
70 - Dependencies: bumped pathlib2 to 2.3.3
71 - Dependencies: bumped webob to 1.8.4
72 - Dependencies: bumped iso8601 to 0.1.12
73 - Dependencies: bumped more-itertools to 5.0.0
74 - Dependencies: bumped psutil to 5.4.8
75 - Dependencies: bumped pyasn1 to 0.4.5
76 - Dependencies: bumped pygments to 2.3.1
77 - Dependencies: bumped pyramid-debugtoolbar to 4.5.0
78 - Dependencies: bumped subprocess32 to 3.5.3
79 - Dependencies: bumped supervisor to 3.3.5
80 - Dependencies: bumped dogpile.cache to 0.7.1
81 - Dependencies: bumped simplejson to 3.16.0
82 - Dependencies: bumped gevent to 1.4.0
83 - Dependencies: bumped configparser to 3.5.1
84
85
86 Security
87 ^^^^^^^^
88
89 - Fork page: don't expose fork origin link if we don't have permission to access this repository.
90 Additionally don't pre-select such repository in pull request ref selector.
91 - Security: fix possible XSS in the issue tracker URL.
92 - Security: sanitize plaintext renderer with bleach, preventing XSS in rendered html.
93 - Audit logs: added audit logs for API permission calls.
94
95
96 Performance
97 ^^^^^^^^^^^
98
99 - Summary page: don't load repo size when showing expanded information about repository.
100 Size calculation needs to be triggered manually.
101 - Git: use rev-list for fetching last commit data in case of single commit history.
102 In some cases, it is much faster than previously used git log command.
103
104
105 Fixes
106 ^^^^^
107
108 - Installer: fixed 32bit package builds broken in previous releases.
109 - Git: use iterative fetch to prevent errors about too many arguments on
110 synchronizing very large repositories.
111 - Git: pass in the SSL dir that is exposed from wire for remote GIT commands.
112 - LDAP+Groups: improve logging, and fix the case when extracting group name from LDAP
113 returned nothing. We should warn about that, but not FAIL on login.
114 - Default reviewers: fixed submodule support in picking reviewers from annotation for files.
115 - Hooks: handle non-ascii characters in hooks new pull-requests open template.
116 - Diffs: fixed missing limited diff container display on over-size limit diffs.
117 - Diffs: fixed 500 error in case of some very uncommon diffs containing only Unicode characters.
118 - Repositories: handle VCS backend unavailable correctly in advanced settings for the repository.
119 - Remap & rescan: prevent empty/damaged repositories to break the remap operation.
120 - Visual: fixed show revision/commit length settings.
121 - Mercurial submodules: only show submodule in the path that it belongs too.
122 Before even submodules from root node were shown in subdirectories.
123 - UI/Files: fixed icons in file tree search.
124 - WebHook integration: quote URL variables to prevent URL errors with special chars
125 like # in the title.
126 - API: pull-requests, fixed invocation of merge as another user.
127 - VCS: limit fd leaks on subprocessio calls.
128 - VCS: expose SSL certificate path over the wire to the vcsserver, this solves some
129 remote SSL import problems reported.
130
131
132 Upgrade notes
133 ^^^^^^^^^^^^^
134
135 This release brings the new Full-text search capabilities using ElasticSearch 6.
136 If you use Elastic Search backend a backward compatibility mode is enabled and
137 ElasticSearch backend defaults to previously used ElasticSearch 2.
138
139 To use new features a full index rebuild is required, in addition ```--es-version=6``` flag
140 needs to be used with indexer and ```search.es_version = 6``` should be set in rhodecode.ini
141
142 Additionally new mapping format is available for the indexer that has additional capabilities
143 for include/exclude rules. Old format should work as well, but we encourage to
144 generate a new mapping.ini file using rhodecode-index command, and migrate your repositories
145 to the new format.
146
147 Please refer to the :ref:`indexing-ref` documentation for more details.
148
@@ -0,0 +1,107 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import pytest
23
24 from rhodecode.model.db import User, ChangesetComment
25 from rhodecode.model.meta import Session
26 from rhodecode.model.comment import CommentsModel
27 from rhodecode.api.tests.utils import (
28 build_data, api_call, assert_error, assert_call_ok)
29
30
31 @pytest.fixture()
32 def make_repo_comments_factory(request):
33
34 def maker(repo):
35 user = User.get_first_super_admin()
36 commit = repo.scm_instance()[0]
37
38 commit_id = commit.raw_id
39 file_0 = commit.affected_files[0]
40 comments = []
41
42 # general
43 CommentsModel().create(
44 text='General Comment', repo=repo, user=user, commit_id=commit_id,
45 comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False)
46
47 # inline
48 CommentsModel().create(
49 text='Inline Comment', repo=repo, user=user, commit_id=commit_id,
50 f_path=file_0, line_no='n1',
51 comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False)
52
53 # todo
54 CommentsModel().create(
55 text='INLINE TODO Comment', repo=repo, user=user, commit_id=commit_id,
56 f_path=file_0, line_no='n1',
57 comment_type=ChangesetComment.COMMENT_TYPE_TODO, send_email=False)
58
59 @request.addfinalizer
60 def cleanup():
61 for comment in comments:
62 Session().delete(comment)
63 return maker
64
65
66 @pytest.mark.usefixtures("testuser_api", "app")
67 class TestGetRepo(object):
68
69 @pytest.mark.parametrize('filters, expected_count', [
70 ({}, 3),
71 ({'comment_type': ChangesetComment.COMMENT_TYPE_NOTE}, 2),
72 ({'comment_type': ChangesetComment.COMMENT_TYPE_TODO}, 1),
73 ({'commit_id': 'FILLED DYNAMIC'}, 3),
74 ])
75 def test_api_get_repo_comments(self, backend, user_util,
76 make_repo_comments_factory, filters, expected_count):
77 commits = [{'message': 'A'}, {'message': 'B'}]
78 repo = backend.create_repo(commits=commits)
79 make_repo_comments_factory(repo)
80
81 api_call_params = {'repoid': repo.repo_name,}
82 api_call_params.update(filters)
83
84 if 'commit_id' in api_call_params:
85 commit = repo.scm_instance()[0]
86 commit_id = commit.raw_id
87 api_call_params['commit_id'] = commit_id
88
89 id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params)
90 response = api_call(self.app, params)
91 result = assert_call_ok(id_, given=response.body)
92
93 assert len(result) == expected_count
94
95 def test_api_get_repo_comments_wrong_comment_typ(self, backend_hg):
96
97 repo = backend_hg.create_repo()
98 make_repo_comments_factory(repo)
99
100 api_call_params = {'repoid': repo.repo_name,}
101 api_call_params.update({'comment_type': 'bogus'})
102
103 expected = 'comment_type must be one of `{}` got {}'.format(
104 ChangesetComment.COMMENT_TYPES, 'bogus')
105 id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params)
106 response = api_call(self.app, params)
107 assert_error(id_, expected, given=response.body)
@@ -0,0 +1,59 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import pytest
23
24 from rhodecode.api.tests.utils import build_data, api_call, assert_ok, assert_error
25
26
27 @pytest.mark.usefixtures("testuser_api", "app")
28 class TestStoreException(object):
29
30 def test_store_exception_invalid_json(self):
31 id_, params = build_data(self.apikey, 'store_exception',
32 exc_data_json='XXX,{')
33 response = api_call(self.app, params)
34
35 expected = 'Failed to parse JSON data from exc_data_json field. ' \
36 'Please make sure it contains a valid JSON.'
37 assert_error(id_, expected, given=response.body)
38
39 def test_store_exception_missing_json_params_json(self):
40 id_, params = build_data(self.apikey, 'store_exception',
41 exc_data_json='{"foo":"bar"}')
42 response = api_call(self.app, params)
43
44 expected = "Missing exc_traceback, or exc_type_name in " \
45 "exc_data_json field. Missing: 'exc_traceback'"
46 assert_error(id_, expected, given=response.body)
47
48 def test_store_exception(self):
49 id_, params = build_data(
50 self.apikey, 'store_exception',
51 exc_data_json='{"exc_traceback": "invalid", "exc_type_name":"ValueError"}')
52 response = api_call(self.app, params)
53 exc_id = response.json['result']['exc_id']
54
55 expected = {
56 'exc_id': exc_id,
57 'exc_url': 'http://example.com/_admin/settings/exceptions/{}'.format(exc_id)
58 }
59 assert_ok(id_, expected, given=response.body)
@@ -0,0 +1,49 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import os
21 from rhodecode.apps.file_store import config_keys
22 from rhodecode.config.middleware import _bool_setting, _string_setting
23
24
25 def _sanitize_settings_and_apply_defaults(settings):
26 """
27 Set defaults, convert to python types and validate settings.
28 """
29 _bool_setting(settings, config_keys.enabled, 'true')
30
31 _string_setting(settings, config_keys.backend, 'local')
32
33 default_store = os.path.join(os.path.dirname(settings['__file__']), 'upload_store')
34 _string_setting(settings, config_keys.store_path, default_store)
35
36
37 def includeme(config):
38 settings = config.registry.settings
39 _sanitize_settings_and_apply_defaults(settings)
40
41 config.add_route(
42 name='upload_file',
43 pattern='/_file_store/upload')
44 config.add_route(
45 name='download_file',
46 pattern='/_file_store/download/{fid}')
47
48 # Scan module for configuration decorators.
49 config.scan('.views', ignore='.tests')
@@ -0,0 +1,27 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 # Definition of setting keys used to configure this module. Defined here to
23 # avoid repetition of keys throughout the module.
24
25 enabled = 'file_store.enabled'
26 backend = 'file_store.backend'
27 store_path = 'file_store.storage_path'
@@ -0,0 +1,31 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 class FileNotAllowedException(Exception):
23 """
24 Thrown if file does not have an allowed extension.
25 """
26
27
28 class FileOverSizeException(Exception):
29 """
30 Thrown if file is over the set limit.
31 """
@@ -0,0 +1,66 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 ANY = []
23 TEXT_EXT = ['txt', 'md', 'rst', 'log']
24 DOCUMENTS_EXT = ['pdf', 'rtf', 'odf', 'ods', 'gnumeric', 'abw', 'doc', 'docx', 'xls', 'xlsx']
25 IMAGES_EXT = ['jpg', 'jpe', 'jpeg', 'png', 'gif', 'svg', 'bmp', 'tiff']
26 AUDIO_EXT = ['wav', 'mp3', 'aac', 'ogg', 'oga', 'flac']
27 VIDEO_EXT = ['mpeg', '3gp', 'avi', 'divx', 'dvr', 'flv', 'mp4', 'wmv']
28 DATA_EXT = ['csv', 'ini', 'json', 'plist', 'xml', 'yaml', 'yml']
29 SCRIPTS_EXT = ['js', 'php', 'pl', 'py', 'rb', 'sh', 'go', 'c', 'h']
30 ARCHIVES_EXT = ['gz', 'bz2', 'zip', 'tar', 'tgz', 'txz', '7z']
31 EXECUTABLES_EXT = ['so', 'exe', 'dll']
32
33
34 DEFAULT = DOCUMENTS_EXT + TEXT_EXT + IMAGES_EXT + DATA_EXT
35
36 GROUPS = dict((
37 ('any', ANY),
38 ('text', TEXT_EXT),
39 ('documents', DOCUMENTS_EXT),
40 ('images', IMAGES_EXT),
41 ('audio', AUDIO_EXT),
42 ('video', VIDEO_EXT),
43 ('data', DATA_EXT),
44 ('scripts', SCRIPTS_EXT),
45 ('archives', ARCHIVES_EXT),
46 ('executables', EXECUTABLES_EXT),
47 ('default', DEFAULT),
48 ))
49
50
51 def resolve_extensions(extensions, groups=None):
52 """
53 Calculate allowed extensions based on a list of extensions provided, and optional
54 groups of extensions from the available lists.
55
56 :param extensions: a list of extensions e.g ['py', 'txt']
57 :param groups: additionally groups to extend the extensions.
58 """
59 groups = groups or []
60 valid_exts = set([x.lower() for x in extensions])
61
62 for group in groups:
63 if group in GROUPS:
64 valid_exts.update(GROUPS[group])
65
66 return valid_exts
@@ -0,0 +1,211 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import os
22 import time
23 import shutil
24 import hashlib
25
26 from rhodecode.lib.ext_json import json
27 from rhodecode.apps.file_store import utils
28 from rhodecode.apps.file_store.extensions import resolve_extensions
29 from rhodecode.apps.file_store.exceptions import FileNotAllowedException
30
31 METADATA_VER = 'v1'
32
33
34 class LocalFileStorage(object):
35
36 @classmethod
37 def resolve_name(cls, name, directory):
38 """
39 Resolves a unique name and the correct path. If a filename
40 for that path already exists then a numeric prefix with values > 0 will be
41 added, for example test.jpg -> test-1.jpg etc. initially file would have 0 prefix.
42
43 :param name: base name of file
44 :param directory: absolute directory path
45 """
46
47 basename, ext = os.path.splitext(name)
48 counter = 0
49 while True:
50 name = '%s-%d%s' % (basename, counter, ext)
51
52 # sub_store prefix to optimize disk usage, e.g some_path/ab/final_file
53 sub_store = cls._sub_store_from_filename(basename)
54 sub_store_path = os.path.join(directory, sub_store)
55 if not os.path.exists(sub_store_path):
56 os.makedirs(sub_store_path)
57
58 path = os.path.join(sub_store_path, name)
59 if not os.path.exists(path):
60 return name, path
61 counter += 1
62
63 @classmethod
64 def _sub_store_from_filename(cls, filename):
65 return filename[:2]
66
67 @classmethod
68 def calculate_path_hash(cls, file_path):
69 """
70 Efficient calculation of file_path sha256 sum
71
72 :param file_path:
73 :return: sha256sum
74 """
75 digest = hashlib.sha256()
76 with open(file_path, 'rb') as f:
77 for chunk in iter(lambda: f.read(1024 * 100), b""):
78 digest.update(chunk)
79
80 return digest.hexdigest()
81
82 def __init__(self, base_path, extension_groups=None):
83
84 """
85 Local file storage
86
87 :param base_path: the absolute base path where uploads are stored
88 :param extension_groups: extensions string
89 """
90
91 extension_groups = extension_groups or ['any']
92 self.base_path = base_path
93 self.extensions = resolve_extensions([], groups=extension_groups)
94
95 def store_path(self, filename):
96 """
97 Returns absolute file path of the filename, joined to the
98 base_path.
99
100 :param filename: base name of file
101 """
102 sub_store = self._sub_store_from_filename(filename)
103 return os.path.join(self.base_path, sub_store, filename)
104
105 def delete(self, filename):
106 """
107 Deletes the filename. Filename is resolved with the
108 absolute path based on base_path. If file does not exist,
109 returns **False**, otherwise **True**
110
111 :param filename: base name of file
112 """
113 if self.exists(filename):
114 os.remove(self.store_path(filename))
115 return True
116 return False
117
118 def exists(self, filename):
119 """
120 Checks if file exists. Resolves filename's absolute
121 path based on base_path.
122
123 :param filename: base name of file
124 """
125 return os.path.exists(self.store_path(filename))
126
127 def filename_allowed(self, filename, extensions=None):
128 """Checks if a filename has an allowed extension
129
130 :param filename: base name of file
131 :param extensions: iterable of extensions (or self.extensions)
132 """
133 _, ext = os.path.splitext(filename)
134 return self.extension_allowed(ext, extensions)
135
136 def extension_allowed(self, ext, extensions=None):
137 """
138 Checks if an extension is permitted. Both e.g. ".jpg" and
139 "jpg" can be passed in. Extension lookup is case-insensitive.
140
141 :param ext: extension to check
142 :param extensions: iterable of extensions to validate against (or self.extensions)
143 """
144
145 extensions = extensions or self.extensions
146 if not extensions:
147 return True
148 if ext.startswith('.'):
149 ext = ext[1:]
150 return ext.lower() in extensions
151
152 def save_file(self, file_obj, filename, directory=None, extensions=None,
153 extra_metadata=None, **kwargs):
154 """
155 Saves a file object to the uploads location.
156 Returns the resolved filename, i.e. the directory +
157 the (randomized/incremented) base name.
158
159 :param file_obj: **cgi.FieldStorage** object (or similar)
160 :param filename: original filename
161 :param directory: relative path of sub-directory
162 :param extensions: iterable of allowed extensions, if not default
163 :param extra_metadata: extra JSON metadata to store next to the file with .meta suffix
164 """
165
166 extensions = extensions or self.extensions
167
168 if not self.filename_allowed(filename, extensions):
169 raise FileNotAllowedException()
170
171 if directory:
172 dest_directory = os.path.join(self.base_path, directory)
173 else:
174 dest_directory = self.base_path
175
176 if not os.path.exists(dest_directory):
177 os.makedirs(dest_directory)
178
179 filename = utils.uid_filename(filename)
180
181 # resolve also produces special sub-dir for file optimized store
182 filename, path = self.resolve_name(filename, dest_directory)
183 stored_file_dir = os.path.dirname(path)
184
185 file_obj.seek(0)
186
187 with open(path, "wb") as dest:
188 shutil.copyfileobj(file_obj, dest)
189
190 metadata = {}
191 if extra_metadata:
192 metadata = extra_metadata
193
194 size = os.stat(path).st_size
195 file_hash = self.calculate_path_hash(path)
196
197 metadata.update(
198 {"filename": filename,
199 "size": size,
200 "time": time.time(),
201 "sha256": file_hash,
202 "meta_ver": METADATA_VER})
203
204 filename_meta = filename + '.meta'
205 with open(os.path.join(stored_file_dir, filename_meta), "wb") as dest_meta:
206 dest_meta.write(json.dumps(metadata))
207
208 if directory:
209 filename = os.path.join(directory, filename)
210
211 return filename, metadata
@@ -0,0 +1,20 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
@@ -0,0 +1,111 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import os
21 import pytest
22
23 from rhodecode.lib.ext_json import json
24 from rhodecode.tests import TestController
25 from rhodecode.apps.file_store import utils, config_keys
26
27
28 def route_path(name, params=None, **kwargs):
29 import urllib
30
31 base_url = {
32 'upload_file': '/_file_store/upload',
33 'download_file': '/_file_store/download/{fid}',
34
35 }[name].format(**kwargs)
36
37 if params:
38 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
39 return base_url
40
41
42 class TestFileStoreViews(TestController):
43
44 @pytest.mark.parametrize("fid, content, exists", [
45 ('abcde-0.jpg', "xxxxx", True),
46 ('abcde-0.exe', "1234567", True),
47 ('abcde-0.jpg', "xxxxx", False),
48 ])
49 def test_get_files_from_store(self, fid, content, exists, tmpdir):
50 self.log_user()
51 store_path = self.app._pyramid_settings[config_keys.store_path]
52
53 if exists:
54 status = 200
55 store = utils.get_file_storage({config_keys.store_path: store_path})
56 filesystem_file = os.path.join(str(tmpdir), fid)
57 with open(filesystem_file, 'wb') as f:
58 f.write(content)
59
60 with open(filesystem_file, 'rb') as f:
61 fid, metadata = store.save_file(f, fid, extra_metadata={'filename': fid})
62
63 else:
64 status = 404
65
66 response = self.app.get(route_path('download_file', fid=fid), status=status)
67
68 if exists:
69 assert response.text == content
70 file_store_path = os.path.dirname(store.resolve_name(fid, store_path)[1])
71 metadata_file = os.path.join(file_store_path, fid + '.meta')
72 assert os.path.exists(metadata_file)
73 with open(metadata_file, 'rb') as f:
74 json_data = json.loads(f.read())
75
76 assert json_data
77 assert 'size' in json_data
78
79 def test_upload_files_without_content_to_store(self):
80 self.log_user()
81 response = self.app.post(
82 route_path('upload_file'),
83 params={'csrf_token': self.csrf_token},
84 status=200)
85
86 assert response.json == {
87 u'error': u'store_file data field is missing',
88 u'access_path': None,
89 u'store_fid': None}
90
91 def test_upload_files_bogus_content_to_store(self):
92 self.log_user()
93 response = self.app.post(
94 route_path('upload_file'),
95 params={'csrf_token': self.csrf_token, 'store_file': 'bogus'},
96 status=200)
97
98 assert response.json == {
99 u'error': u'filename cannot be read from the data field',
100 u'access_path': None,
101 u'store_fid': None}
102
103 def test_upload_content_to_store(self):
104 self.log_user()
105 response = self.app.post(
106 route_path('upload_file'),
107 upload_files=[('store_file', 'myfile.txt', 'SOME CONTENT')],
108 params={'csrf_token': self.csrf_token},
109 status=200)
110
111 assert response.json['store_fid']
@@ -0,0 +1,47 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import os
23 import uuid
24
25
26 def get_file_storage(settings):
27 from rhodecode.apps.file_store.local_store import LocalFileStorage
28 from rhodecode.apps.file_store import config_keys
29 store_path = settings.get(config_keys.store_path)
30 return LocalFileStorage(base_path=store_path)
31
32
33 def uid_filename(filename, randomized=True):
34 """
35 Generates a randomized or stable (uuid) filename,
36 preserving the original extension.
37
38 :param filename: the original filename
39 :param randomized: define if filename should be stable (sha1 based) or randomized
40 """
41 _, ext = os.path.splitext(filename)
42 if randomized:
43 uid = uuid.uuid4()
44 else:
45 hash_key = '{}.{}'.format(filename, 'store')
46 uid = uuid.uuid5(uuid.NAMESPACE_URL, hash_key)
47 return str(uid) + ext.lower()
@@ -0,0 +1,115 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import logging
21
22 from pyramid.view import view_config
23 from pyramid.response import FileResponse
24 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
25
26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps.file_store import utils
28 from rhodecode.apps.file_store.exceptions import (
29 FileNotAllowedException, FileOverSizeException)
30
31 from rhodecode.lib import helpers as h
32 from rhodecode.lib import audit_logger
33 from rhodecode.lib.auth import (CSRFRequired, NotAnonymous)
34 from rhodecode.model.db import Session, FileStore
35
36 log = logging.getLogger(__name__)
37
38
39 class FileStoreView(BaseAppView):
40 upload_key = 'store_file'
41
42 def load_default_context(self):
43 c = self._get_local_tmpl_context()
44 self.storage = utils.get_file_storage(self.request.registry.settings)
45 return c
46
47 @NotAnonymous()
48 @CSRFRequired()
49 @view_config(route_name='upload_file', request_method='POST', renderer='json_ext')
50 def upload_file(self):
51 self.load_default_context()
52 file_obj = self.request.POST.get(self.upload_key)
53
54 if file_obj is None:
55 return {'store_fid': None,
56 'access_path': None,
57 'error': '{} data field is missing'.format(self.upload_key)}
58
59 if not hasattr(file_obj, 'filename'):
60 return {'store_fid': None,
61 'access_path': None,
62 'error': 'filename cannot be read from the data field'}
63
64 filename = file_obj.filename
65
66 metadata = {
67 'user_uploaded': {'username': self._rhodecode_user.username,
68 'user_id': self._rhodecode_user.user_id,
69 'ip': self._rhodecode_user.ip_addr}}
70 try:
71 store_fid, metadata = self.storage.save_file(
72 file_obj.file, filename, extra_metadata=metadata)
73 except FileNotAllowedException:
74 return {'store_fid': None,
75 'access_path': None,
76 'error': 'File {} is not allowed.'.format(filename)}
77
78 except FileOverSizeException:
79 return {'store_fid': None,
80 'access_path': None,
81 'error': 'File {} is exceeding allowed limit.'.format(filename)}
82
83 try:
84 entry = FileStore.create(
85 file_uid=store_fid, filename=metadata["filename"],
86 file_hash=metadata["sha256"], file_size=metadata["size"],
87 file_description='upload attachment',
88 check_acl=False, user_id=self._rhodecode_user.user_id
89 )
90 Session().add(entry)
91 Session().commit()
92 log.debug('Stored upload in DB as %s', entry)
93 except Exception:
94 log.exception('Failed to store file %s', filename)
95 return {'store_fid': None,
96 'access_path': None,
97 'error': 'File {} failed to store in DB.'.format(filename)}
98
99 return {'store_fid': store_fid,
100 'access_path': h.route_path('download_file', fid=store_fid)}
101
102 @view_config(route_name='download_file')
103 def download_file(self):
104 self.load_default_context()
105 file_uid = self.request.matchdict['fid']
106 log.debug('Requesting FID:%s from store %s', file_uid, self.storage)
107
108 if not self.storage.exists(file_uid):
109 log.debug('File with FID:%s not found in the store', file_uid)
110 raise HTTPNotFound()
111
112 FileStore.bump_access_counter(file_uid)
113
114 file_path = self.storage.store_path(file_uid)
115 return FileResponse(file_path)
@@ -0,0 +1,110 b''
1 # Example to validate pushed files names and size using some sort of rules
2
3
4
5 @has_kwargs({
6 'server_url': 'url of instance that triggered this hook',
7 'config': 'path to .ini config used',
8 'scm': 'type of version control "git", "hg", "svn"',
9 'username': 'username of actor who triggered this event',
10 'ip': 'ip address of actor who triggered this hook',
11 'action': '',
12 'repository': 'repository name',
13 'repo_store_path': 'full path to where repositories are stored',
14 'commit_ids': 'pre transaction metadata for commit ids',
15 'hook_type': '',
16 'user_agent': 'Client user agent, e.g git or mercurial CLI version',
17 })
18 def _pre_push_hook(*args, **kwargs):
19 """
20 Post push hook
21 To stop version control from storing the transaction and send a message to user
22 use non-zero HookResponse with a message, e.g return HookResponse(1, 'Not allowed')
23
24 This message will be shown back to client during PUSH operation
25
26 Commit ids might look like that::
27
28 [{u'hg_env|git_env': ...,
29 u'multiple_heads': [],
30 u'name': u'default',
31 u'new_rev': u'd0befe0692e722e01d5677f27a104631cf798b69',
32 u'old_rev': u'd0befe0692e722e01d5677f27a104631cf798b69',
33 u'ref': u'',
34 u'total_commits': 2,
35 u'type': u'branch'}]
36 """
37 import fnmatch
38 from .helpers import extra_fields, extract_pre_files
39 from .utils import str2bool, aslist
40 from rhodecode.lib.helpers import format_byte_size_binary
41
42 # returns list of dicts with key-val fetched from extra fields
43 repo_extra_fields = extra_fields.run(**kwargs)
44
45 # optionally use 'extra fields' to control the logic per repo
46 # e.g store a list of patterns to be forbidden e.g `*.exe, *.dump`
47 forbid_files = repo_extra_fields.get('forbid_files_glob', {}).get('field_value')
48 forbid_files = aslist(forbid_files)
49
50 # optionally get bytes limit for a single file, e.g 1024 for 1KB
51 forbid_size_over = repo_extra_fields.get('forbid_size_over', {}).get('field_value')
52 forbid_size_over = int(forbid_size_over or 0)
53
54 def validate_file_name_and_size(file_data, forbidden_files=None, size_limit=None):
55 """
56 This function validates commited files against some sort of rules.
57 It should return a valid boolean, and a reason for failure
58
59 file_data =[
60 'raw_diff', 'old_revision', 'stats', 'original_filename', 'is_limited_diff',
61 'chunks', 'new_revision', 'operation', 'exceeds_limit', 'filename'
62 ]
63 file_data['ops'] = {
64 # is file binary
65 'binary': False,
66
67 # lines
68 'added': 32,
69 'deleted': 0
70
71 'ops': {3: 'modified file'},
72 'new_mode': '100644',
73 'old_mode': None
74 }
75 """
76 file_name = file_data['filename']
77 operation = file_data['operation'] # can be A(dded), M(odified), D(eleted)
78
79 # check files names
80 if forbidden_files:
81 reason = 'File {} is forbidden to be pushed'.format(file_name)
82 for forbidden_pattern in forbid_files:
83 # here we can also filter for operation, e.g if check for only ADDED files
84 # if operation == 'A':
85 if fnmatch.fnmatch(file_name, forbidden_pattern):
86 return False, reason
87
88 # validate A(dded) files and size
89 if size_limit and operation == 'A':
90 size = len(file_data['raw_diff'])
91
92 reason = 'File {} size of {} bytes exceeds limit {}'.format(
93 file_name, format_byte_size_binary(size),
94 format_byte_size_binary(size_limit))
95 if size > size_limit:
96 return False, reason
97
98 return True, ''
99
100 if forbid_files or forbid_size_over:
101 # returns list of dicts with key-val fetched from extra fields
102 file_list = extract_pre_files.run(**kwargs)
103
104 for file_data in file_list:
105 file_valid, reason = validate_file_name_and_size(
106 file_data, forbid_files, forbid_size_over)
107 if not file_valid:
108 return HookResponse(1, reason)
109
110 return HookResponse(0, '')
@@ -0,0 +1,96 b''
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
20 """
21 us in hooks::
22
23 from .helpers import extract_pre_files
24 # returns list of dicts with key-val fetched from extra fields
25 file_list = extract_pre_files.run(**kwargs)
26
27 """
28 import re
29 import collections
30 import json
31
32 from rhodecode.lib import diffs
33 from rhodecode.lib.vcs.backends.hg.diff import MercurialDiff
34 from rhodecode.lib.vcs.backends.git.diff import GitDiff
35
36
37 def get_hg_files(repo, refs):
38 files = []
39 return files
40
41
42 def get_git_files(repo, refs):
43 files = []
44
45 for data in refs:
46 # we should now extract commit data
47 old_rev = data['old_rev']
48 new_rev = data['new_rev']
49
50 if '00000000' in old_rev:
51 # new branch, we don't need to extract nothing
52 return files
53
54 git_env = dict(data['git_env'])
55
56 cmd = [
57 'diff', old_rev, new_rev
58 ]
59
60 stdout, stderr = repo.run_git_command(cmd, extra_env=git_env)
61 vcs_diff = GitDiff(stdout)
62
63 diff_processor = diffs.DiffProcessor(vcs_diff, format='newdiff')
64 # this is list of dicts with diff information
65 # _parsed[0].keys()
66 # ['raw_diff', 'old_revision', 'stats', 'original_filename',
67 # 'is_limited_diff', 'chunks', 'new_revision', 'operation',
68 # 'exceeds_limit', 'filename']
69 files = _parsed = diff_processor.prepare()
70
71 return files
72
73
74 def run(*args, **kwargs):
75 from rhodecode.model.db import Repository
76
77 vcs_type = kwargs['scm']
78 # use temp name then the main one propagated
79 repo_name = kwargs.pop('REPOSITORY', None) or kwargs['repository']
80
81 repo = Repository.get_by_repo_name(repo_name)
82 vcs_repo = repo.scm_instance(cache=False)
83
84 files = []
85
86 if vcs_type == 'git':
87 for rev_data in kwargs['commit_ids']:
88 new_environ = dict((k, v) for k, v in rev_data['git_env'])
89 files = get_git_files(vcs_repo, kwargs['commit_ids'])
90
91 if vcs_type == 'hg':
92 for rev_data in kwargs['commit_ids']:
93 new_environ = dict((k, v) for k, v in rev_data['hg_env'])
94 files = get_hg_files(vcs_repo, kwargs['commit_ids'])
95
96 return files
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,5 +1,5 b''
1 [bumpversion]
1 [bumpversion]
2 current_version = 4.15.2
2 current_version = 4.16.0
3 message = release: Bump version {current_version} to {new_version}
3 message = release: Bump version {current_version} to {new_version}
4
4
5 [bumpversion:file:rhodecode/VERSION]
5 [bumpversion:file:rhodecode/VERSION]
@@ -5,25 +5,20 b' done = false'
5 done = true
5 done = true
6
6
7 [task:rc_tools_pinned]
7 [task:rc_tools_pinned]
8 done = true
9
8
10 [task:fixes_on_stable]
9 [task:fixes_on_stable]
11 done = true
12
10
13 [task:pip2nix_generated]
11 [task:pip2nix_generated]
14 done = true
15
12
16 [task:changelog_updated]
13 [task:changelog_updated]
17 done = true
18
14
19 [task:generate_api_docs]
15 [task:generate_api_docs]
20 done = true
16
17 [task:updated_translation]
21
18
22 [release]
19 [release]
23 state = prepared
20 state = in_progress
24 version = 4.15.2
21 version = 4.16.0
25
26 [task:updated_translation]
27
22
28 [task:generate_js_routes]
23 [task:generate_js_routes]
29
24
@@ -12,8 +12,6 b' permission notice:'
12 file:licenses/msgpack_license.txt
12 file:licenses/msgpack_license.txt
13 Copyright (c) 2009 - tornado
13 Copyright (c) 2009 - tornado
14 file:licenses/tornado_license.txt
14 file:licenses/tornado_license.txt
15 Copyright (c) 2015 - pygments-markdown-lexer
16 file:licenses/pygments_markdown_lexer_license.txt
17 Copyright 2006 - diff_match_patch
15 Copyright 2006 - diff_match_patch
18 file:licenses/diff_match_patch_license.txt
16 file:licenses/diff_match_patch_license.txt
19
17
@@ -1,5 +1,5 b''
1
1
2 .PHONY: clean docs docs-clean docs-cleanup test test-clean test-only test-only-postgres test-only-mysql web-build
2 .PHONY: clean docs docs-clean docs-cleanup test test-clean test-only test-only-postgres test-only-mysql web-build generate-pkgs
3
3
4 NODE_PATH=./node_modules
4 NODE_PATH=./node_modules
5 WEBPACK=./node_binaries/webpack
5 WEBPACK=./node_binaries/webpack
@@ -8,7 +8,7 b' GRUNT=./node_binaries/grunt'
8
8
9 clean:
9 clean:
10 make test-clean
10 make test-clean
11 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';'
11 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' -o -iname '*.orig' \) -exec rm '{}' ';'
12
12
13 test:
13 test:
14 make test-clean
14 make test-clean
@@ -51,3 +51,5 b' docs-cleanup:'
51 web-build:
51 web-build:
52 NODE_PATH=$(NODE_PATH) $(GRUNT)
52 NODE_PATH=$(NODE_PATH) $(GRUNT)
53
53
54 generate-pkgs:
55 nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses"
@@ -53,7 +53,7 b' asyncore_use_poll = true'
53 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
53 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
54
54
55 #use = egg:gunicorn#main
55 #use = egg:gunicorn#main
56 ## Sets the number of process workers. More workers means more concurent connections
56 ## Sets the number of process workers. More workers means more concurrent connections
57 ## RhodeCode can handle at the same time. Each additional worker also it increases
57 ## RhodeCode can handle at the same time. Each additional worker also it increases
58 ## memory usage as each has it's own set of caches.
58 ## memory usage as each has it's own set of caches.
59 ## Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
59 ## Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
@@ -133,10 +133,10 b' rhodecode.api.url = /_admin/api'
133 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
133 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
134 #rhodecode.encrypted_values.strict = false
134 #rhodecode.encrypted_values.strict = false
135
135
136 ## return gzipped responses from Rhodecode (static files/application)
136 ## return gzipped responses from RhodeCode (static files/application)
137 gzip_responses = false
137 gzip_responses = false
138
138
139 ## autogenerate javascript routes file on startup
139 ## auto-generate javascript routes file on startup
140 generate_js_files = false
140 generate_js_files = false
141
141
142 ## System global default language.
142 ## System global default language.
@@ -153,7 +153,7 b' startup.import_repos = false'
153 ## the repository.
153 ## the repository.
154 #archive_cache_dir = /tmp/tarballcache
154 #archive_cache_dir = /tmp/tarballcache
155
155
156 ## URL at which the application is running. This is used for bootstraping
156 ## URL at which the application is running. This is used for Bootstrapping
157 ## requests in context when no web request is available. Used in ishell, or
157 ## requests in context when no web request is available. Used in ishell, or
158 ## SSH calls. Set this for events to receive proper url for SSH calls.
158 ## SSH calls. Set this for events to receive proper url for SSH calls.
159 app.base_url = http://rhodecode.local
159 app.base_url = http://rhodecode.local
@@ -203,7 +203,7 b' gist_alias_url ='
203 ## used for access.
203 ## used for access.
204 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
204 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
205 ## came from the the logged in user who own this authentication token.
205 ## came from the the logged in user who own this authentication token.
206 ## Additionally @TOKEN syntaxt can be used to bound the view to specific
206 ## Additionally @TOKEN syntax can be used to bound the view to specific
207 ## authentication token. Such view would be only accessible when used together
207 ## authentication token. Such view would be only accessible when used together
208 ## with this authentication token
208 ## with this authentication token
209 ##
209 ##
@@ -227,14 +227,14 b' default_encoding = UTF-8'
227
227
228 ## instance-id prefix
228 ## instance-id prefix
229 ## a prefix key for this instance used for cache invalidation when running
229 ## a prefix key for this instance used for cache invalidation when running
230 ## multiple instances of rhodecode, make sure it's globally unique for
230 ## multiple instances of RhodeCode, make sure it's globally unique for
231 ## all running rhodecode instances. Leave empty if you don't use it
231 ## all running RhodeCode instances. Leave empty if you don't use it
232 instance_id =
232 instance_id =
233
233
234 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
234 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
235 ## of an authentication plugin also if it is disabled by it's settings.
235 ## of an authentication plugin also if it is disabled by it's settings.
236 ## This could be useful if you are unable to log in to the system due to broken
236 ## This could be useful if you are unable to log in to the system due to broken
237 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
237 ## authentication settings. Then you can enable e.g. the internal RhodeCode auth
238 ## module to log in again and fix the settings.
238 ## module to log in again and fix the settings.
239 ##
239 ##
240 ## Available builtin plugin IDs (hash is part of the ID):
240 ## Available builtin plugin IDs (hash is part of the ID):
@@ -250,7 +250,7 b' instance_id ='
250 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
250 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
251 ## handling that causing a series of failed authentication calls.
251 ## handling that causing a series of failed authentication calls.
252 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
252 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
253 ## This will be served instead of default 401 on bad authnetication
253 ## This will be served instead of default 401 on bad authentication
254 auth_ret_code =
254 auth_ret_code =
255
255
256 ## use special detection method when serving auth_ret_code, instead of serving
256 ## use special detection method when serving auth_ret_code, instead of serving
@@ -284,6 +284,13 b' labs_settings_active = true'
284 ## This is used to store exception from RhodeCode in shared directory
284 ## This is used to store exception from RhodeCode in shared directory
285 #exception_tracker.store_path =
285 #exception_tracker.store_path =
286
286
287 ## File store configuration. This is used to store and serve uploaded files
288 file_store.enabled = true
289 ## Storage backend, available options are: local
290 file_store.backend = local
291 ## path to store the uploaded binaries
292 file_store.storage_path = %(here)s/data/file_store
293
287
294
288 ####################################
295 ####################################
289 ### CELERY CONFIG ####
296 ### CELERY CONFIG ####
@@ -325,6 +332,7 b' rc_cache.cache_perms.expiration_time = 3'
325 #rc_cache.cache_perms.arguments.host = localhost
332 #rc_cache.cache_perms.arguments.host = localhost
326 #rc_cache.cache_perms.arguments.port = 6379
333 #rc_cache.cache_perms.arguments.port = 6379
327 #rc_cache.cache_perms.arguments.db = 0
334 #rc_cache.cache_perms.arguments.db = 0
335 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
328 #rc_cache.cache_perms.arguments.distributed_lock = true
336 #rc_cache.cache_perms.arguments.distributed_lock = true
329
337
330 ## `cache_repo` cache settings for FileTree, Readme, RSS FEEDS
338 ## `cache_repo` cache settings for FileTree, Readme, RSS FEEDS
@@ -340,6 +348,7 b' rc_cache.cache_repo.expiration_time = 25'
340 #rc_cache.cache_repo.arguments.host = localhost
348 #rc_cache.cache_repo.arguments.host = localhost
341 #rc_cache.cache_repo.arguments.port = 6379
349 #rc_cache.cache_repo.arguments.port = 6379
342 #rc_cache.cache_repo.arguments.db = 1
350 #rc_cache.cache_repo.arguments.db = 1
351 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
343 #rc_cache.cache_repo.arguments.distributed_lock = true
352 #rc_cache.cache_repo.arguments.distributed_lock = true
344
353
345 ## cache settings for SQL queries, this needs to use memory type backend
354 ## cache settings for SQL queries, this needs to use memory type backend
@@ -424,7 +433,7 b' channelstream.server = 127.0.0.1:9800'
424 ## location of the channelstream server from outside world
433 ## location of the channelstream server from outside world
425 ## use ws:// for http or wss:// for https. This address needs to be handled
434 ## use ws:// for http or wss:// for https. This address needs to be handled
426 ## by external HTTP server such as Nginx or Apache
435 ## by external HTTP server such as Nginx or Apache
427 ## see nginx/apache configuration examples in our docs
436 ## see Nginx/Apache configuration examples in our docs
428 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
437 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
429 channelstream.secret = secret
438 channelstream.secret = secret
430 channelstream.history.location = %(here)s/channelstream_history
439 channelstream.history.location = %(here)s/channelstream_history
@@ -441,14 +450,14 b' channelstream.proxy_path = /_channelstre'
441 ## Appenlight is tailored to work with RhodeCode, see
450 ## Appenlight is tailored to work with RhodeCode, see
442 ## http://appenlight.com for details how to obtain an account
451 ## http://appenlight.com for details how to obtain an account
443
452
444 ## appenlight integration enabled
453 ## Appenlight integration enabled
445 appenlight = false
454 appenlight = false
446
455
447 appenlight.server_url = https://api.appenlight.com
456 appenlight.server_url = https://api.appenlight.com
448 appenlight.api_key = YOUR_API_KEY
457 appenlight.api_key = YOUR_API_KEY
449 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
458 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
450
459
451 # used for JS client
460 ## used for JS client
452 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
461 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
453
462
454 ## TWEAK AMOUNT OF INFO SENT HERE
463 ## TWEAK AMOUNT OF INFO SENT HERE
@@ -473,7 +482,7 b' appenlight.logging.level = WARNING'
473 ## (saves API quota for intensive logging)
482 ## (saves API quota for intensive logging)
474 appenlight.logging_on_error = false
483 appenlight.logging_on_error = false
475
484
476 ## list of additonal keywords that should be grabbed from environ object
485 ## list of additional keywords that should be grabbed from environ object
477 ## can be string with comma separated list of words in lowercase
486 ## can be string with comma separated list of words in lowercase
478 ## (by default client will always send following info:
487 ## (by default client will always send following info:
479 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
488 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
@@ -533,7 +542,7 b' sqlalchemy.db1.convert_unicode = true'
533 vcs.server.enable = true
542 vcs.server.enable = true
534 vcs.server = localhost:9900
543 vcs.server = localhost:9900
535
544
536 ## Web server connectivity protocol, responsible for web based VCS operatations
545 ## Web server connectivity protocol, responsible for web based VCS operations
537 ## Available protocols are:
546 ## Available protocols are:
538 ## `http` - use http-rpc backend (default)
547 ## `http` - use http-rpc backend (default)
539 vcs.server.protocol = http
548 vcs.server.protocol = http
@@ -582,7 +591,8 b' svn.proxy.config_file_path = %(here)s/mo'
582 ## In most cases it should be set to `/`.
591 ## In most cases it should be set to `/`.
583 svn.proxy.location_root = /
592 svn.proxy.location_root = /
584 ## Command to reload the mod dav svn configuration on change.
593 ## Command to reload the mod dav svn configuration on change.
585 ## Example: `/etc/init.d/apache2 reload`
594 ## Example: `/etc/init.d/apache2 reload` or /home/USER/apache_reload.sh
595 ## Make sure user who runs RhodeCode process is allowed to reload Apache
586 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
596 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
587 ## If the timeout expires before the reload command finishes, the command will
597 ## If the timeout expires before the reload command finishes, the command will
588 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
598 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
@@ -593,7 +603,7 b' svn.proxy.location_root = /'
593 ############################################################
603 ############################################################
594
604
595 ## Defines if a custom authorized_keys file should be created and written on
605 ## Defines if a custom authorized_keys file should be created and written on
596 ## any change user ssh keys. Setting this to false also disables posibility
606 ## any change user ssh keys. Setting this to false also disables possibility
597 ## of adding SSH keys by users from web interface. Super admins can still
607 ## of adding SSH keys by users from web interface. Super admins can still
598 ## manage SSH Keys.
608 ## manage SSH Keys.
599 ssh.generate_authorized_keyfile = false
609 ssh.generate_authorized_keyfile = false
@@ -601,13 +611,13 b' ssh.generate_authorized_keyfile = false'
601 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
611 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
602 # ssh.authorized_keys_ssh_opts =
612 # ssh.authorized_keys_ssh_opts =
603
613
604 ## Path to the authrozied_keys file where the generate entries are placed.
614 ## Path to the authorized_keys file where the generate entries are placed.
605 ## It is possible to have multiple key files specified in `sshd_config` e.g.
615 ## It is possible to have multiple key files specified in `sshd_config` e.g.
606 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
616 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
607 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
617 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
608
618
609 ## Command to execute the SSH wrapper. The binary is available in the
619 ## Command to execute the SSH wrapper. The binary is available in the
610 ## rhodecode installation directory.
620 ## RhodeCode installation directory.
611 ## e.g ~/.rccontrol/community-1/profile/bin/rc-ssh-wrapper
621 ## e.g ~/.rccontrol/community-1/profile/bin/rc-ssh-wrapper
612 ssh.wrapper_cmd = ~/.rccontrol/community-1/rc-ssh-wrapper
622 ssh.wrapper_cmd = ~/.rccontrol/community-1/rc-ssh-wrapper
613
623
@@ -615,7 +625,7 b' ssh.wrapper_cmd = ~/.rccontrol/community'
615 ssh.wrapper_cmd_allow_shell = false
625 ssh.wrapper_cmd_allow_shell = false
616
626
617 ## Enables logging, and detailed output send back to the client during SSH
627 ## Enables logging, and detailed output send back to the client during SSH
618 ## operations. Usefull for debugging, shouldn't be used in production.
628 ## operations. Useful for debugging, shouldn't be used in production.
619 ssh.enable_debug_logging = true
629 ssh.enable_debug_logging = true
620
630
621 ## Paths to binary executable, by default they are the names, but we can
631 ## Paths to binary executable, by default they are the names, but we can
@@ -624,6 +634,10 b' ssh.executable.hg = ~/.rccontrol/vcsserv'
624 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
634 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
625 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
635 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
626
636
637 ## Enables SSH key generator web interface. Disabling this still allows users
638 ## to add their own keys.
639 ssh.enable_ui_key_generator = true
640
627
641
628 ## Dummy marker to add new entries after.
642 ## Dummy marker to add new entries after.
629 ## Add any custom entries below. Please don't remove.
643 ## Add any custom entries below. Please don't remove.
@@ -53,7 +53,7 b' port = 5000'
53 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
53 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
54
54
55 use = egg:gunicorn#main
55 use = egg:gunicorn#main
56 ## Sets the number of process workers. More workers means more concurent connections
56 ## Sets the number of process workers. More workers means more concurrent connections
57 ## RhodeCode can handle at the same time. Each additional worker also it increases
57 ## RhodeCode can handle at the same time. Each additional worker also it increases
58 ## memory usage as each has it's own set of caches.
58 ## memory usage as each has it's own set of caches.
59 ## Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
59 ## Recommended value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers, but no more
@@ -108,10 +108,10 b' use = egg:rhodecode-enterprise-ce'
108 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
108 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
109 #rhodecode.encrypted_values.strict = false
109 #rhodecode.encrypted_values.strict = false
110
110
111 ## return gzipped responses from Rhodecode (static files/application)
111 ## return gzipped responses from RhodeCode (static files/application)
112 gzip_responses = false
112 gzip_responses = false
113
113
114 ## autogenerate javascript routes file on startup
114 ## auto-generate javascript routes file on startup
115 generate_js_files = false
115 generate_js_files = false
116
116
117 ## System global default language.
117 ## System global default language.
@@ -128,7 +128,7 b' startup.import_repos = false'
128 ## the repository.
128 ## the repository.
129 #archive_cache_dir = /tmp/tarballcache
129 #archive_cache_dir = /tmp/tarballcache
130
130
131 ## URL at which the application is running. This is used for bootstraping
131 ## URL at which the application is running. This is used for Bootstrapping
132 ## requests in context when no web request is available. Used in ishell, or
132 ## requests in context when no web request is available. Used in ishell, or
133 ## SSH calls. Set this for events to receive proper url for SSH calls.
133 ## SSH calls. Set this for events to receive proper url for SSH calls.
134 app.base_url = http://rhodecode.local
134 app.base_url = http://rhodecode.local
@@ -178,7 +178,7 b' gist_alias_url ='
178 ## used for access.
178 ## used for access.
179 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
179 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
180 ## came from the the logged in user who own this authentication token.
180 ## came from the the logged in user who own this authentication token.
181 ## Additionally @TOKEN syntaxt can be used to bound the view to specific
181 ## Additionally @TOKEN syntax can be used to bound the view to specific
182 ## authentication token. Such view would be only accessible when used together
182 ## authentication token. Such view would be only accessible when used together
183 ## with this authentication token
183 ## with this authentication token
184 ##
184 ##
@@ -202,14 +202,14 b' default_encoding = UTF-8'
202
202
203 ## instance-id prefix
203 ## instance-id prefix
204 ## a prefix key for this instance used for cache invalidation when running
204 ## a prefix key for this instance used for cache invalidation when running
205 ## multiple instances of rhodecode, make sure it's globally unique for
205 ## multiple instances of RhodeCode, make sure it's globally unique for
206 ## all running rhodecode instances. Leave empty if you don't use it
206 ## all running RhodeCode instances. Leave empty if you don't use it
207 instance_id =
207 instance_id =
208
208
209 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
209 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
210 ## of an authentication plugin also if it is disabled by it's settings.
210 ## of an authentication plugin also if it is disabled by it's settings.
211 ## This could be useful if you are unable to log in to the system due to broken
211 ## This could be useful if you are unable to log in to the system due to broken
212 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
212 ## authentication settings. Then you can enable e.g. the internal RhodeCode auth
213 ## module to log in again and fix the settings.
213 ## module to log in again and fix the settings.
214 ##
214 ##
215 ## Available builtin plugin IDs (hash is part of the ID):
215 ## Available builtin plugin IDs (hash is part of the ID):
@@ -225,7 +225,7 b' instance_id ='
225 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
225 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
226 ## handling that causing a series of failed authentication calls.
226 ## handling that causing a series of failed authentication calls.
227 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
227 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
228 ## This will be served instead of default 401 on bad authnetication
228 ## This will be served instead of default 401 on bad authentication
229 auth_ret_code =
229 auth_ret_code =
230
230
231 ## use special detection method when serving auth_ret_code, instead of serving
231 ## use special detection method when serving auth_ret_code, instead of serving
@@ -259,6 +259,13 b' labs_settings_active = true'
259 ## This is used to store exception from RhodeCode in shared directory
259 ## This is used to store exception from RhodeCode in shared directory
260 #exception_tracker.store_path =
260 #exception_tracker.store_path =
261
261
262 ## File store configuration. This is used to store and serve uploaded files
263 file_store.enabled = true
264 ## Storage backend, available options are: local
265 file_store.backend = local
266 ## path to store the uploaded binaries
267 file_store.storage_path = %(here)s/data/file_store
268
262
269
263 ####################################
270 ####################################
264 ### CELERY CONFIG ####
271 ### CELERY CONFIG ####
@@ -300,6 +307,7 b' rc_cache.cache_perms.expiration_time = 3'
300 #rc_cache.cache_perms.arguments.host = localhost
307 #rc_cache.cache_perms.arguments.host = localhost
301 #rc_cache.cache_perms.arguments.port = 6379
308 #rc_cache.cache_perms.arguments.port = 6379
302 #rc_cache.cache_perms.arguments.db = 0
309 #rc_cache.cache_perms.arguments.db = 0
310 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
303 #rc_cache.cache_perms.arguments.distributed_lock = true
311 #rc_cache.cache_perms.arguments.distributed_lock = true
304
312
305 ## `cache_repo` cache settings for FileTree, Readme, RSS FEEDS
313 ## `cache_repo` cache settings for FileTree, Readme, RSS FEEDS
@@ -315,6 +323,7 b' rc_cache.cache_repo.expiration_time = 25'
315 #rc_cache.cache_repo.arguments.host = localhost
323 #rc_cache.cache_repo.arguments.host = localhost
316 #rc_cache.cache_repo.arguments.port = 6379
324 #rc_cache.cache_repo.arguments.port = 6379
317 #rc_cache.cache_repo.arguments.db = 1
325 #rc_cache.cache_repo.arguments.db = 1
326 ## more Redis options: https://dogpilecache.sqlalchemy.org/en/latest/api.html#redis-backends
318 #rc_cache.cache_repo.arguments.distributed_lock = true
327 #rc_cache.cache_repo.arguments.distributed_lock = true
319
328
320 ## cache settings for SQL queries, this needs to use memory type backend
329 ## cache settings for SQL queries, this needs to use memory type backend
@@ -399,7 +408,7 b' channelstream.server = 127.0.0.1:9800'
399 ## location of the channelstream server from outside world
408 ## location of the channelstream server from outside world
400 ## use ws:// for http or wss:// for https. This address needs to be handled
409 ## use ws:// for http or wss:// for https. This address needs to be handled
401 ## by external HTTP server such as Nginx or Apache
410 ## by external HTTP server such as Nginx or Apache
402 ## see nginx/apache configuration examples in our docs
411 ## see Nginx/Apache configuration examples in our docs
403 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
412 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
404 channelstream.secret = secret
413 channelstream.secret = secret
405 channelstream.history.location = %(here)s/channelstream_history
414 channelstream.history.location = %(here)s/channelstream_history
@@ -416,14 +425,14 b' channelstream.proxy_path = /_channelstre'
416 ## Appenlight is tailored to work with RhodeCode, see
425 ## Appenlight is tailored to work with RhodeCode, see
417 ## http://appenlight.com for details how to obtain an account
426 ## http://appenlight.com for details how to obtain an account
418
427
419 ## appenlight integration enabled
428 ## Appenlight integration enabled
420 appenlight = false
429 appenlight = false
421
430
422 appenlight.server_url = https://api.appenlight.com
431 appenlight.server_url = https://api.appenlight.com
423 appenlight.api_key = YOUR_API_KEY
432 appenlight.api_key = YOUR_API_KEY
424 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
433 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
425
434
426 # used for JS client
435 ## used for JS client
427 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
436 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
428
437
429 ## TWEAK AMOUNT OF INFO SENT HERE
438 ## TWEAK AMOUNT OF INFO SENT HERE
@@ -448,7 +457,7 b' appenlight.logging.level = WARNING'
448 ## (saves API quota for intensive logging)
457 ## (saves API quota for intensive logging)
449 appenlight.logging_on_error = false
458 appenlight.logging_on_error = false
450
459
451 ## list of additonal keywords that should be grabbed from environ object
460 ## list of additional keywords that should be grabbed from environ object
452 ## can be string with comma separated list of words in lowercase
461 ## can be string with comma separated list of words in lowercase
453 ## (by default client will always send following info:
462 ## (by default client will always send following info:
454 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
463 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
@@ -506,7 +515,7 b' sqlalchemy.db1.convert_unicode = true'
506 vcs.server.enable = true
515 vcs.server.enable = true
507 vcs.server = localhost:9900
516 vcs.server = localhost:9900
508
517
509 ## Web server connectivity protocol, responsible for web based VCS operatations
518 ## Web server connectivity protocol, responsible for web based VCS operations
510 ## Available protocols are:
519 ## Available protocols are:
511 ## `http` - use http-rpc backend (default)
520 ## `http` - use http-rpc backend (default)
512 vcs.server.protocol = http
521 vcs.server.protocol = http
@@ -555,7 +564,8 b' svn.proxy.config_file_path = %(here)s/mo'
555 ## In most cases it should be set to `/`.
564 ## In most cases it should be set to `/`.
556 svn.proxy.location_root = /
565 svn.proxy.location_root = /
557 ## Command to reload the mod dav svn configuration on change.
566 ## Command to reload the mod dav svn configuration on change.
558 ## Example: `/etc/init.d/apache2 reload`
567 ## Example: `/etc/init.d/apache2 reload` or /home/USER/apache_reload.sh
568 ## Make sure user who runs RhodeCode process is allowed to reload Apache
559 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
569 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
560 ## If the timeout expires before the reload command finishes, the command will
570 ## If the timeout expires before the reload command finishes, the command will
561 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
571 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
@@ -566,7 +576,7 b' svn.proxy.location_root = /'
566 ############################################################
576 ############################################################
567
577
568 ## Defines if a custom authorized_keys file should be created and written on
578 ## Defines if a custom authorized_keys file should be created and written on
569 ## any change user ssh keys. Setting this to false also disables posibility
579 ## any change user ssh keys. Setting this to false also disables possibility
570 ## of adding SSH keys by users from web interface. Super admins can still
580 ## of adding SSH keys by users from web interface. Super admins can still
571 ## manage SSH Keys.
581 ## manage SSH Keys.
572 ssh.generate_authorized_keyfile = false
582 ssh.generate_authorized_keyfile = false
@@ -574,13 +584,13 b' ssh.generate_authorized_keyfile = false'
574 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
584 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
575 # ssh.authorized_keys_ssh_opts =
585 # ssh.authorized_keys_ssh_opts =
576
586
577 ## Path to the authrozied_keys file where the generate entries are placed.
587 ## Path to the authorized_keys file where the generate entries are placed.
578 ## It is possible to have multiple key files specified in `sshd_config` e.g.
588 ## It is possible to have multiple key files specified in `sshd_config` e.g.
579 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
589 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
580 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
590 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
581
591
582 ## Command to execute the SSH wrapper. The binary is available in the
592 ## Command to execute the SSH wrapper. The binary is available in the
583 ## rhodecode installation directory.
593 ## RhodeCode installation directory.
584 ## e.g ~/.rccontrol/community-1/profile/bin/rc-ssh-wrapper
594 ## e.g ~/.rccontrol/community-1/profile/bin/rc-ssh-wrapper
585 ssh.wrapper_cmd = ~/.rccontrol/community-1/rc-ssh-wrapper
595 ssh.wrapper_cmd = ~/.rccontrol/community-1/rc-ssh-wrapper
586
596
@@ -588,7 +598,7 b' ssh.wrapper_cmd = ~/.rccontrol/community'
588 ssh.wrapper_cmd_allow_shell = false
598 ssh.wrapper_cmd_allow_shell = false
589
599
590 ## Enables logging, and detailed output send back to the client during SSH
600 ## Enables logging, and detailed output send back to the client during SSH
591 ## operations. Usefull for debugging, shouldn't be used in production.
601 ## operations. Useful for debugging, shouldn't be used in production.
592 ssh.enable_debug_logging = false
602 ssh.enable_debug_logging = false
593
603
594 ## Paths to binary executable, by default they are the names, but we can
604 ## Paths to binary executable, by default they are the names, but we can
@@ -597,6 +607,10 b' ssh.executable.hg = ~/.rccontrol/vcsserv'
597 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
607 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
598 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
608 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
599
609
610 ## Enables SSH key generator web interface. Disabling this still allows users
611 ## to add their own keys.
612 ssh.enable_ui_key_generator = true
613
600
614
601 ## Dummy marker to add new entries after.
615 ## Dummy marker to add new entries after.
602 ## Add any custom entries below. Please don't remove.
616 ## Add any custom entries below. Please don't remove.
@@ -19,14 +19,15 b''
19 # }
19 # }
20
20
21 args@
21 args@
22 { pythonPackages ? "python27Packages"
22 { system ? builtins.currentSystem
23 , pythonPackages ? "python27Packages"
23 , pythonExternalOverrides ? self: super: {}
24 , pythonExternalOverrides ? self: super: {}
24 , doCheck ? false
25 , doCheck ? false
25 , ...
26 , ...
26 }:
27 }:
27
28
28 let
29 let
29 pkgs_ = (import <nixpkgs> {});
30 pkgs_ = args.pkgs or (import <nixpkgs> { inherit system; });
30 in
31 in
31
32
32 let
33 let
@@ -80,7 +81,8 b' let'
80
81
81 nodeEnv = import ./pkgs/node-default.nix {
82 nodeEnv = import ./pkgs/node-default.nix {
82 inherit
83 inherit
83 pkgs;
84 pkgs
85 system;
84 };
86 };
85 nodeDependencies = nodeEnv.shell.nodeDependencies;
87 nodeDependencies = nodeEnv.shell.nodeDependencies;
86
88
@@ -116,7 +116,7 b' Full-text Search Backup'
116
116
117 You may also have full text search set up, but the index can be rebuild from
117 You may also have full text search set up, but the index can be rebuild from
118 re-imported |repos| if necessary. You will most likely want to backup your
118 re-imported |repos| if necessary. You will most likely want to backup your
119 :file:`mapping.ini` file if you've configured that. For more information, see
119 :file:`search_mapping.ini` file if you've configured that. For more information, see
120 the :ref:`indexing-ref` section.
120 the :ref:`indexing-ref` section.
121
121
122 Restoration Steps
122 Restoration Steps
@@ -140,7 +140,7 b' Post Restoration Steps'
140 Once you have restored your |RCE| instance to basic functionality, you can
140 Once you have restored your |RCE| instance to basic functionality, you can
141 then work on restoring any specific setup changes you had made.
141 then work on restoring any specific setup changes you had made.
142
142
143 * To recreate the |RCE| index, use the backed up :file:`mapping.ini` file if
143 * To recreate the |RCE| index, use the backed up :file:`search_mapping.ini` file if
144 you had made changes and rerun the indexer. See the
144 you had made changes and rerun the indexer. See the
145 :ref:`indexing-ref` section for details.
145 :ref:`indexing-ref` section for details.
146 * To reconfigure any extensions, copy the backed up extensions into the
146 * To reconfigure any extensions, copy the backed up extensions into the
@@ -23,9 +23,9 b' sections.'
23 * :ref:`increase-gunicorn`
23 * :ref:`increase-gunicorn`
24 * :ref:`x-frame`
24 * :ref:`x-frame`
25
25
26 \- **mapping.ini**
26 \- **search_mapping.ini**
27 Default location:
27 Default location:
28 :file:`/home/{user}/.rccontrol/{instance-id}/mapping.ini`
28 :file:`/home/{user}/.rccontrol/{instance-id}/search_mapping.ini`
29
29
30 This file is used to control the |RCE| indexer. It comes configured
30 This file is used to control the |RCE| indexer. It comes configured
31 to index your instance. To change the default configuration, see
31 to index your instance. To change the default configuration, see
@@ -3,35 +3,41 b''
3 Full-text Search
3 Full-text Search
4 ----------------
4 ----------------
5
5
6 By default RhodeCode is configured to use `Whoosh`_ to index |repos| and
6 RhodeCode provides a full text search capabilities to search inside file content,
7 provide full-text search.
7 commit message, and file paths. Indexing is not enabled by default and to use
8 full text search building an index is a pre-requisite.
8
9
9 |RCE| also provides support for `Elasticsearch`_ as a backend for scalable
10 By default RhodeCode is configured to use `Whoosh`_ to index |repos| and
10 search. See :ref:`enable-elasticsearch` for details.
11 provide full-text search. `Whoosh`_ works well for a small amount of data and
12 shouldn't be used in case of large code-bases and lots of repositories.
13
14 |RCE| also provides support for `ElasticSearch 6`_ as a backend more for advanced
15 and scalable search. See :ref:`enable-elasticsearch` for details.
11
16
12 Indexing
17 Indexing
13 ^^^^^^^^
18 ^^^^^^^^
14
19
15 To run the indexer you need to use an |authtoken| with admin rights to all
20 To run the indexer you need to have an |authtoken| with admin rights to all |repos|.
16 |repos|.
17
21
18 To index new content added, you have the option to set the indexer up in a
22 To index repositories stored in RhodeCode, you have the option to set the indexer up in a
19 number of ways, for example:
23 number of ways, for example:
20
24
21 * Call the indexer via a cron job. We recommend running this nightly,
25 * Call the indexer via a cron job. We recommend running this once at night.
22 unless you need everything indexed immediately.
26 In case you need everything indexed immediately it's possible to index few
23 * Set the indexer to infinitely loop and reindex as soon as it has run its
27 times during the day. Indexer has a special locking mechanism that won't allow
24 cycle.
28 two instances of indexer running at once. It's safe to run it even every 1hr.
29 * Set the indexer to infinitely loop and reindex as soon as it has run its previous cycle.
25 * Hook the indexer up with your CI server to reindex after each push.
30 * Hook the indexer up with your CI server to reindex after each push.
26
31
27 The indexer works by indexing new commits added since the last run. If you
32 The indexer works by indexing new commits added since the last run, and comparing
28 wish to build a brand new index from scratch each time,
33 file changes to index only new or modified files.
29 use the ``force`` option in the configuration file.
34 If you wish to build a brand new index from scratch each time, use the ``force``
35 option in the configuration file, or run it with --force flag.
30
36
31 .. important::
37 .. important::
32
38
33 You need to have |RCT| installed, see :ref:`install-tools`. Since |RCE|
39 You need to have |RCT| installed, see :ref:`install-tools`. Since |RCE|
34 3.5.0 they are installed by default.
40 3.5.0 they are installed by default and available with community/enterprise installations.
35
41
36 To set up indexing, use the following steps:
42 To set up indexing, use the following steps:
37
43
@@ -45,6 +51,13 b' 4. :ref:`advanced-indexing`'
45 Configure the ``.rhoderc`` File
51 Configure the ``.rhoderc`` File
46 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47
53
54 .. note::
55
56 Optionally it's possible to use indexer without the ``.rhoderc``. Simply instead of
57 executing with `--instance-name=enterprise-1` execute providing the host and token
58 directly: `--api-host=http://127.0.0.1:10000 --api-key=<auth-token-goes-here>`
59
60
48 |RCT| uses the :file:`/home/{user}/.rhoderc` file for connection details
61 |RCT| uses the :file:`/home/{user}/.rhoderc` file for connection details
49 to |RCE| instances. If this file is not automatically created,
62 to |RCE| instances. If this file is not automatically created,
50 you can configure it using the following example. You need to configure the
63 you can configure it using the following example. You need to configure the
@@ -58,9 +71,9 b' details for each instance you want to in'
58
71
59 - NAME: enterprise-1
72 - NAME: enterprise-1
60 - STATUS: RUNNING
73 - STATUS: RUNNING
61 - TYPE: Momentum
74 - TYPE: Enterprise
62 - VERSION: 1.5.0
75 - VERSION: 4.1.0
63 - URL: http://127.0.0.1:10000
76 - URL: http://127.0.0.1:10003
64
77
65 To get your API Token, on the |RCE| interface go to
78 To get your API Token, on the |RCE| interface go to
66 :menuselection:`username --> My Account --> Auth tokens`
79 :menuselection:`username --> My Account --> Auth tokens`
@@ -72,29 +85,35 b' To get your API Token, on the |RCE| inte'
72 [instance:enterprise-1]
85 [instance:enterprise-1]
73 api_host = http://127.0.0.1:10000
86 api_host = http://127.0.0.1:10000
74 api_key = <auth token goes here>
87 api_key = <auth token goes here>
75 repo_dir = /home/<username>/repos
88
76
89
77 .. _run-index:
90 .. _run-index:
78
91
79 Run the Indexer
92 Run the Indexer
80 ^^^^^^^^^^^^^^^
93 ^^^^^^^^^^^^^^^
81
94
82 Run the indexer using the following command, and specify the instance you
95 Run the indexer using the following command, and specify the instance you want to index:
83 want to index:
84
96
85 .. code-block:: bash
97 .. code-block:: bash
86
98
87 # From inside a virtualevv
99 # Using default simples indexing of all repositories
88 (venv)$ rhodecode-index --instance-name=enterprise-1
89
90 # Using default installation
91 $ /home/user/.rccontrol/enterprise-1/profile/bin/rhodecode-index \
100 $ /home/user/.rccontrol/enterprise-1/profile/bin/rhodecode-index \
92 --instance-name=enterprise-1
101 --instance-name=enterprise-1
93
102
94 # Using a custom mapping file
103 # Using a custom mapping file with indexing rules, and using elasticsearch 6 backend
95 $ /home/user/.rccontrol/enterprise-1/profile/bin/rhodecode-index \
104 $ /home/user/.rccontrol/enterprise-1/profile/bin/rhodecode-index \
96 --instance-name=enterprise-1 \
105 --instance-name=enterprise-1 \
97 --mapping=/home/user/.rccontrol/enterprise-1/mapping.ini
106 --mapping=/home/user/.rccontrol/enterprise-1/search_mapping.ini \
107 --es-version=6 --engine-location=http://elasticsearch-host:9200
108
109 # Using a custom mapping file and invocation without ``.rhoderc``
110 $ /home/user/.rccontrol/enterprise-1/profile/bin/rhodecode-index \
111 --api-host=http://rhodecodecode.myserver.com --api-key=xxxxx \
112 --mapping=/home/user/.rccontrol/enterprise-1/search_mapping.ini
113
114 # From inside a virtualev on your local machine or CI server.
115 (venv)$ rhodecode-index --instance-name=enterprise-1
116
98
117
99 .. note::
118 .. note::
100
119
@@ -136,119 +155,173 b' 3. Save the file.'
136 # using a specially configured mapping file
155 # using a specially configured mapping file
137 */15 * * * * ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
156 */15 * * * * ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
138 --instance-name=enterprise-4 \
157 --instance-name=enterprise-4 \
139 --mapping=/home/user/.rccontrol/enterprise-4/mapping.ini
158 --mapping=/home/user/.rccontrol/enterprise-4/search_mapping.ini
140
159
141 .. _advanced-indexing:
160 .. _advanced-indexing:
142
161
143 Advanced Indexing
162 Advanced Indexing
144 ^^^^^^^^^^^^^^^^^
163 ^^^^^^^^^^^^^^^^^
145
164
146 |RCT| indexes based on the :file:`mapping.ini` file. To configure your index,
165
147 you can specify different options in this file. The default location is:
166 Force Re-Indexing single repository
167 +++++++++++++++++++++++++++++++++++
168
169 Often it's required to re-index whole repository because of some repository changes,
170 or to remove some indexed secrets, or files. There's a special `--repo-name=` flag
171 for the indexer that limits execution to a single repository. For example to force-reindex
172 single repository such call can be made::
173
174 rhodecode-index --instance-name=enterprise-1 --force --repo-name=rhodecode-vcsserver
175
176
177 Removing repositories from index
178 ++++++++++++++++++++++++++++++++
148
179
149 * :file:`/home/{user}/.rccontrol/{instance-id}/mapping.ini`, using default
180 The indexer automatically removes renamed repositories and builds index for new names.
150 |RCT|.
181 In the same way if a listed repository in mapping.ini is not reported existing by the
182 server it's removed from the index.
183 In case that you wish to remove indexed repository manually such call would allow that::
184
185 rhodecode-index --instance-name=enterprise-1 --remove-only --repo-name=rhodecode-vcsserver
186
187
188 Using search_mapping.ini file for advanced index rules
189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
190
191 By default rhodecode-index runs for all repositories, all files with parsing limits
192 defined by the CLI default arguments. You can change those limits by calling with
193 different flags such as `--max-filesize=2048kb` or `--repo-limit=10`
194
195 For more advanced execution logic it's possible to use a configuration file that
196 would define detailed rules which repositories and how should be indexed.
197
198 |RCT| provides an example index configuration file called :file:`search_mapping.ini`.
199 This file is created by default during installation and is located at:
200
201 * :file:`/home/{user}/.rccontrol/{instance-id}/search_mapping.ini`, using default |RCT|.
151 * :file:`~/venv/lib/python2.7/site-packages/rhodecode_tools/templates/mapping.ini`,
202 * :file:`~/venv/lib/python2.7/site-packages/rhodecode_tools/templates/mapping.ini`,
152 when using ``virtualenv``.
203 when using ``virtualenv``.
153
204
154 .. note::
205 .. note::
155
206
156 If you need to create the :file:`mapping.ini` file, use the |RCT|
207 If you need to create the :file:`search_mapping.ini` file manually, use the |RCT|
157 ``rhodecode-index --create-mapping path/to/file`` API call. For details,
208 ``rhodecode-index --create-mapping path/to/search_mapping.ini`` API call.
158 see the :ref:`tools-cli` section.
209 For details, see the :ref:`tools-cli` section.
159
160 The indexer runs in a random order to prevent a failing |repo| from stopping
161 a build. To configure different indexing scenarios, set the following options
162 inside the :file:`mapping.ini` and specify the altered file using the
163 ``--mapping`` option.
164
210
165 * ``index_files`` : Index the specified file types.
211 To Run the indexer with mapping file provide it using `--mapping` flag::
166 * ``skip_files`` : Do not index the specified file types.
167 * ``index_files_content`` : Index the content of the specified file types.
168 * ``skip_files_content`` : Do not index the content of the specified files.
169 * ``force`` : Create a fresh index on each run.
170 * ``max_filesize`` : Files larger than the set size will not be indexed.
171 * ``commit_parse_limit`` : Set the batch size when indexing commit messages.
172 Set to a lower number to lessen memory load.
173 * ``repo_limit`` : Set the maximum number or |repos| indexed per run.
174 * ``[INCLUDE]`` : Set |repos| you want indexed. This takes precedent over
175 ``[EXCLUDE]``.
176 * ``[EXCLUDE]`` : Set |repos| you do not want indexed. Exclude can be used to
177 not index branches, forks, or log |repos|.
178
212
179 At the end of the file you can specify conditions for specific |repos| that
213 rhodecode-index --instance-name=enterprise-1 --mapping=/my/path/search_mapping.ini
180 will override the default values. To configure your indexer,
214
181 use the following example :file:`mapping.ini` file.
215
216 Here's a detailed example of using :file:`search_mapping.ini` file.
182
217
183 .. code-block:: ini
218 .. code-block:: ini
184
219
185 [__DEFAULT__]
220 [__DEFAULT__]
186 # default patterns for indexing files and content of files.
221 ; Create index on commits data, and files data in this order. Available options
187 # Binary files are skipped by default.
222 ; are `commits`, `files`
223 index_types = commits,files
224
225 ; Commit fetch limit. In what amount of chunks commits should be fetched
226 ; via api and parsed. This allows server to transfer smaller chunks and be less loaded
227 commit_fetch_limit = 1000
188
228
189 # Index python and markdown files
229 ; Commit process limit. Limit the number of commits indexer should fetch, and
190 index_files = *.py, *.md
230 ; store inside the full text search index. eg. if repo has 2000 commits, and
231 ; limit is 1000, on the first run it will process commits 0-1000 and on the
232 ; second 1000-2000 commits. Help reduce memory usage, default is 50000
233 ; (set -1 for unlimited)
234 commit_process_limit = 20000
191
235
192 # Do not index these file types
236 ; Limit of how many repositories each run can process, default is -1 (unlimited)
193 skip_files = *.svg, *.log, *.dump, *.txt
237 ; in case of 1000s of repositories it's better to execute in chunks to not overload
238 ; the server.
239 repo_limit = -1
194
240
195 # Index both file types and their content
241 ; Default patterns for indexing files and content of files. Binary files
196 index_files_content = *.cpp, *.ini, *.py
242 ; are skipped by default.
243
244 ; Add to index those comma separated files; globs syntax
245 ; e.g index_files = *.py, *.c, *.h, *.js
246 index_files = *,
247
248 ; Do not add to index those comma separated files, this excludes
249 ; both search by name and content; globs syntax
250 ; e.g index_files = *.key, *.sql, *.xml, *.pem, *.crt
251 skip_files = ,
197
252
198 # Index file names, but not file content
253 ; Add to index content of those comma separated files; globs syntax
199 skip_files_content = *.svg,
254 ; e.g index_files = *.h, *.obj
255 index_files_content = *,
200
256
201 # Force rebuilding an index from scratch. Each repository will be rebuild
257 ; Do not add to index content of those comma separated files; globs syntax
202 # from scratch with a global flag. Use local flag to rebuild single repos
258 ; Binary files are not indexed by default.
259 ; e.g index_files = *.min.js, *.xml, *.dump, *.log, *.dump
260 skip_files_content = ,
261
262 ; Force rebuilding an index from scratch. Each repository will be rebuild from
263 ; scratch with a global flag. Use --repo-name=NAME --force to rebuild single repo
203 force = false
264 force = false
204
265
205 # Do not index files larger than 385KB
266 ; maximum file size that indexer will use, files above that limit are not going
206 max_filesize = 385KB
267 ; to have they content indexed.
268 ; Possible options are KB (kilobytes), MB (megabytes), eg 1MB or 1024KB
269 max_filesize = 10MB
207
270
208 # Limit commit indexing to 500 per batch
209 commit_parse_limit = 500
210
211 # Limit each index run to 25 repos
212 repo_limit = 25
213
271
214 # __INCLUDE__ is more important that __EXCLUDE__.
272 [__INDEX_RULES__]
215
273 ; Ordered match rules for repositories. A list of all repositories will be fetched
216 [__INCLUDE__]
274 ; using API and this list will be filtered using those rules.
217 # Include all repos with these names
275 ; Syntax for entry: `glob_pattern_OR_full_repo_name = 0 OR 1` where 0=exclude, 1=include
276 ; When this ordered list is traversed first match will return the include/exclude marker
277 ; For example:
278 ; upstream/binary_repo = 0
279 ; upstream/subrepo/xml_files = 0
280 ; upstream/* = 1
281 ; special-repo = 1
282 ; * = 0
283 ; This will index all repositories under upstream/*, but skip upstream/binary_repo
284 ; and upstream/sub_repo/xml_files, last * = 0 means skip all other matches
218
285
219 docs/* = 1
220 lib/* = 1
221
222 [__EXCLUDE__]
223 # Do not include the following repo in index
224
286
225 dev-docs/* = 1
287 ; == EXPLICIT REPOSITORY INDEXING ==
226 legacy-repos/* = 1
288 ; If defined this will skip using __INDEX_RULES__, and will not use API to fetch
227 *-dev/* = 1
289 ; list of repositories, it will explicitly take names defined with [NAME] format and
228
290 ; try to build the index, to build index just for repo_name_1 and special-repo use:
229 # Each repo that needs special indexing is a separate section below.
291 ; [repo_name_1]
230 # In each section set the options to override the global configuration
292 ; [special-repo]
231 # parameters above.
232 # If special settings are not configured, the global configuration values
233 # above are inherited. If no special repositories are
234 # defined here RhodeCode will use the API to ask for all repositories
235
293
236 # For this repo use different settings
294 ; == PER REPOSITORY CONFIGURATION ==
237 [special-repo]
295 ; This allows overriding the global configuration per repository.
238 commit_parse_limit = 20,
296 ; example to set specific file limit, and skip certain files for repository special-repo
239 skip_files = *.idea, *.xml,
297 ; the CLI flags doesn't override the conf settings.
298 ; [conf:special-repo]
299 ; max_filesize = 5mb
300 ; skip_files = *.xml, *.sql
301
240
302
241 # For another repo use different settings
303
242 [another-special-repo]
304 In case of 1000s of repositories it can be tricky to write the include/exclude rules at first.
243 index_files = *,
305 There's a special flag to test the mapping file rules and list repositories that would
244 max_filesize = 800MB
306 be indexed. Run the indexer with `--show-matched-repos` to list only the
245 commit_parse_limit = 20000
307 match repositories defined in .ini file rules::
308
309 rhodecode-index --instance-name=enterprise-1 --show-matched-repos --mapping=/my/path/search_mapping.ini
310
246
311
247 .. _enable-elasticsearch:
312 .. _enable-elasticsearch:
248
313
249 Enabling Elasticsearch
314 Enabling ElasticSearch
250 ^^^^^^^^^^^^^^^^^^^^^^
315 ^^^^^^^^^^^^^^^^^^^^^^
251
316
317 ElasticSearch is available in EE edition only. It provides much scalable and more advanced
318 search capabilities. While Whoosh is fine for upto 1-2GB of data, beyond that amount it
319 starts slowing down, and can cause other problems.
320 New ElasticSearch 6 also provides much more advanced query language.
321 It allows advanced filtering by file paths, extensions, use OR statements, ranges etc.
322 Please check query language examples in the search field for some advanced query language usage.
323
324
252 1. Open the :file:`rhodecode.ini` file for the instance you wish to edit. The
325 1. Open the :file:`rhodecode.ini` file for the instance you wish to edit. The
253 default location is
326 default location is
254 :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
327 :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
@@ -268,9 +341,19 b' and change it to:'
268 .. code-block:: ini
341 .. code-block:: ini
269
342
270 search.module = rc_elasticsearch
343 search.module = rc_elasticsearch
271 search.location = http://localhost:9200/
344 search.location = http://localhost:9200
345 ## specify Elastic Search version, 6 for latest or 2 for legacy
346 search.es_version = 6
347
348 where ``search.location`` points to the ElasticSearch server
349 by default running on port 9200.
272
350
273 where ``search.location`` points to the elasticsearch server.
351 Index invocation also needs change. Please provide --es-version= and
352 --engine-location= parameters to define ElasticSearch server location and it's version.
353 For example::
354
355 rhodecode-index --instace-name=enterprise-1 --es-version=6 --engine-location=http://localhost:9200
356
274
357
275 .. _Whoosh: https://pypi.python.org/pypi/Whoosh/
358 .. _Whoosh: https://pypi.python.org/pypi/Whoosh/
276 .. _Elasticsearch: https://www.elastic.co/ No newline at end of file
359 .. _ElasticSearch 6: https://www.elastic.co/
@@ -9,6 +9,9 b' Use the following example to configure N'
9 ## Rate limiter for certain pages to prevent brute force attacks
9 ## Rate limiter for certain pages to prevent brute force attacks
10 limit_req_zone $binary_remote_addr zone=req_limit:10m rate=1r/s;
10 limit_req_zone $binary_remote_addr zone=req_limit:10m rate=1r/s;
11
11
12 ## cache zone
13 proxy_cache_path /etc/nginx/nginx_cache levels=1:2 use_temp_path=off keys_zone=cache_zone:10m inactive=720h max_size=10g;
14
12 ## Custom log format
15 ## Custom log format
13 log_format log_custom '$remote_addr - $remote_user [$time_local] '
16 log_format log_custom '$remote_addr - $remote_user [$time_local] '
14 '"$request" $status $body_bytes_sent '
17 '"$request" $status $body_bytes_sent '
@@ -141,6 +144,34 b' Use the following example to configure N'
141 try_files $uri @rhodecode_http;
144 try_files $uri @rhodecode_http;
142 }
145 }
143
146
147 ## Special Cache for file store, make sure you enable this intentionally as
148 ## it could bypass upload files permissions
149 # location /_file_store/download {
150 #
151 # proxy_cache cache_zone;
152 # # ignore Set-Cookie
153 # proxy_ignore_headers Set-Cookie;
154 # proxy_ignore_headers Cookie;
155 #
156 # proxy_cache_key $host$uri$is_args$args;
157 # proxy_cache_methods GET;
158 #
159 # proxy_cache_bypass $http_cache_control;
160 # proxy_cache_valid 200 302 720h;
161 #
162 # proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
163 #
164 # # returns cache status in headers
165 # add_header X-Proxy-Cache $upstream_cache_status;
166 # add_header Cache-Control "public";
167 #
168 # proxy_cache_lock on;
169 # proxy_cache_lock_age 5m;
170 #
171 # proxy_pass http://rc;
172 #
173 # }
174
144 location / {
175 location / {
145 try_files $uri @rhodecode_http;
176 try_files $uri @rhodecode_http;
146 }
177 }
@@ -35,7 +35,7 b' 2. On the |repo| group settings page you'
35
35
36 * :guilabel:`Owner`: Lets you change the group owner. Useful when users are
36 * :guilabel:`Owner`: Lets you change the group owner. Useful when users are
37 moving roles within an organisation.
37 moving roles within an organisation.
38 * :guilabel:`Group parent`: Lets you add the |repo| group as a sub-group
38 * :guilabel:`Repository group`: Lets you add the |repo| group as a sub-group
39 of a larger group, i.e. :guilabel:`QA-Repos >> QA-Repos-Berlin`
39 of a larger group, i.e. :guilabel:`QA-Repos >> QA-Repos-Berlin`
40 * :guilabel:`Enable automatic locking`: For more information,
40 * :guilabel:`Enable automatic locking`: For more information,
41 see :ref:`repo-locking`
41 see :ref:`repo-locking`
@@ -30,3 +30,5 b' The following are the most common system'
30 enable-debug
30 enable-debug
31 admin-tricks
31 admin-tricks
32 cleanup-cmds
32 cleanup-cmds
33 restore-deleted-repositories
34
@@ -78,7 +78,7 b' Configuration Files'
78 -------------------
78 -------------------
79
79
80 * :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
80 * :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
81 * :file:`/home/{user}/.rccontrol/{instance-id}/mapping.ini`
81 * :file:`/home/{user}/.rccontrol/{instance-id}/search_mapping.ini`
82 * :file:`/home/{user}/.rccontrol/{vcsserver-id}/vcsserver.ini`
82 * :file:`/home/{user}/.rccontrol/{vcsserver-id}/vcsserver.ini`
83 * :file:`/home/{user}/.rccontrol/supervisor/supervisord.ini`
83 * :file:`/home/{user}/.rccontrol/supervisor/supervisord.ini`
84 * :file:`/home/{user}/.rccontrol.ini`
84 * :file:`/home/{user}/.rccontrol.ini`
@@ -196,7 +196,8 b' are not required in args.'
196 .. --- API DEFS MARKER ---
196 .. --- API DEFS MARKER ---
197 .. toctree::
197 .. toctree::
198
198
199 methods/views
199 methods/repo-methods
200 methods/store-methods
200 methods/license-methods
201 methods/license-methods
201 methods/deprecated-methods
202 methods/deprecated-methods
202 methods/gist-methods
203 methods/gist-methods
@@ -83,7 +83,7 b' comment_pull_request'
83 create_pull_request
83 create_pull_request
84 -------------------
84 -------------------
85
85
86 .. py:function:: create_pull_request(apiuser, source_repo, target_repo, source_ref, target_ref, title=<Optional:''>, description=<Optional:''>, description_renderer=<Optional:''>, reviewers=<Optional:None>)
86 .. py:function:: create_pull_request(apiuser, source_repo, target_repo, source_ref, target_ref, owner=<Optional:<OptionalAttr:apiuser>>, title=<Optional:''>, description=<Optional:''>, description_renderer=<Optional:''>, reviewers=<Optional:None>)
87
87
88 Creates a new pull request.
88 Creates a new pull request.
89
89
@@ -104,6 +104,8 b' create_pull_request'
104 :type source_ref: str
104 :type source_ref: str
105 :param target_ref: Set the target ref name.
105 :param target_ref: Set the target ref name.
106 :type target_ref: str
106 :type target_ref: str
107 :param owner: user_id or username
108 :type owner: Optional(str)
107 :param title: Optionally Set the pull request title, it's generated otherwise
109 :param title: Optionally Set the pull request title, it's generated otherwise
108 :type title: str
110 :type title: str
109 :param description: Set the pull request description.
111 :param description: Set the pull request description.
@@ -248,7 +250,7 b' get_pull_request_comments'
248 get_pull_requests
250 get_pull_requests
249 -----------------
251 -----------------
250
252
251 .. py:function:: get_pull_requests(apiuser, repoid, status=<Optional:'new'>)
253 .. py:function:: get_pull_requests(apiuser, repoid, status=<Optional:'new'>, merge_state=<Optional:True>)
252
254
253 Get all pull requests from the repository specified in `repoid`.
255 Get all pull requests from the repository specified in `repoid`.
254
256
@@ -262,6 +264,9 b' get_pull_requests'
262 * ``open``
264 * ``open``
263 * ``closed``
265 * ``closed``
264 :type status: str
266 :type status: str
267 :param merge_state: Optional calculate merge state for each repository.
268 This could result in longer time to fetch the data
269 :type merge_state: bool
265
270
266 Example output:
271 Example output:
267
272
@@ -358,6 +363,7 b' merge_pull_request'
358 "result": {
363 "result": {
359 "executed": "<bool>",
364 "executed": "<bool>",
360 "failure_reason": "<int>",
365 "failure_reason": "<int>",
366 "merge_status_message": "<str>",
361 "merge_commit_id": "<merge_commit_id>",
367 "merge_commit_id": "<merge_commit_id>",
362 "possible": "<bool>",
368 "possible": "<bool>",
363 "merge_ref": {
369 "merge_ref": {
@@ -394,6 +394,105 b' get_repo_changesets'
394 of changed files.
394 of changed files.
395
395
396
396
397 get_repo_comments
398 -----------------
399
400 .. py:function:: get_repo_comments(apiuser, repoid, commit_id=<Optional:None>, comment_type=<Optional:None>, userid=<Optional:None>)
401
402 Get all comments for a repository
403
404 :param apiuser: This is filled automatically from the |authtoken|.
405 :type apiuser: AuthUser
406 :param repoid: Set the repository name or repository ID.
407 :type repoid: str or int
408 :param commit_id: Optionally filter the comments by the commit_id
409 :type commit_id: Optional(str), default: None
410 :param comment_type: Optionally filter the comments by the comment_type
411 one of: 'note', 'todo'
412 :type comment_type: Optional(str), default: None
413 :param userid: Optionally filter the comments by the author of comment
414 :type userid: Optional(str or int), Default: None
415
416 Example error output:
417
418 .. code-block:: bash
419
420 {
421 "id" : <id_given_in_input>,
422 "result" : [
423 {
424 "comment_author": <USER_DETAILS>,
425 "comment_created_on": "2017-02-01T14:38:16.309",
426 "comment_f_path": "file.txt",
427 "comment_id": 282,
428 "comment_lineno": "n1",
429 "comment_resolved_by": null,
430 "comment_status": [],
431 "comment_text": "This file needs a header",
432 "comment_type": "todo"
433 }
434 ],
435 "error" : null
436 }
437
438
439 get_repo_file
440 -------------
441
442 .. py:function:: get_repo_file(apiuser, repoid, commit_id, file_path, max_file_bytes=<Optional:None>, details=<Optional:'basic'>, cache=<Optional:True>)
443
444 Returns a single file from repository at given revision.
445
446 This command can only be run using an |authtoken| with admin rights,
447 or users with at least read rights to |repos|.
448
449 :param apiuser: This is filled automatically from the |authtoken|.
450 :type apiuser: AuthUser
451 :param repoid: The repository name or repository ID.
452 :type repoid: str or int
453 :param commit_id: The revision for which listing should be done.
454 :type commit_id: str
455 :param file_path: The path from which to start displaying.
456 :type file_path: str
457 :param details: Returns different set of information about nodes.
458 The valid options are ``minimal`` ``basic`` and ``full``.
459 :type details: Optional(str)
460 :param max_file_bytes: Only return file content under this file size bytes
461 :type max_file_bytes: Optional(int)
462 :param cache: Use internal caches for fetching files. If disabled fetching
463 files is slower but more memory efficient
464 :type cache: Optional(bool)
465 Example output:
466
467 .. code-block:: bash
468
469 id : <id_given_in_input>
470 result: {
471 "binary": false,
472 "extension": "py",
473 "lines": 35,
474 "content": "....",
475 "md5": "76318336366b0f17ee249e11b0c99c41",
476 "mimetype": "text/x-python",
477 "name": "python.py",
478 "size": 817,
479 "type": "file",
480 }
481 error: null
482
483
484 get_repo_fts_tree
485 -----------------
486
487 .. py:function:: get_repo_fts_tree(apiuser, repoid, commit_id, root_path)
488
489 Returns a list of tree nodes for path at given revision. This api is built
490 strictly for usage in full text search building, and shouldn't be consumed
491
492 This command can only be run using an |authtoken| with admin rights,
493 or users with at least read rights to |repos|.
494
495
397 get_repo_nodes
496 get_repo_nodes
398 --------------
497 --------------
399
498
@@ -419,8 +518,8 b' get_repo_nodes'
419 ``all`` (default), ``files`` and ``dirs``.
518 ``all`` (default), ``files`` and ``dirs``.
420 :type ret_type: Optional(str)
519 :type ret_type: Optional(str)
421 :param details: Returns extended information about nodes, such as
520 :param details: Returns extended information about nodes, such as
422 md5, binary, and or content. The valid options are ``basic`` and
521 md5, binary, and or content.
423 ``full``.
522 The valid options are ``basic`` and ``full``.
424 :type details: Optional(str)
523 :type details: Optional(str)
425 :param max_file_bytes: Only return file content under this file size bytes
524 :param max_file_bytes: Only return file content under this file size bytes
426 :type details: Optional(int)
525 :type details: Optional(int)
@@ -432,10 +531,17 b' get_repo_nodes'
432 id : <id_given_in_input>
531 id : <id_given_in_input>
433 result: [
532 result: [
434 {
533 {
435 "name" : "<name>"
534 "binary": false,
436 "type" : "<type>",
535 "content": "File line
437 "binary": "<true|false>" (only in extended mode)
536 Line2
438 "md5" : "<md5 of file content>" (only in extended mode)
537 ",
538 "extension": "md",
539 "lines": 2,
540 "md5": "059fa5d29b19c0657e384749480f6422",
541 "mimetype": "text/x-minidsrc",
542 "name": "file.md",
543 "size": 580,
544 "type": "file"
439 },
545 },
440 ...
546 ...
441 ]
547 ]
@@ -103,7 +103,7 b' get_method'
103 :param apiuser: This is filled automatically from the |authtoken|.
103 :param apiuser: This is filled automatically from the |authtoken|.
104 :type apiuser: AuthUser
104 :type apiuser: AuthUser
105 :param pattern: pattern to match method names against
105 :param pattern: pattern to match method names against
106 :type older_then: Optional("*")
106 :type pattern: Optional("*")
107
107
108 Example output:
108 Example output:
109
109
@@ -232,3 +232,37 b' rescan_repos'
232 }
232 }
233
233
234
234
235 store_exception
236 ---------------
237
238 .. py:function:: store_exception(apiuser, exc_data_json, prefix=<Optional:'rhodecode'>)
239
240 Stores sent exception inside the built-in exception tracker in |RCE| server.
241
242 This command can only be run using an |authtoken| with admin rights to
243 the specified repository.
244
245 This command takes the following options:
246
247 :param apiuser: This is filled automatically from the |authtoken|.
248 :type apiuser: AuthUser
249
250 :param exc_data_json: JSON data with exception e.g
251 {"exc_traceback": "Value `1` is not allowed", "exc_type_name": "ValueError"}
252 :type exc_data_json: JSON data
253
254 :param prefix: prefix for error type, e.g 'rhodecode', 'vcsserver', 'rhodecode-tools'
255 :type prefix: Optional("rhodecode")
256
257 Example output:
258
259 .. code-block:: bash
260
261 id : <id_given_in_input>
262 "result": {
263 "exc_id": 139718459226384,
264 "exc_url": "http://localhost:8080/_admin/settings/exceptions/139718459226384"
265 }
266 error : null
267
268
@@ -15,4 +15,5 b' Please check for reference two example p'
15
15
16 auth-saml-duosecurity
16 auth-saml-duosecurity
17 auth-saml-onelogin
17 auth-saml-onelogin
18 auth-saml-bulk-enroll-users
18
19
@@ -73,6 +73,10 b' 2. Enable the SSH module on instance.'
73 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
73 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
74 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
74 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
75
75
76 ## Enables SSH key generator web interface. Disabling this still allows users
77 ## to add their own keys.
78 ssh.enable_ui_key_generator = true
79
76
80
77 3. Set base_url for instance to enable proper event handling (Optional):
81 3. Set base_url for instance to enable proper event handling (Optional):
78
82
@@ -52,6 +52,7 b' run::'
52 Followed by::
52 Followed by::
53
53
54 nix-channel --update
54 nix-channel --update
55 nix-env -i nix-2.0.4
55
56
56
57
57 Install required binaries
58 Install required binaries
@@ -65,6 +66,18 b' run::'
65 nix-env -i nix-prefetch-git
66 nix-env -i nix-prefetch-git
66
67
67
68
69 Speed up JS build by installing PhantomJS
70 -----------------------------------------
71
72 PhantomJS will be downloaded each time nix-shell is invoked. To speed this by
73 setting already downloaded version do this::
74
75 nix-env -i phantomjs-2.1.1
76
77 # and set nix bin path
78 export PATH=$PATH:~/.nix-profile/bin
79
80
68 Clone the required repositories
81 Clone the required repositories
69 -------------------------------
82 -------------------------------
70
83
@@ -76,8 +89,8 b' you have it installed before continuing.'
76 To obtain the required sources, use the following commands::
89 To obtain the required sources, use the following commands::
77
90
78 mkdir rhodecode-develop && cd rhodecode-develop
91 mkdir rhodecode-develop && cd rhodecode-develop
79 hg clone https://code.rhodecode.com/rhodecode-enterprise-ce
92 hg clone -u default https://code.rhodecode.com/rhodecode-enterprise-ce
80 hg clone https://code.rhodecode.com/rhodecode-vcsserver
93 hg clone -u default https://code.rhodecode.com/rhodecode-vcsserver
81
94
82 .. note::
95 .. note::
83
96
@@ -93,11 +106,15 b' need to install the following.'
93
106
94 required libraries::
107 required libraries::
95
108
109 # svn related
96 sudo apt-get install libapr1-dev libaprutil1-dev
110 sudo apt-get install libapr1-dev libaprutil1-dev
97 sudo apt-get install libsvn-dev
111 sudo apt-get install libsvn-dev
112 # libcurl required too
113 sudo apt-get install libcurl4-openssl-dev
114 # mysql/pg server for development, optional
98 sudo apt-get install mysql-server libmysqlclient-dev
115 sudo apt-get install mysql-server libmysqlclient-dev
99 sudo apt-get install postgresql postgresql-contrib libpq-dev
116 sudo apt-get install postgresql postgresql-contrib libpq-dev
100 sudo apt-get install libcurl4-openssl-dev
117
101
118
102
119
103 Enter the Development Shell
120 Enter the Development Shell
@@ -182,7 +199,7 b" To use the application's frontend and pr"
182 you will need to compile the CSS and JavaScript with Grunt.
199 you will need to compile the CSS and JavaScript with Grunt.
183 This is easily done from within the nix-shell using the following command::
200 This is easily done from within the nix-shell using the following command::
184
201
185 grunt
202 make web-build
186
203
187 When developing new features you will need to recompile following any
204 When developing new features you will need to recompile following any
188 changes made to the CSS or JavaScript files when developing the code::
205 changes made to the CSS or JavaScript files when developing the code::
@@ -18,11 +18,11 b' Activating rcextensions'
18 To activate rcextensions simply copy or rename the created template rcextensions
18 To activate rcextensions simply copy or rename the created template rcextensions
19 into the path where the rhodecode.ini file is located::
19 into the path where the rhodecode.ini file is located::
20
20
21 pushd ~/rccontrol/enterprise-1/
21 pushd ~/.rccontrol/enterprise-1/
22 or
22 or
23 pushd ~/rccontrol/community-1/
23 pushd ~/.rccontrol/community-1/
24
24
25 mv etc/rcextensions.tmpl rcextensions
25 mv profile/etc/rcextensions.tmpl rcextensions
26
26
27
27
28 rcextensions are loaded when |RCE| starts. So a restart is required after activation or
28 rcextensions are loaded when |RCE| starts. So a restart is required after activation or
@@ -104,7 +104,7 b' Upgrade notes'
104 - In this release, we're shipping a new `rcextensions`. The changes made are
104 - In this release, we're shipping a new `rcextensions`. The changes made are
105 backward incompatible. An update of `rcextensions` is required
105 backward incompatible. An update of `rcextensions` is required
106 prior to using them again. Please check the new `rcextensions.tmpl` directory
106 prior to using them again. Please check the new `rcextensions.tmpl` directory
107 located in `etc/rcextensions.tmpl` in your instance installation path.
107 located in `profile/etc/rcextensions.tmpl` in your instance installation path.
108 Old code should be 100% portable by just copy&paste to the right function.
108 Old code should be 100% portable by just copy&paste to the right function.
109
109
110 - Mailing: We introduced a new mailing library. The older options should be compatible and
110 - Mailing: We introduced a new mailing library. The older options should be compatible and
@@ -9,6 +9,7 b' Release Notes'
9 .. toctree::
9 .. toctree::
10 :maxdepth: 1
10 :maxdepth: 1
11
11
12 release-notes-4.16.0.rst
12 release-notes-4.15.2.rst
13 release-notes-4.15.2.rst
13 release-notes-4.15.1.rst
14 release-notes-4.15.1.rst
14 release-notes-4.15.0.rst
15 release-notes-4.15.0.rst
@@ -516,7 +516,7 b' Example usage:'
516 $ ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
516 $ ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
517 --instance-name=enterprise-4
517 --instance-name=enterprise-4
518
518
519 # Run indexer based on mapping.ini file
519 # Run indexer based on search_mapping.ini file
520 # This is using pre-350 virtualenv
520 # This is using pre-350 virtualenv
521 (venv)$ rhodecode-index --instance-name=enterprise-1
521 (venv)$ rhodecode-index --instance-name=enterprise-1
522
522
@@ -527,7 +527,7 b' Example usage:'
527
527
528 # Create the indexing mapping file
528 # Create the indexing mapping file
529 $ ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
529 $ ~/.rccontrol/enterprise-4/profile/bin/rhodecode-index \
530 --create-mapping mapping.ini --instance-name=enterprise-4
530 --create-mapping search_mapping.ini --instance-name=enterprise-4
531
531
532 .. _tools-rhodecode-list-instance:
532 .. _tools-rhodecode-list-instance:
533
533
@@ -52,7 +52,7 b''
52 "<%= dirs.js.src %>/plugins/jquery.auto-grow-input.js",
52 "<%= dirs.js.src %>/plugins/jquery.auto-grow-input.js",
53 "<%= dirs.js.src %>/plugins/jquery.autocomplete.js",
53 "<%= dirs.js.src %>/plugins/jquery.autocomplete.js",
54 "<%= dirs.js.src %>/plugins/jquery.debounce.js",
54 "<%= dirs.js.src %>/plugins/jquery.debounce.js",
55 "<%= dirs.js.src %>/plugins/jquery.mark.js",
55 "<%= dirs.js.node_modules %>/mark.js/dist/jquery.mark.min.js",
56 "<%= dirs.js.src %>/plugins/jquery.timeago.js",
56 "<%= dirs.js.src %>/plugins/jquery.timeago.js",
57 "<%= dirs.js.src %>/plugins/jquery.timeago-extension.js",
57 "<%= dirs.js.src %>/plugins/jquery.timeago-extension.js",
58 "<%= dirs.js.src %>/select2/select2.js",
58 "<%= dirs.js.src %>/select2/select2.js",
@@ -22,6 +22,7 b''
22 "grunt-contrib-watch": "^0.6.1",
22 "grunt-contrib-watch": "^0.6.1",
23 "grunt-webpack": "^3.1.3",
23 "grunt-webpack": "^3.1.3",
24 "jquery": "1.11.3",
24 "jquery": "1.11.3",
25 "mark.js": "8.11.1",
25 "jshint": "^2.9.1-rc3",
26 "jshint": "^2.9.1-rc3",
26 "moment": "^2.18.1",
27 "moment": "^2.18.1",
27 "mousetrap": "^1.6.1",
28 "mousetrap": "^1.6.1",
This diff has been collapsed as it changes many lines, (696 lines changed) Show them Hide them
@@ -409,13 +409,13 b' let'
409 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
409 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
410 };
410 };
411 };
411 };
412 "@webcomponents/shadycss-1.6.0" = {
412 "@webcomponents/shadycss-1.7.1" = {
413 name = "_at_webcomponents_slash_shadycss";
413 name = "_at_webcomponents_slash_shadycss";
414 packageName = "@webcomponents/shadycss";
414 packageName = "@webcomponents/shadycss";
415 version = "1.6.0";
415 version = "1.7.1";
416 src = fetchurl {
416 src = fetchurl {
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.6.0.tgz";
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.7.1.tgz";
418 sha512 = "iURGZZU6BaiRJtGgjMn208QxPkY11QwT/VmuHNa4Yb+kJxU/WODe4C8b0LDOtnk4KJzJg50hCfwvPRAjePEzbA==";
418 sha512 = "6SZqLajRPWL0rrKDZOGF8PCBq5B9JqgFmE5rX5psk6i8WrqiMkSCuO8+rnirzViTsU5CqnjQPFC3OvG4YJdMrQ==";
419 };
419 };
420 };
420 };
421 "@webcomponents/webcomponentsjs-2.2.1" = {
421 "@webcomponents/webcomponentsjs-2.2.1" = {
@@ -499,13 +499,13 b' let'
499 sha1 = "82ffb02b29e662ae53bdc20af15947706739c536";
499 sha1 = "82ffb02b29e662ae53bdc20af15947706739c536";
500 };
500 };
501 };
501 };
502 "ajv-6.6.1" = {
502 "ajv-6.6.2" = {
503 name = "ajv";
503 name = "ajv";
504 packageName = "ajv";
504 packageName = "ajv";
505 version = "6.6.1";
505 version = "6.6.2";
506 src = fetchurl {
506 src = fetchurl {
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz";
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz";
508 sha512 = "ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==";
508 sha512 = "FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==";
509 };
509 };
510 };
510 };
511 "ajv-keywords-3.2.0" = {
511 "ajv-keywords-3.2.0" = {
@@ -815,15 +815,6 b' let'
815 sha1 = "b6bbe0b0674b9d719708ca38de8c237cb526c3d1";
815 sha1 = "b6bbe0b0674b9d719708ca38de8c237cb526c3d1";
816 };
816 };
817 };
817 };
818 "async-1.0.0" = {
819 name = "async";
820 packageName = "async";
821 version = "1.0.0";
822 src = fetchurl {
823 url = "https://registry.npmjs.org/async/-/async-1.0.0.tgz";
824 sha1 = "f8fc04ca3a13784ade9e1641af98578cfbd647a9";
825 };
826 };
827 "async-2.6.1" = {
818 "async-2.6.1" = {
828 name = "async";
819 name = "async";
829 packageName = "async";
820 packageName = "async";
@@ -1445,6 +1436,15 b' let'
1445 sha512 = "+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==";
1436 sha512 = "+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==";
1446 };
1437 };
1447 };
1438 };
1439 "big.js-5.2.2" = {
1440 name = "big.js";
1441 packageName = "big.js";
1442 version = "5.2.2";
1443 src = fetchurl {
1444 url = "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz";
1445 sha512 = "vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==";
1446 };
1447 };
1448 "binary-extensions-1.12.0" = {
1448 "binary-extensions-1.12.0" = {
1449 name = "binary-extensions";
1449 name = "binary-extensions";
1450 packageName = "binary-extensions";
1450 packageName = "binary-extensions";
@@ -1679,22 +1679,22 b' let'
1679 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1679 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1680 };
1680 };
1681 };
1681 };
1682 "caniuse-db-1.0.30000912" = {
1682 "caniuse-db-1.0.30000927" = {
1683 name = "caniuse-db";
1683 name = "caniuse-db";
1684 packageName = "caniuse-db";
1684 packageName = "caniuse-db";
1685 version = "1.0.30000912";
1685 version = "1.0.30000927";
1686 src = fetchurl {
1686 src = fetchurl {
1687 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000912.tgz";
1687 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000927.tgz";
1688 sha512 = "uiepPdHcJ06Na9t15L5l+pp3NWQU4IETbmleghD6tqCqbIYqhHSu7nVfbK2gqPjfy+9jl/wHF1UQlyTszh9tJQ==";
1688 sha512 = "CX/QvLA8oh7kQ9cHCCzFm0UZW4KwSyQSRJ5A1XtH42HaMJQ0yh+9fEVWagMqv9I1vSCtaqA5Mb8k0uKfv7jhDw==";
1689 };
1689 };
1690 };
1690 };
1691 "caniuse-lite-1.0.30000912" = {
1691 "caniuse-lite-1.0.30000927" = {
1692 name = "caniuse-lite";
1692 name = "caniuse-lite";
1693 packageName = "caniuse-lite";
1693 packageName = "caniuse-lite";
1694 version = "1.0.30000912";
1694 version = "1.0.30000927";
1695 src = fetchurl {
1695 src = fetchurl {
1696 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000912.tgz";
1696 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000927.tgz";
1697 sha512 = "M3zAtV36U+xw5mMROlTXpAHClmPAor6GPKAMD5Yi7glCB5sbMPFtnQ3rGpk4XqPdUrrTIaVYSJZxREZWNy8QJg==";
1697 sha512 = "ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g==";
1698 };
1698 };
1699 };
1699 };
1700 "caseless-0.12.0" = {
1700 "caseless-0.12.0" = {
@@ -1733,13 +1733,13 b' let'
1733 sha1 = "a8115c55e4a702fe4d150abd3872822a7e09fc98";
1733 sha1 = "a8115c55e4a702fe4d150abd3872822a7e09fc98";
1734 };
1734 };
1735 };
1735 };
1736 "chalk-2.4.1" = {
1736 "chalk-2.4.2" = {
1737 name = "chalk";
1737 name = "chalk";
1738 packageName = "chalk";
1738 packageName = "chalk";
1739 version = "2.4.1";
1739 version = "2.4.2";
1740 src = fetchurl {
1740 src = fetchurl {
1741 url = "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz";
1741 url = "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz";
1742 sha512 = "ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==";
1742 sha512 = "Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==";
1743 };
1743 };
1744 };
1744 };
1745 "chokidar-2.0.4" = {
1745 "chokidar-2.0.4" = {
@@ -1958,15 +1958,6 b' let'
1958 sha1 = "2423fe6678ac0c5dae8852e5d0e5be08c997abcc";
1958 sha1 = "2423fe6678ac0c5dae8852e5d0e5be08c997abcc";
1959 };
1959 };
1960 };
1960 };
1961 "colors-1.0.3" = {
1962 name = "colors";
1963 packageName = "colors";
1964 version = "1.0.3";
1965 src = fetchurl {
1966 url = "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz";
1967 sha1 = "0433f44d809680fdeb60ed260f1b0c262e82a40b";
1968 };
1969 };
1970 "colors-1.1.2" = {
1961 "colors-1.1.2" = {
1971 name = "colors";
1962 name = "colors";
1972 packageName = "colors";
1963 packageName = "colors";
@@ -1976,13 +1967,13 b' let'
1976 sha1 = "168a4701756b6a7f51a12ce0c97bfa28c084ed63";
1967 sha1 = "168a4701756b6a7f51a12ce0c97bfa28c084ed63";
1977 };
1968 };
1978 };
1969 };
1979 "colors-1.3.2" = {
1970 "colors-1.3.3" = {
1980 name = "colors";
1971 name = "colors";
1981 packageName = "colors";
1972 packageName = "colors";
1982 version = "1.3.2";
1973 version = "1.3.3";
1983 src = fetchurl {
1974 src = fetchurl {
1984 url = "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz";
1975 url = "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz";
1985 sha512 = "rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==";
1976 sha512 = "mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==";
1986 };
1977 };
1987 };
1978 };
1988 "combined-stream-1.0.7" = {
1979 "combined-stream-1.0.7" = {
@@ -2102,13 +2093,13 b' let'
2102 sha512 = "Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==";
2093 sha512 = "Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==";
2103 };
2094 };
2104 };
2095 };
2105 "core-js-2.5.7" = {
2096 "core-js-2.6.1" = {
2106 name = "core-js";
2097 name = "core-js";
2107 packageName = "core-js";
2098 packageName = "core-js";
2108 version = "2.5.7";
2099 version = "2.6.1";
2109 src = fetchurl {
2100 src = fetchurl {
2110 url = "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz";
2101 url = "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz";
2111 sha512 = "RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==";
2102 sha512 = "L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==";
2112 };
2103 };
2113 };
2104 };
2114 "core-util-is-1.0.2" = {
2105 "core-util-is-1.0.2" = {
@@ -2246,15 +2237,6 b' let'
2246 sha1 = "ddd52c587033f49e94b71fc55569f252e8ff5f85";
2237 sha1 = "ddd52c587033f49e94b71fc55569f252e8ff5f85";
2247 };
2238 };
2248 };
2239 };
2249 "cycle-1.0.3" = {
2250 name = "cycle";
2251 packageName = "cycle";
2252 version = "1.0.3";
2253 src = fetchurl {
2254 url = "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz";
2255 sha1 = "21e80b2be8580f98b468f379430662b046c34ad2";
2256 };
2257 };
2258 "cyclist-0.2.2" = {
2240 "cyclist-0.2.2" = {
2259 name = "cyclist";
2241 name = "cyclist";
2260 packageName = "cyclist";
2242 packageName = "cyclist";
@@ -2489,13 +2471,13 b' let'
2489 sha1 = "bd28773e2642881aec51544924299c5cd822185b";
2471 sha1 = "bd28773e2642881aec51544924299c5cd822185b";
2490 };
2472 };
2491 };
2473 };
2492 "domelementtype-1.3.0" = {
2474 "domelementtype-1.3.1" = {
2493 name = "domelementtype";
2475 name = "domelementtype";
2494 packageName = "domelementtype";
2476 packageName = "domelementtype";
2495 version = "1.3.0";
2477 version = "1.3.1";
2496 src = fetchurl {
2478 src = fetchurl {
2497 url = "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz";
2479 url = "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz";
2498 sha1 = "b17aed82e8ab59e52dd9c19b1756e0fc187204c2";
2480 sha512 = "BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==";
2499 };
2481 };
2500 };
2482 };
2501 "domhandler-2.1.0" = {
2483 "domhandler-2.1.0" = {
@@ -2552,13 +2534,13 b' let'
2552 sha1 = "3a83a904e54353287874c564b7549386849a98c9";
2534 sha1 = "3a83a904e54353287874c564b7549386849a98c9";
2553 };
2535 };
2554 };
2536 };
2555 "electron-to-chromium-1.3.85" = {
2537 "electron-to-chromium-1.3.98" = {
2556 name = "electron-to-chromium";
2538 name = "electron-to-chromium";
2557 packageName = "electron-to-chromium";
2539 packageName = "electron-to-chromium";
2558 version = "1.3.85";
2540 version = "1.3.98";
2559 src = fetchurl {
2541 src = fetchurl {
2560 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.85.tgz";
2542 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.98.tgz";
2561 sha512 = "kWSDVVF9t3mft2OHVZy4K85X2beP6c6mFm3teFS/mLSDJpQwuFIWHrULCX+w6H1E55ZYmFRlT+ATAFRwhrYzsw==";
2543 sha512 = "WIZdNuvE3dFr6kkPgv4d/cfswNZD6XbeLBM8baOIQTsnbf4xWrVEaLvp7oNnbnMWWXDqq7Tbv+H5JfciLTJm4Q==";
2562 };
2544 };
2563 };
2545 };
2564 "elliptic-6.4.1" = {
2546 "elliptic-6.4.1" = {
@@ -2633,13 +2615,13 b' let'
2633 sha512 = "MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==";
2615 sha512 = "MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==";
2634 };
2616 };
2635 };
2617 };
2636 "es-abstract-1.12.0" = {
2618 "es-abstract-1.13.0" = {
2637 name = "es-abstract";
2619 name = "es-abstract";
2638 packageName = "es-abstract";
2620 packageName = "es-abstract";
2639 version = "1.12.0";
2621 version = "1.13.0";
2640 src = fetchurl {
2622 src = fetchurl {
2641 url = "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz";
2623 url = "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz";
2642 sha512 = "C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==";
2624 sha512 = "vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==";
2643 };
2625 };
2644 };
2626 };
2645 "es-to-primitive-1.2.0" = {
2627 "es-to-primitive-1.2.0" = {
@@ -2651,15 +2633,6 b' let'
2651 sha512 = "qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==";
2633 sha512 = "qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==";
2652 };
2634 };
2653 };
2635 };
2654 "es6-promise-4.2.5" = {
2655 name = "es6-promise";
2656 packageName = "es6-promise";
2657 version = "4.2.5";
2658 src = fetchurl {
2659 url = "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz";
2660 sha512 = "n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==";
2661 };
2662 };
2663 "es6-templates-0.2.3" = {
2636 "es6-templates-0.2.3" = {
2664 name = "es6-templates";
2637 name = "es6-templates";
2665 packageName = "es6-templates";
2638 packageName = "es6-templates";
@@ -2777,13 +2750,13 b' let'
2777 sha512 = "/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==";
2750 sha512 = "/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==";
2778 };
2751 };
2779 };
2752 };
2780 "execa-0.10.0" = {
2753 "execa-1.0.0" = {
2781 name = "execa";
2754 name = "execa";
2782 packageName = "execa";
2755 packageName = "execa";
2783 version = "0.10.0";
2756 version = "1.0.0";
2784 src = fetchurl {
2757 src = fetchurl {
2785 url = "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz";
2758 url = "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz";
2786 sha512 = "7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==";
2759 sha512 = "adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==";
2787 };
2760 };
2788 };
2761 };
2789 "exit-0.1.2" = {
2762 "exit-0.1.2" = {
@@ -2858,15 +2831,6 b' let'
2858 sha512 = "Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==";
2831 sha512 = "Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==";
2859 };
2832 };
2860 };
2833 };
2861 "extract-zip-1.6.7" = {
2862 name = "extract-zip";
2863 packageName = "extract-zip";
2864 version = "1.6.7";
2865 src = fetchurl {
2866 url = "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz";
2867 sha1 = "a840b4b8af6403264c8db57f4f1a74333ef81fe9";
2868 };
2869 };
2870 "extsprintf-1.3.0" = {
2834 "extsprintf-1.3.0" = {
2871 name = "extsprintf";
2835 name = "extsprintf";
2872 packageName = "extsprintf";
2836 packageName = "extsprintf";
@@ -2876,15 +2840,6 b' let'
2876 sha1 = "96918440e3041a7a414f8c52e3c574eb3c3e1e05";
2840 sha1 = "96918440e3041a7a414f8c52e3c574eb3c3e1e05";
2877 };
2841 };
2878 };
2842 };
2879 "eyes-0.1.8" = {
2880 name = "eyes";
2881 packageName = "eyes";
2882 version = "0.1.8";
2883 src = fetchurl {
2884 url = "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz";
2885 sha1 = "62cf120234c683785d902348a800ef3e0cc20bc0";
2886 };
2887 };
2888 "fast-deep-equal-2.0.1" = {
2843 "fast-deep-equal-2.0.1" = {
2889 name = "fast-deep-equal";
2844 name = "fast-deep-equal";
2890 packageName = "fast-deep-equal";
2845 packageName = "fast-deep-equal";
@@ -2930,15 +2885,6 b' let'
2930 sha1 = "c14c5b3bf14d7417ffbfd990c0a7495cd9f337bc";
2885 sha1 = "c14c5b3bf14d7417ffbfd990c0a7495cd9f337bc";
2931 };
2886 };
2932 };
2887 };
2933 "fd-slicer-1.0.1" = {
2934 name = "fd-slicer";
2935 packageName = "fd-slicer";
2936 version = "1.0.1";
2937 src = fetchurl {
2938 url = "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz";
2939 sha1 = "8b5bcbd9ec327c5041bf9ab023fd6750f1177e65";
2940 };
2941 };
2942 "file-sync-cmp-0.1.1" = {
2888 "file-sync-cmp-0.1.1" = {
2943 name = "file-sync-cmp";
2889 name = "file-sync-cmp";
2944 packageName = "file-sync-cmp";
2890 packageName = "file-sync-cmp";
@@ -3002,22 +2948,22 b' let'
3002 sha1 = "9326b1488c22d1a6088650a86901b2d9a90a2cbc";
2948 sha1 = "9326b1488c22d1a6088650a86901b2d9a90a2cbc";
3003 };
2949 };
3004 };
2950 };
3005 "fined-1.1.0" = {
2951 "fined-1.1.1" = {
3006 name = "fined";
2952 name = "fined";
3007 packageName = "fined";
2953 packageName = "fined";
3008 version = "1.1.0";
2954 version = "1.1.1";
3009 src = fetchurl {
2955 src = fetchurl {
3010 url = "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz";
2956 url = "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz";
3011 sha1 = "b37dc844b76a2f5e7081e884f7c0ae344f153476";
2957 sha512 = "jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==";
3012 };
2958 };
3013 };
2959 };
3014 "flagged-respawn-1.0.0" = {
2960 "flagged-respawn-1.0.1" = {
3015 name = "flagged-respawn";
2961 name = "flagged-respawn";
3016 packageName = "flagged-respawn";
2962 packageName = "flagged-respawn";
3017 version = "1.0.0";
2963 version = "1.0.1";
3018 src = fetchurl {
2964 src = fetchurl {
3019 url = "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz";
2965 url = "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz";
3020 sha1 = "4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7";
2966 sha512 = "lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==";
3021 };
2967 };
3022 };
2968 };
3023 "flatten-1.0.2" = {
2969 "flatten-1.0.2" = {
@@ -3092,15 +3038,6 b' let'
3092 sha1 = "8bfb5502bde4a4d36cfdeea007fcca21d7e382af";
3038 sha1 = "8bfb5502bde4a4d36cfdeea007fcca21d7e382af";
3093 };
3039 };
3094 };
3040 };
3095 "fs-extra-1.0.0" = {
3096 name = "fs-extra";
3097 packageName = "fs-extra";
3098 version = "1.0.0";
3099 src = fetchurl {
3100 url = "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz";
3101 sha1 = "cd3ce5f7e7cb6145883fcae3191e9877f8587950";
3102 };
3103 };
3104 "fs-write-stream-atomic-1.0.10" = {
3041 "fs-write-stream-atomic-1.0.10" = {
3105 name = "fs-write-stream-atomic";
3042 name = "fs-write-stream-atomic";
3106 packageName = "fs-write-stream-atomic";
3043 packageName = "fs-write-stream-atomic";
@@ -3155,13 +3092,13 b' let'
3155 sha512 = "3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==";
3092 sha512 = "3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==";
3156 };
3093 };
3157 };
3094 };
3158 "get-stream-3.0.0" = {
3095 "get-stream-4.1.0" = {
3159 name = "get-stream";
3096 name = "get-stream";
3160 packageName = "get-stream";
3097 packageName = "get-stream";
3161 version = "3.0.0";
3098 version = "4.1.0";
3162 src = fetchurl {
3099 src = fetchurl {
3163 url = "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz";
3100 url = "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz";
3164 sha1 = "8e943d1358dc37555054ecbe2edb05aa174ede14";
3101 sha512 = "GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==";
3165 };
3102 };
3166 };
3103 };
3167 "get-value-2.0.6" = {
3104 "get-value-2.0.6" = {
@@ -3236,13 +3173,13 b' let'
3236 sha512 = "sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==";
3173 sha512 = "sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==";
3237 };
3174 };
3238 };
3175 };
3239 "global-modules-path-2.3.0" = {
3176 "global-modules-path-2.3.1" = {
3240 name = "global-modules-path";
3177 name = "global-modules-path";
3241 packageName = "global-modules-path";
3178 packageName = "global-modules-path";
3242 version = "2.3.0";
3179 version = "2.3.1";
3243 src = fetchurl {
3180 src = fetchurl {
3244 url = "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz";
3181 url = "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.1.tgz";
3245 sha512 = "HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==";
3182 sha512 = "y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==";
3246 };
3183 };
3247 };
3184 };
3248 "global-prefix-1.0.2" = {
3185 "global-prefix-1.0.2" = {
@@ -3533,22 +3470,13 b' let'
3533 sha1 = "5fc8686847ecd73499403319a6b0a3f3f6ae4918";
3470 sha1 = "5fc8686847ecd73499403319a6b0a3f3f6ae4918";
3534 };
3471 };
3535 };
3472 };
3536 "hash.js-1.1.5" = {
3473 "hash.js-1.1.7" = {
3537 name = "hash.js";
3474 name = "hash.js";
3538 packageName = "hash.js";
3475 packageName = "hash.js";
3539 version = "1.1.5";
3476 version = "1.1.7";
3540 src = fetchurl {
3477 src = fetchurl {
3541 url = "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz";
3478 url = "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz";
3542 sha512 = "eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==";
3479 sha512 = "taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==";
3543 };
3544 };
3545 "hasha-2.2.0" = {
3546 name = "hasha";
3547 packageName = "hasha";
3548 version = "2.2.0";
3549 src = fetchurl {
3550 url = "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz";
3551 sha1 = "78d7cbfc1e6d66303fe79837365984517b2f6ee1";
3552 };
3480 };
3553 };
3481 };
3554 "hawk-3.1.3" = {
3482 "hawk-3.1.3" = {
@@ -4217,13 +4145,13 b' let'
4217 sha1 = "dd8b74278b27102d29df63eae28308a8cfa1b583";
4145 sha1 = "dd8b74278b27102d29df63eae28308a8cfa1b583";
4218 };
4146 };
4219 };
4147 };
4220 "js-base64-2.4.9" = {
4148 "js-base64-2.5.0" = {
4221 name = "js-base64";
4149 name = "js-base64";
4222 packageName = "js-base64";
4150 packageName = "js-base64";
4223 version = "2.4.9";
4151 version = "2.5.0";
4224 src = fetchurl {
4152 src = fetchurl {
4225 url = "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz";
4153 url = "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz";
4226 sha512 = "xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==";
4154 sha512 = "wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==";
4227 };
4155 };
4228 };
4156 };
4229 "js-tokens-3.0.2" = {
4157 "js-tokens-3.0.2" = {
@@ -4280,13 +4208,13 b' let'
4280 sha1 = "46c3fec8c1892b12b0833db9bc7622176dbab34b";
4208 sha1 = "46c3fec8c1892b12b0833db9bc7622176dbab34b";
4281 };
4209 };
4282 };
4210 };
4283 "jshint-2.9.6" = {
4211 "jshint-2.9.7" = {
4284 name = "jshint";
4212 name = "jshint";
4285 packageName = "jshint";
4213 packageName = "jshint";
4286 version = "2.9.6";
4214 version = "2.9.7";
4287 src = fetchurl {
4215 src = fetchurl {
4288 url = "https://registry.npmjs.org/jshint/-/jshint-2.9.6.tgz";
4216 url = "https://registry.npmjs.org/jshint/-/jshint-2.9.7.tgz";
4289 sha512 = "KO9SIAKTlJQOM4lE64GQUtGBRpTOuvbrRrSZw3AhUxMNG266nX9hK2cKA4SBhXOj0irJGyNyGSLT62HGOVDEOA==";
4217 sha512 = "Q8XN38hGsVQhdlM+4gd1Xl7OB1VieSuCJf+fEJjpo59JH99bVJhXRXAh26qQ15wfdd1VPMuDWNeSWoNl53T4YA==";
4290 };
4218 };
4291 };
4219 };
4292 "json-parse-better-errors-1.0.2" = {
4220 "json-parse-better-errors-1.0.2" = {
@@ -4343,13 +4271,13 b' let'
4343 sha1 = "1eade7acc012034ad84e2396767ead9fa5495821";
4271 sha1 = "1eade7acc012034ad84e2396767ead9fa5495821";
4344 };
4272 };
4345 };
4273 };
4346 "jsonfile-2.4.0" = {
4274 "json5-1.0.1" = {
4347 name = "jsonfile";
4275 name = "json5";
4348 packageName = "jsonfile";
4276 packageName = "json5";
4349 version = "2.4.0";
4277 version = "1.0.1";
4350 src = fetchurl {
4278 src = fetchurl {
4351 url = "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz";
4279 url = "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz";
4352 sha1 = "3736a2b428b87bbda0cc83b53fa3d633a35c2ae8";
4280 sha512 = "aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==";
4353 };
4281 };
4354 };
4282 };
4355 "jsonify-0.0.0" = {
4283 "jsonify-0.0.0" = {
@@ -4370,15 +4298,6 b' let'
4370 sha1 = "313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2";
4298 sha1 = "313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2";
4371 };
4299 };
4372 };
4300 };
4373 "kew-0.7.0" = {
4374 name = "kew";
4375 packageName = "kew";
4376 version = "0.7.0";
4377 src = fetchurl {
4378 url = "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz";
4379 sha1 = "79d93d2d33363d6fdd2970b335d9141ad591d79b";
4380 };
4381 };
4382 "kind-of-3.2.2" = {
4301 "kind-of-3.2.2" = {
4383 name = "kind-of";
4302 name = "kind-of";
4384 packageName = "kind-of";
4303 packageName = "kind-of";
@@ -4415,15 +4334,6 b' let'
4415 sha512 = "s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==";
4334 sha512 = "s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==";
4416 };
4335 };
4417 };
4336 };
4418 "klaw-1.3.1" = {
4419 name = "klaw";
4420 packageName = "klaw";
4421 version = "1.3.1";
4422 src = fetchurl {
4423 url = "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz";
4424 sha1 = "4088433b46b3b1ba259d78785d8e96f73ba02439";
4425 };
4426 };
4427 "lazy-cache-1.0.4" = {
4337 "lazy-cache-1.0.4" = {
4428 name = "lazy-cache";
4338 name = "lazy-cache";
4429 packageName = "lazy-cache";
4339 packageName = "lazy-cache";
@@ -4478,13 +4388,13 b' let'
4478 sha1 = "f86e6374d43205a6e6c60e9196f17c0299bfb348";
4388 sha1 = "f86e6374d43205a6e6c60e9196f17c0299bfb348";
4479 };
4389 };
4480 };
4390 };
4481 "loader-utils-1.1.0" = {
4391 "loader-utils-1.2.3" = {
4482 name = "loader-utils";
4392 name = "loader-utils";
4483 packageName = "loader-utils";
4393 packageName = "loader-utils";
4484 version = "1.1.0";
4394 version = "1.2.3";
4485 src = fetchurl {
4395 src = fetchurl {
4486 url = "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz";
4396 url = "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz";
4487 sha1 = "c98aef488bcceda2ffb5e2de646d6a754429f5cd";
4397 sha512 = "fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==";
4488 };
4398 };
4489 };
4399 };
4490 "locate-path-2.0.0" = {
4400 "locate-path-2.0.0" = {
@@ -4676,6 +4586,15 b' let'
4676 sha1 = "ecdca8f13144e660f1b5bd41f12f3479d98dfb8f";
4586 sha1 = "ecdca8f13144e660f1b5bd41f12f3479d98dfb8f";
4677 };
4587 };
4678 };
4588 };
4589 "mark.js-8.11.1" = {
4590 name = "mark.js";
4591 packageName = "mark.js";
4592 version = "8.11.1";
4593 src = fetchurl {
4594 url = "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz";
4595 sha1 = "180f1f9ebef8b0e638e4166ad52db879beb2ffc5";
4596 };
4597 };
4679 "math-expression-evaluator-1.2.17" = {
4598 "math-expression-evaluator-1.2.17" = {
4680 name = "math-expression-evaluator";
4599 name = "math-expression-evaluator";
4681 packageName = "math-expression-evaluator";
4600 packageName = "math-expression-evaluator";
@@ -4820,6 +4739,15 b' let'
4820 sha1 = "857fcabfc3397d2625b8228262e86aa7a011b05d";
4739 sha1 = "857fcabfc3397d2625b8228262e86aa7a011b05d";
4821 };
4740 };
4822 };
4741 };
4742 "minimist-1.2.0" = {
4743 name = "minimist";
4744 packageName = "minimist";
4745 version = "1.2.0";
4746 src = fetchurl {
4747 url = "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz";
4748 sha1 = "a35008b20f41383eec1fb914f4cd5df79a264284";
4749 };
4750 };
4823 "mississippi-2.0.0" = {
4751 "mississippi-2.0.0" = {
4824 name = "mississippi";
4752 name = "mississippi";
4825 packageName = "mississippi";
4753 packageName = "mississippi";
@@ -4847,13 +4775,13 b' let'
4847 sha1 = "30057438eac6cf7f8c4767f38648d6697d75c903";
4775 sha1 = "30057438eac6cf7f8c4767f38648d6697d75c903";
4848 };
4776 };
4849 };
4777 };
4850 "moment-2.22.2" = {
4778 "moment-2.23.0" = {
4851 name = "moment";
4779 name = "moment";
4852 packageName = "moment";
4780 packageName = "moment";
4853 version = "2.22.2";
4781 version = "2.23.0";
4854 src = fetchurl {
4782 src = fetchurl {
4855 url = "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz";
4783 url = "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz";
4856 sha1 = "3c257f9839fc0e93ff53149632239eb90783ff66";
4784 sha512 = "3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==";
4857 };
4785 };
4858 };
4786 };
4859 "mousetrap-1.6.2" = {
4787 "mousetrap-1.6.2" = {
@@ -4883,13 +4811,13 b' let'
4883 sha1 = "5608aeadfc00be6c2901df5f9861788de0d597c8";
4811 sha1 = "5608aeadfc00be6c2901df5f9861788de0d597c8";
4884 };
4812 };
4885 };
4813 };
4886 "nan-2.11.1" = {
4814 "nan-2.12.1" = {
4887 name = "nan";
4815 name = "nan";
4888 packageName = "nan";
4816 packageName = "nan";
4889 version = "2.11.1";
4817 version = "2.12.1";
4890 src = fetchurl {
4818 src = fetchurl {
4891 url = "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz";
4819 url = "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz";
4892 sha512 = "iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==";
4820 sha512 = "JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==";
4893 };
4821 };
4894 };
4822 };
4895 "nanomatch-1.2.13" = {
4823 "nanomatch-1.2.13" = {
@@ -5144,13 +5072,13 b' let'
5144 sha1 = "ffbc4988336e0e833de0c168c7ef152121aa7fb3";
5072 sha1 = "ffbc4988336e0e833de0c168c7ef152121aa7fb3";
5145 };
5073 };
5146 };
5074 };
5147 "os-locale-3.0.1" = {
5075 "os-locale-3.1.0" = {
5148 name = "os-locale";
5076 name = "os-locale";
5149 packageName = "os-locale";
5077 packageName = "os-locale";
5150 version = "3.0.1";
5078 version = "3.1.0";
5151 src = fetchurl {
5079 src = fetchurl {
5152 url = "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz";
5080 url = "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz";
5153 sha512 = "7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==";
5081 sha512 = "Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==";
5154 };
5082 };
5155 };
5083 };
5156 "os-tmpdir-1.0.2" = {
5084 "os-tmpdir-1.0.2" = {
@@ -5207,13 +5135,13 b' let'
5207 sha512 = "vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==";
5135 sha512 = "vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==";
5208 };
5136 };
5209 };
5137 };
5210 "p-limit-2.0.0" = {
5138 "p-limit-2.1.0" = {
5211 name = "p-limit";
5139 name = "p-limit";
5212 packageName = "p-limit";
5140 packageName = "p-limit";
5213 version = "2.0.0";
5141 version = "2.1.0";
5214 src = fetchurl {
5142 src = fetchurl {
5215 url = "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz";
5143 url = "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz";
5216 sha512 = "fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==";
5144 sha512 = "NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==";
5217 };
5145 };
5218 };
5146 };
5219 "p-locate-2.0.0" = {
5147 "p-locate-2.0.0" = {
@@ -5432,15 +5360,6 b' let'
5432 sha512 = "U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==";
5360 sha512 = "U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==";
5433 };
5361 };
5434 };
5362 };
5435 "pend-1.2.0" = {
5436 name = "pend";
5437 packageName = "pend";
5438 version = "1.2.0";
5439 src = fetchurl {
5440 url = "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz";
5441 sha1 = "7a57eb550a6783f9115331fcf4663d5c8e007a50";
5442 };
5443 };
5444 "performance-now-0.2.0" = {
5363 "performance-now-0.2.0" = {
5445 name = "performance-now";
5364 name = "performance-now";
5446 packageName = "performance-now";
5365 packageName = "performance-now";
@@ -5450,24 +5369,6 b' let'
5450 sha1 = "33ef30c5c77d4ea21c5a53869d91b56d8f2555e5";
5369 sha1 = "33ef30c5c77d4ea21c5a53869d91b56d8f2555e5";
5451 };
5370 };
5452 };
5371 };
5453 "phantom-4.0.12" = {
5454 name = "phantom";
5455 packageName = "phantom";
5456 version = "4.0.12";
5457 src = fetchurl {
5458 url = "https://registry.npmjs.org/phantom/-/phantom-4.0.12.tgz";
5459 sha512 = "Tz82XhtPmwCk1FFPmecy7yRGZG2btpzY2KI9fcoPT7zT9det0CcMyfBFPp1S8DqzsnQnm8ZYEfdy528mwVtksA==";
5460 };
5461 };
5462 "phantomjs-prebuilt-2.1.16" = {
5463 name = "phantomjs-prebuilt";
5464 packageName = "phantomjs-prebuilt";
5465 version = "2.1.16";
5466 src = fetchurl {
5467 url = "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz";
5468 sha1 = "efd212a4a3966d3647684ea8ba788549be2aefef";
5469 };
5470 };
5471 "pify-3.0.0" = {
5372 "pify-3.0.0" = {
5472 name = "pify";
5373 name = "pify";
5473 packageName = "pify";
5374 packageName = "pify";
@@ -5477,24 +5378,6 b' let'
5477 sha1 = "e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176";
5378 sha1 = "e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176";
5478 };
5379 };
5479 };
5380 };
5480 "pinkie-2.0.4" = {
5481 name = "pinkie";
5482 packageName = "pinkie";
5483 version = "2.0.4";
5484 src = fetchurl {
5485 url = "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz";
5486 sha1 = "72556b80cfa0d48a974e80e77248e80ed4f7f870";
5487 };
5488 };
5489 "pinkie-promise-2.0.1" = {
5490 name = "pinkie-promise";
5491 packageName = "pinkie-promise";
5492 version = "2.0.1";
5493 src = fetchurl {
5494 url = "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz";
5495 sha1 = "2135d6dfa7a358c069ac9b178776288228450ffa";
5496 };
5497 };
5498 "pkg-dir-2.0.0" = {
5381 "pkg-dir-2.0.0" = {
5499 name = "pkg-dir";
5382 name = "pkg-dir";
5500 packageName = "pkg-dir";
5383 packageName = "pkg-dir";
@@ -5882,15 +5765,6 b' let'
5882 sha512 = "MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==";
5765 sha512 = "MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==";
5883 };
5766 };
5884 };
5767 };
5885 "progress-1.1.8" = {
5886 name = "progress";
5887 packageName = "progress";
5888 version = "1.1.8";
5889 src = fetchurl {
5890 url = "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz";
5891 sha1 = "e260c78f6161cdd9b0e56cc3e0a85de17c7a57be";
5892 };
5893 };
5894 "promise-7.3.1" = {
5768 "promise-7.3.1" = {
5895 name = "promise";
5769 name = "promise";
5896 packageName = "promise";
5770 packageName = "promise";
@@ -5945,6 +5819,15 b' let'
5945 sha512 = "ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==";
5819 sha512 = "ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==";
5946 };
5820 };
5947 };
5821 };
5822 "pump-3.0.0" = {
5823 name = "pump";
5824 packageName = "pump";
5825 version = "3.0.0";
5826 src = fetchurl {
5827 url = "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz";
5828 sha512 = "LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==";
5829 };
5830 };
5948 "pumpify-1.5.1" = {
5831 "pumpify-1.5.1" = {
5949 name = "pumpify";
5832 name = "pumpify";
5950 packageName = "pumpify";
5833 packageName = "pumpify";
@@ -6278,15 +6161,6 b' let'
6278 sha1 = "c6928946a0e06c5f8d6f8a9333469ffda46298a0";
6161 sha1 = "c6928946a0e06c5f8d6f8a9333469ffda46298a0";
6279 };
6162 };
6280 };
6163 };
6281 "request-progress-2.0.1" = {
6282 name = "request-progress";
6283 packageName = "request-progress";
6284 version = "2.0.1";
6285 src = fetchurl {
6286 url = "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz";
6287 sha1 = "5d36bb57961c673aa5b788dbc8141fdf23b44e08";
6288 };
6289 };
6290 "require-directory-2.1.1" = {
6164 "require-directory-2.1.1" = {
6291 name = "require-directory";
6165 name = "require-directory";
6292 packageName = "require-directory";
6166 packageName = "require-directory";
@@ -6305,13 +6179,13 b' let'
6305 sha1 = "97f717b69d48784f5f526a6c5aa8ffdda055a4d1";
6179 sha1 = "97f717b69d48784f5f526a6c5aa8ffdda055a4d1";
6306 };
6180 };
6307 };
6181 };
6308 "resolve-1.8.1" = {
6182 "resolve-1.9.0" = {
6309 name = "resolve";
6183 name = "resolve";
6310 packageName = "resolve";
6184 packageName = "resolve";
6311 version = "1.8.1";
6185 version = "1.9.0";
6312 src = fetchurl {
6186 src = fetchurl {
6313 url = "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz";
6187 url = "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz";
6314 sha512 = "AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==";
6188 sha512 = "TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==";
6315 };
6189 };
6316 };
6190 };
6317 "resolve-cwd-2.0.0" = {
6191 "resolve-cwd-2.0.0" = {
@@ -6377,13 +6251,13 b' let'
6377 sha1 = "e439be2aaee327321952730f99a8929e4fc50582";
6251 sha1 = "e439be2aaee327321952730f99a8929e4fc50582";
6378 };
6252 };
6379 };
6253 };
6380 "rimraf-2.6.2" = {
6254 "rimraf-2.6.3" = {
6381 name = "rimraf";
6255 name = "rimraf";
6382 packageName = "rimraf";
6256 packageName = "rimraf";
6383 version = "2.6.2";
6257 version = "2.6.3";
6384 src = fetchurl {
6258 src = fetchurl {
6385 url = "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz";
6259 url = "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz";
6386 sha512 = "lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==";
6260 sha512 = "mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==";
6387 };
6261 };
6388 };
6262 };
6389 "ripemd160-2.0.2" = {
6263 "ripemd160-2.0.2" = {
@@ -6467,13 +6341,13 b' let'
6467 sha512 = "RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==";
6341 sha512 = "RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==";
6468 };
6342 };
6469 };
6343 };
6470 "serialize-javascript-1.5.0" = {
6344 "serialize-javascript-1.6.1" = {
6471 name = "serialize-javascript";
6345 name = "serialize-javascript";
6472 packageName = "serialize-javascript";
6346 packageName = "serialize-javascript";
6473 version = "1.5.0";
6347 version = "1.6.1";
6474 src = fetchurl {
6348 src = fetchurl {
6475 url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz";
6349 url = "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz";
6476 sha512 = "Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==";
6350 sha512 = "A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==";
6477 };
6351 };
6478 };
6352 };
6479 "set-blocking-2.0.0" = {
6353 "set-blocking-2.0.0" = {
@@ -6701,15 +6575,6 b' let'
6701 sha1 = "3e935d7ddd73631b97659956d55128e87b5084a3";
6575 sha1 = "3e935d7ddd73631b97659956d55128e87b5084a3";
6702 };
6576 };
6703 };
6577 };
6704 "split-1.0.1" = {
6705 name = "split";
6706 packageName = "split";
6707 version = "1.0.1";
6708 src = fetchurl {
6709 url = "https://registry.npmjs.org/split/-/split-1.0.1.tgz";
6710 sha512 = "mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==";
6711 };
6712 };
6713 "split-string-3.1.0" = {
6578 "split-string-3.1.0" = {
6714 name = "split-string";
6579 name = "split-string";
6715 packageName = "split-string";
6580 packageName = "split-string";
@@ -6728,13 +6593,13 b' let'
6728 sha1 = "04e6926f662895354f3dd015203633b857297e2c";
6593 sha1 = "04e6926f662895354f3dd015203633b857297e2c";
6729 };
6594 };
6730 };
6595 };
6731 "sshpk-1.15.2" = {
6596 "sshpk-1.16.0" = {
6732 name = "sshpk";
6597 name = "sshpk";
6733 packageName = "sshpk";
6598 packageName = "sshpk";
6734 version = "1.15.2";
6599 version = "1.16.0";
6735 src = fetchurl {
6600 src = fetchurl {
6736 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz";
6601 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz";
6737 sha512 = "Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==";
6602 sha512 = "Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==";
6738 };
6603 };
6739 };
6604 };
6740 "ssri-5.3.0" = {
6605 "ssri-5.3.0" = {
@@ -6746,15 +6611,6 b' let'
6746 sha512 = "XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==";
6611 sha512 = "XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==";
6747 };
6612 };
6748 };
6613 };
6749 "stack-trace-0.0.10" = {
6750 name = "stack-trace";
6751 packageName = "stack-trace";
6752 version = "0.0.10";
6753 src = fetchurl {
6754 url = "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz";
6755 sha1 = "547c70b347e8d32b4e108ea1a2a159e5fdde19c0";
6756 };
6757 };
6758 "static-extend-0.1.2" = {
6614 "static-extend-0.1.2" = {
6759 name = "static-extend";
6615 name = "static-extend";
6760 packageName = "static-extend";
6616 packageName = "static-extend";
@@ -6989,15 +6845,6 b' let'
6989 sha512 = "9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==";
6845 sha512 = "9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==";
6990 };
6846 };
6991 };
6847 };
6992 "throttleit-1.0.0" = {
6993 name = "throttleit";
6994 packageName = "throttleit";
6995 version = "1.0.0";
6996 src = fetchurl {
6997 url = "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz";
6998 sha1 = "9e785836daf46743145a5984b6268d828528ac6c";
6999 };
7000 };
7001 "through-2.3.8" = {
6848 "through-2.3.8" = {
7002 name = "through";
6849 name = "through";
7003 packageName = "through";
6850 packageName = "through";
@@ -7259,15 +7106,6 b' let'
7259 sha1 = "8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b";
7106 sha1 = "8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b";
7260 };
7107 };
7261 };
7108 };
7262 "unicode-5.2.0-0.7.5" = {
7263 name = "unicode-5.2.0";
7264 packageName = "unicode-5.2.0";
7265 version = "0.7.5";
7266 src = fetchurl {
7267 url = "https://registry.npmjs.org/unicode-5.2.0/-/unicode-5.2.0-0.7.5.tgz";
7268 sha512 = "KVGLW1Bri30x00yv4HNM8kBxoqFXr0Sbo55735nvrlsx4PYBZol3UtoWgO492fSwmsetzPEZzy73rbU8OGXJcA==";
7269 };
7270 };
7271 "union-value-1.0.0" = {
7109 "union-value-1.0.0" = {
7272 name = "union-value";
7110 name = "union-value";
7273 packageName = "union-value";
7111 packageName = "union-value";
@@ -7439,13 +7277,13 b' let'
7439 sha512 = "1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==";
7277 sha512 = "1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==";
7440 };
7278 };
7441 };
7279 };
7442 "v8flags-3.1.1" = {
7280 "v8flags-3.1.2" = {
7443 name = "v8flags";
7281 name = "v8flags";
7444 packageName = "v8flags";
7282 packageName = "v8flags";
7445 version = "3.1.1";
7283 version = "3.1.2";
7446 src = fetchurl {
7284 src = fetchurl {
7447 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz";
7285 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz";
7448 sha512 = "iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==";
7286 sha512 = "MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==";
7449 };
7287 };
7450 };
7288 };
7451 "vendors-1.0.2" = {
7289 "vendors-1.0.2" = {
@@ -7583,15 +7421,6 b' let'
7583 sha1 = "5438cd2ea93b202efa3a19fe8887aee7c94f9c9d";
7421 sha1 = "5438cd2ea93b202efa3a19fe8887aee7c94f9c9d";
7584 };
7422 };
7585 };
7423 };
7586 "winston-2.4.4" = {
7587 name = "winston";
7588 packageName = "winston";
7589 version = "2.4.4";
7590 src = fetchurl {
7591 url = "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz";
7592 sha512 = "NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==";
7593 };
7594 };
7595 "wordwrap-0.0.2" = {
7424 "wordwrap-0.0.2" = {
7596 name = "wordwrap";
7425 name = "wordwrap";
7597 packageName = "wordwrap";
7426 packageName = "wordwrap";
@@ -7682,15 +7511,6 b' let'
7682 sha512 = "C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==";
7511 sha512 = "C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==";
7683 };
7512 };
7684 };
7513 };
7685 "yauzl-2.4.1" = {
7686 name = "yauzl";
7687 packageName = "yauzl";
7688 version = "2.4.1";
7689 src = fetchurl {
7690 url = "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz";
7691 sha1 = "9528f442dab1b2284e58b4379bb194e22e0c4005";
7692 };
7693 };
7694 };
7514 };
7695 args = {
7515 args = {
7696 name = "rhodecode-enterprise";
7516 name = "rhodecode-enterprise";
@@ -7743,7 +7563,7 b' let'
7743 sources."@webassemblyjs/wasm-parser-1.7.10"
7563 sources."@webassemblyjs/wasm-parser-1.7.10"
7744 sources."@webassemblyjs/wast-parser-1.7.10"
7564 sources."@webassemblyjs/wast-parser-1.7.10"
7745 sources."@webassemblyjs/wast-printer-1.7.10"
7565 sources."@webassemblyjs/wast-printer-1.7.10"
7746 sources."@webcomponents/shadycss-1.6.0"
7566 sources."@webcomponents/shadycss-1.7.1"
7747 sources."@webcomponents/webcomponentsjs-2.2.1"
7567 sources."@webcomponents/webcomponentsjs-2.2.1"
7748 sources."@xtuc/ieee754-1.2.0"
7568 sources."@xtuc/ieee754-1.2.0"
7749 sources."@xtuc/long-4.2.1"
7569 sources."@xtuc/long-4.2.1"
@@ -7818,6 +7638,7 b' let'
7818 })
7638 })
7819 (sources."babel-core-6.26.3" // {
7639 (sources."babel-core-6.26.3" // {
7820 dependencies = [
7640 dependencies = [
7641 sources."json5-0.5.1"
7821 sources."lodash-4.17.11"
7642 sources."lodash-4.17.11"
7822 sources."minimatch-3.0.4"
7643 sources."minimatch-3.0.4"
7823 ];
7644 ];
@@ -7916,7 +7737,7 b' let'
7916 })
7737 })
7917 sources."base64-js-1.3.0"
7738 sources."base64-js-1.3.0"
7918 sources."bcrypt-pbkdf-1.0.2"
7739 sources."bcrypt-pbkdf-1.0.2"
7919 sources."big.js-3.2.0"
7740 sources."big.js-5.2.2"
7920 sources."binary-extensions-1.12.0"
7741 sources."binary-extensions-1.12.0"
7921 sources."bluebird-3.5.3"
7742 sources."bluebird-3.5.3"
7922 sources."bn.js-4.11.8"
7743 sources."bn.js-4.11.8"
@@ -7946,7 +7767,7 b' let'
7946 sources."graceful-fs-4.1.15"
7767 sources."graceful-fs-4.1.15"
7947 sources."lru-cache-4.1.5"
7768 sources."lru-cache-4.1.5"
7948 sources."minimatch-3.0.4"
7769 sources."minimatch-3.0.4"
7949 sources."rimraf-2.6.2"
7770 sources."rimraf-2.6.3"
7950 ];
7771 ];
7951 })
7772 })
7952 sources."cache-base-1.0.1"
7773 sources."cache-base-1.0.1"
@@ -7957,8 +7778,8 b' let'
7957 sources."browserslist-1.7.7"
7778 sources."browserslist-1.7.7"
7958 ];
7779 ];
7959 })
7780 })
7960 sources."caniuse-db-1.0.30000912"
7781 sources."caniuse-db-1.0.30000927"
7961 sources."caniuse-lite-1.0.30000912"
7782 sources."caniuse-lite-1.0.30000927"
7962 sources."caseless-0.12.0"
7783 sources."caseless-0.12.0"
7963 sources."center-align-0.1.3"
7784 sources."center-align-0.1.3"
7964 sources."chalk-0.5.1"
7785 sources."chalk-0.5.1"
@@ -8045,7 +7866,7 b' let'
8045 dependencies = [
7866 dependencies = [
8046 sources."glob-7.1.3"
7867 sources."glob-7.1.3"
8047 sources."minimatch-3.0.4"
7868 sources."minimatch-3.0.4"
8048 sources."rimraf-2.6.2"
7869 sources."rimraf-2.6.3"
8049 ];
7870 ];
8050 })
7871 })
8051 sources."copy-descriptor-0.1.1"
7872 sources."copy-descriptor-0.1.1"
@@ -8055,7 +7876,7 b' let'
8055 sources."minimatch-3.0.4"
7876 sources."minimatch-3.0.4"
8056 ];
7877 ];
8057 })
7878 })
8058 sources."core-js-2.5.7"
7879 sources."core-js-2.6.1"
8059 sources."core-util-is-1.0.2"
7880 sources."core-util-is-1.0.2"
8060 sources."create-ecdh-4.0.3"
7881 sources."create-ecdh-4.0.3"
8061 sources."create-hash-1.2.0"
7882 sources."create-hash-1.2.0"
@@ -8079,7 +7900,6 b' let'
8079 sources."cssesc-0.1.0"
7900 sources."cssesc-0.1.0"
8080 sources."cssnano-3.10.0"
7901 sources."cssnano-3.10.0"
8081 sources."csso-2.3.2"
7902 sources."csso-2.3.2"
8082 sources."cycle-1.0.3"
8083 sources."cyclist-0.2.2"
7903 sources."cyclist-0.2.2"
8084 (sources."dashdash-1.14.1" // {
7904 (sources."dashdash-1.14.1" // {
8085 dependencies = [
7905 dependencies = [
@@ -8116,7 +7936,7 b' let'
8116 ];
7936 ];
8117 })
7937 })
8118 sources."domain-browser-1.2.0"
7938 sources."domain-browser-1.2.0"
8119 sources."domelementtype-1.3.0"
7939 sources."domelementtype-1.3.1"
8120 sources."domhandler-2.3.0"
7940 sources."domhandler-2.3.0"
8121 sources."domutils-1.5.1"
7941 sources."domutils-1.5.1"
8122 (sources."duplexify-3.6.1" // {
7942 (sources."duplexify-3.6.1" // {
@@ -8126,7 +7946,7 b' let'
8126 ];
7946 ];
8127 })
7947 })
8128 sources."ecc-jsbn-0.1.2"
7948 sources."ecc-jsbn-0.1.2"
8129 sources."electron-to-chromium-1.3.85"
7949 sources."electron-to-chromium-1.3.98"
8130 sources."elliptic-6.4.1"
7950 sources."elliptic-6.4.1"
8131 sources."emojis-list-2.1.0"
7951 sources."emojis-list-2.1.0"
8132 sources."end-of-stream-1.4.1"
7952 sources."end-of-stream-1.4.1"
@@ -8137,9 +7957,8 b' let'
8137 })
7957 })
8138 sources."entities-1.0.0"
7958 sources."entities-1.0.0"
8139 sources."errno-0.1.7"
7959 sources."errno-0.1.7"
8140 sources."es-abstract-1.12.0"
7960 sources."es-abstract-1.13.0"
8141 sources."es-to-primitive-1.2.0"
7961 sources."es-to-primitive-1.2.0"
8142 sources."es6-promise-4.2.5"
8143 sources."es6-templates-0.2.3"
7962 sources."es6-templates-0.2.3"
8144 sources."escape-string-regexp-1.0.5"
7963 sources."escape-string-regexp-1.0.5"
8145 sources."eslint-scope-4.0.0"
7964 sources."eslint-scope-4.0.0"
@@ -8151,7 +7970,7 b' let'
8151 sources."eventemitter2-0.4.14"
7970 sources."eventemitter2-0.4.14"
8152 sources."events-1.1.1"
7971 sources."events-1.1.1"
8153 sources."evp_bytestokey-1.0.3"
7972 sources."evp_bytestokey-1.0.3"
8154 sources."execa-0.10.0"
7973 sources."execa-1.0.0"
8155 sources."exit-0.1.2"
7974 sources."exit-0.1.2"
8156 (sources."expand-brackets-2.1.4" // {
7975 (sources."expand-brackets-2.1.4" // {
8157 dependencies = [
7976 dependencies = [
@@ -8185,15 +8004,12 b' let'
8185 sources."extend-shallow-2.0.1"
8004 sources."extend-shallow-2.0.1"
8186 ];
8005 ];
8187 })
8006 })
8188 sources."extract-zip-1.6.7"
8189 sources."extsprintf-1.3.0"
8007 sources."extsprintf-1.3.0"
8190 sources."eyes-0.1.8"
8191 sources."fast-deep-equal-2.0.1"
8008 sources."fast-deep-equal-2.0.1"
8192 sources."fast-json-stable-stringify-2.0.0"
8009 sources."fast-json-stable-stringify-2.0.0"
8193 sources."fastparse-1.1.2"
8010 sources."fastparse-1.1.2"
8194 sources."favico.js-0.3.10"
8011 sources."favico.js-0.3.10"
8195 sources."faye-websocket-0.4.4"
8012 sources."faye-websocket-0.4.4"
8196 sources."fd-slicer-1.0.1"
8197 sources."file-sync-cmp-0.1.1"
8013 sources."file-sync-cmp-0.1.1"
8198 (sources."fill-range-4.0.0" // {
8014 (sources."fill-range-4.0.0" // {
8199 dependencies = [
8015 dependencies = [
@@ -8209,8 +8025,8 b' let'
8209 sources."minimatch-0.3.0"
8025 sources."minimatch-0.3.0"
8210 ];
8026 ];
8211 })
8027 })
8212 sources."fined-1.1.0"
8028 sources."fined-1.1.1"
8213 sources."flagged-respawn-1.0.0"
8029 sources."flagged-respawn-1.0.1"
8214 sources."flatten-1.0.2"
8030 sources."flatten-1.0.2"
8215 (sources."flush-write-stream-1.0.3" // {
8031 (sources."flush-write-stream-1.0.3" // {
8216 dependencies = [
8032 dependencies = [
@@ -8229,11 +8045,6 b' let'
8229 sources."string_decoder-1.1.1"
8045 sources."string_decoder-1.1.1"
8230 ];
8046 ];
8231 })
8047 })
8232 (sources."fs-extra-1.0.0" // {
8233 dependencies = [
8234 sources."graceful-fs-4.1.15"
8235 ];
8236 })
8237 (sources."fs-write-stream-atomic-1.0.10" // {
8048 (sources."fs-write-stream-atomic-1.0.10" // {
8238 dependencies = [
8049 dependencies = [
8239 sources."graceful-fs-4.1.15"
8050 sources."graceful-fs-4.1.15"
@@ -8244,7 +8055,11 b' let'
8244 sources."function-bind-1.1.1"
8055 sources."function-bind-1.1.1"
8245 sources."gaze-0.5.2"
8056 sources."gaze-0.5.2"
8246 sources."get-caller-file-1.0.3"
8057 sources."get-caller-file-1.0.3"
8247 sources."get-stream-3.0.0"
8058 (sources."get-stream-4.1.0" // {
8059 dependencies = [
8060 sources."pump-3.0.0"
8061 ];
8062 })
8248 sources."get-value-2.0.6"
8063 sources."get-value-2.0.6"
8249 sources."getobject-0.1.0"
8064 sources."getobject-0.1.0"
8250 (sources."getpass-0.1.7" // {
8065 (sources."getpass-0.1.7" // {
@@ -8259,7 +8074,7 b' let'
8259 })
8074 })
8260 sources."glob-parent-3.1.0"
8075 sources."glob-parent-3.1.0"
8261 sources."global-modules-1.0.0"
8076 sources."global-modules-1.0.0"
8262 sources."global-modules-path-2.3.0"
8077 sources."global-modules-path-2.3.1"
8263 (sources."global-prefix-1.0.2" // {
8078 (sources."global-prefix-1.0.2" // {
8264 dependencies = [
8079 dependencies = [
8265 sources."which-1.3.1"
8080 sources."which-1.3.1"
@@ -8351,8 +8166,7 b' let'
8351 ];
8166 ];
8352 })
8167 })
8353 sources."hash-base-3.0.4"
8168 sources."hash-base-3.0.4"
8354 sources."hash.js-1.1.5"
8169 sources."hash.js-1.1.7"
8355 sources."hasha-2.2.0"
8356 sources."hawk-3.1.3"
8170 sources."hawk-3.1.3"
8357 sources."he-1.2.0"
8171 sources."he-1.2.0"
8358 sources."hmac-drbg-1.0.1"
8172 sources."hmac-drbg-1.0.1"
@@ -8369,6 +8183,8 b' let'
8369 })
8183 })
8370 (sources."html-webpack-plugin-3.2.0" // {
8184 (sources."html-webpack-plugin-3.2.0" // {
8371 dependencies = [
8185 dependencies = [
8186 sources."big.js-3.2.0"
8187 sources."json5-0.5.1"
8372 sources."loader-utils-0.2.17"
8188 sources."loader-utils-0.2.17"
8373 sources."lodash-4.17.11"
8189 sources."lodash-4.17.11"
8374 ];
8190 ];
@@ -8381,7 +8197,7 b' let'
8381 (sources."icss-utils-2.1.0" // {
8197 (sources."icss-utils-2.1.0" // {
8382 dependencies = [
8198 dependencies = [
8383 sources."ansi-styles-3.2.1"
8199 sources."ansi-styles-3.2.1"
8384 sources."chalk-2.4.1"
8200 sources."chalk-2.4.2"
8385 sources."postcss-6.0.23"
8201 sources."postcss-6.0.23"
8386 sources."source-map-0.6.1"
8202 sources."source-map-0.6.1"
8387 sources."supports-color-5.5.0"
8203 sources."supports-color-5.5.0"
@@ -8395,7 +8211,7 b' let'
8395 dependencies = [
8211 dependencies = [
8396 sources."find-up-3.0.0"
8212 sources."find-up-3.0.0"
8397 sources."locate-path-3.0.0"
8213 sources."locate-path-3.0.0"
8398 sources."p-limit-2.0.0"
8214 sources."p-limit-2.1.0"
8399 sources."p-locate-3.0.0"
8215 sources."p-locate-3.0.0"
8400 sources."p-try-2.0.0"
8216 sources."p-try-2.0.0"
8401 sources."pkg-dir-3.0.0"
8217 sources."pkg-dir-3.0.0"
@@ -8445,12 +8261,12 b' let'
8445 sources."isobject-3.0.1"
8261 sources."isobject-3.0.1"
8446 sources."isstream-0.1.2"
8262 sources."isstream-0.1.2"
8447 sources."jquery-1.11.3"
8263 sources."jquery-1.11.3"
8448 sources."js-base64-2.4.9"
8264 sources."js-base64-2.5.0"
8449 sources."js-tokens-3.0.2"
8265 sources."js-tokens-3.0.2"
8450 sources."js-yaml-2.0.5"
8266 sources."js-yaml-2.0.5"
8451 sources."jsbn-0.1.1"
8267 sources."jsbn-0.1.1"
8452 sources."jsesc-1.3.0"
8268 sources."jsesc-1.3.0"
8453 (sources."jshint-2.9.6" // {
8269 (sources."jshint-2.9.7" // {
8454 dependencies = [
8270 dependencies = [
8455 sources."lodash-4.17.11"
8271 sources."lodash-4.17.11"
8456 sources."minimatch-3.0.4"
8272 sources."minimatch-3.0.4"
@@ -8461,25 +8277,14 b' let'
8461 sources."json-schema-traverse-0.4.1"
8277 sources."json-schema-traverse-0.4.1"
8462 sources."json-stable-stringify-1.0.1"
8278 sources."json-stable-stringify-1.0.1"
8463 sources."json-stringify-safe-5.0.1"
8279 sources."json-stringify-safe-5.0.1"
8464 sources."json5-0.5.1"
8280 sources."json5-1.0.1"
8465 (sources."jsonfile-2.4.0" // {
8466 dependencies = [
8467 sources."graceful-fs-4.1.15"
8468 ];
8469 })
8470 sources."jsonify-0.0.0"
8281 sources."jsonify-0.0.0"
8471 (sources."jsprim-1.4.1" // {
8282 (sources."jsprim-1.4.1" // {
8472 dependencies = [
8283 dependencies = [
8473 sources."assert-plus-1.0.0"
8284 sources."assert-plus-1.0.0"
8474 ];
8285 ];
8475 })
8286 })
8476 sources."kew-0.7.0"
8477 sources."kind-of-6.0.2"
8287 sources."kind-of-6.0.2"
8478 (sources."klaw-1.3.1" // {
8479 dependencies = [
8480 sources."graceful-fs-4.1.15"
8481 ];
8482 })
8483 sources."lazy-cache-1.0.4"
8288 sources."lazy-cache-1.0.4"
8484 sources."lcid-2.0.0"
8289 sources."lcid-2.0.0"
8485 (sources."less-2.7.3" // {
8290 (sources."less-2.7.3" // {
@@ -8493,7 +8298,7 b' let'
8493 ];
8298 ];
8494 })
8299 })
8495 sources."loader-runner-2.3.1"
8300 sources."loader-runner-2.3.1"
8496 sources."loader-utils-1.1.0"
8301 sources."loader-utils-1.2.3"
8497 sources."locate-path-2.0.0"
8302 sources."locate-path-2.0.0"
8498 sources."lodash-0.9.2"
8303 sources."lodash-0.9.2"
8499 sources."lodash.camelcase-4.3.0"
8304 sources."lodash.camelcase-4.3.0"
@@ -8510,6 +8315,7 b' let'
8510 sources."map-age-cleaner-0.1.3"
8315 sources."map-age-cleaner-0.1.3"
8511 sources."map-cache-0.2.2"
8316 sources."map-cache-0.2.2"
8512 sources."map-visit-1.0.0"
8317 sources."map-visit-1.0.0"
8318 sources."mark.js-8.11.1"
8513 sources."math-expression-evaluator-1.2.17"
8319 sources."math-expression-evaluator-1.2.17"
8514 sources."md5.js-1.3.5"
8320 sources."md5.js-1.3.5"
8515 sources."mem-4.0.0"
8321 sources."mem-4.0.0"
@@ -8528,25 +8334,29 b' let'
8528 sources."minimalistic-assert-1.0.1"
8334 sources."minimalistic-assert-1.0.1"
8529 sources."minimalistic-crypto-utils-1.0.1"
8335 sources."minimalistic-crypto-utils-1.0.1"
8530 sources."minimatch-0.2.14"
8336 sources."minimatch-0.2.14"
8531 sources."minimist-0.0.8"
8337 sources."minimist-1.2.0"
8532 sources."mississippi-2.0.0"
8338 sources."mississippi-2.0.0"
8533 (sources."mixin-deep-1.3.1" // {
8339 (sources."mixin-deep-1.3.1" // {
8534 dependencies = [
8340 dependencies = [
8535 sources."is-extendable-1.0.1"
8341 sources."is-extendable-1.0.1"
8536 ];
8342 ];
8537 })
8343 })
8538 sources."mkdirp-0.5.1"
8344 (sources."mkdirp-0.5.1" // {
8539 sources."moment-2.22.2"
8345 dependencies = [
8346 sources."minimist-0.0.8"
8347 ];
8348 })
8349 sources."moment-2.23.0"
8540 sources."mousetrap-1.6.2"
8350 sources."mousetrap-1.6.2"
8541 (sources."move-concurrently-1.0.1" // {
8351 (sources."move-concurrently-1.0.1" // {
8542 dependencies = [
8352 dependencies = [
8543 sources."glob-7.1.3"
8353 sources."glob-7.1.3"
8544 sources."minimatch-3.0.4"
8354 sources."minimatch-3.0.4"
8545 sources."rimraf-2.6.2"
8355 sources."rimraf-2.6.3"
8546 ];
8356 ];
8547 })
8357 })
8548 sources."ms-2.0.0"
8358 sources."ms-2.0.0"
8549 sources."nan-2.11.1"
8359 sources."nan-2.12.1"
8550 sources."nanomatch-1.2.13"
8360 sources."nanomatch-1.2.13"
8551 sources."neo-async-2.6.0"
8361 sources."neo-async-2.6.0"
8552 sources."nice-try-1.0.5"
8362 sources."nice-try-1.0.5"
@@ -8598,7 +8408,7 b' let'
8598 sources."once-1.4.0"
8408 sources."once-1.4.0"
8599 sources."os-browserify-0.3.0"
8409 sources."os-browserify-0.3.0"
8600 sources."os-homedir-1.0.2"
8410 sources."os-homedir-1.0.2"
8601 sources."os-locale-3.0.1"
8411 sources."os-locale-3.1.0"
8602 sources."os-tmpdir-1.0.2"
8412 sources."os-tmpdir-1.0.2"
8603 sources."osenv-0.1.5"
8413 sources."osenv-0.1.5"
8604 sources."p-defer-1.0.0"
8414 sources."p-defer-1.0.0"
@@ -8635,22 +8445,13 b' let'
8635 sources."path-root-regex-0.1.2"
8445 sources."path-root-regex-0.1.2"
8636 sources."path-type-3.0.0"
8446 sources."path-type-3.0.0"
8637 sources."pbkdf2-3.0.17"
8447 sources."pbkdf2-3.0.17"
8638 sources."pend-1.2.0"
8639 sources."performance-now-0.2.0"
8448 sources."performance-now-0.2.0"
8640 sources."phantom-4.0.12"
8641 (sources."phantomjs-prebuilt-2.1.16" // {
8642 dependencies = [
8643 sources."which-1.3.1"
8644 ];
8645 })
8646 sources."pify-3.0.0"
8449 sources."pify-3.0.0"
8647 sources."pinkie-2.0.4"
8648 sources."pinkie-promise-2.0.1"
8649 sources."pkg-dir-2.0.0"
8450 sources."pkg-dir-2.0.0"
8650 (sources."polymer-webpack-loader-2.0.3" // {
8451 (sources."polymer-webpack-loader-2.0.3" // {
8651 dependencies = [
8452 dependencies = [
8652 sources."ansi-styles-3.2.1"
8453 sources."ansi-styles-3.2.1"
8653 sources."chalk-2.4.1"
8454 sources."chalk-2.4.2"
8654 sources."html-loader-0.5.5"
8455 sources."html-loader-0.5.5"
8655 (sources."postcss-6.0.23" // {
8456 (sources."postcss-6.0.23" // {
8656 dependencies = [
8457 dependencies = [
@@ -8700,7 +8501,7 b' let'
8700 (sources."postcss-modules-extract-imports-1.2.1" // {
8501 (sources."postcss-modules-extract-imports-1.2.1" // {
8701 dependencies = [
8502 dependencies = [
8702 sources."ansi-styles-3.2.1"
8503 sources."ansi-styles-3.2.1"
8703 sources."chalk-2.4.1"
8504 sources."chalk-2.4.2"
8704 sources."postcss-6.0.23"
8505 sources."postcss-6.0.23"
8705 sources."source-map-0.6.1"
8506 sources."source-map-0.6.1"
8706 sources."supports-color-5.5.0"
8507 sources."supports-color-5.5.0"
@@ -8709,7 +8510,7 b' let'
8709 (sources."postcss-modules-local-by-default-1.2.0" // {
8510 (sources."postcss-modules-local-by-default-1.2.0" // {
8710 dependencies = [
8511 dependencies = [
8711 sources."ansi-styles-3.2.1"
8512 sources."ansi-styles-3.2.1"
8712 sources."chalk-2.4.1"
8513 sources."chalk-2.4.2"
8713 sources."postcss-6.0.23"
8514 sources."postcss-6.0.23"
8714 sources."source-map-0.6.1"
8515 sources."source-map-0.6.1"
8715 sources."supports-color-5.5.0"
8516 sources."supports-color-5.5.0"
@@ -8718,7 +8519,7 b' let'
8718 (sources."postcss-modules-scope-1.1.0" // {
8519 (sources."postcss-modules-scope-1.1.0" // {
8719 dependencies = [
8520 dependencies = [
8720 sources."ansi-styles-3.2.1"
8521 sources."ansi-styles-3.2.1"
8721 sources."chalk-2.4.1"
8522 sources."chalk-2.4.2"
8722 sources."postcss-6.0.23"
8523 sources."postcss-6.0.23"
8723 sources."source-map-0.6.1"
8524 sources."source-map-0.6.1"
8724 sources."supports-color-5.5.0"
8525 sources."supports-color-5.5.0"
@@ -8727,7 +8528,7 b' let'
8727 (sources."postcss-modules-values-1.3.0" // {
8528 (sources."postcss-modules-values-1.3.0" // {
8728 dependencies = [
8529 dependencies = [
8729 sources."ansi-styles-3.2.1"
8530 sources."ansi-styles-3.2.1"
8730 sources."chalk-2.4.1"
8531 sources."chalk-2.4.2"
8731 sources."postcss-6.0.23"
8532 sources."postcss-6.0.23"
8732 sources."source-map-0.6.1"
8533 sources."source-map-0.6.1"
8733 sources."supports-color-5.5.0"
8534 sources."supports-color-5.5.0"
@@ -8749,7 +8550,6 b' let'
8749 sources."private-0.1.8"
8550 sources."private-0.1.8"
8750 sources."process-0.11.10"
8551 sources."process-0.11.10"
8751 sources."process-nextick-args-2.0.0"
8552 sources."process-nextick-args-2.0.0"
8752 sources."progress-1.1.8"
8753 sources."promise-7.3.1"
8553 sources."promise-7.3.1"
8754 sources."promise-inflight-1.0.1"
8554 sources."promise-inflight-1.0.1"
8755 sources."prr-1.0.1"
8555 sources."prr-1.0.1"
@@ -8823,10 +8623,9 b' let'
8823 sources."repeat-string-1.6.1"
8623 sources."repeat-string-1.6.1"
8824 sources."repeating-2.0.1"
8624 sources."repeating-2.0.1"
8825 sources."request-2.81.0"
8625 sources."request-2.81.0"
8826 sources."request-progress-2.0.1"
8827 sources."require-directory-2.1.1"
8626 sources."require-directory-2.1.1"
8828 sources."require-main-filename-1.0.1"
8627 sources."require-main-filename-1.0.1"
8829 sources."resolve-1.8.1"
8628 sources."resolve-1.9.0"
8830 sources."resolve-cwd-2.0.0"
8629 sources."resolve-cwd-2.0.0"
8831 sources."resolve-dir-1.0.1"
8630 sources."resolve-dir-1.0.1"
8832 sources."resolve-from-3.0.0"
8631 sources."resolve-from-3.0.0"
@@ -8842,12 +8641,12 b' let'
8842 sources."sax-1.2.4"
8641 sources."sax-1.2.4"
8843 (sources."schema-utils-0.4.7" // {
8642 (sources."schema-utils-0.4.7" // {
8844 dependencies = [
8643 dependencies = [
8845 sources."ajv-6.6.1"
8644 sources."ajv-6.6.2"
8846 ];
8645 ];
8847 })
8646 })
8848 sources."select-1.1.2"
8647 sources."select-1.1.2"
8849 sources."semver-5.6.0"
8648 sources."semver-5.6.0"
8850 sources."serialize-javascript-1.5.0"
8649 sources."serialize-javascript-1.6.1"
8851 sources."set-blocking-2.0.0"
8650 sources."set-blocking-2.0.0"
8852 (sources."set-value-2.0.0" // {
8651 (sources."set-value-2.0.0" // {
8853 dependencies = [
8652 dependencies = [
@@ -8897,16 +8696,14 b' let'
8897 sources."source-map-resolve-0.5.2"
8696 sources."source-map-resolve-0.5.2"
8898 sources."source-map-support-0.4.18"
8697 sources."source-map-support-0.4.18"
8899 sources."source-map-url-0.4.0"
8698 sources."source-map-url-0.4.0"
8900 sources."split-1.0.1"
8901 sources."split-string-3.1.0"
8699 sources."split-string-3.1.0"
8902 sources."sprintf-js-1.0.3"
8700 sources."sprintf-js-1.0.3"
8903 (sources."sshpk-1.15.2" // {
8701 (sources."sshpk-1.16.0" // {
8904 dependencies = [
8702 dependencies = [
8905 sources."assert-plus-1.0.0"
8703 sources."assert-plus-1.0.0"
8906 ];
8704 ];
8907 })
8705 })
8908 sources."ssri-5.3.0"
8706 sources."ssri-5.3.0"
8909 sources."stack-trace-0.0.10"
8910 (sources."static-extend-0.1.2" // {
8707 (sources."static-extend-0.1.2" // {
8911 dependencies = [
8708 dependencies = [
8912 sources."define-property-0.2.5"
8709 sources."define-property-0.2.5"
@@ -8963,7 +8760,6 b' let'
8963 ];
8760 ];
8964 })
8761 })
8965 sources."tapable-1.1.1"
8762 sources."tapable-1.1.1"
8966 sources."throttleit-1.0.0"
8967 sources."through-2.3.8"
8763 sources."through-2.3.8"
8968 (sources."through2-2.0.5" // {
8764 (sources."through2-2.0.5" // {
8969 dependencies = [
8765 dependencies = [
@@ -8993,9 +8789,11 b' let'
8993 sources."trim-right-1.0.1"
8789 sources."trim-right-1.0.1"
8994 (sources."ts-loader-1.3.3" // {
8790 (sources."ts-loader-1.3.3" // {
8995 dependencies = [
8791 dependencies = [
8996 sources."colors-1.3.2"
8792 sources."big.js-3.2.0"
8793 sources."colors-1.3.3"
8997 sources."enhanced-resolve-3.4.1"
8794 sources."enhanced-resolve-3.4.1"
8998 sources."graceful-fs-4.1.15"
8795 sources."graceful-fs-4.1.15"
8796 sources."json5-0.5.1"
8999 sources."loader-utils-0.2.17"
8797 sources."loader-utils-0.2.17"
9000 sources."tapable-0.2.9"
8798 sources."tapable-0.2.9"
9001 ];
8799 ];
@@ -9025,7 +8823,6 b' let'
9025 sources."unc-path-regex-0.1.2"
8823 sources."unc-path-regex-0.1.2"
9026 sources."underscore-1.7.0"
8824 sources."underscore-1.7.0"
9027 sources."underscore.string-2.2.1"
8825 sources."underscore.string-2.2.1"
9028 sources."unicode-5.2.0-0.7.5"
9029 (sources."union-value-1.0.0" // {
8826 (sources."union-value-1.0.0" // {
9030 dependencies = [
8827 dependencies = [
9031 sources."extend-shallow-2.0.1"
8828 sources."extend-shallow-2.0.1"
@@ -9066,7 +8863,7 b' let'
9066 sources."utila-0.4.0"
8863 sources."utila-0.4.0"
9067 sources."uuid-3.3.2"
8864 sources."uuid-3.3.2"
9068 sources."v8-compile-cache-2.0.2"
8865 sources."v8-compile-cache-2.0.2"
9069 sources."v8flags-3.1.1"
8866 sources."v8flags-3.1.2"
9070 sources."vendors-1.0.2"
8867 sources."vendors-1.0.2"
9071 (sources."verror-1.10.0" // {
8868 (sources."verror-1.10.0" // {
9072 dependencies = [
8869 dependencies = [
@@ -9082,13 +8879,13 b' let'
9082 sources."waypoints-4.0.1"
8879 sources."waypoints-4.0.1"
9083 (sources."webpack-4.23.1" // {
8880 (sources."webpack-4.23.1" // {
9084 dependencies = [
8881 dependencies = [
9085 sources."ajv-6.6.1"
8882 sources."ajv-6.6.2"
9086 ];
8883 ];
9087 })
8884 })
9088 (sources."webpack-cli-3.1.2" // {
8885 (sources."webpack-cli-3.1.2" // {
9089 dependencies = [
8886 dependencies = [
9090 sources."ansi-styles-3.2.1"
8887 sources."ansi-styles-3.2.1"
9091 sources."chalk-2.4.1"
8888 sources."chalk-2.4.2"
9092 sources."supports-color-5.5.0"
8889 sources."supports-color-5.5.0"
9093 ];
8890 ];
9094 })
8891 })
@@ -9121,12 +8918,6 b' let'
9121 sources."which-1.0.9"
8918 sources."which-1.0.9"
9122 sources."which-module-2.0.0"
8919 sources."which-module-2.0.0"
9123 sources."window-size-0.1.0"
8920 sources."window-size-0.1.0"
9124 (sources."winston-2.4.4" // {
9125 dependencies = [
9126 sources."async-1.0.0"
9127 sources."colors-1.0.3"
9128 ];
9129 })
9130 sources."wordwrap-0.0.2"
8921 sources."wordwrap-0.0.2"
9131 sources."worker-farm-1.6.0"
8922 sources."worker-farm-1.6.0"
9132 (sources."wrap-ansi-2.1.0" // {
8923 (sources."wrap-ansi-2.1.0" // {
@@ -9144,13 +8935,12 b' let'
9144 dependencies = [
8935 dependencies = [
9145 sources."find-up-3.0.0"
8936 sources."find-up-3.0.0"
9146 sources."locate-path-3.0.0"
8937 sources."locate-path-3.0.0"
9147 sources."p-limit-2.0.0"
8938 sources."p-limit-2.1.0"
9148 sources."p-locate-3.0.0"
8939 sources."p-locate-3.0.0"
9149 sources."p-try-2.0.0"
8940 sources."p-try-2.0.0"
9150 ];
8941 ];
9151 })
8942 })
9152 sources."yargs-parser-11.1.1"
8943 sources."yargs-parser-11.1.1"
9153 sources."yauzl-2.4.1"
9154 ];
8944 ];
9155 buildInputs = globalBuildInputs;
8945 buildInputs = globalBuildInputs;
9156 meta = {
8946 meta = {
@@ -219,11 +219,11 b' self: super: {'
219 };
219 };
220 };
220 };
221 "click" = super.buildPythonPackage {
221 "click" = super.buildPythonPackage {
222 name = "click-6.6";
222 name = "click-7.0";
223 doCheck = false;
223 doCheck = false;
224 src = fetchurl {
224 src = fetchurl {
225 url = "https://files.pythonhosted.org/packages/7a/00/c14926d8232b36b08218067bcd5853caefb4737cda3f0a47437151344792/click-6.6.tar.gz";
225 url = "https://files.pythonhosted.org/packages/f8/5c/f60e9d8a1e77005f664b76ff8aeaee5bc05d0a91798afd7f53fc998dbc47/Click-7.0.tar.gz";
226 sha256 = "1sggipyz52crrybwbr9xvwxd4aqigvplf53k9w3ygxmzivd1jsnc";
226 sha256 = "1mzjixd4vjbjvzb6vylki9w1556a9qmdh35kzmq6cign46av952v";
227 };
227 };
228 meta = {
228 meta = {
229 license = [ pkgs.lib.licenses.bsdOriginal ];
229 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -260,11 +260,11 b' self: super: {'
260 };
260 };
261 };
261 };
262 "configparser" = super.buildPythonPackage {
262 "configparser" = super.buildPythonPackage {
263 name = "configparser-3.5.0";
263 name = "configparser-3.7.1";
264 doCheck = false;
264 doCheck = false;
265 src = fetchurl {
265 src = fetchurl {
266 url = "https://files.pythonhosted.org/packages/7c/69/c2ce7e91c89dc073eb1aa74c0621c3eefbffe8216b3f9af9d3885265c01c/configparser-3.5.0.tar.gz";
266 url = "https://files.pythonhosted.org/packages/b6/a6/eceea7c5a5dbcf56815bed411c38cabd8a879386be10717b160e7362b5a2/configparser-3.7.1.tar.gz";
267 sha256 = "0fi7vf09vi1588jd8f16a021m5y6ih2hy7rpbjb408xw45qb822k";
267 sha256 = "0cnz213il9lhgda6x70fw7mfqr8da43s3wm343lwzhqx94mgmmav";
268 };
268 };
269 meta = {
269 meta = {
270 license = [ pkgs.lib.licenses.mit ];
270 license = [ pkgs.lib.licenses.mit ];
@@ -374,11 +374,14 b' self: super: {'
374 };
374 };
375 };
375 };
376 "dogpile.cache" = super.buildPythonPackage {
376 "dogpile.cache" = super.buildPythonPackage {
377 name = "dogpile.cache-0.6.7";
377 name = "dogpile.cache-0.7.1";
378 doCheck = false;
378 doCheck = false;
379 propagatedBuildInputs = [
380 self."decorator"
381 ];
379 src = fetchurl {
382 src = fetchurl {
380 url = "https://files.pythonhosted.org/packages/ee/bd/440da735a11c6087eed7cc8747fc4b995cbac2464168682f8ee1c8e43844/dogpile.cache-0.6.7.tar.gz";
383 url = "https://files.pythonhosted.org/packages/84/3e/dbf1cfc5228f1d3dca80ef714db2c5aaec5cd9efaf54d7e3daef6bc48b19/dogpile.cache-0.7.1.tar.gz";
381 sha256 = "1aw8rx8vhb75y7zc6gi67g21sw057jdx7i8m3jq7kf3nqavxx9zw";
384 sha256 = "0caazmrzhnfqb5yrp8myhw61ny637jj69wcngrpbvi31jlcpy6v9";
382 };
385 };
383 meta = {
386 meta = {
384 license = [ pkgs.lib.licenses.bsdOriginal ];
387 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -407,30 +410,75 b' self: super: {'
407 };
410 };
408 };
411 };
409 "elasticsearch" = super.buildPythonPackage {
412 "elasticsearch" = super.buildPythonPackage {
410 name = "elasticsearch-2.3.0";
413 name = "elasticsearch-6.3.1";
411 doCheck = false;
414 doCheck = false;
412 propagatedBuildInputs = [
415 propagatedBuildInputs = [
413 self."urllib3"
416 self."urllib3"
414 ];
417 ];
415 src = fetchurl {
418 src = fetchurl {
416 url = "https://files.pythonhosted.org/packages/10/35/5fd52c5f0b0ee405ed4b5195e8bce44c5e041787680dc7b94b8071cac600/elasticsearch-2.3.0.tar.gz";
419 url = "https://files.pythonhosted.org/packages/9d/ce/c4664e8380e379a9402ecfbaf158e56396da90d520daba21cfa840e0eb71/elasticsearch-6.3.1.tar.gz";
417 sha256 = "10ad2dk73xsys9vajwsncibs69asa63w1hgwz6lz1prjpyi80c5y";
420 sha256 = "12y93v0yn7a4xmf969239g8gb3l4cdkclfpbk1qc8hx5qkymrnma";
418 };
421 };
419 meta = {
422 meta = {
420 license = [ pkgs.lib.licenses.asl20 ];
423 license = [ pkgs.lib.licenses.asl20 ];
421 };
424 };
422 };
425 };
423 "elasticsearch-dsl" = super.buildPythonPackage {
426 "elasticsearch-dsl" = super.buildPythonPackage {
424 name = "elasticsearch-dsl-2.2.0";
427 name = "elasticsearch-dsl-6.3.1";
425 doCheck = false;
428 doCheck = false;
426 propagatedBuildInputs = [
429 propagatedBuildInputs = [
427 self."six"
430 self."six"
428 self."python-dateutil"
431 self."python-dateutil"
429 self."elasticsearch"
432 self."elasticsearch"
433 self."ipaddress"
434 ];
435 src = fetchurl {
436 url = "https://files.pythonhosted.org/packages/4c/0d/1549f50c591db6bb4e66cbcc8d34a6e537c3d89aa426b167c244fd46420a/elasticsearch-dsl-6.3.1.tar.gz";
437 sha256 = "1gh8a0shqi105k325hgwb9avrpdjh0mc6mxwfg9ba7g6lssb702z";
438 };
439 meta = {
440 license = [ pkgs.lib.licenses.asl20 ];
441 };
442 };
443 "elasticsearch1" = super.buildPythonPackage {
444 name = "elasticsearch1-1.10.0";
445 doCheck = false;
446 propagatedBuildInputs = [
447 self."urllib3"
430 ];
448 ];
431 src = fetchurl {
449 src = fetchurl {
432 url = "https://files.pythonhosted.org/packages/66/2f/52a086968788e58461641570f45c3207a52d46ebbe9b77dc22b6a8ffda66/elasticsearch-dsl-2.2.0.tar.gz";
450 url = "https://files.pythonhosted.org/packages/a6/eb/73e75f9681fa71e3157b8ee878534235d57f24ee64f0e77f8d995fb57076/elasticsearch1-1.10.0.tar.gz";
433 sha256 = "1g4kxzxsdwlsl2a9kscmx11pafgimhj7y8wrfksv8pgvpkfb9fwr";
451 sha256 = "0g89444kd5zwql4vbvyrmi2m6l6dcj6ga98j4hqxyyyz6z20aki2";
452 };
453 meta = {
454 license = [ pkgs.lib.licenses.asl20 ];
455 };
456 };
457 "elasticsearch1-dsl" = super.buildPythonPackage {
458 name = "elasticsearch1-dsl-0.0.12";
459 doCheck = false;
460 propagatedBuildInputs = [
461 self."six"
462 self."python-dateutil"
463 self."elasticsearch1"
464 ];
465 src = fetchurl {
466 url = "https://files.pythonhosted.org/packages/eb/9d/785342775cb10eddc9b8d7457d618a423b4f0b89d8b2b2d1bc27190d71db/elasticsearch1-dsl-0.0.12.tar.gz";
467 sha256 = "0ig1ly39v93hba0z975wnhbmzwj28w6w1sqlr2g7cn5spp732bhk";
468 };
469 meta = {
470 license = [ pkgs.lib.licenses.asl20 ];
471 };
472 };
473 "elasticsearch2" = super.buildPythonPackage {
474 name = "elasticsearch2-2.5.0";
475 doCheck = false;
476 propagatedBuildInputs = [
477 self."urllib3"
478 ];
479 src = fetchurl {
480 url = "https://files.pythonhosted.org/packages/84/77/63cf63d4ba11d913b5278406f2a37b0712bec6fc85edfb6151a33eaeba25/elasticsearch2-2.5.0.tar.gz";
481 sha256 = "0ky0q16lbvz022yv6q3pix7aamf026p1y994537ccjf0p0dxnbxr";
434 };
482 };
435 meta = {
483 meta = {
436 license = [ pkgs.lib.licenses.asl20 ];
484 license = [ pkgs.lib.licenses.asl20 ];
@@ -517,14 +565,14 b' self: super: {'
517 };
565 };
518 };
566 };
519 "gevent" = super.buildPythonPackage {
567 "gevent" = super.buildPythonPackage {
520 name = "gevent-1.3.7";
568 name = "gevent-1.4.0";
521 doCheck = false;
569 doCheck = false;
522 propagatedBuildInputs = [
570 propagatedBuildInputs = [
523 self."greenlet"
571 self."greenlet"
524 ];
572 ];
525 src = fetchurl {
573 src = fetchurl {
526 url = "https://files.pythonhosted.org/packages/10/c1/9499b146bfa43aa4f1e0ed1bab1bd3209a4861d25650c11725036c731cf5/gevent-1.3.7.tar.gz";
574 url = "https://files.pythonhosted.org/packages/ed/27/6c49b70808f569b66ec7fac2e78f076e9b204db9cf5768740cff3d5a07ae/gevent-1.4.0.tar.gz";
527 sha256 = "0b0fr04qdk1p4sniv87fh8z5psac60x01pv054kpgi94520g81iz";
575 sha256 = "1lchr4akw2jkm5v4kz7bdm4wv3knkfhbfn9vkkz4s5yrkcxzmdqy";
528 };
576 };
529 meta = {
577 meta = {
530 license = [ pkgs.lib.licenses.mit ];
578 license = [ pkgs.lib.licenses.mit ];
@@ -673,11 +721,11 b' self: super: {'
673 };
721 };
674 };
722 };
675 "iso8601" = super.buildPythonPackage {
723 "iso8601" = super.buildPythonPackage {
676 name = "iso8601-0.1.11";
724 name = "iso8601-0.1.12";
677 doCheck = false;
725 doCheck = false;
678 src = fetchurl {
726 src = fetchurl {
679 url = "https://files.pythonhosted.org/packages/c0/75/c9209ee4d1b5975eb8c2cba4428bde6b61bd55664a98290dd015cdb18e98/iso8601-0.1.11.tar.gz";
727 url = "https://files.pythonhosted.org/packages/45/13/3db24895497345fb44c4248c08b16da34a9eb02643cea2754b21b5ed08b0/iso8601-0.1.12.tar.gz";
680 sha256 = "0c7gh3lsdjds262h0v1sqc66l7hqgfwbakn96qrhdbl0i3vm5yz8";
728 sha256 = "10nyvvnrhw2w3p09v1ica4lgj6f4g9j3kkfx17qmraiq3w7b5i29";
681 };
729 };
682 meta = {
730 meta = {
683 license = [ pkgs.lib.licenses.mit ];
731 license = [ pkgs.lib.licenses.mit ];
@@ -768,14 +816,14 b' self: super: {'
768 };
816 };
769 };
817 };
770 "kombu" = super.buildPythonPackage {
818 "kombu" = super.buildPythonPackage {
771 name = "kombu-4.2.0";
819 name = "kombu-4.2.1";
772 doCheck = false;
820 doCheck = false;
773 propagatedBuildInputs = [
821 propagatedBuildInputs = [
774 self."amqp"
822 self."amqp"
775 ];
823 ];
776 src = fetchurl {
824 src = fetchurl {
777 url = "https://files.pythonhosted.org/packages/ab/b1/46a7a8babf5e60f3b2ca081a100af8edfcf132078a726375f52a054e70cf/kombu-4.2.0.tar.gz";
825 url = "https://files.pythonhosted.org/packages/39/9f/556b988833abede4a80dbd18b2bdf4e8ff4486dd482ed45da961347e8ed2/kombu-4.2.1.tar.gz";
778 sha256 = "1yz19qlqf0inl1mnwlpq9j6kj9r67clpy0xg99phyg4329rw80fn";
826 sha256 = "10lh3hncvw67fz0k5vgbx3yh9gjfpqdlia1f13i28cgnc1nfrbc6";
779 };
827 };
780 meta = {
828 meta = {
781 license = [ pkgs.lib.licenses.bsdOriginal ];
829 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -818,11 +866,11 b' self: super: {'
818 };
866 };
819 };
867 };
820 "markupsafe" = super.buildPythonPackage {
868 "markupsafe" = super.buildPythonPackage {
821 name = "markupsafe-1.0";
869 name = "markupsafe-1.1.0";
822 doCheck = false;
870 doCheck = false;
823 src = fetchurl {
871 src = fetchurl {
824 url = "https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz";
872 url = "https://files.pythonhosted.org/packages/ac/7e/1b4c2e05809a4414ebce0892fe1e32c14ace86ca7d50c70f00979ca9b3a3/MarkupSafe-1.1.0.tar.gz";
825 sha256 = "0rdn1s8x9ni7ss8rfiacj7x1085lx8mh2zdwqslnw8xc3l4nkgm6";
873 sha256 = "1lxirjypbdd3l9jl4vliilhfnhy7c7f2vlldqg1b0i74khn375sf";
826 };
874 };
827 meta = {
875 meta = {
828 license = [ pkgs.lib.licenses.bsdOriginal ];
876 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -862,14 +910,14 b' self: super: {'
862 };
910 };
863 };
911 };
864 "more-itertools" = super.buildPythonPackage {
912 "more-itertools" = super.buildPythonPackage {
865 name = "more-itertools-4.3.0";
913 name = "more-itertools-5.0.0";
866 doCheck = false;
914 doCheck = false;
867 propagatedBuildInputs = [
915 propagatedBuildInputs = [
868 self."six"
916 self."six"
869 ];
917 ];
870 src = fetchurl {
918 src = fetchurl {
871 url = "https://files.pythonhosted.org/packages/88/ff/6d485d7362f39880810278bdc906c13300db05485d9c65971dec1142da6a/more-itertools-4.3.0.tar.gz";
919 url = "https://files.pythonhosted.org/packages/dd/26/30fc0d541d9fdf55faf5ba4b0fd68f81d5bd2447579224820ad525934178/more-itertools-5.0.0.tar.gz";
872 sha256 = "17h3na0rdh8xq30w4b9pizgkdxmm51896bxw600x84jflg9vaxn4";
920 sha256 = "1r12cm6mcdwdzz7d47a6g4l437xsvapdlgyhqay3i2nrlv03da9q";
873 };
921 };
874 meta = {
922 meta = {
875 license = [ pkgs.lib.licenses.mit ];
923 license = [ pkgs.lib.licenses.mit ];
@@ -960,32 +1008,32 b' self: super: {'
960 };
1008 };
961 };
1009 };
962 "paste" = super.buildPythonPackage {
1010 "paste" = super.buildPythonPackage {
963 name = "paste-2.0.3";
1011 name = "paste-3.0.5";
964 doCheck = false;
1012 doCheck = false;
965 propagatedBuildInputs = [
1013 propagatedBuildInputs = [
966 self."six"
1014 self."six"
967 ];
1015 ];
968 src = fetchurl {
1016 src = fetchurl {
969 url = "https://files.pythonhosted.org/packages/30/c3/5c2f7c7a02e4f58d4454353fa1c32c94f79fa4e36d07a67c0ac295ea369e/Paste-2.0.3.tar.gz";
1017 url = "https://files.pythonhosted.org/packages/d4/41/91bde422400786b1b06357c1e6e3a5379f54dc3002aeb337cb767233304e/Paste-3.0.5.tar.gz";
970 sha256 = "062jk0nlxf6lb2wwj6zc20rlvrwsnikpkh90y0dn8cjch93s6ii3";
1018 sha256 = "1a6i8fh1fg8r4x800fvy9r82m15clwjim6yf2g9r4dff0y40dchv";
971 };
1019 };
972 meta = {
1020 meta = {
973 license = [ pkgs.lib.licenses.mit ];
1021 license = [ pkgs.lib.licenses.mit ];
974 };
1022 };
975 };
1023 };
976 "pastedeploy" = super.buildPythonPackage {
1024 "pastedeploy" = super.buildPythonPackage {
977 name = "pastedeploy-1.5.2";
1025 name = "pastedeploy-2.0.1";
978 doCheck = false;
1026 doCheck = false;
979 src = fetchurl {
1027 src = fetchurl {
980 url = "https://files.pythonhosted.org/packages/0f/90/8e20cdae206c543ea10793cbf4136eb9a8b3f417e04e40a29d72d9922cbd/PasteDeploy-1.5.2.tar.gz";
1028 url = "https://files.pythonhosted.org/packages/19/a0/5623701df7e2478a68a1b685d1a84518024eef994cde7e4da8449a31616f/PasteDeploy-2.0.1.tar.gz";
981 sha256 = "1jz3m4hq8v6hyhfjz9425nd3nvn52cvbfipdcd72krjmla4qz1fm";
1029 sha256 = "02imfbbx1mi2h546f3sr37m47dk9qizaqhzzlhx8bkzxa6fzn8yl";
982 };
1030 };
983 meta = {
1031 meta = {
984 license = [ pkgs.lib.licenses.mit ];
1032 license = [ pkgs.lib.licenses.mit ];
985 };
1033 };
986 };
1034 };
987 "pastescript" = super.buildPythonPackage {
1035 "pastescript" = super.buildPythonPackage {
988 name = "pastescript-2.0.2";
1036 name = "pastescript-3.0.0";
989 doCheck = false;
1037 doCheck = false;
990 propagatedBuildInputs = [
1038 propagatedBuildInputs = [
991 self."paste"
1039 self."paste"
@@ -993,23 +1041,23 b' self: super: {'
993 self."six"
1041 self."six"
994 ];
1042 ];
995 src = fetchurl {
1043 src = fetchurl {
996 url = "https://files.pythonhosted.org/packages/e5/f0/78e766c3dcc61a4f3a6f71dd8c95168ae9c7a31722b5663d19c1fdf62cb6/PasteScript-2.0.2.tar.gz";
1044 url = "https://files.pythonhosted.org/packages/08/2a/3797377a884ab9a064ad4d564ed612e54d26d7997caa8229c9c9df4eac31/PasteScript-3.0.0.tar.gz";
997 sha256 = "1h3nnhn45kf4pbcv669ik4faw04j58k8vbj1hwrc532k0nc28gy0";
1045 sha256 = "1hvmyz1sbn7ws1syw567ph7km9fi0wi75r3vlyzx6sk0z26xkm6r";
998 };
1046 };
999 meta = {
1047 meta = {
1000 license = [ pkgs.lib.licenses.mit ];
1048 license = [ pkgs.lib.licenses.mit ];
1001 };
1049 };
1002 };
1050 };
1003 "pathlib2" = super.buildPythonPackage {
1051 "pathlib2" = super.buildPythonPackage {
1004 name = "pathlib2-2.3.2";
1052 name = "pathlib2-2.3.3";
1005 doCheck = false;
1053 doCheck = false;
1006 propagatedBuildInputs = [
1054 propagatedBuildInputs = [
1007 self."six"
1055 self."six"
1008 self."scandir"
1056 self."scandir"
1009 ];
1057 ];
1010 src = fetchurl {
1058 src = fetchurl {
1011 url = "https://files.pythonhosted.org/packages/db/a8/7d6439c1aec525ed70810abee5b7d7f3aa35347f59bc28343e8f62019aa2/pathlib2-2.3.2.tar.gz";
1059 url = "https://files.pythonhosted.org/packages/bf/d7/a2568f4596b75d2c6e2b4094a7e64f620decc7887f69a1f2811931ea15b9/pathlib2-2.3.3.tar.gz";
1012 sha256 = "10yb0iv5x2hs631rcppkhbddx799d3h8pcwmkbh2a66ns3w71ccf";
1060 sha256 = "0hpp92vqqgcd8h92msm9slv161b1q160igjwnkf2ag6cx0c96695";
1013 };
1061 };
1014 meta = {
1062 meta = {
1015 license = [ pkgs.lib.licenses.mit ];
1063 license = [ pkgs.lib.licenses.mit ];
@@ -1084,11 +1132,11 b' self: super: {'
1084 };
1132 };
1085 };
1133 };
1086 "pluggy" = super.buildPythonPackage {
1134 "pluggy" = super.buildPythonPackage {
1087 name = "pluggy-0.8.0";
1135 name = "pluggy-0.8.1";
1088 doCheck = false;
1136 doCheck = false;
1089 src = fetchurl {
1137 src = fetchurl {
1090 url = "https://files.pythonhosted.org/packages/65/25/81d0de17cd00f8ca994a4e74e3c4baf7cd25072c0b831dad5c7d9d6138f8/pluggy-0.8.0.tar.gz";
1138 url = "https://files.pythonhosted.org/packages/38/e1/83b10c17688af7b2998fa5342fec58ecbd2a5a7499f31e606ae6640b71ac/pluggy-0.8.1.tar.gz";
1091 sha256 = "1580p47l2zqzsza8jcnw1h2wh3vvmygk6ly8bvi4w0g8j14sjys4";
1139 sha256 = "05l6g42p9ilmabw0hlbiyxy6gyzjri41m5l11a8dzgvi77q35p4d";
1092 };
1140 };
1093 meta = {
1141 meta = {
1094 license = [ pkgs.lib.licenses.mit ];
1142 license = [ pkgs.lib.licenses.mit ];
@@ -1110,11 +1158,11 b' self: super: {'
1110 };
1158 };
1111 };
1159 };
1112 "psutil" = super.buildPythonPackage {
1160 "psutil" = super.buildPythonPackage {
1113 name = "psutil-5.4.7";
1161 name = "psutil-5.4.8";
1114 doCheck = false;
1162 doCheck = false;
1115 src = fetchurl {
1163 src = fetchurl {
1116 url = "https://files.pythonhosted.org/packages/7d/9a/1e93d41708f8ed2b564395edfa3389f0fd6d567597401c2e5e2775118d8b/psutil-5.4.7.tar.gz";
1164 url = "https://files.pythonhosted.org/packages/e3/58/0eae6e4466e5abf779d7e2b71fac7fba5f59e00ea36ddb3ed690419ccb0f/psutil-5.4.8.tar.gz";
1117 sha256 = "0fsgmvzwbdbszkwfnqhib8jcxm4w6zyhvlxlcda0rfm5cyqj4qsv";
1165 sha256 = "1hyna338sml2cl1mfb2gs89np18z27mvyhmq4ifh22x07n7mq9kf";
1118 };
1166 };
1119 meta = {
1167 meta = {
1120 license = [ pkgs.lib.licenses.bsdOriginal ];
1168 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1180,25 +1228,25 b' self: super: {'
1180 };
1228 };
1181 };
1229 };
1182 "pyasn1" = super.buildPythonPackage {
1230 "pyasn1" = super.buildPythonPackage {
1183 name = "pyasn1-0.4.4";
1231 name = "pyasn1-0.4.5";
1184 doCheck = false;
1232 doCheck = false;
1185 src = fetchurl {
1233 src = fetchurl {
1186 url = "https://files.pythonhosted.org/packages/10/46/059775dc8e50f722d205452bced4b3cc965d27e8c3389156acd3b1123ae3/pyasn1-0.4.4.tar.gz";
1234 url = "https://files.pythonhosted.org/packages/46/60/b7e32f6ff481b8a1f6c8f02b0fd9b693d1c92ddd2efb038ec050d99a7245/pyasn1-0.4.5.tar.gz";
1187 sha256 = "0drilmx5j25aplfr5wrml0030cs5fgxp9yp94fhllxgx28yjm3zm";
1235 sha256 = "1xqh3jh2nfi2bflk5a0vn59y3pp1vn54f3ksx652sid92gz2096s";
1188 };
1236 };
1189 meta = {
1237 meta = {
1190 license = [ pkgs.lib.licenses.bsdOriginal ];
1238 license = [ pkgs.lib.licenses.bsdOriginal ];
1191 };
1239 };
1192 };
1240 };
1193 "pyasn1-modules" = super.buildPythonPackage {
1241 "pyasn1-modules" = super.buildPythonPackage {
1194 name = "pyasn1-modules-0.2.2";
1242 name = "pyasn1-modules-0.2.4";
1195 doCheck = false;
1243 doCheck = false;
1196 propagatedBuildInputs = [
1244 propagatedBuildInputs = [
1197 self."pyasn1"
1245 self."pyasn1"
1198 ];
1246 ];
1199 src = fetchurl {
1247 src = fetchurl {
1200 url = "https://files.pythonhosted.org/packages/37/33/74ebdc52be534e683dc91faf263931bc00ae05c6073909fde53999088541/pyasn1-modules-0.2.2.tar.gz";
1248 url = "https://files.pythonhosted.org/packages/bd/a5/ef7bf693e8a8f015386c9167483199f54f8a8ec01d1c737e05524f16e792/pyasn1-modules-0.2.4.tar.gz";
1201 sha256 = "0ivm850yi7ajjbi8j115qpsj95bgxdsx48nbjzg0zip788c3xkx0";
1249 sha256 = "0z3w5dqrrvdplg9ma45j8n23xvyrj9ki8mg4ibqbn7l4qpl90855";
1202 };
1250 };
1203 meta = {
1251 meta = {
1204 license = [ pkgs.lib.licenses.bsdOriginal ];
1252 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1238,30 +1286,16 b' self: super: {'
1238 };
1286 };
1239 };
1287 };
1240 "pygments" = super.buildPythonPackage {
1288 "pygments" = super.buildPythonPackage {
1241 name = "pygments-2.3.0";
1289 name = "pygments-2.3.1";
1242 doCheck = false;
1290 doCheck = false;
1243 src = fetchurl {
1291 src = fetchurl {
1244 url = "https://files.pythonhosted.org/packages/63/a2/91c31c4831853dedca2a08a0f94d788fc26a48f7281c99a303769ad2721b/Pygments-2.3.0.tar.gz";
1292 url = "https://files.pythonhosted.org/packages/64/69/413708eaf3a64a6abb8972644e0f20891a55e621c6759e2c3f3891e05d63/Pygments-2.3.1.tar.gz";
1245 sha256 = "1z34ms51dh4jq4h3cizp7vd1dmsxcbvffkjsd2xxfav22nn6lrl2";
1293 sha256 = "0ji87g09jph8jqcvclgb02qvxasdnr9pzvk90rl66d90yqcxmyjz";
1246 };
1294 };
1247 meta = {
1295 meta = {
1248 license = [ pkgs.lib.licenses.bsdOriginal ];
1296 license = [ pkgs.lib.licenses.bsdOriginal ];
1249 };
1297 };
1250 };
1298 };
1251 "pygments-markdown-lexer" = super.buildPythonPackage {
1252 name = "pygments-markdown-lexer-0.1.0.dev39";
1253 doCheck = false;
1254 propagatedBuildInputs = [
1255 self."pygments"
1256 ];
1257 src = fetchurl {
1258 url = "https://files.pythonhosted.org/packages/c3/12/674cdee66635d638cedb2c5d9c85ce507b7b2f91bdba29e482f1b1160ff6/pygments-markdown-lexer-0.1.0.dev39.zip";
1259 sha256 = "1pzb5wy23q3fhs0rqzasjnw6hdzwjngpakb73i98cn0b8lk8q4jc";
1260 };
1261 meta = {
1262 license = [ pkgs.lib.licenses.asl20 ];
1263 };
1264 };
1265 "pymysql" = super.buildPythonPackage {
1299 "pymysql" = super.buildPythonPackage {
1266 name = "pymysql-0.8.1";
1300 name = "pymysql-0.8.1";
1267 doCheck = false;
1301 doCheck = false;
@@ -1285,35 +1319,34 b' self: super: {'
1285 };
1319 };
1286 };
1320 };
1287 "pyparsing" = super.buildPythonPackage {
1321 "pyparsing" = super.buildPythonPackage {
1288 name = "pyparsing-1.5.7";
1322 name = "pyparsing-2.3.0";
1289 doCheck = false;
1323 doCheck = false;
1290 src = fetchurl {
1324 src = fetchurl {
1291 url = "https://files.pythonhosted.org/packages/6f/2c/47457771c02a8ff0f302b695e094ec309e30452232bd79198ee94fda689f/pyparsing-1.5.7.tar.gz";
1325 url = "https://files.pythonhosted.org/packages/d0/09/3e6a5eeb6e04467b737d55f8bba15247ac0876f98fae659e58cd744430c6/pyparsing-2.3.0.tar.gz";
1292 sha256 = "17z7ws076z977sclj628fvwrp8y9j2rvdjcsq42v129n1gwi8vk4";
1326 sha256 = "14k5v7n3xqw8kzf42x06bzp184spnlkya2dpjyflax6l3yrallzk";
1293 };
1327 };
1294 meta = {
1328 meta = {
1295 license = [ pkgs.lib.licenses.mit ];
1329 license = [ pkgs.lib.licenses.mit ];
1296 };
1330 };
1297 };
1331 };
1298 "pyramid" = super.buildPythonPackage {
1332 "pyramid" = super.buildPythonPackage {
1299 name = "pyramid-1.9.2";
1333 name = "pyramid-1.10.1";
1300 doCheck = false;
1334 doCheck = false;
1301 propagatedBuildInputs = [
1335 propagatedBuildInputs = [
1302 self."setuptools"
1336 self."hupper"
1303 self."webob"
1304 self."repoze.lru"
1305 self."zope.interface"
1306 self."zope.deprecation"
1307 self."venusian"
1308 self."translationstring"
1309 self."pastedeploy"
1310 self."plaster"
1337 self."plaster"
1311 self."plaster-pastedeploy"
1338 self."plaster-pastedeploy"
1312 self."hupper"
1339 self."setuptools"
1340 self."translationstring"
1341 self."venusian"
1342 self."webob"
1343 self."zope.deprecation"
1344 self."zope.interface"
1345 self."repoze.lru"
1313 ];
1346 ];
1314 src = fetchurl {
1347 src = fetchurl {
1315 url = "https://files.pythonhosted.org/packages/a0/c1/b321d07cfc4870541989ad131c86a1d593bfe802af0eca9718a0dadfb97a/pyramid-1.9.2.tar.gz";
1348 url = "https://files.pythonhosted.org/packages/0a/3e/22e3ac9be1b70a01139adba8906ee4b8f628bb469fea3c52f6c97b73063c/pyramid-1.10.1.tar.gz";
1316 sha256 = "09drsl0346nchgxp2j7sa5hlk7mkhfld9wvbd0wicacrp26a92fg";
1349 sha256 = "1h5105nfh6rsrfjiyw20aavyibj36la3hajy6vh1fa77xb4y3hrp";
1317 };
1350 };
1318 meta = {
1351 meta = {
1319 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1352 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
@@ -1335,7 +1368,7 b' self: super: {'
1335 };
1368 };
1336 };
1369 };
1337 "pyramid-debugtoolbar" = super.buildPythonPackage {
1370 "pyramid-debugtoolbar" = super.buildPythonPackage {
1338 name = "pyramid-debugtoolbar-4.4";
1371 name = "pyramid-debugtoolbar-4.5";
1339 doCheck = false;
1372 doCheck = false;
1340 propagatedBuildInputs = [
1373 propagatedBuildInputs = [
1341 self."pyramid"
1374 self."pyramid"
@@ -1345,8 +1378,8 b' self: super: {'
1345 self."ipaddress"
1378 self."ipaddress"
1346 ];
1379 ];
1347 src = fetchurl {
1380 src = fetchurl {
1348 url = "https://files.pythonhosted.org/packages/00/6f/c04eb4e715a7a5a4b24079ab7ffd1dceb1f70b2e24fc17686a2922dbac0a/pyramid_debugtoolbar-4.4.tar.gz";
1381 url = "https://files.pythonhosted.org/packages/14/28/1f240239af340d19ee271ac62958158c79edb01a44ad8c9885508dd003d2/pyramid_debugtoolbar-4.5.tar.gz";
1349 sha256 = "17p7nxvapvy2hab1rah3ndq2kbs4v83pixj8x2n4m7008ai9lxsz";
1382 sha256 = "0x2p3409pnx66n6dx5vc0mk2r1cp1ydr8mp120w44r9pwcngbibl";
1350 };
1383 };
1351 meta = {
1384 meta = {
1352 license = [ { fullName = "Repoze Public License"; } pkgs.lib.licenses.bsdOriginal ];
1385 license = [ { fullName = "Repoze Public License"; } pkgs.lib.licenses.bsdOriginal ];
@@ -1519,11 +1552,11 b' self: super: {'
1519 };
1552 };
1520 };
1553 };
1521 "python-editor" = super.buildPythonPackage {
1554 "python-editor" = super.buildPythonPackage {
1522 name = "python-editor-1.0.3";
1555 name = "python-editor-1.0.4";
1523 doCheck = false;
1556 doCheck = false;
1524 src = fetchurl {
1557 src = fetchurl {
1525 url = "https://files.pythonhosted.org/packages/65/1e/adf6e000ea5dc909aa420352d6ba37f16434c8a3c2fa030445411a1ed545/python-editor-1.0.3.tar.gz";
1558 url = "https://files.pythonhosted.org/packages/0a/85/78f4a216d28343a67b7397c99825cff336330893f00601443f7c7b2f2234/python-editor-1.0.4.tar.gz";
1526 sha256 = "0rf5xz8vw93v7mhdcvind7fkykipzga430wkcd7wk892xsn6dh53";
1559 sha256 = "0yrjh8w72ivqxi4i7xsg5b1vz15x8fg51xra7c3bgfyxqnyadzai";
1527 };
1560 };
1528 meta = {
1561 meta = {
1529 license = [ pkgs.lib.licenses.asl20 { fullName = "Apache"; } ];
1562 license = [ pkgs.lib.licenses.asl20 { fullName = "Apache"; } ];
@@ -1657,7 +1690,7 b' self: super: {'
1657 };
1690 };
1658 };
1691 };
1659 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1692 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1660 name = "rhodecode-enterprise-ce-4.15.2";
1693 name = "rhodecode-enterprise-ce-4.16.0";
1661 buildInputs = [
1694 buildInputs = [
1662 self."pytest"
1695 self."pytest"
1663 self."py"
1696 self."py"
@@ -1668,9 +1701,10 b' self: super: {'
1668 self."pytest-timeout"
1701 self."pytest-timeout"
1669 self."gprof2dot"
1702 self."gprof2dot"
1670 self."mock"
1703 self."mock"
1671 self."webtest"
1672 self."cov-core"
1704 self."cov-core"
1673 self."coverage"
1705 self."coverage"
1706 self."webtest"
1707 self."beautifulsoup4"
1674 self."configobj"
1708 self."configobj"
1675 ];
1709 ];
1676 doCheck = true;
1710 doCheck = true;
@@ -1723,7 +1757,6 b' self: super: {'
1723 self."pycrypto"
1757 self."pycrypto"
1724 self."pycurl"
1758 self."pycurl"
1725 self."pyflakes"
1759 self."pyflakes"
1726 self."pygments-markdown-lexer"
1727 self."pygments"
1760 self."pygments"
1728 self."pyparsing"
1761 self."pyparsing"
1729 self."pyramid-beaker"
1762 self."pyramid-beaker"
@@ -1794,9 +1827,10 b' self: super: {'
1794 self."pytest-timeout"
1827 self."pytest-timeout"
1795 self."gprof2dot"
1828 self."gprof2dot"
1796 self."mock"
1829 self."mock"
1797 self."webtest"
1798 self."cov-core"
1830 self."cov-core"
1799 self."coverage"
1831 self."coverage"
1832 self."webtest"
1833 self."beautifulsoup4"
1800 ];
1834 ];
1801 src = ./.;
1835 src = ./.;
1802 meta = {
1836 meta = {
@@ -1804,7 +1838,7 b' self: super: {'
1804 };
1838 };
1805 };
1839 };
1806 "rhodecode-tools" = super.buildPythonPackage {
1840 "rhodecode-tools" = super.buildPythonPackage {
1807 name = "rhodecode-tools-1.0.1";
1841 name = "rhodecode-tools-1.2.1";
1808 doCheck = false;
1842 doCheck = false;
1809 propagatedBuildInputs = [
1843 propagatedBuildInputs = [
1810 self."click"
1844 self."click"
@@ -1813,14 +1847,16 b' self: super: {'
1813 self."mako"
1847 self."mako"
1814 self."markupsafe"
1848 self."markupsafe"
1815 self."requests"
1849 self."requests"
1816 self."elasticsearch"
1817 self."elasticsearch-dsl"
1818 self."urllib3"
1850 self."urllib3"
1819 self."whoosh"
1851 self."whoosh"
1852 self."elasticsearch"
1853 self."elasticsearch-dsl"
1854 self."elasticsearch2"
1855 self."elasticsearch1-dsl"
1820 ];
1856 ];
1821 src = fetchurl {
1857 src = fetchurl {
1822 url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.0.1.tar.gz?md5=ffb5d6bcb855305b93cfe23ad42e500b";
1858 url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.2.1.tar.gz?md5=25bc2f7de1da318e547236d3fb463d28";
1823 sha256 = "0nr300s4sg685qs4wgbwlplwriawrwi6jq79z37frcnpyc89gpvm";
1859 sha256 = "1k8l3s4mvshza1zay6dfxprq54fyb5dc85dqdva9wa3f466y0adk";
1824 };
1860 };
1825 meta = {
1861 meta = {
1826 license = [ { fullName = "Apache 2.0 and Proprietary"; } ];
1862 license = [ { fullName = "Apache 2.0 and Proprietary"; } ];
@@ -1864,11 +1900,11 b' self: super: {'
1864 };
1900 };
1865 };
1901 };
1866 "setuptools" = super.buildPythonPackage {
1902 "setuptools" = super.buildPythonPackage {
1867 name = "setuptools-40.6.2";
1903 name = "setuptools-40.8.0";
1868 doCheck = false;
1904 doCheck = false;
1869 src = fetchurl {
1905 src = fetchurl {
1870 url = "https://files.pythonhosted.org/packages/b0/d1/8acb42f391cba52e35b131e442e80deffbb8d0676b93261d761b1f0ef8fb/setuptools-40.6.2.zip";
1906 url = "https://files.pythonhosted.org/packages/c2/f7/c7b501b783e5a74cf1768bc174ee4fb0a8a6ee5af6afa92274ff964703e0/setuptools-40.8.0.zip";
1871 sha256 = "0r2c5hapirlzm34h7pl1lgkm6gk7bcrlrdj28qgsvaqg3f74vfw6";
1907 sha256 = "0k9hifpgahnw2a26w3cr346iy733k6d3nwh3f7g9m13y6f8fqkkf";
1872 };
1908 };
1873 meta = {
1909 meta = {
1874 license = [ pkgs.lib.licenses.mit ];
1910 license = [ pkgs.lib.licenses.mit ];
@@ -1897,11 +1933,11 b' self: super: {'
1897 };
1933 };
1898 };
1934 };
1899 "simplejson" = super.buildPythonPackage {
1935 "simplejson" = super.buildPythonPackage {
1900 name = "simplejson-3.11.1";
1936 name = "simplejson-3.16.0";
1901 doCheck = false;
1937 doCheck = false;
1902 src = fetchurl {
1938 src = fetchurl {
1903 url = "https://files.pythonhosted.org/packages/08/48/c97b668d6da7d7bebe7ea1817a6f76394b0ec959cb04214ca833c34359df/simplejson-3.11.1.tar.gz";
1939 url = "https://files.pythonhosted.org/packages/e3/24/c35fb1c1c315fc0fffe61ea00d3f88e85469004713dab488dee4f35b0aff/simplejson-3.16.0.tar.gz";
1904 sha256 = "1rr58dppsq73p0qcd9bsw066cdd3v63sqv7j6sqni8frvm4jv8h1";
1940 sha256 = "19cws1syk8jzq2pw43878dv6fjkb0ifvjpx0i9aajix6kc9jkwxi";
1905 };
1941 };
1906 meta = {
1942 meta = {
1907 license = [ { fullName = "Academic Free License (AFL)"; } pkgs.lib.licenses.mit ];
1943 license = [ { fullName = "Academic Free License (AFL)"; } pkgs.lib.licenses.mit ];
@@ -1945,25 +1981,25 b' self: super: {'
1945 };
1981 };
1946 };
1982 };
1947 "subprocess32" = super.buildPythonPackage {
1983 "subprocess32" = super.buildPythonPackage {
1948 name = "subprocess32-3.5.2";
1984 name = "subprocess32-3.5.3";
1949 doCheck = false;
1985 doCheck = false;
1950 src = fetchurl {
1986 src = fetchurl {
1951 url = "https://files.pythonhosted.org/packages/c3/5f/7117737fc7114061837a4f51670d863dd7f7f9c762a6546fa8a0dcfe61c8/subprocess32-3.5.2.tar.gz";
1987 url = "https://files.pythonhosted.org/packages/be/2b/beeba583e9877e64db10b52a96915afc0feabf7144dcbf2a0d0ea68bf73d/subprocess32-3.5.3.tar.gz";
1952 sha256 = "11v62shwmdys48g7ncs3a8jwwnkcl8d4zcwy6dk73z1zy2f9hazb";
1988 sha256 = "1hr5fan8i719hmlmz73hf8rhq74014w07d8ryg7krvvf6692kj3b";
1953 };
1989 };
1954 meta = {
1990 meta = {
1955 license = [ pkgs.lib.licenses.psfl ];
1991 license = [ pkgs.lib.licenses.psfl ];
1956 };
1992 };
1957 };
1993 };
1958 "supervisor" = super.buildPythonPackage {
1994 "supervisor" = super.buildPythonPackage {
1959 name = "supervisor-3.3.4";
1995 name = "supervisor-3.3.5";
1960 doCheck = false;
1996 doCheck = false;
1961 propagatedBuildInputs = [
1997 propagatedBuildInputs = [
1962 self."meld3"
1998 self."meld3"
1963 ];
1999 ];
1964 src = fetchurl {
2000 src = fetchurl {
1965 url = "https://files.pythonhosted.org/packages/44/60/698e54b4a4a9b956b2d709b4b7b676119c833d811d53ee2500f1b5e96dc3/supervisor-3.3.4.tar.gz";
2001 url = "https://files.pythonhosted.org/packages/ba/65/92575a8757ed576beaee59251f64a3287bde82bdc03964b89df9e1d29e1b/supervisor-3.3.5.tar.gz";
1966 sha256 = "0wp62z9xprvz2krg02xnbwcnq6pxfq3byd8cxx8c2d8xznih28i1";
2002 sha256 = "1w3ahridzbc6rxfpbyx8lij6pjlcgf2ymzyg53llkjqxalp6sk8v";
1967 };
2003 };
1968 meta = {
2004 meta = {
1969 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2005 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
@@ -2059,11 +2095,11 b' self: super: {'
2059 };
2095 };
2060 };
2096 };
2061 "urllib3" = super.buildPythonPackage {
2097 "urllib3" = super.buildPythonPackage {
2062 name = "urllib3-1.21";
2098 name = "urllib3-1.24.1";
2063 doCheck = false;
2099 doCheck = false;
2064 src = fetchurl {
2100 src = fetchurl {
2065 url = "https://files.pythonhosted.org/packages/34/95/7b28259d0006ed681c424cd71a668363265eac92b67dddd018eb9a22bff8/urllib3-1.21.tar.gz";
2101 url = "https://files.pythonhosted.org/packages/b1/53/37d82ab391393565f2f831b8eedbffd57db5a718216f82f1a8b4d381a1c1/urllib3-1.24.1.tar.gz";
2066 sha256 = "0irnj4wvh2y36s4q3l2vas9qr9m766w6w418nb490j3mf8a8zw6h";
2102 sha256 = "08lwd9f3hqznyf32vnzwvp87pchx062nkbgyrf67rwlkgj0jk5fy";
2067 };
2103 };
2068 meta = {
2104 meta = {
2069 license = [ pkgs.lib.licenses.mit ];
2105 license = [ pkgs.lib.licenses.mit ];
@@ -2081,22 +2117,22 b' self: super: {'
2081 };
2117 };
2082 };
2118 };
2083 "venusian" = super.buildPythonPackage {
2119 "venusian" = super.buildPythonPackage {
2084 name = "venusian-1.1.0";
2120 name = "venusian-1.2.0";
2085 doCheck = false;
2121 doCheck = false;
2086 src = fetchurl {
2122 src = fetchurl {
2087 url = "https://files.pythonhosted.org/packages/38/24/b4b470ab9e0a2e2e9b9030c7735828c8934b4c6b45befd1bb713ec2aeb2d/venusian-1.1.0.tar.gz";
2123 url = "https://files.pythonhosted.org/packages/7e/6f/40a9d43ac77cb51cb62be5b5662d170f43f8037bdc4eab56336c4ca92bb7/venusian-1.2.0.tar.gz";
2088 sha256 = "0zapz131686qm0gazwy8bh11vr57pr89jbwbl50s528sqy9f80lr";
2124 sha256 = "0ghyx66g8ikx9nx1mnwqvdcqm11i1vlq0hnvwl50s48bp22q5v34";
2089 };
2125 };
2090 meta = {
2126 meta = {
2091 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2127 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2092 };
2128 };
2093 };
2129 };
2094 "vine" = super.buildPythonPackage {
2130 "vine" = super.buildPythonPackage {
2095 name = "vine-1.1.4";
2131 name = "vine-1.2.0";
2096 doCheck = false;
2132 doCheck = false;
2097 src = fetchurl {
2133 src = fetchurl {
2098 url = "https://files.pythonhosted.org/packages/32/23/36284986e011f3c130d802c3c66abd8f1aef371eae110ddf80c5ae22e1ff/vine-1.1.4.tar.gz";
2134 url = "https://files.pythonhosted.org/packages/46/1a/c94317efa98040c5d50fe3cf9080cafb0372ff5afb0283dc018c751c6746/vine-1.2.0.tar.gz";
2099 sha256 = "0wkskb2hb494v9gixqnf4bl972p4ibcmxdykzpwjlfa5picns4aj";
2135 sha256 = "0xjz2sjbr5jrpjk411b7alkghdskhphgsqqrbi7abqfh2pli6j7f";
2100 };
2136 };
2101 meta = {
2137 meta = {
2102 license = [ pkgs.lib.licenses.bsdOriginal ];
2138 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -2182,18 +2218,18 b' self: super: {'
2182 };
2218 };
2183 };
2219 };
2184 "webob" = super.buildPythonPackage {
2220 "webob" = super.buildPythonPackage {
2185 name = "webob-1.7.4";
2221 name = "webob-1.8.4";
2186 doCheck = false;
2222 doCheck = false;
2187 src = fetchurl {
2223 src = fetchurl {
2188 url = "https://files.pythonhosted.org/packages/75/34/731e23f52371852dfe7490a61644826ba7fe70fd52a377aaca0f4956ba7f/WebOb-1.7.4.tar.gz";
2224 url = "https://files.pythonhosted.org/packages/e4/6c/99e322c3d4cc11d9060a67a9bf2f7c9c581f40988c11fffe89bb8c36bc5e/WebOb-1.8.4.tar.gz";
2189 sha256 = "1na01ljg04z40il7vcrn8g29vaw7nvg1xvhk64cr4jys5wcay44d";
2225 sha256 = "16cfg5y4n6sihz59vsmns2yqbfm0gfsn3l5xgz2g0pdhilaib0x4";
2190 };
2226 };
2191 meta = {
2227 meta = {
2192 license = [ pkgs.lib.licenses.mit ];
2228 license = [ pkgs.lib.licenses.mit ];
2193 };
2229 };
2194 };
2230 };
2195 "webtest" = super.buildPythonPackage {
2231 "webtest" = super.buildPythonPackage {
2196 name = "webtest-2.0.29";
2232 name = "webtest-2.0.32";
2197 doCheck = false;
2233 doCheck = false;
2198 propagatedBuildInputs = [
2234 propagatedBuildInputs = [
2199 self."six"
2235 self."six"
@@ -2202,8 +2238,8 b' self: super: {'
2202 self."beautifulsoup4"
2238 self."beautifulsoup4"
2203 ];
2239 ];
2204 src = fetchurl {
2240 src = fetchurl {
2205 url = "https://files.pythonhosted.org/packages/94/de/8f94738be649997da99c47b104aa3c3984ecec51a1d8153ed09638253d56/WebTest-2.0.29.tar.gz";
2241 url = "https://files.pythonhosted.org/packages/27/9f/9e74449d272ffbef4fb3012e6dbc53c0b24822d545e7a33a342f80131e59/WebTest-2.0.32.tar.gz";
2206 sha256 = "0bcj1ica5lnmj5zbvk46x28kgphcsgh7sfnwjmn0cr94mhawrg6v";
2242 sha256 = "0qp0nnbazzm4ibjiyqfcn6f230svk09i4g58zg2i9x1ga06h48a2";
2207 };
2243 };
2208 meta = {
2244 meta = {
2209 license = [ pkgs.lib.licenses.mit ];
2245 license = [ pkgs.lib.licenses.mit ];
@@ -1,12 +1,15 b''
1 # This file defines how to "build" for packaging.
1 # This file defines how to "build" for packaging.
2
2
3 { doCheck ? false
3 { pkgs ? import <nixpkgs> {}
4 , system ? builtins.currentSystem
5 , doCheck ? false
4 }:
6 }:
5
7
6 let
8 let
7 enterprise_ce = import ./default.nix {
9 enterprise_ce = import ./default.nix {
8 inherit
10 inherit
9 doCheck;
11 doCheck
12 system;
10
13
11 # disable checkPhase for build
14 # disable checkPhase for build
12 checkPhase = ''
15 checkPhase = ''
@@ -12,7 +12,7 b' bleach==3.0.2'
12 celery==4.1.1
12 celery==4.1.1
13 chameleon==2.24
13 chameleon==2.24
14 channelstream==0.5.2
14 channelstream==0.5.2
15 click==6.6
15 click==7.0
16 colander==1.5.1
16 colander==1.5.1
17 # our custom configobj
17 # our custom configobj
18 https://code.rhodecode.com/upstream/configobj/archive/a11ff0a0bd4fbda9e3a91267e720f88329efb4a6.tar.gz?md5=9916c524ea11a6c418217af6b28d4b3c#egg=configobj==5.0.6
18 https://code.rhodecode.com/upstream/configobj/archive/a11ff0a0bd4fbda9e3a91267e720f88329efb4a6.tar.gz?md5=9916c524ea11a6c418217af6b28d4b3c#egg=configobj==5.0.6
@@ -20,7 +20,7 b' cssselect==1.0.3'
20 decorator==4.1.2
20 decorator==4.1.2
21 deform==2.0.7
21 deform==2.0.7
22 docutils==0.14.0
22 docutils==0.14.0
23 dogpile.cache==0.6.7
23 dogpile.cache==0.7.1
24 dogpile.core==0.4.1
24 dogpile.core==0.4.1
25 ecdsa==0.13
25 ecdsa==0.13
26 formencode==1.2.4
26 formencode==1.2.4
@@ -28,42 +28,41 b' future==0.14.3'
28 futures==3.0.2
28 futures==3.0.2
29 gnureadline==6.3.8
29 gnureadline==6.3.8
30 infrae.cache==1.0.1
30 infrae.cache==1.0.1
31 iso8601==0.1.11
31 iso8601==0.1.12
32 itsdangerous==0.24
32 itsdangerous==0.24
33 jinja2==2.9.6
33 jinja2==2.9.6
34 billiard==3.5.0.3
34 billiard==3.5.0.3
35 kombu==4.2.0
35 kombu==4.2.1
36 lxml==4.2.5
36 lxml==4.2.5
37 mako==1.0.7
37 mako==1.0.7
38 markdown==2.6.11
38 markdown==2.6.11
39 markupsafe==1.0.0
39 markupsafe==1.1.0
40 msgpack-python==0.5.6
40 msgpack-python==0.5.6
41 pyotp==2.2.7
41 pyotp==2.2.7
42 packaging==15.2
42 packaging==15.2
43 paste==2.0.3
43 paste==3.0.5
44 pastedeploy==1.5.2
44 pastedeploy==2.0.1
45 pastescript==2.0.2
45 pastescript==3.0.0
46 pathlib2==2.3.2
46 pathlib2==2.3.3
47 peppercorn==0.6
47 peppercorn==0.6
48 psutil==5.4.7
48 psutil==5.4.8
49 py-bcrypt==0.4
49 py-bcrypt==0.4
50 pycrypto==2.6.1
50 pycrypto==2.6.1
51 pycurl==7.43.0.2
51 pycurl==7.43.0.2
52 pyflakes==0.8.1
52 pyflakes==0.8.1
53 pygments-markdown-lexer==0.1.0.dev39
53 pygments==2.3.1
54 pygments==2.3.0
54 pyparsing==2.3.0
55 pyparsing==1.5.7
56 pyramid-beaker==0.8
55 pyramid-beaker==0.8
57 pyramid-debugtoolbar==4.4.0
56 pyramid-debugtoolbar==4.5.0
58 pyramid-jinja2==2.7
57 pyramid-jinja2==2.7
59 pyramid-mako==1.0.2
58 pyramid-mako==1.0.2
60 pyramid==1.9.2
59 pyramid==1.10.1
61 pyramid_mailer==0.15.1
60 pyramid_mailer==0.15.1
62 python-dateutil
61 python-dateutil
63 python-ldap==3.1.0
62 python-ldap==3.1.0
64 python-memcached==1.59
63 python-memcached==1.59
65 python-pam==1.8.4
64 python-pam==1.8.4
66 python-saml
65 python-saml==2.4.2
67 pytz==2018.4
66 pytz==2018.4
68 tzlocal==1.5.1
67 tzlocal==1.5.1
69 pyzmq==14.6.0
68 pyzmq==14.6.0
@@ -72,21 +71,21 b' redis==2.10.6'
72 repoze.lru==0.7
71 repoze.lru==0.7
73 requests==2.9.1
72 requests==2.9.1
74 routes==2.4.1
73 routes==2.4.1
75 simplejson==3.11.1
74 simplejson==3.16.0
76 six==1.11.0
75 six==1.11.0
77 sqlalchemy==1.1.18
76 sqlalchemy==1.1.18
78 sshpubkeys==2.2.0
77 sshpubkeys==2.2.0
79 subprocess32==3.5.2
78 subprocess32==3.5.3
80 supervisor==3.3.4
79 supervisor==3.3.5
81 tempita==0.5.2
80 tempita==0.5.2
82 translationstring==1.3
81 translationstring==1.3
83 urllib3==1.21
82 urllib3==1.24.1
84 urlobject==2.4.3
83 urlobject==2.4.3
85 venusian==1.1.0
84 venusian==1.2.0
86 weberror==0.10.3
85 weberror==0.10.3
87 webhelpers2==2.0
86 webhelpers2==2.0
88 webhelpers==1.3
87 webhelpers==1.3
89 webob==1.7.4
88 webob==1.8.4
90 whoosh==2.7.4
89 whoosh==2.7.4
91 wsgiref==0.1.2
90 wsgiref==0.1.2
92 zope.cachedescriptors==4.3.1
91 zope.cachedescriptors==4.3.1
@@ -113,7 +112,7 b' invoke==0.13.0'
113 bumpversion==0.5.3
112 bumpversion==0.5.3
114
113
115 ## http servers
114 ## http servers
116 gevent==1.3.7
115 gevent==1.4.0
117 greenlet==0.4.15
116 greenlet==0.4.15
118 gunicorn==19.9.0
117 gunicorn==19.9.0
119 waitress==1.1.0
118 waitress==1.1.0
@@ -124,7 +123,7 b' ipdb==0.11.0'
124 ipython==5.1.0
123 ipython==5.1.0
125
124
126 ## rhodecode-tools, special case
125 ## rhodecode-tools, special case
127 https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.0.1.tar.gz?md5=ffb5d6bcb855305b93cfe23ad42e500b#egg=rhodecode-tools==1.0.1
126 https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.2.1.tar.gz?md5=25bc2f7de1da318e547236d3fb463d28#egg=rhodecode-tools==1.2.1
128
127
129 ## appenlight
128 ## appenlight
130 appenlight-client==0.6.26
129 appenlight-client==0.6.26
@@ -9,6 +9,8 b' pytest-timeout==1.3.2'
9 gprof2dot==2017.9.19
9 gprof2dot==2017.9.19
10
10
11 mock==1.0.1
11 mock==1.0.1
12 webtest==2.0.29
13 cov-core==1.15.0
12 cov-core==1.15.0
14 coverage==4.5.1
13 coverage==4.5.1
14
15 webtest==2.0.32
16 beautifulsoup4==4.6.3
@@ -1,1 +1,1 b''
1 4.15.2 No newline at end of file
1 4.16.0 No newline at end of file
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -18,12 +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 """
22
23 RhodeCode, a web based repository management software
24 versioning implementation: http://www.python.org/dev/peps/pep-0386/
25 """
26
27 import os
21 import os
28 import sys
22 import sys
29 import platform
23 import platform
@@ -51,7 +45,7 b' PYRAMID_SETTINGS = {}'
51 EXTENSIONS = {}
45 EXTENSIONS = {}
52
46
53 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
47 __version__ = ('.'.join((str(each) for each in VERSION[:3])))
54 __dbversion__ = 91 # defines current db version for migrations
48 __dbversion__ = 95 # defines current db version for migrations
55 __platform__ = platform.system()
49 __platform__ = platform.system()
56 __license__ = 'AGPLv3, and Commercial License'
50 __license__ = 'AGPLv3, and Commercial License'
57 __author__ = 'RhodeCode GmbH'
51 __author__ = 'RhodeCode GmbH'
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -21,6 +21,7 b''
21 import inspect
21 import inspect
22 import itertools
22 import itertools
23 import logging
23 import logging
24 import sys
24 import types
25 import types
25 import fnmatch
26 import fnmatch
26
27
@@ -38,6 +39,7 b' from rhodecode.api.exc import ('
38 from rhodecode.apps._base import TemplateArgs
39 from rhodecode.apps._base import TemplateArgs
39 from rhodecode.lib.auth import AuthUser
40 from rhodecode.lib.auth import AuthUser
40 from rhodecode.lib.base import get_ip_addr, attach_context_attributes
41 from rhodecode.lib.base import get_ip_addr, attach_context_attributes
42 from rhodecode.lib.exc_tracking import store_exception
41 from rhodecode.lib.ext_json import json
43 from rhodecode.lib.ext_json import json
42 from rhodecode.lib.utils2 import safe_str
44 from rhodecode.lib.utils2 import safe_str
43 from rhodecode.lib.plugins.utils import get_plugin_settings
45 from rhodecode.lib.plugins.utils import get_plugin_settings
@@ -140,15 +142,14 b' def jsonrpc_error(request, message, reti'
140 def exception_view(exc, request):
142 def exception_view(exc, request):
141 rpc_id = getattr(request, 'rpc_id', None)
143 rpc_id = getattr(request, 'rpc_id', None)
142
144
143 fault_message = 'undefined error'
144 if isinstance(exc, JSONRPCError):
145 if isinstance(exc, JSONRPCError):
145 fault_message = exc.message
146 fault_message = safe_str(exc.message)
146 log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
147 log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
147 elif isinstance(exc, JSONRPCValidationError):
148 elif isinstance(exc, JSONRPCValidationError):
148 colander_exc = exc.colander_exception
149 colander_exc = exc.colander_exception
149 # TODO(marcink): think maybe of nicer way to serialize errors ?
150 # TODO(marcink): think maybe of nicer way to serialize errors ?
150 fault_message = colander_exc.asdict()
151 fault_message = colander_exc.asdict()
151 log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
152 log.debug('json-rpc colander error rpc_id:%s "%s"', rpc_id, fault_message)
152 elif isinstance(exc, JSONRPCForbidden):
153 elif isinstance(exc, JSONRPCForbidden):
153 fault_message = 'Access was denied to this resource.'
154 fault_message = 'Access was denied to this resource.'
154 log.warning('json-rpc forbidden call rpc_id:%s "%s"', rpc_id, fault_message)
155 log.warning('json-rpc forbidden call rpc_id:%s "%s"', rpc_id, fault_message)
@@ -170,6 +171,10 b' def exception_view(exc, request):'
170
171
171 fault_message = "No such method: {}. Similar methods: {}".format(
172 fault_message = "No such method: {}. Similar methods: {}".format(
172 method, similar)
173 method, similar)
174 else:
175 fault_message = 'undefined error'
176 exc_info = exc.exc_info()
177 store_exception(id(exc_info), exc_info, prefix='rhodecode-api')
173
178
174 return jsonrpc_error(request, fault_message, rpc_id)
179 return jsonrpc_error(request, fault_message, rpc_id)
175
180
@@ -292,8 +297,10 b' def request_view(request):'
292 raise
297 raise
293 except Exception:
298 except Exception:
294 log.exception('Unhandled exception occurred on api call: %s', func)
299 log.exception('Unhandled exception occurred on api call: %s', func)
295 return jsonrpc_error(request, retid=request.rpc_id,
300 exc_info = sys.exc_info()
296 message='Internal server error')
301 store_exception(id(exc_info), exc_info, prefix='rhodecode-api')
302 return jsonrpc_error(
303 request, retid=request.rpc_id, message='Internal server error')
297
304
298
305
299 def setup_request(request):
306 def setup_request(request):
@@ -414,8 +421,7 b' def add_jsonrpc_method(config, view, **k'
414
421
415 if method is None:
422 if method is None:
416 raise ConfigurationError(
423 raise ConfigurationError(
417 'Cannot register a JSON-RPC method without specifying the '
424 'Cannot register a JSON-RPC method without specifying the "method"')
418 '"method"')
419
425
420 # we define custom predicate, to enable to detect conflicting methods,
426 # we define custom predicate, to enable to detect conflicting methods,
421 # those predicates are kind of "translation" from the decorator variables
427 # those predicates are kind of "translation" from the decorator variables
@@ -524,6 +530,7 b' def includeme(config):'
524
530
525 # match filter by given method only
531 # match filter by given method only
526 config.add_view_predicate('jsonrpc_method', MethodPredicate)
532 config.add_view_predicate('jsonrpc_method', MethodPredicate)
533 config.add_view_predicate('jsonrpc_method_not_found', NotFoundPredicate)
527
534
528 config.add_renderer(DEFAULT_RENDERER, ExtJsonRenderer(
535 config.add_renderer(DEFAULT_RENDERER, ExtJsonRenderer(
529 serializer=json.dumps, indent=4))
536 serializer=json.dumps, indent=4))
@@ -538,5 +545,4 b' def includeme(config):'
538 config.scan(plugin_module, ignore='rhodecode.api.tests')
545 config.scan(plugin_module, ignore='rhodecode.api.tests')
539 # register some exception handling view
546 # register some exception handling view
540 config.add_view(exception_view, context=JSONRPCBaseError)
547 config.add_view(exception_view, context=JSONRPCBaseError)
541 config.add_view_predicate('jsonrpc_method_not_found', NotFoundPredicate)
542 config.add_notfound_view(exception_view, jsonrpc_method_not_found=True)
548 config.add_notfound_view(exception_view, jsonrpc_method_not_found=True)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -86,7 +86,9 b' class TestApi(object):'
86 def test_api_non_existing_method_have_similar(self, request):
86 def test_api_non_existing_method_have_similar(self, request):
87 id_, params = build_data(self.apikey, 'comment', args='xx')
87 id_, params = build_data(self.apikey, 'comment', args='xx')
88 response = api_call(self.app, params)
88 response = api_call(self.app, params)
89 expected = 'No such method: comment. Similar methods: changeset_comment, comment_pull_request, get_pull_request_comments, comment_commit'
89 expected = 'No such method: comment. ' \
90 'Similar methods: changeset_comment, comment_pull_request, ' \
91 'get_pull_request_comments, comment_commit, get_repo_comments'
90 assert_error(id_, expected, given=response.body)
92 assert_error(id_, expected, given=response.body)
91
93
92 def test_api_disabled_user(self, request):
94 def test_api_disabled_user(self, request):
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -38,7 +38,7 b' class TestGetMethod(object):'
38 response = api_call(self.app, params)
38 response = api_call(self.app, params)
39
39
40 expected = ['changeset_comment', 'comment_pull_request',
40 expected = ['changeset_comment', 'comment_pull_request',
41 'get_pull_request_comments', 'comment_commit']
41 'get_pull_request_comments', 'comment_commit', 'get_repo_comments']
42 assert_ok(id_, expected, given=response.body)
42 assert_ok(id_, expected, given=response.body)
43
43
44 def test_get_methods_on_single_match(self):
44 def test_get_methods_on_single_match(self):
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -65,6 +65,7 b' class TestGetPullRequest(object):'
65 'title': pull_request.title,
65 'title': pull_request.title,
66 'description': pull_request.description,
66 'description': pull_request.description,
67 'status': pull_request.status,
67 'status': pull_request.status,
68 'state': pull_request.pull_request_state,
68 'created_on': pull_request.created_on,
69 'created_on': pull_request.created_on,
69 'updated_on': pull_request.updated_on,
70 'updated_on': pull_request.updated_on,
70 'commit_ids': pull_request.revisions,
71 'commit_ids': pull_request.revisions,
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -59,6 +59,7 b' class TestGetPullRequestComments(object)'
59 'status_lbl': 'Under Review'},
59 'status_lbl': 'Under Review'},
60 'comment_text': 'Auto status change to |new_status|\n\n.. |new_status| replace:: *"Under Review"*',
60 'comment_text': 'Auto status change to |new_status|\n\n.. |new_status| replace:: *"Under Review"*',
61 'comment_type': 'note',
61 'comment_type': 'note',
62 'comment_resolved_by': None,
62 'pull_request_version': None}
63 'pull_request_version': None}
63 ]
64 ]
64 assert_ok(id_, expected, response.body)
65 assert_ok(id_, expected, response.body)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -29,11 +29,10 b' from rhodecode.api.tests.utils import ('
29
29
30 @pytest.mark.usefixtures("testuser_api", "app")
30 @pytest.mark.usefixtures("testuser_api", "app")
31 class TestMergePullRequest(object):
31 class TestMergePullRequest(object):
32
32 @pytest.mark.backends("git", "hg")
33 @pytest.mark.backends("git", "hg")
33 def test_api_merge_pull_request_merge_failed(self, pr_util, no_notifications):
34 def test_api_merge_pull_request_merge_failed(self, pr_util, no_notifications):
34 pull_request = pr_util.create_pull_request(mergeable=True)
35 pull_request = pr_util.create_pull_request(mergeable=True)
35 author = pull_request.user_id
36 repo = pull_request.target_repo.repo_id
37 pull_request_id = pull_request.pull_request_id
36 pull_request_id = pull_request.pull_request_id
38 pull_request_repo = pull_request.target_repo.repo_name
37 pull_request_repo = pull_request.target_repo.repo_name
39
38
@@ -46,8 +45,7 b' class TestMergePullRequest(object):'
46
45
47 # The above api call detaches the pull request DB object from the
46 # The above api call detaches the pull request DB object from the
48 # session because of an unconditional transaction rollback in our
47 # session because of an unconditional transaction rollback in our
49 # middleware. Therefore we need to add it back here if we want to use
48 # middleware. Therefore we need to add it back here if we want to use it.
50 # it.
51 Session().add(pull_request)
49 Session().add(pull_request)
52
50
53 expected = 'merge not possible for following reasons: ' \
51 expected = 'merge not possible for following reasons: ' \
@@ -55,6 +53,29 b' class TestMergePullRequest(object):'
55 assert_error(id_, expected, given=response.body)
53 assert_error(id_, expected, given=response.body)
56
54
57 @pytest.mark.backends("git", "hg")
55 @pytest.mark.backends("git", "hg")
56 def test_api_merge_pull_request_merge_failed_disallowed_state(
57 self, pr_util, no_notifications):
58 pull_request = pr_util.create_pull_request(mergeable=True, approved=True)
59 pull_request_id = pull_request.pull_request_id
60 pull_request_repo = pull_request.target_repo.repo_name
61
62 pr = PullRequest.get(pull_request_id)
63 pr.pull_request_state = pull_request.STATE_UPDATING
64 Session().add(pr)
65 Session().commit()
66
67 id_, params = build_data(
68 self.apikey, 'merge_pull_request',
69 repoid=pull_request_repo,
70 pullrequestid=pull_request_id)
71
72 response = api_call(self.app, params)
73 expected = 'Operation forbidden because pull request is in state {}, '\
74 'only state {} is allowed.'.format(PullRequest.STATE_UPDATING,
75 PullRequest.STATE_CREATED)
76 assert_error(id_, expected, given=response.body)
77
78 @pytest.mark.backends("git", "hg")
58 def test_api_merge_pull_request(self, pr_util, no_notifications):
79 def test_api_merge_pull_request(self, pr_util, no_notifications):
59 pull_request = pr_util.create_pull_request(mergeable=True, approved=True)
80 pull_request = pr_util.create_pull_request(mergeable=True, approved=True)
60 author = pull_request.user_id
81 author = pull_request.user_id
@@ -88,6 +109,7 b' class TestMergePullRequest(object):'
88 expected = {
109 expected = {
89 'executed': True,
110 'executed': True,
90 'failure_reason': 0,
111 'failure_reason': 0,
112 'merge_status_message': 'This pull request can be automatically merged.',
91 'possible': True,
113 'possible': True,
92 'merge_commit_id': pull_request.shadow_merge_ref.commit_id,
114 'merge_commit_id': pull_request.shadow_merge_ref.commit_id,
93 'merge_ref': pull_request.shadow_merge_ref._asdict()
115 'merge_ref': pull_request.shadow_merge_ref._asdict()
@@ -112,6 +134,107 b' class TestMergePullRequest(object):'
112 assert_error(id_, expected, given=response.body)
134 assert_error(id_, expected, given=response.body)
113
135
114 @pytest.mark.backends("git", "hg")
136 @pytest.mark.backends("git", "hg")
137 def test_api_merge_pull_request_as_another_user_no_perms_to_merge(
138 self, pr_util, no_notifications, user_util):
139 merge_user = user_util.create_user()
140 merge_user_id = merge_user.user_id
141 merge_user_username = merge_user.username
142
143 pull_request = pr_util.create_pull_request(mergeable=True, approved=True)
144
145 pull_request_id = pull_request.pull_request_id
146 pull_request_repo = pull_request.target_repo.repo_name
147
148 id_, params = build_data(
149 self.apikey, 'comment_pull_request',
150 repoid=pull_request_repo,
151 pullrequestid=pull_request_id,
152 status='approved')
153
154 response = api_call(self.app, params)
155 expected = {
156 'comment_id': response.json.get('result', {}).get('comment_id'),
157 'pull_request_id': pull_request_id,
158 'status': {'given': 'approved', 'was_changed': True}
159 }
160 assert_ok(id_, expected, given=response.body)
161 id_, params = build_data(
162 self.apikey, 'merge_pull_request',
163 repoid=pull_request_repo,
164 pullrequestid=pull_request_id,
165 userid=merge_user_id
166 )
167
168 response = api_call(self.app, params)
169 expected = 'merge not possible for following reasons: User `{}` ' \
170 'not allowed to perform merge.'.format(merge_user_username)
171 assert_error(id_, expected, response.body)
172
173 @pytest.mark.backends("git", "hg")
174 def test_api_merge_pull_request_as_another_user(self, pr_util, no_notifications, user_util):
175 merge_user = user_util.create_user()
176 merge_user_id = merge_user.user_id
177 pull_request = pr_util.create_pull_request(mergeable=True, approved=True)
178 user_util.grant_user_permission_to_repo(
179 pull_request.target_repo, merge_user, 'repository.write')
180 author = pull_request.user_id
181 repo = pull_request.target_repo.repo_id
182 pull_request_id = pull_request.pull_request_id
183 pull_request_repo = pull_request.target_repo.repo_name
184
185 id_, params = build_data(
186 self.apikey, 'comment_pull_request',
187 repoid=pull_request_repo,
188 pullrequestid=pull_request_id,
189 status='approved')
190
191 response = api_call(self.app, params)
192 expected = {
193 'comment_id': response.json.get('result', {}).get('comment_id'),
194 'pull_request_id': pull_request_id,
195 'status': {'given': 'approved', 'was_changed': True}
196 }
197 assert_ok(id_, expected, given=response.body)
198
199 id_, params = build_data(
200 self.apikey, 'merge_pull_request',
201 repoid=pull_request_repo,
202 pullrequestid=pull_request_id,
203 userid=merge_user_id
204 )
205
206 response = api_call(self.app, params)
207
208 pull_request = PullRequest.get(pull_request_id)
209
210 expected = {
211 'executed': True,
212 'failure_reason': 0,
213 'merge_status_message': 'This pull request can be automatically merged.',
214 'possible': True,
215 'merge_commit_id': pull_request.shadow_merge_ref.commit_id,
216 'merge_ref': pull_request.shadow_merge_ref._asdict()
217 }
218
219 assert_ok(id_, expected, response.body)
220
221 journal = UserLog.query() \
222 .filter(UserLog.user_id == merge_user_id) \
223 .filter(UserLog.repository_id == repo) \
224 .order_by('user_log_id') \
225 .all()
226 assert journal[-2].action == 'repo.pull_request.merge'
227 assert journal[-1].action == 'repo.pull_request.close'
228
229 id_, params = build_data(
230 self.apikey, 'merge_pull_request',
231 repoid=pull_request_repo, pullrequestid=pull_request_id, userid=merge_user_id)
232 response = api_call(self.app, params)
233
234 expected = 'merge not possible for following reasons: This pull request is closed.'
235 assert_error(id_, expected, given=response.body)
236
237 @pytest.mark.backends("git", "hg")
115 def test_api_merge_pull_request_repo_error(self, pr_util):
238 def test_api_merge_pull_request_repo_error(self, pr_util):
116 pull_request = pr_util.create_pull_request()
239 pull_request = pr_util.create_pull_request()
117 id_, params = build_data(
240 id_, params = build_data(
@@ -123,8 +246,7 b' class TestMergePullRequest(object):'
123 assert_error(id_, expected, given=response.body)
246 assert_error(id_, expected, given=response.body)
124
247
125 @pytest.mark.backends("git", "hg")
248 @pytest.mark.backends("git", "hg")
126 def test_api_merge_pull_request_non_admin_with_userid_error(self,
249 def test_api_merge_pull_request_non_admin_with_userid_error(self, pr_util):
127 pr_util):
128 pull_request = pr_util.create_pull_request(mergeable=True)
250 pull_request = pr_util.create_pull_request(mergeable=True)
129 id_, params = build_data(
251 id_, params = build_data(
130 self.apikey_regular, 'merge_pull_request',
252 self.apikey_regular, 'merge_pull_request',
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -28,6 +28,19 b' from rhodecode.lib.ext_json import json'
28 API_URL = '/_admin/api'
28 API_URL = '/_admin/api'
29
29
30
30
31 def assert_call_ok(id_, given):
32 expected = jsonify({
33 'id': id_,
34 'error': None,
35 'result': None
36 })
37 given = json.loads(given)
38
39 assert expected['id'] == given['id']
40 assert expected['error'] == given['error']
41 return given['result']
42
43
31 def assert_ok(id_, expected, given):
44 def assert_ok(id_, expected, given):
32 expected = jsonify({
45 expected = jsonify({
33 'id': id_,
46 'id': id_,
@@ -55,8 +68,6 b' def jsonify(obj):'
55 def build_data(apikey, method, **kw):
68 def build_data(apikey, method, **kw):
56 """
69 """
57 Builds API data with given random ID
70 Builds API data with given random ID
58
59 :param random_id:
60 """
71 """
61 random_id = random.randrange(1, 9999)
72 random_id = random.randrange(1, 9999)
62 return random_id, json.dumps({
73 return random_id, json.dumps({
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2014-2018 RhodeCode GmbH
3 # Copyright (C) 2014-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -30,7 +30,7 b' from rhodecode.lib.auth import ('
30 HasPermissionAnyApi, HasRepoPermissionAnyApi, HasRepoGroupPermissionAnyApi)
30 HasPermissionAnyApi, HasRepoPermissionAnyApi, HasRepoGroupPermissionAnyApi)
31 from rhodecode.lib.utils import safe_unicode
31 from rhodecode.lib.utils import safe_unicode
32 from rhodecode.lib.vcs.exceptions import RepositoryError
32 from rhodecode.lib.vcs.exceptions import RepositoryError
33 from rhodecode.controllers.utils import get_commit_from_ref_name
33 from rhodecode.lib.view_utils import get_commit_from_ref_name
34 from rhodecode.lib.utils2 import str2bool
34 from rhodecode.lib.utils2 import str2bool
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2015-2018 RhodeCode GmbH
3 # Copyright (C) 2015-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -26,13 +26,13 b' from rhodecode.api import jsonrpc_method'
26 from rhodecode.api.utils import (
26 from rhodecode.api.utils import (
27 has_superadmin_permission, Optional, OAttr, get_repo_or_error,
27 has_superadmin_permission, Optional, OAttr, get_repo_or_error,
28 get_pull_request_or_error, get_commit_or_error, get_user_or_error,
28 get_pull_request_or_error, get_commit_or_error, get_user_or_error,
29 validate_repo_permissions, resolve_ref_or_error)
29 validate_repo_permissions, resolve_ref_or_error, validate_set_owner_permissions)
30 from rhodecode.lib.auth import (HasRepoPermissionAnyApi)
30 from rhodecode.lib.auth import (HasRepoPermissionAnyApi)
31 from rhodecode.lib.base import vcs_operation_context
31 from rhodecode.lib.base import vcs_operation_context
32 from rhodecode.lib.utils2 import str2bool
32 from rhodecode.lib.utils2 import str2bool
33 from rhodecode.model.changeset_status import ChangesetStatusModel
33 from rhodecode.model.changeset_status import ChangesetStatusModel
34 from rhodecode.model.comment import CommentsModel
34 from rhodecode.model.comment import CommentsModel
35 from rhodecode.model.db import Session, ChangesetStatus, ChangesetComment
35 from rhodecode.model.db import Session, ChangesetStatus, ChangesetComment, PullRequest
36 from rhodecode.model.pull_request import PullRequestModel, MergeCheck
36 from rhodecode.model.pull_request import PullRequestModel, MergeCheck
37 from rhodecode.model.settings import SettingsModel
37 from rhodecode.model.settings import SettingsModel
38 from rhodecode.model.validation_schema import Invalid
38 from rhodecode.model.validation_schema import Invalid
@@ -128,16 +128,21 b' def get_pull_request(request, apiuser, p'
128 else:
128 else:
129 repo = pull_request.target_repo
129 repo = pull_request.target_repo
130
130
131 if not PullRequestModel().check_user_read(
131 if not PullRequestModel().check_user_read(pull_request, apiuser, api=True):
132 pull_request, apiuser, api=True):
133 raise JSONRPCError('repository `%s` or pull request `%s` '
132 raise JSONRPCError('repository `%s` or pull request `%s` '
134 'does not exist' % (repoid, pullrequestid))
133 'does not exist' % (repoid, pullrequestid))
135 data = pull_request.get_api_data()
134
135 # NOTE(marcink): only calculate and return merge state if the pr state is 'created'
136 # otherwise we can lock the repo on calculation of merge state while update/merge
137 # is happening.
138 merge_state = pull_request.pull_request_state == pull_request.STATE_CREATED
139 data = pull_request.get_api_data(with_merge_state=merge_state)
136 return data
140 return data
137
141
138
142
139 @jsonrpc_method()
143 @jsonrpc_method()
140 def get_pull_requests(request, apiuser, repoid, status=Optional('new')):
144 def get_pull_requests(request, apiuser, repoid, status=Optional('new'),
145 merge_state=Optional(True)):
141 """
146 """
142 Get all pull requests from the repository specified in `repoid`.
147 Get all pull requests from the repository specified in `repoid`.
143
148
@@ -151,6 +156,9 b' def get_pull_requests(request, apiuser, '
151 * ``open``
156 * ``open``
152 * ``closed``
157 * ``closed``
153 :type status: str
158 :type status: str
159 :param merge_state: Optional calculate merge state for each repository.
160 This could result in longer time to fetch the data
161 :type merge_state: bool
154
162
155 Example output:
163 Example output:
156
164
@@ -228,8 +236,10 b' def get_pull_requests(request, apiuser, '
228 validate_repo_permissions(apiuser, repoid, repo, _perms)
236 validate_repo_permissions(apiuser, repoid, repo, _perms)
229
237
230 status = Optional.extract(status)
238 status = Optional.extract(status)
231 pull_requests = PullRequestModel().get_all(repo, statuses=[status])
239 merge_state = Optional.extract(merge_state, binary=True)
232 data = [pr.get_api_data() for pr in pull_requests]
240 pull_requests = PullRequestModel().get_all(repo, statuses=[status],
241 order_by='id', order_dir='desc')
242 data = [pr.get_api_data(with_merge_state=merge_state) for pr in pull_requests]
233 return data
243 return data
234
244
235
245
@@ -259,6 +269,7 b' def merge_pull_request('
259 "result": {
269 "result": {
260 "executed": "<bool>",
270 "executed": "<bool>",
261 "failure_reason": "<int>",
271 "failure_reason": "<int>",
272 "merge_status_message": "<str>",
262 "merge_commit_id": "<merge_commit_id>",
273 "merge_commit_id": "<merge_commit_id>",
263 "possible": "<bool>",
274 "possible": "<bool>",
264 "merge_ref": {
275 "merge_ref": {
@@ -274,17 +285,25 b' def merge_pull_request('
274 repo = get_repo_or_error(repoid)
285 repo = get_repo_or_error(repoid)
275 else:
286 else:
276 repo = pull_request.target_repo
287 repo = pull_request.target_repo
277
288 auth_user = apiuser
278 if not isinstance(userid, Optional):
289 if not isinstance(userid, Optional):
279 if (has_superadmin_permission(apiuser) or
290 if (has_superadmin_permission(apiuser) or
280 HasRepoPermissionAnyApi('repository.admin')(
291 HasRepoPermissionAnyApi('repository.admin')(
281 user=apiuser, repo_name=repo.repo_name)):
292 user=apiuser, repo_name=repo.repo_name)):
282 apiuser = get_user_or_error(userid)
293 apiuser = get_user_or_error(userid)
294 auth_user = apiuser.AuthUser()
283 else:
295 else:
284 raise JSONRPCError('userid is not the same as your user')
296 raise JSONRPCError('userid is not the same as your user')
285
297
286 check = MergeCheck.validate(
298 if pull_request.pull_request_state != PullRequest.STATE_CREATED:
287 pull_request, auth_user=apiuser, translator=request.translate)
299 raise JSONRPCError(
300 'Operation forbidden because pull request is in state {}, '
301 'only state {} is allowed.'.format(
302 pull_request.pull_request_state, PullRequest.STATE_CREATED))
303
304 with pull_request.set_state(PullRequest.STATE_UPDATING):
305 check = MergeCheck.validate(pull_request, auth_user=auth_user,
306 translator=request.translate)
288 merge_possible = not check.failed
307 merge_possible = not check.failed
289
308
290 if not merge_possible:
309 if not merge_possible:
@@ -300,20 +319,20 b' def merge_pull_request('
300 target_repo = pull_request.target_repo
319 target_repo = pull_request.target_repo
301 extras = vcs_operation_context(
320 extras = vcs_operation_context(
302 request.environ, repo_name=target_repo.repo_name,
321 request.environ, repo_name=target_repo.repo_name,
303 username=apiuser.username, action='push',
322 username=auth_user.username, action='push',
304 scm=target_repo.repo_type)
323 scm=target_repo.repo_type)
324 with pull_request.set_state(PullRequest.STATE_UPDATING):
305 merge_response = PullRequestModel().merge_repo(
325 merge_response = PullRequestModel().merge_repo(
306 pull_request, apiuser, extras=extras)
326 pull_request, apiuser, extras=extras)
307 if merge_response.executed:
327 if merge_response.executed:
308 PullRequestModel().close_pull_request(
328 PullRequestModel().close_pull_request(pull_request.pull_request_id, auth_user)
309 pull_request.pull_request_id, apiuser)
310
329
311 Session().commit()
330 Session().commit()
312
331
313 # In previous versions the merge response directly contained the merge
332 # In previous versions the merge response directly contained the merge
314 # commit id. It is now contained in the merge reference object. To be
333 # commit id. It is now contained in the merge reference object. To be
315 # backwards compatible we have to extract it again.
334 # backwards compatible we have to extract it again.
316 merge_response = merge_response._asdict()
335 merge_response = merge_response.asdict()
317 merge_response['merge_commit_id'] = merge_response['merge_ref'].commit_id
336 merge_response['merge_commit_id'] = merge_response['merge_ref'].commit_id
318
337
319 return merge_response
338 return merge_response
@@ -474,14 +493,21 b' def comment_pull_request('
474 else:
493 else:
475 repo = pull_request.target_repo
494 repo = pull_request.target_repo
476
495
496 auth_user = apiuser
477 if not isinstance(userid, Optional):
497 if not isinstance(userid, Optional):
478 if (has_superadmin_permission(apiuser) or
498 if (has_superadmin_permission(apiuser) or
479 HasRepoPermissionAnyApi('repository.admin')(
499 HasRepoPermissionAnyApi('repository.admin')(
480 user=apiuser, repo_name=repo.repo_name)):
500 user=apiuser, repo_name=repo.repo_name)):
481 apiuser = get_user_or_error(userid)
501 apiuser = get_user_or_error(userid)
502 auth_user = apiuser.AuthUser()
482 else:
503 else:
483 raise JSONRPCError('userid is not the same as your user')
504 raise JSONRPCError('userid is not the same as your user')
484
505
506 if pull_request.is_closed():
507 raise JSONRPCError(
508 'pull request `%s` comment failed, pull request is closed' % (
509 pullrequestid,))
510
485 if not PullRequestModel().check_user_read(
511 if not PullRequestModel().check_user_read(
486 pull_request, apiuser, api=True):
512 pull_request, apiuser, api=True):
487 raise JSONRPCError('repository `%s` does not exist' % (repoid,))
513 raise JSONRPCError('repository `%s` does not exist' % (repoid,))
@@ -549,7 +575,7 b' def comment_pull_request('
549 renderer=renderer,
575 renderer=renderer,
550 comment_type=comment_type,
576 comment_type=comment_type,
551 resolves_comment_id=resolves_comment_id,
577 resolves_comment_id=resolves_comment_id,
552 auth_user=apiuser
578 auth_user=auth_user
553 )
579 )
554
580
555 if allowed_to_change_status and status:
581 if allowed_to_change_status and status:
@@ -589,8 +615,8 b' def comment_pull_request('
589 @jsonrpc_method()
615 @jsonrpc_method()
590 def create_pull_request(
616 def create_pull_request(
591 request, apiuser, source_repo, target_repo, source_ref, target_ref,
617 request, apiuser, source_repo, target_repo, source_ref, target_ref,
592 title=Optional(''), description=Optional(''), description_renderer=Optional(''),
618 owner=Optional(OAttr('apiuser')), title=Optional(''), description=Optional(''),
593 reviewers=Optional(None)):
619 description_renderer=Optional(''), reviewers=Optional(None)):
594 """
620 """
595 Creates a new pull request.
621 Creates a new pull request.
596
622
@@ -611,6 +637,8 b' def create_pull_request('
611 :type source_ref: str
637 :type source_ref: str
612 :param target_ref: Set the target ref name.
638 :param target_ref: Set the target ref name.
613 :type target_ref: str
639 :type target_ref: str
640 :param owner: user_id or username
641 :type owner: Optional(str)
614 :param title: Optionally Set the pull request title, it's generated otherwise
642 :param title: Optionally Set the pull request title, it's generated otherwise
615 :type title: str
643 :type title: str
616 :param description: Set the pull request description.
644 :param description: Set the pull request description.
@@ -634,6 +662,8 b' def create_pull_request('
634 _perms = ('repository.admin', 'repository.write', 'repository.read',)
662 _perms = ('repository.admin', 'repository.write', 'repository.read',)
635 validate_repo_permissions(apiuser, source_repo, source_db_repo, _perms)
663 validate_repo_permissions(apiuser, source_repo, source_db_repo, _perms)
636
664
665 owner = validate_set_owner_permissions(apiuser, owner)
666
637 full_source_ref = resolve_ref_or_error(source_ref, source_db_repo)
667 full_source_ref = resolve_ref_or_error(source_ref, source_db_repo)
638 full_target_ref = resolve_ref_or_error(target_ref, target_db_repo)
668 full_target_ref = resolve_ref_or_error(target_ref, target_db_repo)
639
669
@@ -679,7 +709,7 b' def create_pull_request('
679
709
680 # recalculate reviewers logic, to make sure we can validate this
710 # recalculate reviewers logic, to make sure we can validate this
681 reviewer_rules = get_default_reviewers_data(
711 reviewer_rules = get_default_reviewers_data(
682 apiuser.get_instance(), source_db_repo,
712 owner, source_db_repo,
683 source_commit, target_db_repo, target_commit)
713 source_commit, target_db_repo, target_commit)
684
714
685 # now MERGE our given with the calculated
715 # now MERGE our given with the calculated
@@ -706,7 +736,7 b' def create_pull_request('
706 description_renderer = Optional.extract(description_renderer) or default_system_renderer
736 description_renderer = Optional.extract(description_renderer) or default_system_renderer
707
737
708 pull_request = PullRequestModel().create(
738 pull_request = PullRequestModel().create(
709 created_by=apiuser.user_id,
739 created_by=owner.user_id,
710 source_repo=source_repo,
740 source_repo=source_repo,
711 source_ref=full_source_ref,
741 source_ref=full_source_ref,
712 target_repo=target_repo,
742 target_repo=target_repo,
@@ -844,9 +874,16 b' def update_pull_request('
844
874
845 commit_changes = {"added": [], "common": [], "removed": []}
875 commit_changes = {"added": [], "common": [], "removed": []}
846 if str2bool(Optional.extract(update_commits)):
876 if str2bool(Optional.extract(update_commits)):
877
878 if pull_request.pull_request_state != PullRequest.STATE_CREATED:
879 raise JSONRPCError(
880 'Operation forbidden because pull request is in state {}, '
881 'only state {} is allowed.'.format(
882 pull_request.pull_request_state, PullRequest.STATE_CREATED))
883
884 with pull_request.set_state(PullRequest.STATE_UPDATING):
847 if PullRequestModel().has_valid_update_type(pull_request):
885 if PullRequestModel().has_valid_update_type(pull_request):
848 update_response = PullRequestModel().update_commits(
886 update_response = PullRequestModel().update_commits(pull_request)
849 pull_request)
850 commit_changes = update_response.changes or commit_changes
887 commit_changes = update_response.changes or commit_changes
851 Session().commit()
888 Session().commit()
852
889
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -29,13 +29,15 b' from rhodecode.api.utils import ('
29 get_user_group_or_error, get_user_or_error, validate_repo_permissions,
29 get_user_group_or_error, get_user_or_error, validate_repo_permissions,
30 get_perm_or_error, parse_args, get_origin, build_commit_data,
30 get_perm_or_error, parse_args, get_origin, build_commit_data,
31 validate_set_owner_permissions)
31 validate_set_owner_permissions)
32 from rhodecode.lib import audit_logger
32 from rhodecode.lib import audit_logger, rc_cache
33 from rhodecode.lib import repo_maintenance
33 from rhodecode.lib import repo_maintenance
34 from rhodecode.lib.auth import HasPermissionAnyApi, HasUserGroupPermissionAnyApi
34 from rhodecode.lib.auth import HasPermissionAnyApi, HasUserGroupPermissionAnyApi
35 from rhodecode.lib.celerylib.utils import get_task_id
35 from rhodecode.lib.celerylib.utils import get_task_id
36 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_str
36 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_str, safe_int
37 from rhodecode.lib.ext_json import json
37 from rhodecode.lib.ext_json import json
38 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
38 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
39 from rhodecode.lib.vcs import RepositoryError
40 from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError
39 from rhodecode.model.changeset_status import ChangesetStatusModel
41 from rhodecode.model.changeset_status import ChangesetStatusModel
40 from rhodecode.model.comment import CommentsModel
42 from rhodecode.model.comment import CommentsModel
41 from rhodecode.model.db import (
43 from rhodecode.model.db import (
@@ -380,7 +382,7 b' def get_repo_changesets(request, apiuser'
380
382
381 try:
383 try:
382 commits = vcs_repo.get_commits(
384 commits = vcs_repo.get_commits(
383 start_id=start_rev, pre_load=pre_load)
385 start_id=start_rev, pre_load=pre_load, translate_tags=False)
384 except TypeError as e:
386 except TypeError as e:
385 raise JSONRPCError(safe_str(e))
387 raise JSONRPCError(safe_str(e))
386 except Exception:
388 except Exception:
@@ -428,8 +430,8 b' def get_repo_nodes(request, apiuser, rep'
428 ``all`` (default), ``files`` and ``dirs``.
430 ``all`` (default), ``files`` and ``dirs``.
429 :type ret_type: Optional(str)
431 :type ret_type: Optional(str)
430 :param details: Returns extended information about nodes, such as
432 :param details: Returns extended information about nodes, such as
431 md5, binary, and or content. The valid options are ``basic`` and
433 md5, binary, and or content.
432 ``full``.
434 The valid options are ``basic`` and ``full``.
433 :type details: Optional(str)
435 :type details: Optional(str)
434 :param max_file_bytes: Only return file content under this file size bytes
436 :param max_file_bytes: Only return file content under this file size bytes
435 :type details: Optional(int)
437 :type details: Optional(int)
@@ -441,10 +443,15 b' def get_repo_nodes(request, apiuser, rep'
441 id : <id_given_in_input>
443 id : <id_given_in_input>
442 result: [
444 result: [
443 {
445 {
444 "name" : "<name>"
446 "binary": false,
445 "type" : "<type>",
447 "content": "File line\nLine2\n",
446 "binary": "<true|false>" (only in extended mode)
448 "extension": "md",
447 "md5" : "<md5 of file content>" (only in extended mode)
449 "lines": 2,
450 "md5": "059fa5d29b19c0657e384749480f6422",
451 "mimetype": "text/x-minidsrc",
452 "name": "file.md",
453 "size": 580,
454 "type": "file"
448 },
455 },
449 ...
456 ...
450 ]
457 ]
@@ -453,16 +460,14 b' def get_repo_nodes(request, apiuser, rep'
453
460
454 repo = get_repo_or_error(repoid)
461 repo = get_repo_or_error(repoid)
455 if not has_superadmin_permission(apiuser):
462 if not has_superadmin_permission(apiuser):
456 _perms = (
463 _perms = ('repository.admin', 'repository.write', 'repository.read',)
457 'repository.admin', 'repository.write', 'repository.read',)
458 validate_repo_permissions(apiuser, repoid, repo, _perms)
464 validate_repo_permissions(apiuser, repoid, repo, _perms)
459
465
460 ret_type = Optional.extract(ret_type)
466 ret_type = Optional.extract(ret_type)
461 details = Optional.extract(details)
467 details = Optional.extract(details)
462 _extended_types = ['basic', 'full']
468 _extended_types = ['basic', 'full']
463 if details not in _extended_types:
469 if details not in _extended_types:
464 raise JSONRPCError(
470 raise JSONRPCError('ret_type must be one of %s' % (','.join(_extended_types)))
465 'ret_type must be one of %s' % (','.join(_extended_types)))
466 extended_info = False
471 extended_info = False
467 content = False
472 content = False
468 if details == 'basic':
473 if details == 'basic':
@@ -499,6 +504,149 b' def get_repo_nodes(request, apiuser, rep'
499
504
500
505
501 @jsonrpc_method()
506 @jsonrpc_method()
507 def get_repo_file(request, apiuser, repoid, commit_id, file_path,
508 max_file_bytes=Optional(None), details=Optional('basic'),
509 cache=Optional(True)):
510 """
511 Returns a single file from repository at given revision.
512
513 This command can only be run using an |authtoken| with admin rights,
514 or users with at least read rights to |repos|.
515
516 :param apiuser: This is filled automatically from the |authtoken|.
517 :type apiuser: AuthUser
518 :param repoid: The repository name or repository ID.
519 :type repoid: str or int
520 :param commit_id: The revision for which listing should be done.
521 :type commit_id: str
522 :param file_path: The path from which to start displaying.
523 :type file_path: str
524 :param details: Returns different set of information about nodes.
525 The valid options are ``minimal`` ``basic`` and ``full``.
526 :type details: Optional(str)
527 :param max_file_bytes: Only return file content under this file size bytes
528 :type max_file_bytes: Optional(int)
529 :param cache: Use internal caches for fetching files. If disabled fetching
530 files is slower but more memory efficient
531 :type cache: Optional(bool)
532 Example output:
533
534 .. code-block:: bash
535
536 id : <id_given_in_input>
537 result: {
538 "binary": false,
539 "extension": "py",
540 "lines": 35,
541 "content": "....",
542 "md5": "76318336366b0f17ee249e11b0c99c41",
543 "mimetype": "text/x-python",
544 "name": "python.py",
545 "size": 817,
546 "type": "file",
547 }
548 error: null
549 """
550
551 repo = get_repo_or_error(repoid)
552 if not has_superadmin_permission(apiuser):
553 _perms = ('repository.admin', 'repository.write', 'repository.read',)
554 validate_repo_permissions(apiuser, repoid, repo, _perms)
555
556 cache = Optional.extract(cache, binary=True)
557 details = Optional.extract(details)
558 _extended_types = ['minimal', 'minimal+search', 'basic', 'full']
559 if details not in _extended_types:
560 raise JSONRPCError(
561 'ret_type must be one of %s, got %s' % (','.join(_extended_types)), details)
562 extended_info = False
563 content = False
564
565 if details == 'minimal':
566 extended_info = False
567
568 elif details == 'basic':
569 extended_info = True
570
571 elif details == 'full':
572 extended_info = content = True
573
574 try:
575 # check if repo is not empty by any chance, skip quicker if it is.
576 _scm = repo.scm_instance()
577 if _scm.is_empty():
578 return None
579
580 node = ScmModel().get_node(
581 repo, commit_id, file_path, extended_info=extended_info,
582 content=content, max_file_bytes=max_file_bytes, cache=cache)
583 except NodeDoesNotExistError:
584 raise JSONRPCError('There is no file in repo: `{}` at path `{}` for commit: `{}`'.format(
585 repo.repo_name, file_path, commit_id))
586 except Exception:
587 log.exception("Exception occurred while trying to get repo %s file",
588 repo.repo_name)
589 raise JSONRPCError('failed to get repo: `{}` file at path {}'.format(
590 repo.repo_name, file_path))
591
592 return node
593
594
595 @jsonrpc_method()
596 def get_repo_fts_tree(request, apiuser, repoid, commit_id, root_path):
597 """
598 Returns a list of tree nodes for path at given revision. This api is built
599 strictly for usage in full text search building, and shouldn't be consumed
600
601 This command can only be run using an |authtoken| with admin rights,
602 or users with at least read rights to |repos|.
603
604 """
605
606 repo = get_repo_or_error(repoid)
607 if not has_superadmin_permission(apiuser):
608 _perms = ('repository.admin', 'repository.write', 'repository.read',)
609 validate_repo_permissions(apiuser, repoid, repo, _perms)
610
611 repo_id = repo.repo_id
612 cache_seconds = safe_int(rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
613 cache_on = cache_seconds > 0
614
615 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
616 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
617
618 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
619 condition=cache_on)
620 def compute_fts_tree(repo_id, commit_id, root_path, cache_ver):
621 return ScmModel().get_fts_data(repo_id, commit_id, root_path)
622
623 try:
624 # check if repo is not empty by any chance, skip quicker if it is.
625 _scm = repo.scm_instance()
626 if _scm.is_empty():
627 return []
628 except RepositoryError:
629 log.exception("Exception occurred while trying to get repo nodes")
630 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
631
632 try:
633 # we need to resolve commit_id to a FULL sha for cache to work correctly.
634 # sending 'master' is a pointer that needs to be translated to current commit.
635 commit_id = _scm.get_commit(commit_id=commit_id).raw_id
636 log.debug(
637 'Computing FTS REPO TREE for repo_id %s commit_id `%s` '
638 'with caching: %s[TTL: %ss]' % (
639 repo_id, commit_id, cache_on, cache_seconds or 0))
640
641 tree_files = compute_fts_tree(repo_id, commit_id, root_path, 'v1')
642 return tree_files
643
644 except Exception:
645 log.exception("Exception occurred while trying to get repo nodes")
646 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
647
648
649 @jsonrpc_method()
502 def get_repo_refs(request, apiuser, repoid):
650 def get_repo_refs(request, apiuser, repoid):
503 """
651 """
504 Returns a dictionary of current references. It returns
652 Returns a dictionary of current references. It returns
@@ -1506,6 +1654,73 b' def comment_commit('
1506
1654
1507
1655
1508 @jsonrpc_method()
1656 @jsonrpc_method()
1657 def get_repo_comments(request, apiuser, repoid,
1658 commit_id=Optional(None), comment_type=Optional(None),
1659 userid=Optional(None)):
1660 """
1661 Get all comments for a repository
1662
1663 :param apiuser: This is filled automatically from the |authtoken|.
1664 :type apiuser: AuthUser
1665 :param repoid: Set the repository name or repository ID.
1666 :type repoid: str or int
1667 :param commit_id: Optionally filter the comments by the commit_id
1668 :type commit_id: Optional(str), default: None
1669 :param comment_type: Optionally filter the comments by the comment_type
1670 one of: 'note', 'todo'
1671 :type comment_type: Optional(str), default: None
1672 :param userid: Optionally filter the comments by the author of comment
1673 :type userid: Optional(str or int), Default: None
1674
1675 Example error output:
1676
1677 .. code-block:: bash
1678
1679 {
1680 "id" : <id_given_in_input>,
1681 "result" : [
1682 {
1683 "comment_author": <USER_DETAILS>,
1684 "comment_created_on": "2017-02-01T14:38:16.309",
1685 "comment_f_path": "file.txt",
1686 "comment_id": 282,
1687 "comment_lineno": "n1",
1688 "comment_resolved_by": null,
1689 "comment_status": [],
1690 "comment_text": "This file needs a header",
1691 "comment_type": "todo"
1692 }
1693 ],
1694 "error" : null
1695 }
1696
1697 """
1698 repo = get_repo_or_error(repoid)
1699 if not has_superadmin_permission(apiuser):
1700 _perms = ('repository.read', 'repository.write', 'repository.admin')
1701 validate_repo_permissions(apiuser, repoid, repo, _perms)
1702
1703 commit_id = Optional.extract(commit_id)
1704
1705 userid = Optional.extract(userid)
1706 if userid:
1707 user = get_user_or_error(userid)
1708 else:
1709 user = None
1710
1711 comment_type = Optional.extract(comment_type)
1712 if comment_type and comment_type not in ChangesetComment.COMMENT_TYPES:
1713 raise JSONRPCError(
1714 'comment_type must be one of `{}` got {}'.format(
1715 ChangesetComment.COMMENT_TYPES, comment_type)
1716 )
1717
1718 comments = CommentsModel().get_repository_comments(
1719 repo=repo, comment_type=comment_type, user=user, commit_id=commit_id)
1720 return comments
1721
1722
1723 @jsonrpc_method()
1509 def grant_user_permission(request, apiuser, repoid, userid, perm):
1724 def grant_user_permission(request, apiuser, repoid, userid, perm):
1510 """
1725 """
1511 Grant permissions for the specified user on the given repository,
1726 Grant permissions for the specified user on the given repository,
@@ -1543,9 +1758,18 b' def grant_user_permission(request, apius'
1543 _perms = ('repository.admin',)
1758 _perms = ('repository.admin',)
1544 validate_repo_permissions(apiuser, repoid, repo, _perms)
1759 validate_repo_permissions(apiuser, repoid, repo, _perms)
1545
1760
1761 perm_additions = [[user.user_id, perm.permission_name, "user"]]
1546 try:
1762 try:
1763 changes = RepoModel().update_permissions(
1764 repo=repo, perm_additions=perm_additions, cur_user=apiuser)
1547
1765
1548 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
1766 action_data = {
1767 'added': changes['added'],
1768 'updated': changes['updated'],
1769 'deleted': changes['deleted'],
1770 }
1771 audit_logger.store_api(
1772 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1549
1773
1550 Session().commit()
1774 Session().commit()
1551 return {
1775 return {
@@ -1555,8 +1779,7 b' def grant_user_permission(request, apius'
1555 'success': True
1779 'success': True
1556 }
1780 }
1557 except Exception:
1781 except Exception:
1558 log.exception(
1782 log.exception("Exception occurred while trying edit permissions for repo")
1559 "Exception occurred while trying edit permissions for repo")
1560 raise JSONRPCError(
1783 raise JSONRPCError(
1561 'failed to edit permission for user: `%s` in repo: `%s`' % (
1784 'failed to edit permission for user: `%s` in repo: `%s`' % (
1562 userid, repoid
1785 userid, repoid
@@ -1597,8 +1820,19 b' def revoke_user_permission(request, apiu'
1597 _perms = ('repository.admin',)
1820 _perms = ('repository.admin',)
1598 validate_repo_permissions(apiuser, repoid, repo, _perms)
1821 validate_repo_permissions(apiuser, repoid, repo, _perms)
1599
1822
1823 perm_deletions = [[user.user_id, None, "user"]]
1600 try:
1824 try:
1601 RepoModel().revoke_user_permission(repo=repo, user=user)
1825 changes = RepoModel().update_permissions(
1826 repo=repo, perm_deletions=perm_deletions, cur_user=user)
1827
1828 action_data = {
1829 'added': changes['added'],
1830 'updated': changes['updated'],
1831 'deleted': changes['deleted'],
1832 }
1833 audit_logger.store_api(
1834 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1835
1602 Session().commit()
1836 Session().commit()
1603 return {
1837 return {
1604 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1838 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
@@ -1607,8 +1841,7 b' def revoke_user_permission(request, apiu'
1607 'success': True
1841 'success': True
1608 }
1842 }
1609 except Exception:
1843 except Exception:
1610 log.exception(
1844 log.exception("Exception occurred while trying revoke permissions to repo")
1611 "Exception occurred while trying revoke permissions to repo")
1612 raise JSONRPCError(
1845 raise JSONRPCError(
1613 'failed to edit permission for user: `%s` in repo: `%s`' % (
1846 'failed to edit permission for user: `%s` in repo: `%s`' % (
1614 userid, repoid
1847 userid, repoid
@@ -1674,9 +1907,17 b' def grant_user_group_permission(request,'
1674 raise JSONRPCError(
1907 raise JSONRPCError(
1675 'user group `%s` does not exist' % (usergroupid,))
1908 'user group `%s` does not exist' % (usergroupid,))
1676
1909
1910 perm_additions = [[user_group.users_group_id, perm.permission_name, "user_group"]]
1677 try:
1911 try:
1678 RepoModel().grant_user_group_permission(
1912 changes = RepoModel().update_permissions(
1679 repo=repo, group_name=user_group, perm=perm)
1913 repo=repo, perm_additions=perm_additions, cur_user=apiuser)
1914 action_data = {
1915 'added': changes['added'],
1916 'updated': changes['updated'],
1917 'deleted': changes['deleted'],
1918 }
1919 audit_logger.store_api(
1920 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1680
1921
1681 Session().commit()
1922 Session().commit()
1682 return {
1923 return {
@@ -1739,9 +1980,17 b' def revoke_user_group_permission(request'
1739 raise JSONRPCError(
1980 raise JSONRPCError(
1740 'user group `%s` does not exist' % (usergroupid,))
1981 'user group `%s` does not exist' % (usergroupid,))
1741
1982
1983 perm_deletions = [[user_group.users_group_id, None, "user_group"]]
1742 try:
1984 try:
1743 RepoModel().revoke_user_group_permission(
1985 changes = RepoModel().update_permissions(
1744 repo=repo, group_name=user_group)
1986 repo=repo, perm_deletions=perm_deletions, cur_user=apiuser)
1987 action_data = {
1988 'added': changes['added'],
1989 'updated': changes['updated'],
1990 'deleted': changes['deleted'],
1991 }
1992 audit_logger.store_api(
1993 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1745
1994
1746 Session().commit()
1995 Session().commit()
1747 return {
1996 return {
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -453,10 +453,19 b' def grant_user_permission_to_repo_group('
453
453
454 perm_additions = [[user.user_id, perm.permission_name, "user"]]
454 perm_additions = [[user.user_id, perm.permission_name, "user"]]
455 try:
455 try:
456 RepoGroupModel().update_permissions(repo_group=repo_group,
456 changes = RepoGroupModel().update_permissions(
457 perm_additions=perm_additions,
457 repo_group=repo_group, perm_additions=perm_additions,
458 recursive=apply_to_children,
458 recursive=apply_to_children, cur_user=apiuser)
459 cur_user=apiuser)
459
460 action_data = {
461 'added': changes['added'],
462 'updated': changes['updated'],
463 'deleted': changes['deleted'],
464 }
465 audit_logger.store_api(
466 'repo_group.edit.permissions', action_data=action_data,
467 user=apiuser)
468
460 Session().commit()
469 Session().commit()
461 return {
470 return {
462 'msg': 'Granted perm: `%s` (recursive:%s) for user: '
471 'msg': 'Granted perm: `%s` (recursive:%s) for user: '
@@ -527,10 +536,19 b' def revoke_user_permission_from_repo_gro'
527
536
528 perm_deletions = [[user.user_id, None, "user"]]
537 perm_deletions = [[user.user_id, None, "user"]]
529 try:
538 try:
530 RepoGroupModel().update_permissions(repo_group=repo_group,
539 changes = RepoGroupModel().update_permissions(
531 perm_deletions=perm_deletions,
540 repo_group=repo_group, perm_deletions=perm_deletions,
532 recursive=apply_to_children,
541 recursive=apply_to_children, cur_user=apiuser)
533 cur_user=apiuser)
542
543 action_data = {
544 'added': changes['added'],
545 'updated': changes['updated'],
546 'deleted': changes['deleted'],
547 }
548 audit_logger.store_api(
549 'repo_group.edit.permissions', action_data=action_data,
550 user=apiuser)
551
534 Session().commit()
552 Session().commit()
535 return {
553 return {
536 'msg': 'Revoked perm (recursive:%s) for user: '
554 'msg': 'Revoked perm (recursive:%s) for user: '
@@ -611,10 +629,19 b' def grant_user_group_permission_to_repo_'
611
629
612 perm_additions = [[user_group.users_group_id, perm.permission_name, "user_group"]]
630 perm_additions = [[user_group.users_group_id, perm.permission_name, "user_group"]]
613 try:
631 try:
614 RepoGroupModel().update_permissions(repo_group=repo_group,
632 changes = RepoGroupModel().update_permissions(
615 perm_additions=perm_additions,
633 repo_group=repo_group, perm_additions=perm_additions,
616 recursive=apply_to_children,
634 recursive=apply_to_children, cur_user=apiuser)
617 cur_user=apiuser)
635
636 action_data = {
637 'added': changes['added'],
638 'updated': changes['updated'],
639 'deleted': changes['deleted'],
640 }
641 audit_logger.store_api(
642 'repo_group.edit.permissions', action_data=action_data,
643 user=apiuser)
644
618 Session().commit()
645 Session().commit()
619 return {
646 return {
620 'msg': 'Granted perm: `%s` (recursive:%s) '
647 'msg': 'Granted perm: `%s` (recursive:%s) '
@@ -694,10 +721,19 b' def revoke_user_group_permission_from_re'
694
721
695 perm_deletions = [[user_group.users_group_id, None, "user_group"]]
722 perm_deletions = [[user_group.users_group_id, None, "user_group"]]
696 try:
723 try:
697 RepoGroupModel().update_permissions(repo_group=repo_group,
724 changes = RepoGroupModel().update_permissions(
698 perm_deletions=perm_deletions,
725 repo_group=repo_group, perm_deletions=perm_deletions,
699 recursive=apply_to_children,
726 recursive=apply_to_children, cur_user=apiuser)
700 cur_user=apiuser)
727
728 action_data = {
729 'added': changes['added'],
730 'updated': changes['updated'],
731 'deleted': changes['deleted'],
732 }
733 audit_logger.store_api(
734 'repo_group.edit.permissions', action_data=action_data,
735 user=apiuser)
736
701 Session().commit()
737 Session().commit()
702 return {
738 return {
703 'msg': 'Revoked perm (recursive:%s) for user group: '
739 'msg': 'Revoked perm (recursive:%s) for user group: '
@@ -716,4 +752,3 b' def revoke_user_group_permission_from_re'
716 user_group.users_group_name, repo_group.name
752 user_group.users_group_name, repo_group.name
717 )
753 )
718 )
754 )
719
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -21,6 +21,9 b''
21 import inspect
21 import inspect
22 import logging
22 import logging
23 import itertools
23 import itertools
24 import base64
25
26 from pyramid import compat
24
27
25 from rhodecode.api import (
28 from rhodecode.api import (
26 jsonrpc_method, JSONRPCError, JSONRPCForbidden, find_methods)
29 jsonrpc_method, JSONRPCError, JSONRPCForbidden, find_methods)
@@ -30,10 +33,15 b' from rhodecode.api.utils import ('
30 from rhodecode.lib.utils import repo2db_mapper
33 from rhodecode.lib.utils import repo2db_mapper
31 from rhodecode.lib import system_info
34 from rhodecode.lib import system_info
32 from rhodecode.lib import user_sessions
35 from rhodecode.lib import user_sessions
36 from rhodecode.lib import exc_tracking
37 from rhodecode.lib.ext_json import json
33 from rhodecode.lib.utils2 import safe_int
38 from rhodecode.lib.utils2 import safe_int
34 from rhodecode.model.db import UserIpMap
39 from rhodecode.model.db import UserIpMap
35 from rhodecode.model.scm import ScmModel
40 from rhodecode.model.scm import ScmModel
36 from rhodecode.model.settings import VcsSettingsModel
41 from rhodecode.model.settings import VcsSettingsModel
42 from rhodecode.apps.file_store import utils
43 from rhodecode.apps.file_store.exceptions import FileNotAllowedException, \
44 FileOverSizeException
37
45
38 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
39
47
@@ -293,7 +301,7 b' def get_method(request, apiuser, pattern'
293 :param apiuser: This is filled automatically from the |authtoken|.
301 :param apiuser: This is filled automatically from the |authtoken|.
294 :type apiuser: AuthUser
302 :type apiuser: AuthUser
295 :param pattern: pattern to match method names against
303 :param pattern: pattern to match method names against
296 :type older_then: Optional("*")
304 :type pattern: Optional("*")
297
305
298 Example output:
306 Example output:
299
307
@@ -349,3 +357,63 b' def get_method(request, apiuser, pattern'
349 args_desc.append(func_kwargs)
357 args_desc.append(func_kwargs)
350
358
351 return matches.keys() + args_desc
359 return matches.keys() + args_desc
360
361
362 @jsonrpc_method()
363 def store_exception(request, apiuser, exc_data_json, prefix=Optional('rhodecode')):
364 """
365 Stores sent exception inside the built-in exception tracker in |RCE| server.
366
367 This command can only be run using an |authtoken| with admin rights to
368 the specified repository.
369
370 This command takes the following options:
371
372 :param apiuser: This is filled automatically from the |authtoken|.
373 :type apiuser: AuthUser
374
375 :param exc_data_json: JSON data with exception e.g
376 {"exc_traceback": "Value `1` is not allowed", "exc_type_name": "ValueError"}
377 :type exc_data_json: JSON data
378
379 :param prefix: prefix for error type, e.g 'rhodecode', 'vcsserver', 'rhodecode-tools'
380 :type prefix: Optional("rhodecode")
381
382 Example output:
383
384 .. code-block:: bash
385
386 id : <id_given_in_input>
387 "result": {
388 "exc_id": 139718459226384,
389 "exc_url": "http://localhost:8080/_admin/settings/exceptions/139718459226384"
390 }
391 error : null
392 """
393 if not has_superadmin_permission(apiuser):
394 raise JSONRPCForbidden()
395
396 prefix = Optional.extract(prefix)
397 exc_id = exc_tracking.generate_id()
398
399 try:
400 exc_data = json.loads(exc_data_json)
401 except Exception:
402 log.error('Failed to parse JSON: %r', exc_data_json)
403 raise JSONRPCError('Failed to parse JSON data from exc_data_json field. '
404 'Please make sure it contains a valid JSON.')
405
406 try:
407 exc_traceback = exc_data['exc_traceback']
408 exc_type_name = exc_data['exc_type_name']
409 except KeyError as err:
410 raise JSONRPCError('Missing exc_traceback, or exc_type_name '
411 'in exc_data_json field. Missing: {}'.format(err))
412
413 exc_tracking._store_exception(
414 exc_id=exc_id, exc_traceback=exc_traceback,
415 exc_type_name=exc_type_name, prefix=prefix)
416
417 exc_url = request.route_url(
418 'admin_settings_exception_tracker_show', exception_id=exc_id)
419 return {'exc_id': exc_id, 'exc_url': exc_url}
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -19,6 +19,7 b''
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 logging
21 import logging
22 from pyramid import compat
22
23
23 from rhodecode.api import (
24 from rhodecode.api import (
24 jsonrpc_method, JSONRPCError, JSONRPCForbidden, JSONRPCValidationError)
25 jsonrpc_method, JSONRPCError, JSONRPCForbidden, JSONRPCValidationError)
@@ -241,7 +242,7 b' def create_user(request, apiuser, userna'
241 # generate temporary password if user is external
242 # generate temporary password if user is external
242 password = PasswordGenerator().gen_password(length=16)
243 password = PasswordGenerator().gen_password(length=16)
243 create_repo_group = Optional.extract(create_personal_repo_group)
244 create_repo_group = Optional.extract(create_personal_repo_group)
244 if isinstance(create_repo_group, basestring):
245 if isinstance(create_repo_group, compat.string_types):
245 create_repo_group = str2bool(create_repo_group)
246 create_repo_group = str2bool(create_repo_group)
246
247
247 username = Optional.extract(username)
248 username = Optional.extract(username)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -22,11 +22,12 b' import time'
22 import logging
22 import logging
23 import operator
23 import operator
24
24
25 from pyramid import compat
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPBadRequest
26 from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPBadRequest
26
27
27 from rhodecode.lib import helpers as h, diffs
28 from rhodecode.lib import helpers as h, diffs
28 from rhodecode.lib.utils2 import (
29 from rhodecode.lib.utils2 import (
29 StrictAttributeDict, safe_int, datetime_to_time, safe_unicode)
30 StrictAttributeDict, str2bool, safe_int, datetime_to_time, safe_unicode)
30 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
31 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
31 from rhodecode.model import repo
32 from rhodecode.model import repo
32 from rhodecode.model import repo_group
33 from rhodecode.model import repo_group
@@ -249,6 +250,12 b' class RepoAppView(BaseAppView):'
249 else: # redirect if we don't show missing requirements
250 else: # redirect if we don't show missing requirements
250 raise HTTPFound(h.route_path('home'))
251 raise HTTPFound(h.route_path('home'))
251
252
253 c.has_origin_repo_read_perm = False
254 if self.db_repo.fork:
255 c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
256 'repository.write', 'repository.read', 'repository.admin')(
257 self.db_repo.fork.repo_name, 'summary fork link')
258
252 return c
259 return c
253
260
254 def _get_f_path_unchecked(self, matchdict, default=None):
261 def _get_f_path_unchecked(self, matchdict, default=None):
@@ -271,6 +278,13 b' class RepoAppView(BaseAppView):'
271 settings = settings_model.get_general_settings()
278 settings = settings_model.get_general_settings()
272 return settings.get(settings_key, default)
279 return settings.get(settings_key, default)
273
280
281 def get_recache_flag(self):
282 for flag_name in ['force_recache', 'force-recache', 'no-cache']:
283 flag_val = self.request.GET.get(flag_name)
284 if str2bool(flag_val):
285 return True
286 return False
287
274
288
275 class PathFilter(object):
289 class PathFilter(object):
276
290
@@ -327,6 +341,13 b' class RepoGroupAppView(BaseAppView):'
327 self.db_repo_group = request.db_repo_group
341 self.db_repo_group = request.db_repo_group
328 self.db_repo_group_name = self.db_repo_group.group_name
342 self.db_repo_group_name = self.db_repo_group.group_name
329
343
344 def _get_local_tmpl_context(self, include_app_defaults=True):
345 _ = self.request.translate
346 c = super(RepoGroupAppView, self)._get_local_tmpl_context(
347 include_app_defaults=include_app_defaults)
348 c.repo_group = self.db_repo_group
349 return c
350
330 def _revoke_perms_on_yourself(self, form_result):
351 def _revoke_perms_on_yourself(self, form_result):
331 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
352 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
332 form_result['perm_updates'])
353 form_result['perm_updates'])
@@ -389,7 +410,7 b' class DataGridAppView(object):'
389 return draw, start, length
410 return draw, start, length
390
411
391 def _get_order_col(self, order_by, model):
412 def _get_order_col(self, order_by, model):
392 if isinstance(order_by, basestring):
413 if isinstance(order_by, compat.string_types):
393 try:
414 try:
394 return operator.attrgetter(order_by)(model)
415 return operator.attrgetter(order_by)(model)
395 except AttributeError:
416 except AttributeError:
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -280,8 +280,12 b' def admin_routes(config):'
280 pattern='/users/{user_id:\d+}/delete',
280 pattern='/users/{user_id:\d+}/delete',
281 user_route=True)
281 user_route=True)
282 config.add_route(
282 config.add_route(
283 name='user_force_password_reset',
283 name='user_enable_force_password_reset',
284 pattern='/users/{user_id:\d+}/password_reset',
284 pattern='/users/{user_id:\d+}/password_reset_enable',
285 user_route=True)
286 config.add_route(
287 name='user_disable_force_password_reset',
288 pattern='/users/{user_id:\d+}/password_reset_disable',
285 user_route=True)
289 user_route=True)
286 config.add_route(
290 config.add_route(
287 name='user_create_personal_repo_group',
291 name='user_create_personal_repo_group',
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -59,8 +59,6 b' def route_path(name, params=None, **kwar'
59 ADMIN_PREFIX + '/users/{user_id}/update',
59 ADMIN_PREFIX + '/users/{user_id}/update',
60 'user_delete':
60 'user_delete':
61 ADMIN_PREFIX + '/users/{user_id}/delete',
61 ADMIN_PREFIX + '/users/{user_id}/delete',
62 'user_force_password_reset':
63 ADMIN_PREFIX + '/users/{user_id}/password_reset',
64 'user_create_personal_repo_group':
62 'user_create_personal_repo_group':
65 ADMIN_PREFIX + '/users/{user_id}/create_repo_group',
63 ADMIN_PREFIX + '/users/{user_id}/create_repo_group',
66
64
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2018-2018 RhodeCode GmbH
3 # Copyright (C) 2018-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -119,8 +119,7 b' class AdminProcessManagementView(BaseApp'
119 result = []
119 result = []
120
120
121 def on_terminate(proc):
121 def on_terminate(proc):
122 msg = "process `PID:{}` terminated with exit code {}".format(
122 msg = "terminated"
123 proc.pid, proc.returncode or 0)
124 result.append(msg)
123 result.append(msg)
125
124
126 procs = []
125 procs = []
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -666,8 +666,8 b' class AdminSettingsView(BaseAppView):'
666 c = self.load_default_context()
666 c = self.load_default_context()
667 c.active = 'search'
667 c.active = 'search'
668
668
669 searcher = searcher_from_config(self.request.registry.settings)
669 c.searcher = searcher_from_config(self.request.registry.settings)
670 c.statistics = searcher.statistics(self.request.translate)
670 c.statistics = c.searcher.statistics(self.request.translate)
671
671
672 return self._get_template_context(c)
672 return self._get_template_context(c)
673
673
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -604,12 +604,9 b' class UsersView(UserAppView):'
604 @HasPermissionAllDecorator('hg.admin')
604 @HasPermissionAllDecorator('hg.admin')
605 @CSRFRequired()
605 @CSRFRequired()
606 @view_config(
606 @view_config(
607 route_name='user_force_password_reset', request_method='POST',
607 route_name='user_enable_force_password_reset', request_method='POST',
608 renderer='rhodecode:templates/admin/users/user_edit.mako')
608 renderer='rhodecode:templates/admin/users/user_edit.mako')
609 def user_force_password_reset(self):
609 def user_enable_force_password_reset(self):
610 """
611 toggle reset password flag for this user
612 """
613 _ = self.request.translate
610 _ = self.request.translate
614 c = self.load_default_context()
611 c = self.load_default_context()
615
612
@@ -617,19 +614,41 b' class UsersView(UserAppView):'
617 c.user = self.db_user
614 c.user = self.db_user
618
615
619 try:
616 try:
620 old_value = c.user.user_data.get('force_password_change')
617 c.user.update_userdata(force_password_change=True)
621 c.user.update_userdata(force_password_change=not old_value)
618
619 msg = _('Force password change enabled for user')
620 audit_logger.store_web('user.edit.password_reset.enabled',
621 user=c.rhodecode_user)
622
623 Session().commit()
624 h.flash(msg, category='success')
625 except Exception:
626 log.exception("Exception during password reset for user")
627 h.flash(_('An error occurred during password reset for user'),
628 category='error')
629
630 raise HTTPFound(h.route_path('user_edit_advanced', user_id=user_id))
622
631
623 if old_value:
632 @LoginRequired()
633 @HasPermissionAllDecorator('hg.admin')
634 @CSRFRequired()
635 @view_config(
636 route_name='user_disable_force_password_reset', request_method='POST',
637 renderer='rhodecode:templates/admin/users/user_edit.mako')
638 def user_disable_force_password_reset(self):
639 _ = self.request.translate
640 c = self.load_default_context()
641
642 user_id = self.db_user_id
643 c.user = self.db_user
644
645 try:
646 c.user.update_userdata(force_password_change=False)
647
624 msg = _('Force password change disabled for user')
648 msg = _('Force password change disabled for user')
625 audit_logger.store_web(
649 audit_logger.store_web(
626 'user.edit.password_reset.disabled',
650 'user.edit.password_reset.disabled',
627 user=c.rhodecode_user)
651 user=c.rhodecode_user)
628 else:
629 msg = _('Force password change enabled for user')
630 audit_logger.store_web(
631 'user.edit.password_reset.enabled',
632 user=c.rhodecode_user)
633
652
634 Session().commit()
653 Session().commit()
635 h.flash(msg, category='success')
654 h.flash(msg, category='success')
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2013-2018 RhodeCode GmbH
3 # Copyright (C) 2013-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -56,6 +56,10 b' def includeme(config):'
56 pattern='/_repos')
56 pattern='/_repos')
57
57
58 config.add_route(
58 config.add_route(
59 name='repo_group_list_data',
60 pattern='/_repo_groups')
61
62 config.add_route(
59 name='goto_switcher_data',
63 name='goto_switcher_data',
60 pattern='/_goto_data')
64 pattern='/_goto_data')
61
65
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -31,7 +31,14 b' def assert_and_get_main_filter_content(r'
31 assert data_item['url']
31 assert data_item['url']
32
32
33 if data_item['type'] == 'search':
33 if data_item['type'] == 'search':
34 assert data_item['value_display'].startswith('Full text search for:')
34 display_val = data_item['value_display']
35 if data_item['id'] == -1:
36 assert 'File search for:' in display_val, display_val
37 elif data_item['id'] == -2:
38 assert 'Commit search for:' in display_val, display_val
39 else:
40 assert False, 'No Proper ID returned {}'.format(data_item['id'])
41
35 elif data_item['type'] == 'repo':
42 elif data_item['type'] == 'repo':
36 repos.append(data_item)
43 repos.append(data_item)
37 elif data_item['type'] == 'repo_group':
44 elif data_item['type'] == 'repo_group':
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -19,7 +19,7 b''
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 # -*- coding: utf-8 -*-
20 # -*- coding: utf-8 -*-
21
21
22 # Copyright (C) 2016-2018 RhodeCode GmbH
22 # Copyright (C) 2016-2019 RhodeCode GmbH
23 #
23 #
24 # This program is free software: you can redistribute it and/or modify
24 # This program is free software: you can redistribute it and/or modify
25 # it under the terms of the GNU Affero General Public License, version 3
25 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -172,7 +172,9 b' class HomeView(BaseAppView):'
172 'id': obj.group_name,
172 'id': obj.group_name,
173 'value': org_query,
173 'value': org_query,
174 'value_display': obj.group_name,
174 'value_display': obj.group_name,
175 'text': obj.group_name,
175 'type': 'repo_group',
176 'type': 'repo_group',
177 'repo_group_id': obj.group_id,
176 'url': h.route_path(
178 'url': h.route_path(
177 'repo_group_home', repo_group_name=obj.group_name)
179 'repo_group_home', repo_group_name=obj.group_name)
178 }
180 }
@@ -246,9 +248,9 b' class HomeView(BaseAppView):'
246 }
248 }
247 for obj in acl_iter]
249 for obj in acl_iter]
248
250
249 def _get_hash_commit_list(self, auth_user, query):
251 def _get_hash_commit_list(self, auth_user, searcher, query):
250 org_query = query
252 org_query = query
251 if not query or len(query) < 3:
253 if not query or len(query) < 3 or not searcher:
252 return []
254 return []
253
255
254 commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
256 commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
@@ -257,24 +259,34 b' class HomeView(BaseAppView):'
257 return []
259 return []
258 commit_hash = commit_hashes[0]
260 commit_hash = commit_hashes[0]
259
261
260 searcher = searcher_from_config(self.request.registry.settings)
261 result = searcher.search(
262 result = searcher.search(
262 'commit_id:%s*' % commit_hash, 'commit', auth_user,
263 'commit_id:{}*'.format(commit_hash), 'commit', auth_user,
263 raise_on_exc=False)
264 raise_on_exc=False)
264
265
265 return [
266 commits = []
266 {
267 for entry in result['results']:
268 repo_data = {
269 'repository_id': entry.get('repository_id'),
270 'repository_type': entry.get('repo_type'),
271 'repository_name': entry.get('repository'),
272 }
273
274 commit_entry = {
267 'id': entry['commit_id'],
275 'id': entry['commit_id'],
268 'value': org_query,
276 'value': org_query,
269 'value_display': 'repo `{}` commit: {}'.format(
277 'value_display': '`{}` commit: {}'.format(
270 entry['repository'], entry['commit_id']),
278 entry['repository'], entry['commit_id']),
271 'type': 'commit',
279 'type': 'commit',
272 'repo': entry['repository'],
280 'repo': entry['repository'],
281 'repo_data': repo_data,
282
273 'url': h.route_path(
283 'url': h.route_path(
274 'repo_commit',
284 'repo_commit',
275 repo_name=entry['repository'], commit_id=entry['commit_id'])
285 repo_name=entry['repository'], commit_id=entry['commit_id'])
276 }
286 }
277 for entry in result['results']]
287
288 commits.append(commit_entry)
289 return commits
278
290
279 @LoginRequired()
291 @LoginRequired()
280 @view_config(
292 @view_config(
@@ -305,6 +317,144 b' class HomeView(BaseAppView):'
305
317
306 @LoginRequired()
318 @LoginRequired()
307 @view_config(
319 @view_config(
320 route_name='repo_group_list_data', request_method='GET',
321 renderer='json_ext', xhr=True)
322 def repo_group_list_data(self):
323 _ = self.request.translate
324 self.load_default_context()
325
326 query = self.request.GET.get('query')
327
328 log.debug('generating repo group list, query:%s',
329 query)
330
331 res = []
332 repo_groups = self._get_repo_group_list(query)
333 if repo_groups:
334 res.append({
335 'text': _('Repository Groups'),
336 'children': repo_groups
337 })
338
339 data = {
340 'more': False,
341 'results': res
342 }
343 return data
344
345 def _get_default_search_queries(self, search_context, searcher, query):
346 if not searcher:
347 return []
348
349 is_es_6 = searcher.is_es_6
350
351 queries = []
352 repo_group_name, repo_name, repo_context = None, None, None
353
354 # repo group context
355 if search_context.get('search_context[repo_group_name]'):
356 repo_group_name = search_context.get('search_context[repo_group_name]')
357 if search_context.get('search_context[repo_name]'):
358 repo_name = search_context.get('search_context[repo_name]')
359 repo_context = search_context.get('search_context[repo_view_type]')
360
361 if is_es_6 and repo_name:
362 # files
363 def query_modifier():
364 qry = query
365 return {'q': qry, 'type': 'content'}
366 label = u'File search for `{}` in this repository.'.format(query)
367 queries.append(
368 {
369 'id': -10,
370 'value': query,
371 'value_display': label,
372 'type': 'search',
373 'url': h.route_path('search_repo',
374 repo_name=repo_name,
375 _query=query_modifier())
376 }
377 )
378
379 # commits
380 def query_modifier():
381 qry = query
382 return {'q': qry, 'type': 'commit'}
383
384 label = u'Commit search for `{}` in this repository.'.format(query)
385 queries.append(
386 {
387 'id': -20,
388 'value': query,
389 'value_display': label,
390 'type': 'search',
391 'url': h.route_path('search_repo',
392 repo_name=repo_name,
393 _query=query_modifier())
394 }
395 )
396
397 elif is_es_6 and repo_group_name:
398 # files
399 def query_modifier():
400 qry = query
401 return {'q': qry, 'type': 'content'}
402
403 label = u'File search for `{}` in this repository group'.format(query)
404 queries.append(
405 {
406 'id': -30,
407 'value': query,
408 'value_display': label,
409 'type': 'search',
410 'url': h.route_path('search_repo_group',
411 repo_group_name=repo_group_name,
412 _query=query_modifier())
413 }
414 )
415
416 # commits
417 def query_modifier():
418 qry = query
419 return {'q': qry, 'type': 'commit'}
420
421 label = u'Commit search for `{}` in this repository group'.format(query)
422 queries.append(
423 {
424 'id': -40,
425 'value': query,
426 'value_display': label,
427 'type': 'search',
428 'url': h.route_path('search_repo_group',
429 repo_group_name=repo_group_name,
430 _query=query_modifier())
431 }
432 )
433
434 if not queries:
435 queries.append(
436 {
437 'id': -1,
438 'value': query,
439 'value_display': u'File search for: `{}`'.format(query),
440 'type': 'search',
441 'url': h.route_path('search',
442 _query={'q': query, 'type': 'content'})
443 })
444 queries.append(
445 {
446 'id': -2,
447 'value': query,
448 'value_display': u'Commit search for: `{}`'.format(query),
449 'type': 'search',
450 'url': h.route_path('search',
451 _query={'q': query, 'type': 'commit'})
452 })
453
454 return queries
455
456 @LoginRequired()
457 @view_config(
308 route_name='goto_switcher_data', request_method='GET',
458 route_name='goto_switcher_data', request_method='GET',
309 renderer='json_ext', xhr=True)
459 renderer='json_ext', xhr=True)
310 def goto_switcher_data(self):
460 def goto_switcher_data(self):
@@ -315,26 +465,21 b' class HomeView(BaseAppView):'
315 query = self.request.GET.get('query')
465 query = self.request.GET.get('query')
316 log.debug('generating main filter data, query %s', query)
466 log.debug('generating main filter data, query %s', query)
317
467
318 default_search_val = u'Full text search for: `{}`'.format(query)
319 res = []
468 res = []
320 if not query:
469 if not query:
321 return {'suggestions': res}
470 return {'suggestions': res}
322
471
323 res.append({
472 searcher = searcher_from_config(self.request.registry.settings)
324 'id': -1,
473 for _q in self._get_default_search_queries(self.request.GET, searcher, query):
325 'value': query,
474 res.append(_q)
326 'value_display': default_search_val,
475
327 'type': 'search',
476 repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]'))
328 'url': h.route_path(
329 'search', _query={'q': query})
330 })
331 repo_group_id = safe_int(self.request.GET.get('repo_group_id'))
332 if repo_group_id:
477 if repo_group_id:
333 repo_group = RepoGroup.get(repo_group_id)
478 repo_group = RepoGroup.get(repo_group_id)
334 composed_hint = '{}/{}'.format(repo_group.group_name, query)
479 composed_hint = '{}/{}'.format(repo_group.group_name, query)
335 show_hint = not query.startswith(repo_group.group_name)
480 show_hint = not query.startswith(repo_group.group_name)
336 if repo_group and show_hint:
481 if repo_group and show_hint:
337 hint = u'Group search: `{}`'.format(composed_hint)
482 hint = u'Repository search inside: `{}`'.format(composed_hint)
338 res.append({
483 res.append({
339 'id': -1,
484 'id': -1,
340 'value': composed_hint,
485 'value': composed_hint,
@@ -351,7 +496,7 b' class HomeView(BaseAppView):'
351 for serialized_repo in repos:
496 for serialized_repo in repos:
352 res.append(serialized_repo)
497 res.append(serialized_repo)
353
498
354 # TODO(marcink): permissions for that ?
499 # TODO(marcink): should all logged in users be allowed to search others?
355 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
500 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
356 if allowed_user_search:
501 if allowed_user_search:
357 users = self._get_user_list(query)
502 users = self._get_user_list(query)
@@ -362,7 +507,7 b' class HomeView(BaseAppView):'
362 for serialized_user_group in user_groups:
507 for serialized_user_group in user_groups:
363 res.append(serialized_user_group)
508 res.append(serialized_user_group)
364
509
365 commits = self._get_hash_commit_list(c.auth_user, query)
510 commits = self._get_hash_commit_list(c.auth_user, searcher, query)
366 if commits:
511 if commits:
367 unique_repos = collections.OrderedDict()
512 unique_repos = collections.OrderedDict()
368 for commit in commits:
513 for commit in commits:
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -107,6 +107,26 b' class TestLoginController(object):'
107
107
108 response.mustcontain('/%s' % HG_REPO)
108 response.mustcontain('/%s' % HG_REPO)
109
109
110 def test_login_regular_forbidden_when_super_admin_restriction(self):
111 from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin
112 with fixture.auth_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN):
113 response = self.app.post(route_path('login'),
114 {'username': 'test_regular',
115 'password': 'test12'})
116
117 response.mustcontain('invalid user name')
118 response.mustcontain('invalid password')
119
120 def test_login_regular_forbidden_when_scope_restriction(self):
121 from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin
122 with fixture.scope_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS):
123 response = self.app.post(route_path('login'),
124 {'username': 'test_regular',
125 'password': 'test12'})
126
127 response.mustcontain('invalid user name')
128 response.mustcontain('invalid password')
129
110 def test_login_ok_came_from(self):
130 def test_login_ok_came_from(self):
111 test_came_from = '/_admin/users?branch=stable'
131 test_came_from = '/_admin/users?branch=stable'
112 _url = '{}?came_from={}'.format(route_path('login'), test_came_from)
132 _url = '{}?came_from={}'.format(route_path('login'), test_came_from)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -74,20 +74,17 b' class TestPasswordReset(TestController):'
74 'default_password_reset': pwd_reset_setting,
74 'default_password_reset': pwd_reset_setting,
75 'default_extern_activate': 'hg.extern_activate.auto',
75 'default_extern_activate': 'hg.extern_activate.auto',
76 }
76 }
77 resp = self.app.post(route_path('admin_permissions_application_update'), params=params)
77 resp = self.app.post(
78 route_path('admin_permissions_application_update'), params=params)
78 self.logout_user()
79 self.logout_user()
79
80
80 login_page = self.app.get(route_path('login'))
81 login_page = self.app.get(route_path('login'))
81 asr_login = AssertResponse(login_page)
82 asr_login = AssertResponse(login_page)
82 index_page = self.app.get(h.route_path('home'))
83 asr_index = AssertResponse(index_page)
84
83
85 if show_link:
84 if show_link:
86 asr_login.one_element_exists('a.pwd_reset')
85 asr_login.one_element_exists('a.pwd_reset')
87 asr_index.one_element_exists('a.pwd_reset')
88 else:
86 else:
89 asr_login.no_element_exists('a.pwd_reset')
87 asr_login.no_element_exists('a.pwd_reset')
90 asr_index.no_element_exists('a.pwd_reset')
91
88
92 response = self.app.get(route_path('reset_password'))
89 response = self.app.get(route_path('reset_password'))
93
90
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -95,6 +95,18 b' def includeme(config):'
95 pattern=ADMIN_PREFIX + '/my_account/watched')
95 pattern=ADMIN_PREFIX + '/my_account/watched')
96
96
97 config.add_route(
97 config.add_route(
98 name='my_account_bookmarks',
99 pattern=ADMIN_PREFIX + '/my_account/bookmarks')
100
101 config.add_route(
102 name='my_account_bookmarks_update',
103 pattern=ADMIN_PREFIX + '/my_account/bookmarks/update')
104
105 config.add_route(
106 name='my_account_goto_bookmark',
107 pattern=ADMIN_PREFIX + '/my_account/bookmark/{bookmark_id}')
108
109 config.add_route(
98 name='my_account_perms',
110 name='my_account_perms',
99 pattern=ADMIN_PREFIX + '/my_account/perms')
111 pattern=ADMIN_PREFIX + '/my_account/perms')
100
112
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -19,7 +19,7 b''
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 # -*- coding: utf-8 -*-
20 # -*- coding: utf-8 -*-
21
21
22 # Copyright (C) 2016-2018 RhodeCode GmbH
22 # Copyright (C) 2016-2019 RhodeCode GmbH
23 #
23 #
24 # This program is free software: you can redistribute it and/or modify
24 # This program is free software: you can redistribute it and/or modify
25 # it under the terms of the GNU Affero General Public License, version 3
25 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -20,29 +20,30 b''
20
20
21 import logging
21 import logging
22 import datetime
22 import datetime
23 import string
23
24
24 import formencode
25 import formencode
25 import formencode.htmlfill
26 import formencode.htmlfill
27 import peppercorn
26 from pyramid.httpexceptions import HTTPFound
28 from pyramid.httpexceptions import HTTPFound
27 from pyramid.view import view_config
29 from pyramid.view import view_config
28 from pyramid.renderers import render
29 from pyramid.response import Response
30
30
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 from rhodecode import forms
32 from rhodecode import forms
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.lib import audit_logger
34 from rhodecode.lib import audit_logger
35 from rhodecode.lib.ext_json import json
35 from rhodecode.lib.ext_json import json
36 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired
36 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired, \
37 HasRepoPermissionAny, HasRepoGroupPermissionAny
37 from rhodecode.lib.channelstream import (
38 from rhodecode.lib.channelstream import (
38 channelstream_request, ChannelstreamException)
39 channelstream_request, ChannelstreamException)
39 from rhodecode.lib.utils2 import safe_int, md5, str2bool
40 from rhodecode.lib.utils2 import safe_int, md5, str2bool
40 from rhodecode.model.auth_token import AuthTokenModel
41 from rhodecode.model.auth_token import AuthTokenModel
41 from rhodecode.model.comment import CommentsModel
42 from rhodecode.model.comment import CommentsModel
42 from rhodecode.model.db import (
43 from rhodecode.model.db import (
43 Repository, UserEmailMap, UserApiKeys, UserFollowing, joinedload,
44 IntegrityError, joinedload,
44 PullRequest)
45 Repository, UserEmailMap, UserApiKeys, UserFollowing,
45 from rhodecode.model.forms import UserForm, UserExtraEmailForm
46 PullRequest, UserBookmark, RepoGroup)
46 from rhodecode.model.meta import Session
47 from rhodecode.model.meta import Session
47 from rhodecode.model.pull_request import PullRequestModel
48 from rhodecode.model.pull_request import PullRequestModel
48 from rhodecode.model.scm import RepoList
49 from rhodecode.model.scm import RepoList
@@ -392,6 +393,140 b' class MyAccountView(BaseAppView, DataGri'
392 @LoginRequired()
393 @LoginRequired()
393 @NotAnonymous()
394 @NotAnonymous()
394 @view_config(
395 @view_config(
396 route_name='my_account_bookmarks', request_method='GET',
397 renderer='rhodecode:templates/admin/my_account/my_account.mako')
398 def my_account_bookmarks(self):
399 c = self.load_default_context()
400 c.active = 'bookmarks'
401 return self._get_template_context(c)
402
403 def _process_entry(self, entry, user_id):
404 position = safe_int(entry.get('position'))
405 if position is None:
406 return
407
408 # check if this is an existing entry
409 is_new = False
410 db_entry = UserBookmark().get_by_position_for_user(position, user_id)
411
412 if db_entry and str2bool(entry.get('remove')):
413 log.debug('Marked bookmark %s for deletion', db_entry)
414 Session().delete(db_entry)
415 return
416
417 if not db_entry:
418 # new
419 db_entry = UserBookmark()
420 is_new = True
421
422 should_save = False
423 default_redirect_url = ''
424
425 # save repo
426 if entry.get('bookmark_repo'):
427 repo = Repository.get(entry['bookmark_repo'])
428 perm_check = HasRepoPermissionAny(
429 'repository.read', 'repository.write', 'repository.admin')
430 if repo and perm_check(repo_name=repo.repo_name):
431 db_entry.repository = repo
432 should_save = True
433 default_redirect_url = '${repo_url}'
434 # save repo group
435 elif entry.get('bookmark_repo_group'):
436 repo_group = RepoGroup.get(entry['bookmark_repo_group'])
437 perm_check = HasRepoGroupPermissionAny(
438 'group.read', 'group.write', 'group.admin')
439
440 if repo_group and perm_check(group_name=repo_group.group_name):
441 db_entry.repository_group = repo_group
442 should_save = True
443 default_redirect_url = '${repo_group_url}'
444 # save generic info
445 elif entry.get('title') and entry.get('redirect_url'):
446 should_save = True
447
448 if should_save:
449 log.debug('Saving bookmark %s, new:%s', db_entry, is_new)
450 # mark user and position
451 db_entry.user_id = user_id
452 db_entry.position = position
453 db_entry.title = entry.get('title')
454 db_entry.redirect_url = entry.get('redirect_url') or default_redirect_url
455
456 Session().add(db_entry)
457
458 @LoginRequired()
459 @NotAnonymous()
460 @CSRFRequired()
461 @view_config(
462 route_name='my_account_bookmarks_update', request_method='POST')
463 def my_account_bookmarks_update(self):
464 _ = self.request.translate
465 c = self.load_default_context()
466 c.active = 'bookmarks'
467
468 controls = peppercorn.parse(self.request.POST.items())
469 user_id = c.user.user_id
470
471 try:
472 for entry in controls.get('bookmarks', []):
473 self._process_entry(entry, user_id)
474
475 Session().commit()
476 h.flash(_("Update Bookmarks"), category='success')
477 except IntegrityError:
478 h.flash(_("Failed to update bookmarks. "
479 "Make sure an unique position is used"), category='error')
480
481 return HTTPFound(h.route_path('my_account_bookmarks'))
482
483 @LoginRequired()
484 @NotAnonymous()
485 @view_config(
486 route_name='my_account_goto_bookmark', request_method='GET',
487 renderer='rhodecode:templates/admin/my_account/my_account.mako')
488 def my_account_goto_bookmark(self):
489
490 bookmark_id = self.request.matchdict['bookmark_id']
491 user_bookmark = UserBookmark().query()\
492 .filter(UserBookmark.user_id == self.request.user.user_id) \
493 .filter(UserBookmark.position == bookmark_id).scalar()
494
495 redirect_url = h.route_path('my_account_bookmarks')
496 if not user_bookmark:
497 raise HTTPFound(redirect_url)
498
499 if user_bookmark.repository:
500 repo_name = user_bookmark.repository.repo_name
501 base_redirect_url = h.route_path(
502 'repo_summary', repo_name=repo_name)
503 if user_bookmark.redirect_url and \
504 '${repo_url}' in user_bookmark.redirect_url:
505 redirect_url = string.Template(user_bookmark.redirect_url)\
506 .safe_substitute({'repo_url': base_redirect_url})
507 else:
508 redirect_url = base_redirect_url
509
510 elif user_bookmark.repository_group:
511 repo_group_name = user_bookmark.repository_group.group_name
512 base_redirect_url = h.route_path(
513 'repo_group_home', repo_group_name=repo_group_name)
514 if user_bookmark.redirect_url and \
515 '${repo_group_url}' in user_bookmark.redirect_url:
516 redirect_url = string.Template(user_bookmark.redirect_url)\
517 .safe_substitute({'repo_group_url': base_redirect_url})
518 else:
519 redirect_url = base_redirect_url
520
521 elif user_bookmark.redirect_url:
522 redirect_url = user_bookmark.redirect_url
523
524 log.debug('Redirecting bookmark %s to %s', user_bookmark, redirect_url)
525 raise HTTPFound(redirect_url)
526
527 @LoginRequired()
528 @NotAnonymous()
529 @view_config(
395 route_name='my_account_perms', request_method='GET',
530 route_name='my_account_perms', request_method='GET',
396 renderer='rhodecode:templates/admin/my_account/my_account.mako')
531 renderer='rhodecode:templates/admin/my_account/my_account.mako')
397 def my_account_perms(self):
532 def my_account_perms(self):
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -71,6 +71,7 b' class MyAccountSshKeysView(BaseAppView, '
71 c = self.load_default_context()
71 c = self.load_default_context()
72
72
73 c.active = 'ssh_keys_generate'
73 c.active = 'ssh_keys_generate'
74 if c.ssh_key_generator_enabled:
74 comment = 'RhodeCode-SSH {}'.format(c.user.email or '')
75 comment = 'RhodeCode-SSH {}'.format(c.user.email or '')
75 c.private, c.public = SshKeyModel().generate_keypair(comment=comment)
76 c.private, c.public = SshKeyModel().generate_keypair(comment=comment)
76 c.target_form_url = h.route_path(
77 c.target_form_url = h.route_path(
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -49,9 +49,13 b' class OpsView(BaseAppView):'
49 'instance': self.request.registry.settings.get('instance_id'),
49 'instance': self.request.registry.settings.get('instance_id'),
50 }
50 }
51 if getattr(self.request, 'user'):
51 if getattr(self.request, 'user'):
52 caller_name = 'anonymous'
53 if self.request.user.user_id:
54 caller_name = self.request.user.username
55
52 data.update({
56 data.update({
53 'caller_ip': self.request.user.ip_addr,
57 'caller_ip': self.request.user.ip_addr,
54 'caller_name': self.request.user.username,
58 'caller_name': caller_name,
55 })
59 })
56 return {'ok': data}
60 return {'ok': data}
57
61
@@ -65,11 +69,13 b' class OpsView(BaseAppView):'
65 """
69 """
66 Test exception handling and emails on errors
70 Test exception handling and emails on errors
67 """
71 """
72
68 class TestException(Exception):
73 class TestException(Exception):
69 pass
74 pass
70
75 # add timeout so we add some sort of rate limiter
76 time.sleep(2)
71 msg = ('RhodeCode Enterprise test exception. '
77 msg = ('RhodeCode Enterprise test exception. '
72 'Generation time: {}'.format(time.time()))
78 'Client:{}. Generation time: {}.'.format(self.request.user, time.time()))
73 raise TestException(msg)
79 raise TestException(msg)
74
80
75 @view_config(
81 @view_config(
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -271,8 +271,8 b' def includeme(config):'
271 repo_route=True)
271 repo_route=True)
272
272
273 config.add_route(
273 config.add_route(
274 name='pullrequest_repo_destinations',
274 name='pullrequest_repo_targets',
275 pattern='/{repo_name:.*?[^/]}/pull-request/repo-destinations',
275 pattern='/{repo_name:.*?[^/]}/pull-request/repo-targets',
276 repo_route=True)
276 repo_route=True)
277
277
278 config.add_route(
278 config.add_route(
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -32,7 +32,6 b' from rhodecode.model.pull_request import'
32 from rhodecode.model.user import UserModel
32 from rhodecode.model.user import UserModel
33 from rhodecode.tests import (
33 from rhodecode.tests import (
34 assert_session_flash, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN)
34 assert_session_flash, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN)
35 from rhodecode.tests.utils import AssertResponse
36
35
37
36
38 def route_path(name, params=None, **kwargs):
37 def route_path(name, params=None, **kwargs):
@@ -45,7 +44,7 b' def route_path(name, params=None, **kwar'
45 'pullrequest_show_all': '/{repo_name}/pull-request',
44 'pullrequest_show_all': '/{repo_name}/pull-request',
46 'pullrequest_show_all_data': '/{repo_name}/pull-request-data',
45 'pullrequest_show_all_data': '/{repo_name}/pull-request-data',
47 'pullrequest_repo_refs': '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
46 'pullrequest_repo_refs': '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
48 'pullrequest_repo_destinations': '/{repo_name}/pull-request/repo-destinations',
47 'pullrequest_repo_targets': '/{repo_name}/pull-request/repo-destinations',
49 'pullrequest_new': '/{repo_name}/pull-request/new',
48 'pullrequest_new': '/{repo_name}/pull-request/new',
50 'pullrequest_create': '/{repo_name}/pull-request/create',
49 'pullrequest_create': '/{repo_name}/pull-request/create',
51 'pullrequest_update': '/{repo_name}/pull-request/{pull_request_id}/update',
50 'pullrequest_update': '/{repo_name}/pull-request/{pull_request_id}/update',
@@ -233,8 +232,7 b' class TestPullrequestsView(object):'
233 route_path('pullrequest_update',
232 route_path('pullrequest_update',
234 repo_name=pull_request.target_repo.repo_name,
233 repo_name=pull_request.target_repo.repo_name,
235 pull_request_id=pull_request_id),
234 pull_request_id=pull_request_id),
236 params={'update_commits': 'true',
235 params={'update_commits': 'true', 'csrf_token': csrf_token})
237 'csrf_token': csrf_token})
238
236
239 expected_msg = str(PullRequestModel.UPDATE_STATUS_MESSAGES[
237 expected_msg = str(PullRequestModel.UPDATE_STATUS_MESSAGES[
240 UpdateFailureReason.MISSING_SOURCE_REF])
238 UpdateFailureReason.MISSING_SOURCE_REF])
@@ -244,7 +242,8 b' class TestPullrequestsView(object):'
244 from rhodecode.lib.vcs.backends.base import MergeFailureReason
242 from rhodecode.lib.vcs.backends.base import MergeFailureReason
245 pull_request = pr_util.create_pull_request(
243 pull_request = pr_util.create_pull_request(
246 approved=True, mergeable=True)
244 approved=True, mergeable=True)
247 pull_request.target_ref = 'branch:invalid-branch:invalid-commit-id'
245 unicode_reference = u'branch:invalid-branch:invalid-commit-id'
246 pull_request.target_ref = unicode_reference
248 Session().add(pull_request)
247 Session().add(pull_request)
249 Session().commit()
248 Session().commit()
250
249
@@ -255,12 +254,12 b' class TestPullrequestsView(object):'
255 pull_request_id=pull_request_id)
254 pull_request_id=pull_request_id)
256
255
257 response = self.app.get(pull_request_url)
256 response = self.app.get(pull_request_url)
258
257 target_ref_id = 'invalid-branch'
259 assertr = AssertResponse(response)
258 merge_resp = MergeResponse(
260 expected_msg = PullRequestModel.MERGE_STATUS_MESSAGES[
259 True, True, '', MergeFailureReason.MISSING_TARGET_REF,
261 MergeFailureReason.MISSING_TARGET_REF]
260 metadata={'target_ref': PullRequest.unicode_to_reference(unicode_reference)})
262 assertr.element_contains(
261 response.assert_response().element_contains(
263 'span[data-role="merge-message"]', str(expected_msg))
262 'span[data-role="merge-message"]', merge_resp.merge_status_message)
264
263
265 def test_comment_and_close_pull_request_custom_message_approved(
264 def test_comment_and_close_pull_request_custom_message_approved(
266 self, pr_util, csrf_token, xhr_header):
265 self, pr_util, csrf_token, xhr_header):
@@ -608,8 +607,7 b' class TestPullrequestsView(object):'
608
607
609 response = self.app.post(
608 response = self.app.post(
610 route_path('pullrequest_merge',
609 route_path('pullrequest_merge',
611 repo_name=repo_name,
610 repo_name=repo_name, pull_request_id=pull_request_id),
612 pull_request_id=pull_request_id),
613 params={'csrf_token': csrf_token}).follow()
611 params={'csrf_token': csrf_token}).follow()
614
612
615 assert response.status_int == 200
613 assert response.status_int == 200
@@ -624,10 +622,13 b' class TestPullrequestsView(object):'
624 pull_request_id = pull_request.pull_request_id
622 pull_request_id = pull_request.pull_request_id
625 repo_name = pull_request.target_repo.scm_instance().name
623 repo_name = pull_request.target_repo.scm_instance().name
626
624
625 merge_resp = MergeResponse(True, False, 'STUB_COMMIT_ID',
626 MergeFailureReason.PUSH_FAILED,
627 metadata={'target': 'shadow repo',
628 'merge_commit': 'xxx'})
627 model_patcher = mock.patch.multiple(
629 model_patcher = mock.patch.multiple(
628 PullRequestModel,
630 PullRequestModel,
629 merge_repo=mock.Mock(return_value=MergeResponse(
631 merge_repo=mock.Mock(return_value=merge_resp),
630 True, False, 'STUB_COMMIT_ID', MergeFailureReason.PUSH_FAILED)),
631 merge_status=mock.Mock(return_value=(True, 'WRONG_MESSAGE')))
632 merge_status=mock.Mock(return_value=(True, 'WRONG_MESSAGE')))
632
633
633 with model_patcher:
634 with model_patcher:
@@ -637,8 +638,10 b' class TestPullrequestsView(object):'
637 pull_request_id=pull_request_id),
638 pull_request_id=pull_request_id),
638 params={'csrf_token': csrf_token}, status=302)
639 params={'csrf_token': csrf_token}, status=302)
639
640
640 assert_session_flash(response, PullRequestModel.MERGE_STATUS_MESSAGES[
641 merge_resp = MergeResponse(True, True, '', MergeFailureReason.PUSH_FAILED,
641 MergeFailureReason.PUSH_FAILED])
642 metadata={'target': 'shadow repo',
643 'merge_commit': 'xxx'})
644 assert_session_flash(response, merge_resp.merge_status_message)
642
645
643 def test_update_source_revision(self, backend, csrf_token):
646 def test_update_source_revision(self, backend, csrf_token):
644 commits = [
647 commits = [
@@ -652,20 +655,20 b' class TestPullrequestsView(object):'
652
655
653 # create pr from a in source to A in target
656 # create pr from a in source to A in target
654 pull_request = PullRequest()
657 pull_request = PullRequest()
658
655 pull_request.source_repo = source
659 pull_request.source_repo = source
656 # TODO: johbo: Make sure that we write the source ref this way!
657 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
660 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
658 branch=backend.default_branch_name, commit_id=commit_ids['change'])
661 branch=backend.default_branch_name, commit_id=commit_ids['change'])
662
659 pull_request.target_repo = target
663 pull_request.target_repo = target
660
661 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
664 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
662 branch=backend.default_branch_name,
665 branch=backend.default_branch_name, commit_id=commit_ids['ancestor'])
663 commit_id=commit_ids['ancestor'])
666
664 pull_request.revisions = [commit_ids['change']]
667 pull_request.revisions = [commit_ids['change']]
665 pull_request.title = u"Test"
668 pull_request.title = u"Test"
666 pull_request.description = u"Description"
669 pull_request.description = u"Description"
667 pull_request.author = UserModel().get_by_username(
670 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
668 TEST_USER_ADMIN_LOGIN)
671 pull_request.pull_request_state = PullRequest.STATE_CREATED
669 Session().add(pull_request)
672 Session().add(pull_request)
670 Session().commit()
673 Session().commit()
671 pull_request_id = pull_request.pull_request_id
674 pull_request_id = pull_request.pull_request_id
@@ -676,23 +679,21 b' class TestPullrequestsView(object):'
676 # update PR
679 # update PR
677 self.app.post(
680 self.app.post(
678 route_path('pullrequest_update',
681 route_path('pullrequest_update',
682 repo_name=target.repo_name, pull_request_id=pull_request_id),
683 params={'update_commits': 'true', 'csrf_token': csrf_token})
684
685 response = self.app.get(
686 route_path('pullrequest_show',
679 repo_name=target.repo_name,
687 repo_name=target.repo_name,
680 pull_request_id=pull_request_id),
688 pull_request_id=pull_request.pull_request_id))
681 params={'update_commits': 'true',
689
682 'csrf_token': csrf_token})
690 assert response.status_int == 200
691 assert 'Pull request updated to' in response.body
692 assert 'with 1 added, 0 removed commits.' in response.body
683
693
684 # check that we have now both revisions
694 # check that we have now both revisions
685 pull_request = PullRequest.get(pull_request_id)
695 pull_request = PullRequest.get(pull_request_id)
686 assert pull_request.revisions == [
696 assert pull_request.revisions == [commit_ids['change-2'], commit_ids['change']]
687 commit_ids['change-2'], commit_ids['change']]
688
689 # TODO: johbo: this should be a test on its own
690 response = self.app.get(route_path(
691 'pullrequest_new',
692 repo_name=target.repo_name))
693 assert response.status_int == 200
694 assert 'Pull request updated to' in response.body
695 assert 'with 1 added, 0 removed commits.' in response.body
696
697
697 def test_update_target_revision(self, backend, csrf_token):
698 def test_update_target_revision(self, backend, csrf_token):
698 commits = [
699 commits = [
@@ -707,21 +708,21 b' class TestPullrequestsView(object):'
707
708
708 # create pr from a in source to A in target
709 # create pr from a in source to A in target
709 pull_request = PullRequest()
710 pull_request = PullRequest()
711
710 pull_request.source_repo = source
712 pull_request.source_repo = source
711 # TODO: johbo: Make sure that we write the source ref this way!
712 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
713 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
713 branch=backend.default_branch_name, commit_id=commit_ids['change'])
714 branch=backend.default_branch_name, commit_id=commit_ids['change'])
715
714 pull_request.target_repo = target
716 pull_request.target_repo = target
715 # TODO: johbo: Target ref should be branch based, since tip can jump
716 # from branch to branch
717 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
717 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
718 branch=backend.default_branch_name,
718 branch=backend.default_branch_name, commit_id=commit_ids['ancestor'])
719 commit_id=commit_ids['ancestor'])
719
720 pull_request.revisions = [commit_ids['change']]
720 pull_request.revisions = [commit_ids['change']]
721 pull_request.title = u"Test"
721 pull_request.title = u"Test"
722 pull_request.description = u"Description"
722 pull_request.description = u"Description"
723 pull_request.author = UserModel().get_by_username(
723 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
724 TEST_USER_ADMIN_LOGIN)
724 pull_request.pull_request_state = PullRequest.STATE_CREATED
725
725 Session().add(pull_request)
726 Session().add(pull_request)
726 Session().commit()
727 Session().commit()
727 pull_request_id = pull_request.pull_request_id
728 pull_request_id = pull_request.pull_request_id
@@ -736,21 +737,19 b' class TestPullrequestsView(object):'
736 route_path('pullrequest_update',
737 route_path('pullrequest_update',
737 repo_name=target.repo_name,
738 repo_name=target.repo_name,
738 pull_request_id=pull_request_id),
739 pull_request_id=pull_request_id),
739 params={'update_commits': 'true',
740 params={'update_commits': 'true', 'csrf_token': csrf_token},
740 'csrf_token': csrf_token},
741 status=200)
741 status=200)
742
742
743 # check that we have now both revisions
743 # check that we have now both revisions
744 pull_request = PullRequest.get(pull_request_id)
744 pull_request = PullRequest.get(pull_request_id)
745 assert pull_request.revisions == [commit_ids['change-rebased']]
745 assert pull_request.revisions == [commit_ids['change-rebased']]
746 assert pull_request.target_ref == 'branch:{branch}:{commit_id}'.format(
746 assert pull_request.target_ref == 'branch:{branch}:{commit_id}'.format(
747 branch=backend.default_branch_name,
747 branch=backend.default_branch_name, commit_id=commit_ids['ancestor-new'])
748 commit_id=commit_ids['ancestor-new'])
749
748
750 # TODO: johbo: This should be a test on its own
749 response = self.app.get(
751 response = self.app.get(route_path(
750 route_path('pullrequest_show',
752 'pullrequest_new',
751 repo_name=target.repo_name,
753 repo_name=target.repo_name))
752 pull_request_id=pull_request.pull_request_id))
754 assert response.status_int == 200
753 assert response.status_int == 200
755 assert 'Pull request updated to' in response.body
754 assert 'Pull request updated to' in response.body
756 assert 'with 1 added, 1 removed commits.' in response.body
755 assert 'with 1 added, 1 removed commits.' in response.body
@@ -772,17 +771,14 b' class TestPullrequestsView(object):'
772 # create pr from a in source to A in target
771 # create pr from a in source to A in target
773 pull_request = PullRequest()
772 pull_request = PullRequest()
774 pull_request.source_repo = source
773 pull_request.source_repo = source
775 # TODO: johbo: Make sure that we write the source ref this way!
774
776 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
775 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
777 branch=backend.default_branch_name,
776 branch=backend.default_branch_name,
778 commit_id=commit_ids['master-commit-3-change-2'])
777 commit_id=commit_ids['master-commit-3-change-2'])
779
778
780 pull_request.target_repo = target
779 pull_request.target_repo = target
781 # TODO: johbo: Target ref should be branch based, since tip can jump
782 # from branch to branch
783 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
780 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
784 branch=backend.default_branch_name,
781 branch=backend.default_branch_name, commit_id=commit_ids['feat-commit-2'])
785 commit_id=commit_ids['feat-commit-2'])
786
782
787 pull_request.revisions = [
783 pull_request.revisions = [
788 commit_ids['feat-commit-1'],
784 commit_ids['feat-commit-1'],
@@ -790,8 +786,8 b' class TestPullrequestsView(object):'
790 ]
786 ]
791 pull_request.title = u"Test"
787 pull_request.title = u"Test"
792 pull_request.description = u"Description"
788 pull_request.description = u"Description"
793 pull_request.author = UserModel().get_by_username(
789 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
794 TEST_USER_ADMIN_LOGIN)
790 pull_request.pull_request_state = PullRequest.STATE_CREATED
795 Session().add(pull_request)
791 Session().add(pull_request)
796 Session().commit()
792 Session().commit()
797 pull_request_id = pull_request.pull_request_id
793 pull_request_id = pull_request.pull_request_id
@@ -807,13 +803,10 b' class TestPullrequestsView(object):'
807 route_path('pullrequest_update',
803 route_path('pullrequest_update',
808 repo_name=target.repo_name,
804 repo_name=target.repo_name,
809 pull_request_id=pull_request_id),
805 pull_request_id=pull_request_id),
810 params={'update_commits': 'true',
806 params={'update_commits': 'true', 'csrf_token': csrf_token},
811 'csrf_token': csrf_token},
812 status=200)
807 status=200)
813
808
814 response = self.app.get(route_path(
809 response = self.app.get(route_path('pullrequest_new', repo_name=target.repo_name))
815 'pullrequest_new',
816 repo_name=target.repo_name))
817 assert response.status_int == 200
810 assert response.status_int == 200
818 response.mustcontain('Pull request updated to')
811 response.mustcontain('Pull request updated to')
819 response.mustcontain('with 0 added, 0 removed commits.')
812 response.mustcontain('with 0 added, 0 removed commits.')
@@ -833,21 +826,17 b' class TestPullrequestsView(object):'
833 # create pr from a in source to A in target
826 # create pr from a in source to A in target
834 pull_request = PullRequest()
827 pull_request = PullRequest()
835 pull_request.source_repo = source
828 pull_request.source_repo = source
836 # TODO: johbo: Make sure that we write the source ref this way!
829
837 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
830 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
838 branch=backend.default_branch_name,
831 branch=backend.default_branch_name, commit_id=commit_ids['change'])
839 commit_id=commit_ids['change'])
840 pull_request.target_repo = target
832 pull_request.target_repo = target
841 # TODO: johbo: Target ref should be branch based, since tip can jump
842 # from branch to branch
843 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
833 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
844 branch=backend.default_branch_name,
834 branch=backend.default_branch_name, commit_id=commit_ids['ancestor'])
845 commit_id=commit_ids['ancestor'])
846 pull_request.revisions = [commit_ids['change']]
835 pull_request.revisions = [commit_ids['change']]
847 pull_request.title = u"Test"
836 pull_request.title = u"Test"
848 pull_request.description = u"Description"
837 pull_request.description = u"Description"
849 pull_request.author = UserModel().get_by_username(
838 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
850 TEST_USER_ADMIN_LOGIN)
839 pull_request.pull_request_state = PullRequest.STATE_CREATED
851 Session().add(pull_request)
840 Session().add(pull_request)
852 Session().commit()
841 Session().commit()
853 pull_request_id = pull_request.pull_request_id
842 pull_request_id = pull_request.pull_request_id
@@ -860,10 +849,8 b' class TestPullrequestsView(object):'
860 # update PR
849 # update PR
861 self.app.post(
850 self.app.post(
862 route_path('pullrequest_update',
851 route_path('pullrequest_update',
863 repo_name=target.repo_name,
852 repo_name=target.repo_name, pull_request_id=pull_request_id),
864 pull_request_id=pull_request_id),
853 params={'update_commits': 'true', 'csrf_token': csrf_token},
865 params={'update_commits': 'true',
866 'csrf_token': csrf_token},
867 status=200)
854 status=200)
868
855
869 # Expect the target reference to be updated correctly
856 # Expect the target reference to be updated correctly
@@ -890,13 +877,12 b' class TestPullrequestsView(object):'
890 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
877 pull_request.source_ref = 'branch:{branch}:{commit_id}'.format(
891 branch=branch_name, commit_id=commit_ids['new-feature'])
878 branch=branch_name, commit_id=commit_ids['new-feature'])
892 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
879 pull_request.target_ref = 'branch:{branch}:{commit_id}'.format(
893 branch=backend_git.default_branch_name,
880 branch=backend_git.default_branch_name, commit_id=commit_ids['old-feature'])
894 commit_id=commit_ids['old-feature'])
895 pull_request.revisions = [commit_ids['new-feature']]
881 pull_request.revisions = [commit_ids['new-feature']]
896 pull_request.title = u"Test"
882 pull_request.title = u"Test"
897 pull_request.description = u"Description"
883 pull_request.description = u"Description"
898 pull_request.author = UserModel().get_by_username(
884 pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
899 TEST_USER_ADMIN_LOGIN)
885 pull_request.pull_request_state = PullRequest.STATE_CREATED
900 Session().add(pull_request)
886 Session().add(pull_request)
901 Session().commit()
887 Session().commit()
902
888
@@ -909,11 +895,11 b' class TestPullrequestsView(object):'
909 pull_request_id=pull_request.pull_request_id))
895 pull_request_id=pull_request.pull_request_id))
910
896
911 assert response.status_int == 200
897 assert response.status_int == 200
912 assert_response = AssertResponse(response)
898
913 assert_response.element_contains(
899 response.assert_response().element_contains(
914 '#changeset_compare_view_content .alert strong',
900 '#changeset_compare_view_content .alert strong',
915 'Missing commits')
901 'Missing commits')
916 assert_response.element_contains(
902 response.assert_response().element_contains(
917 '#changeset_compare_view_content .alert',
903 '#changeset_compare_view_content .alert',
918 'This pull request cannot be displayed, because one or more'
904 'This pull request cannot be displayed, because one or more'
919 ' commits no longer exist in the source repository.')
905 ' commits no longer exist in the source repository.')
@@ -941,15 +927,15 b' class TestPullrequestsView(object):'
941 pull_request_id=pull_request.pull_request_id))
927 pull_request_id=pull_request.pull_request_id))
942
928
943 assert response.status_int == 200
929 assert response.status_int == 200
944 assert_response = AssertResponse(response)
930
945 assert_response.element_contains(
931 response.assert_response().element_contains(
946 '#changeset_compare_view_content .alert strong',
932 '#changeset_compare_view_content .alert strong',
947 'Missing commits')
933 'Missing commits')
948 assert_response.element_contains(
934 response.assert_response().element_contains(
949 '#changeset_compare_view_content .alert',
935 '#changeset_compare_view_content .alert',
950 'This pull request cannot be displayed, because one or more'
936 'This pull request cannot be displayed, because one or more'
951 ' commits no longer exist in the source repository.')
937 ' commits no longer exist in the source repository.')
952 assert_response.element_contains(
938 response.assert_response().element_contains(
953 '#update_commits',
939 '#update_commits',
954 'Update commits')
940 'Update commits')
955
941
@@ -987,8 +973,7 b' class TestPullrequestsView(object):'
987 pull_request_id=pull_request.pull_request_id))
973 pull_request_id=pull_request.pull_request_id))
988
974
989 assert response.status_int == 200
975 assert response.status_int == 200
990 assert_response = AssertResponse(response)
976 response.assert_response().element_contains(
991 assert_response.element_contains(
992 '#changeset_compare_view_content .alert strong',
977 '#changeset_compare_view_content .alert strong',
993 'Missing commits')
978 'Missing commits')
994
979
@@ -1004,12 +989,11 b' class TestPullrequestsView(object):'
1004 repo_name=pull_request.target_repo.scm_instance().name,
989 repo_name=pull_request.target_repo.scm_instance().name,
1005 pull_request_id=pull_request.pull_request_id))
990 pull_request_id=pull_request.pull_request_id))
1006 assert response.status_int == 200
991 assert response.status_int == 200
1007 assert_response = AssertResponse(response)
1008
992
1009 origin = assert_response.get_element('.pr-origininfo .tag')
993 origin = response.assert_response().get_element('.pr-origininfo .tag')
1010 origin_children = origin.getchildren()
994 origin_children = origin.getchildren()
1011 assert len(origin_children) == 1
995 assert len(origin_children) == 1
1012 target = assert_response.get_element('.pr-targetinfo .tag')
996 target = response.assert_response().get_element('.pr-targetinfo .tag')
1013 target_children = target.getchildren()
997 target_children = target.getchildren()
1014 assert len(target_children) == 1
998 assert len(target_children) == 1
1015
999
@@ -1038,13 +1022,12 b' class TestPullrequestsView(object):'
1038 repo_name=pull_request.target_repo.scm_instance().name,
1022 repo_name=pull_request.target_repo.scm_instance().name,
1039 pull_request_id=pull_request.pull_request_id))
1023 pull_request_id=pull_request.pull_request_id))
1040 assert response.status_int == 200
1024 assert response.status_int == 200
1041 assert_response = AssertResponse(response)
1042
1025
1043 origin = assert_response.get_element('.pr-origininfo .tag')
1026 origin = response.assert_response().get_element('.pr-origininfo .tag')
1044 assert origin.text.strip() == 'bookmark: origin'
1027 assert origin.text.strip() == 'bookmark: origin'
1045 assert origin.getchildren() == []
1028 assert origin.getchildren() == []
1046
1029
1047 target = assert_response.get_element('.pr-targetinfo .tag')
1030 target = response.assert_response().get_element('.pr-targetinfo .tag')
1048 assert target.text.strip() == 'bookmark: target'
1031 assert target.text.strip() == 'bookmark: target'
1049 assert target.getchildren() == []
1032 assert target.getchildren() == []
1050
1033
@@ -1060,13 +1043,12 b' class TestPullrequestsView(object):'
1060 repo_name=pull_request.target_repo.scm_instance().name,
1043 repo_name=pull_request.target_repo.scm_instance().name,
1061 pull_request_id=pull_request.pull_request_id))
1044 pull_request_id=pull_request.pull_request_id))
1062 assert response.status_int == 200
1045 assert response.status_int == 200
1063 assert_response = AssertResponse(response)
1064
1046
1065 origin = assert_response.get_element('.pr-origininfo .tag')
1047 origin = response.assert_response().get_element('.pr-origininfo .tag')
1066 assert origin.text.strip() == 'tag: origin'
1048 assert origin.text.strip() == 'tag: origin'
1067 assert origin.getchildren() == []
1049 assert origin.getchildren() == []
1068
1050
1069 target = assert_response.get_element('.pr-targetinfo .tag')
1051 target = response.assert_response().get_element('.pr-targetinfo .tag')
1070 assert target.text.strip() == 'tag: target'
1052 assert target.text.strip() == 'tag: target'
1071 assert target.getchildren() == []
1053 assert target.getchildren() == []
1072
1054
@@ -1090,12 +1072,13 b' class TestPullrequestsView(object):'
1090 repo_name=target_repo.name,
1072 repo_name=target_repo.name,
1091 pull_request_id=pr_id))
1073 pull_request_id=pr_id))
1092
1074
1093 assertr = AssertResponse(response)
1094 if mergeable:
1075 if mergeable:
1095 assertr.element_value_contains('input.pr-mergeinfo', shadow_url)
1076 response.assert_response().element_value_contains(
1096 assertr.element_value_contains('input.pr-mergeinfo ', 'pr-merge')
1077 'input.pr-mergeinfo', shadow_url)
1078 response.assert_response().element_value_contains(
1079 'input.pr-mergeinfo ', 'pr-merge')
1097 else:
1080 else:
1098 assertr.no_element_exists('.pr-mergeinfo')
1081 response.assert_response().no_element_exists('.pr-mergeinfo')
1099
1082
1100
1083
1101 @pytest.mark.usefixtures('app')
1084 @pytest.mark.usefixtures('app')
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -203,7 +203,6 b' class RepoChangelogView(RepoAppView):'
203 pre_load = self._get_preload_attrs()
203 pre_load = self._get_preload_attrs()
204
204
205 partial_xhr = self.request.environ.get('HTTP_X_PARTIAL_XHR')
205 partial_xhr = self.request.environ.get('HTTP_X_PARTIAL_XHR')
206
207 try:
206 try:
208 if f_path:
207 if f_path:
209 log.debug('generating changelog for path %s', f_path)
208 log.debug('generating changelog for path %s', f_path)
@@ -231,7 +230,7 b' class RepoChangelogView(RepoAppView):'
231 else:
230 else:
232 collection = self.rhodecode_vcs_repo.get_commits(
231 collection = self.rhodecode_vcs_repo.get_commits(
233 branch_name=branch_name, show_hidden=show_hidden,
232 branch_name=branch_name, show_hidden=show_hidden,
234 pre_load=pre_load)
233 pre_load=pre_load, translate_tags=False)
235
234
236 self._load_changelog_data(
235 self._load_changelog_data(
237 c, collection, p, chunk_size, c.branch_name,
236 c, collection, p, chunk_size, c.branch_name,
@@ -320,7 +319,8 b' class RepoChangelogView(RepoAppView):'
320 collection = list(reversed(collection))
319 collection = list(reversed(collection))
321 else:
320 else:
322 collection = self.rhodecode_vcs_repo.get_commits(
321 collection = self.rhodecode_vcs_repo.get_commits(
323 branch_name=branch_name, show_hidden=show_hidden, pre_load=pre_load)
322 branch_name=branch_name, show_hidden=show_hidden, pre_load=pre_load,
323 translate_tags=False)
324
324
325 p = safe_int(self.request.GET.get('page', 1), 1)
325 p = safe_int(self.request.GET.get('page', 1), 1)
326 try:
326 try:
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -97,7 +97,7 b' class RepoCommitsView(RepoAppView):'
97 if len(commit_range) == 2:
97 if len(commit_range) == 2:
98 commits = self.rhodecode_vcs_repo.get_commits(
98 commits = self.rhodecode_vcs_repo.get_commits(
99 start_id=commit_range[0], end_id=commit_range[1],
99 start_id=commit_range[0], end_id=commit_range[1],
100 pre_load=pre_load)
100 pre_load=pre_load, translate_tags=False)
101 commits = list(commits)
101 commits = list(commits)
102 else:
102 else:
103 commits = [self.rhodecode_vcs_repo.get_commit(
103 commits = [self.rhodecode_vcs_repo.get_commit(
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -27,12 +27,13 b' from pyramid.renderers import render'
27 from pyramid.response import Response
27 from pyramid.response import Response
28
28
29 from rhodecode.apps._base import RepoAppView
29 from rhodecode.apps._base import RepoAppView
30 from rhodecode.controllers.utils import parse_path_ref, get_commit_from_ref_name
30
31 from rhodecode.lib import helpers as h
31 from rhodecode.lib import helpers as h
32 from rhodecode.lib import diffs, codeblocks
32 from rhodecode.lib import diffs, codeblocks
33 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
34 from rhodecode.lib.utils import safe_str
34 from rhodecode.lib.utils import safe_str
35 from rhodecode.lib.utils2 import safe_unicode, str2bool
35 from rhodecode.lib.utils2 import safe_unicode, str2bool
36 from rhodecode.lib.view_utils import parse_path_ref, get_commit_from_ref_name
36 from rhodecode.lib.vcs.exceptions import (
37 from rhodecode.lib.vcs.exceptions import (
37 EmptyRepositoryError, RepositoryError, RepositoryRequirementError,
38 EmptyRepositoryError, RepositoryError, RepositoryRequirementError,
38 NodeDoesNotExistError)
39 NodeDoesNotExistError)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -34,9 +34,10 b' from pyramid.response import Response'
34 import rhodecode
34 import rhodecode
35 from rhodecode.apps._base import RepoAppView
35 from rhodecode.apps._base import RepoAppView
36
36
37 from rhodecode.controllers.utils import parse_path_ref
37
38 from rhodecode.lib import diffs, helpers as h, rc_cache
38 from rhodecode.lib import diffs, helpers as h, rc_cache
39 from rhodecode.lib import audit_logger
39 from rhodecode.lib import audit_logger
40 from rhodecode.lib.view_utils import parse_path_ref
40 from rhodecode.lib.exceptions import NonRelativePathError
41 from rhodecode.lib.exceptions import NonRelativePathError
41 from rhodecode.lib.codeblocks import (
42 from rhodecode.lib.codeblocks import (
42 filenode_as_lines_tokens, filenode_as_annotated_lines_tokens)
43 filenode_as_lines_tokens, filenode_as_annotated_lines_tokens)
@@ -83,6 +84,7 b' class RepoFilesView(RepoAppView):'
83 def load_default_context(self):
84 def load_default_context(self):
84 c = self._get_local_tmpl_context(include_app_defaults=True)
85 c = self._get_local_tmpl_context(include_app_defaults=True)
85 c.rhodecode_repo = self.rhodecode_vcs_repo
86 c.rhodecode_repo = self.rhodecode_vcs_repo
87 c.enable_downloads = self.db_repo.enable_downloads
86 return c
88 return c
87
89
88 def _ensure_not_locked(self):
90 def _ensure_not_locked(self):
@@ -227,10 +229,11 b' class RepoFilesView(RepoAppView):'
227 self, c, commit_id, f_path, full_load=False):
229 self, c, commit_id, f_path, full_load=False):
228
230
229 repo_id = self.db_repo.repo_id
231 repo_id = self.db_repo.repo_id
232 force_recache = self.get_recache_flag()
230
233
231 cache_seconds = safe_int(
234 cache_seconds = safe_int(
232 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
235 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
233 cache_on = cache_seconds > 0
236 cache_on = not force_recache and cache_seconds > 0
234 log.debug(
237 log.debug(
235 'Computing FILE TREE for repo_id %s commit_id `%s` and path `%s`'
238 'Computing FILE TREE for repo_id %s commit_id `%s` and path `%s`'
236 'with caching: %s[TTL: %ss]' % (
239 'with caching: %s[TTL: %ss]' % (
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -50,8 +50,13 b' class RepoSettingsPermissionsView(RepoAp'
50 route_name='edit_repo_perms', request_method='GET',
50 route_name='edit_repo_perms', request_method='GET',
51 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
51 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
52 def edit_permissions(self):
52 def edit_permissions(self):
53 _ = self.request.translate
53 c = self.load_default_context()
54 c = self.load_default_context()
54 c.active = 'permissions'
55 c.active = 'permissions'
56 if self.request.GET.get('branch_permissions'):
57 h.flash(_('Explicitly add user or user group with write+ '
58 'permission to modify their branch permissions.'),
59 category='notice')
55 return self._get_template_context(c)
60 return self._get_template_context(c)
56
61
57 @LoginRequired()
62 @LoginRequired()
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -137,13 +137,6 b' class RepoPullRequestsView(RepoAppView, '
137 })
137 })
138 return data
138 return data
139
139
140 def get_recache_flag(self):
141 for flag_name in ['force_recache', 'force-recache', 'no-cache']:
142 flag_val = self.request.GET.get(flag_name)
143 if str2bool(flag_val):
144 return True
145 return False
146
147 @LoginRequired()
140 @LoginRequired()
148 @HasRepoPermissionAnyDecorator(
141 @HasRepoPermissionAnyDecorator(
149 'repository.read', 'repository.write', 'repository.admin')
142 'repository.read', 'repository.write', 'repository.admin')
@@ -272,9 +265,22 b' class RepoPullRequestsView(RepoAppView, '
272 route_name='pullrequest_show', request_method='GET',
265 route_name='pullrequest_show', request_method='GET',
273 renderer='rhodecode:templates/pullrequests/pullrequest_show.mako')
266 renderer='rhodecode:templates/pullrequests/pullrequest_show.mako')
274 def pull_request_show(self):
267 def pull_request_show(self):
275 pull_request_id = self.request.matchdict['pull_request_id']
268 _ = self.request.translate
269 c = self.load_default_context()
270
271 pull_request = PullRequest.get_or_404(
272 self.request.matchdict['pull_request_id'])
273 pull_request_id = pull_request.pull_request_id
276
274
277 c = self.load_default_context()
275 if pull_request.pull_request_state != PullRequest.STATE_CREATED:
276 log.debug('show: forbidden because pull request is in state %s',
277 pull_request.pull_request_state)
278 msg = _(u'Cannot show pull requests in state other than `{}`. '
279 u'Current state is: `{}`').format(PullRequest.STATE_CREATED,
280 pull_request.pull_request_state)
281 h.flash(msg, category='error')
282 raise HTTPFound(h.route_path('pullrequest_show_all',
283 repo_name=self.db_repo_name))
278
284
279 version = self.request.GET.get('version')
285 version = self.request.GET.get('version')
280 from_version = self.request.GET.get('from_version') or version
286 from_version = self.request.GET.get('from_version') or version
@@ -754,7 +760,7 b' class RepoPullRequestsView(RepoAppView, '
754
760
755 default_target_repo = source_repo
761 default_target_repo = source_repo
756
762
757 if source_repo.parent:
763 if source_repo.parent and c.has_origin_repo_read_perm:
758 parent_vcs_obj = source_repo.parent.scm_instance()
764 parent_vcs_obj = source_repo.parent.scm_instance()
759 if parent_vcs_obj and not parent_vcs_obj.is_empty():
765 if parent_vcs_obj and not parent_vcs_obj.is_empty():
760 # change default if we have a parent repo
766 # change default if we have a parent repo
@@ -811,37 +817,51 b' class RepoPullRequestsView(RepoAppView, '
811 @HasRepoPermissionAnyDecorator(
817 @HasRepoPermissionAnyDecorator(
812 'repository.read', 'repository.write', 'repository.admin')
818 'repository.read', 'repository.write', 'repository.admin')
813 @view_config(
819 @view_config(
814 route_name='pullrequest_repo_destinations', request_method='GET',
820 route_name='pullrequest_repo_targets', request_method='GET',
815 renderer='json_ext', xhr=True)
821 renderer='json_ext', xhr=True)
816 def pull_request_repo_destinations(self):
822 def pullrequest_repo_targets(self):
817 _ = self.request.translate
823 _ = self.request.translate
818 filter_query = self.request.GET.get('query')
824 filter_query = self.request.GET.get('query')
819
825
820 query = Repository.query() \
826 # get the parents
827 parent_target_repos = []
828 if self.db_repo.parent:
829 parents_query = Repository.query() \
821 .order_by(func.length(Repository.repo_name)) \
830 .order_by(func.length(Repository.repo_name)) \
822 .filter(
831 .filter(Repository.fork_id == self.db_repo.parent.repo_id)
823 or_(Repository.repo_name == self.db_repo.repo_name,
824 Repository.fork_id == self.db_repo.repo_id))
825
832
826 if filter_query:
833 if filter_query:
827 ilike_expression = u'%{}%'.format(safe_unicode(filter_query))
834 ilike_expression = u'%{}%'.format(safe_unicode(filter_query))
828 query = query.filter(
835 parents_query = parents_query.filter(
829 Repository.repo_name.ilike(ilike_expression))
836 Repository.repo_name.ilike(ilike_expression))
837 parents = parents_query.limit(20).all()
838
839 for parent in parents:
840 parent_vcs_obj = parent.scm_instance()
841 if parent_vcs_obj and not parent_vcs_obj.is_empty():
842 parent_target_repos.append(parent)
830
843
831 add_parent = False
844 # get other forks, and repo itself
832 if self.db_repo.parent:
845 query = Repository.query() \
833 if filter_query in self.db_repo.parent.repo_name:
846 .order_by(func.length(Repository.repo_name)) \
834 parent_vcs_obj = self.db_repo.parent.scm_instance()
847 .filter(
835 if parent_vcs_obj and not parent_vcs_obj.is_empty():
848 or_(Repository.repo_id == self.db_repo.repo_id, # repo itself
836 add_parent = True
849 Repository.fork_id == self.db_repo.repo_id) # forks of this repo
850 ) \
851 .filter(~Repository.repo_id.in_([x.repo_id for x in parent_target_repos]))
837
852
838 limit = 20 - 1 if add_parent else 20
853 if filter_query:
839 all_repos = query.limit(limit).all()
854 ilike_expression = u'%{}%'.format(safe_unicode(filter_query))
840 if add_parent:
855 query = query.filter(Repository.repo_name.ilike(ilike_expression))
841 all_repos += [self.db_repo.parent]
856
857 limit = max(20 - len(parent_target_repos), 5) # not less then 5
858 target_repos = query.limit(limit).all()
859
860 all_target_repos = target_repos + parent_target_repos
842
861
843 repos = []
862 repos = []
844 for obj in ScmModel().get_repos(all_repos):
863 # This checks permissions to the repositories
864 for obj in ScmModel().get_repos(all_target_repos):
845 repos.append({
865 repos.append({
846 'id': obj['name'],
866 'id': obj['name'],
847 'text': obj['name'],
867 'text': obj['name'],
@@ -904,12 +924,17 b' class RepoPullRequestsView(RepoAppView, '
904 source_db_repo = Repository.get_by_repo_name(_form['source_repo'])
924 source_db_repo = Repository.get_by_repo_name(_form['source_repo'])
905 target_db_repo = Repository.get_by_repo_name(_form['target_repo'])
925 target_db_repo = Repository.get_by_repo_name(_form['target_repo'])
906
926
927 if not (source_db_repo or target_db_repo):
928 h.flash(_('source_repo or target repo not found'), category='error')
929 raise HTTPFound(
930 h.route_path('pullrequest_new', repo_name=self.db_repo_name))
931
907 # re-check permissions again here
932 # re-check permissions again here
908 # source_repo we must have read permissions
933 # source_repo we must have read permissions
909
934
910 source_perm = HasRepoPermissionAny(
935 source_perm = HasRepoPermissionAny(
911 'repository.read',
936 'repository.read', 'repository.write', 'repository.admin')(
912 'repository.write', 'repository.admin')(source_db_repo.repo_name)
937 source_db_repo.repo_name)
913 if not source_perm:
938 if not source_perm:
914 msg = _('Not Enough permissions to source repo `{}`.'.format(
939 msg = _('Not Enough permissions to source repo `{}`.'.format(
915 source_db_repo.repo_name))
940 source_db_repo.repo_name))
@@ -923,8 +948,8 b' class RepoPullRequestsView(RepoAppView, '
923 # target repo we must have read permissions, and also later on
948 # target repo we must have read permissions, and also later on
924 # we want to check branch permissions here
949 # we want to check branch permissions here
925 target_perm = HasRepoPermissionAny(
950 target_perm = HasRepoPermissionAny(
926 'repository.read',
951 'repository.read', 'repository.write', 'repository.admin')(
927 'repository.write', 'repository.admin')(target_db_repo.repo_name)
952 target_db_repo.repo_name)
928 if not target_perm:
953 if not target_perm:
929 msg = _('Not Enough permissions to target repo `{}`.'.format(
954 msg = _('Not Enough permissions to target repo `{}`.'.format(
930 target_db_repo.repo_name))
955 target_db_repo.repo_name))
@@ -1027,6 +1052,15 b' class RepoPullRequestsView(RepoAppView, '
1027 h.flash(msg, category='error')
1052 h.flash(msg, category='error')
1028 return True
1053 return True
1029
1054
1055 if pull_request.pull_request_state != PullRequest.STATE_CREATED:
1056 log.debug('update: forbidden because pull request is in state %s',
1057 pull_request.pull_request_state)
1058 msg = _(u'Cannot update pull requests in state other than `{}`. '
1059 u'Current state is: `{}`').format(PullRequest.STATE_CREATED,
1060 pull_request.pull_request_state)
1061 h.flash(msg, category='error')
1062 return True
1063
1030 # only owner or admin can update it
1064 # only owner or admin can update it
1031 allowed_to_update = PullRequestModel().check_user_update(
1065 allowed_to_update = PullRequestModel().check_user_update(
1032 pull_request, self._rhodecode_user)
1066 pull_request, self._rhodecode_user)
@@ -1069,6 +1103,8 b' class RepoPullRequestsView(RepoAppView, '
1069
1103
1070 def _update_commits(self, pull_request):
1104 def _update_commits(self, pull_request):
1071 _ = self.request.translate
1105 _ = self.request.translate
1106
1107 with pull_request.set_state(PullRequest.STATE_UPDATING):
1072 resp = PullRequestModel().update_commits(pull_request)
1108 resp = PullRequestModel().update_commits(pull_request)
1073
1109
1074 if resp.executed:
1110 if resp.executed:
@@ -1082,8 +1118,7 b' class RepoPullRequestsView(RepoAppView, '
1082 else:
1118 else:
1083 changed = 'nothing'
1119 changed = 'nothing'
1084
1120
1085 msg = _(
1121 msg = _(u'Pull request updated to "{source_commit_id}" with '
1086 u'Pull request updated to "{source_commit_id}" with '
1087 u'{count_added} added, {count_removed} removed commits. '
1122 u'{count_added} added, {count_removed} removed commits. '
1088 u'Source of changes: {change_source}')
1123 u'Source of changes: {change_source}')
1089 msg = msg.format(
1124 msg = msg.format(
@@ -1094,8 +1129,7 b' class RepoPullRequestsView(RepoAppView, '
1094 h.flash(msg, category='success')
1129 h.flash(msg, category='success')
1095
1130
1096 channel = '/repo${}$/pr/{}'.format(
1131 channel = '/repo${}$/pr/{}'.format(
1097 pull_request.target_repo.repo_name,
1132 pull_request.target_repo.repo_name, pull_request.pull_request_id)
1098 pull_request.pull_request_id)
1099 message = msg + (
1133 message = msg + (
1100 ' - <a onclick="window.location.reload()">'
1134 ' - <a onclick="window.location.reload()">'
1101 '<strong>{}</strong></a>'.format(_('Reload page')))
1135 '<strong>{}</strong></a>'.format(_('Reload page')))
@@ -1128,8 +1162,23 b' class RepoPullRequestsView(RepoAppView, '
1128 """
1162 """
1129 pull_request = PullRequest.get_or_404(
1163 pull_request = PullRequest.get_or_404(
1130 self.request.matchdict['pull_request_id'])
1164 self.request.matchdict['pull_request_id'])
1165 _ = self.request.translate
1166
1167 if pull_request.pull_request_state != PullRequest.STATE_CREATED:
1168 log.debug('show: forbidden because pull request is in state %s',
1169 pull_request.pull_request_state)
1170 msg = _(u'Cannot merge pull requests in state other than `{}`. '
1171 u'Current state is: `{}`').format(PullRequest.STATE_CREATED,
1172 pull_request.pull_request_state)
1173 h.flash(msg, category='error')
1174 raise HTTPFound(
1175 h.route_path('pullrequest_show',
1176 repo_name=pull_request.target_repo.repo_name,
1177 pull_request_id=pull_request.pull_request_id))
1131
1178
1132 self.load_default_context()
1179 self.load_default_context()
1180
1181 with pull_request.set_state(PullRequest.STATE_UPDATING):
1133 check = MergeCheck.validate(
1182 check = MergeCheck.validate(
1134 pull_request, auth_user=self._rhodecode_user,
1183 pull_request, auth_user=self._rhodecode_user,
1135 translator=self.request.translate)
1184 translator=self.request.translate)
@@ -1144,6 +1193,7 b' class RepoPullRequestsView(RepoAppView, '
1144 self.request.environ, repo_name=pull_request.target_repo.repo_name,
1193 self.request.environ, repo_name=pull_request.target_repo.repo_name,
1145 username=self._rhodecode_db_user.username, action='push',
1194 username=self._rhodecode_db_user.username, action='push',
1146 scm=pull_request.target_repo.repo_type)
1195 scm=pull_request.target_repo.repo_type)
1196 with pull_request.set_state(PullRequest.STATE_UPDATING):
1147 self._merge_pull_request(
1197 self._merge_pull_request(
1148 pull_request, self._rhodecode_db_user, extras)
1198 pull_request, self._rhodecode_db_user, extras)
1149 else:
1199 else:
@@ -1167,10 +1217,8 b' class RepoPullRequestsView(RepoAppView, '
1167 h.flash(msg, category='success')
1217 h.flash(msg, category='success')
1168 else:
1218 else:
1169 log.debug(
1219 log.debug(
1170 "The merge was not successful. Merge response: %s",
1220 "The merge was not successful. Merge response: %s", merge_resp)
1171 merge_resp)
1221 msg = merge_resp.merge_status_message
1172 msg = PullRequestModel().merge_status_message(
1173 merge_resp.failure_reason)
1174 h.flash(msg, category='error')
1222 h.flash(msg, category='error')
1175
1223
1176 def _update_reviewers(self, pull_request, review_members, reviewer_rules):
1224 def _update_reviewers(self, pull_request, review_members, reviewer_rules):
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -73,6 +73,8 b' class RepoSettingsView(RepoAppView):'
73 'repository.write', 'repository.read', 'repository.admin')(
73 'repository.write', 'repository.read', 'repository.admin')(
74 self.db_repo.fork.repo_name, 'repo set as fork page')
74 self.db_repo.fork.repo_name, 'repo set as fork page')
75
75
76 c.ver_info_dict = self.rhodecode_vcs_repo.get_hooks_info()
77
76 return self._get_template_context(c)
78 return self._get_template_context(c)
77
79
78 @LoginRequired()
80 @LoginRequired()
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -24,7 +24,7 b' import rhodecode'
24
24
25 from pyramid.view import view_config
25 from pyramid.view import view_config
26
26
27 from rhodecode.controllers import utils
27 from rhodecode.lib.view_utils import get_format_ref_id
28 from rhodecode.apps._base import RepoAppView
28 from rhodecode.apps._base import RepoAppView
29 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
29 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
30 from rhodecode.lib import helpers as h, rc_cache
30 from rhodecode.lib import helpers as h, rc_cache
@@ -141,7 +141,8 b' class RepoSummaryView(RepoAppView):'
141
141
142 pre_load = ['author', 'branch', 'date', 'message']
142 pre_load = ['author', 'branch', 'date', 'message']
143 try:
143 try:
144 collection = self.rhodecode_vcs_repo.get_commits(pre_load=pre_load)
144 collection = self.rhodecode_vcs_repo.get_commits(
145 pre_load=pre_load, translate_tags=False)
145 except EmptyRepositoryError:
146 except EmptyRepositoryError:
146 collection = self.rhodecode_vcs_repo
147 collection = self.rhodecode_vcs_repo
147
148
@@ -351,7 +352,7 b' class RepoSummaryView(RepoAppView):'
351 return data
352 return data
352
353
353 def _create_reference_data(self, repo, full_repo_name, refs_to_create):
354 def _create_reference_data(self, repo, full_repo_name, refs_to_create):
354 format_ref_id = utils.get_format_ref_id(repo)
355 format_ref_id = get_format_ref_id(repo)
355
356
356 result = []
357 result = []
357 for title, refs, ref_type in refs_to_create:
358 for title, refs, ref_type in refs_to_create:
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -28,7 +28,16 b' def includeme(config):'
28
28
29 config.add_route(
29 config.add_route(
30 name='search_repo',
30 name='search_repo',
31 pattern='/{repo_name:.*?[^/]}/_search', repo_route=True)
32
33 config.add_route(
34 name='search_repo_alt',
31 pattern='/{repo_name:.*?[^/]}/search', repo_route=True)
35 pattern='/{repo_name:.*?[^/]}/search', repo_route=True)
32
36
37 config.add_route(
38 name='search_repo_group',
39 pattern='/{repo_group_name:.*?[^/]}/_search',
40 repo_group_route=True)
41
33 # Scan module for configuration decorators.
42 # Scan module for configuration decorators.
34 config.scan('.views', ignore='.tests')
43 config.scan('.views', ignore='.tests')
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -23,8 +23,9 b' import urllib'
23 from pyramid.view import view_config
23 from pyramid.view import view_config
24 from webhelpers.util import update_params
24 from webhelpers.util import update_params
25
25
26 from rhodecode.apps._base import BaseAppView, RepoAppView
26 from rhodecode.apps._base import BaseAppView, RepoAppView, RepoGroupAppView
27 from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator)
27 from rhodecode.lib.auth import (
28 LoginRequired, HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator)
28 from rhodecode.lib.helpers import Page
29 from rhodecode.lib.helpers import Page
29 from rhodecode.lib.utils2 import safe_str
30 from rhodecode.lib.utils2 import safe_str
30 from rhodecode.lib.index import searcher_from_config
31 from rhodecode.lib.index import searcher_from_config
@@ -34,22 +35,25 b' from rhodecode.model.validation_schema.s'
34 log = logging.getLogger(__name__)
35 log = logging.getLogger(__name__)
35
36
36
37
37 def search(request, tmpl_context, repo_name):
38 def perform_search(request, tmpl_context, repo_name=None, repo_group_name=None):
38 searcher = searcher_from_config(request.registry.settings)
39 searcher = searcher_from_config(request.registry.settings)
39 formatted_results = []
40 formatted_results = []
40 execution_time = ''
41 execution_time = ''
41
42
42 schema = search_schema.SearchParamsSchema()
43 schema = search_schema.SearchParamsSchema()
43
44 search_tags = []
44 search_params = {}
45 search_params = {}
45 errors = []
46 errors = []
46 try:
47 try:
47 search_params = schema.deserialize(
48 search_params = schema.deserialize(
48 dict(search_query=request.GET.get('q'),
49 dict(
50 search_query=request.GET.get('q'),
49 search_type=request.GET.get('type'),
51 search_type=request.GET.get('type'),
50 search_sort=request.GET.get('sort'),
52 search_sort=request.GET.get('sort'),
53 search_max_lines=request.GET.get('max_lines'),
51 page_limit=request.GET.get('page_limit'),
54 page_limit=request.GET.get('page_limit'),
52 requested_page=request.GET.get('page'))
55 requested_page=request.GET.get('page'),
56 )
53 )
57 )
54 except validation_schema.Invalid as e:
58 except validation_schema.Invalid as e:
55 errors = e.children
59 errors = e.children
@@ -57,20 +61,22 b' def search(request, tmpl_context, repo_n'
57 def url_generator(**kw):
61 def url_generator(**kw):
58 q = urllib.quote(safe_str(search_query))
62 q = urllib.quote(safe_str(search_query))
59 return update_params(
63 return update_params(
60 "?q=%s&type=%s" % (q, safe_str(search_type)), **kw)
64 "?q=%s&type=%s&max_lines=%s" % (
65 q, safe_str(search_type), search_max_lines), **kw)
61
66
62 c = tmpl_context
67 c = tmpl_context
63 search_query = search_params.get('search_query')
68 search_query = search_params.get('search_query')
64 search_type = search_params.get('search_type')
69 search_type = search_params.get('search_type')
65 search_sort = search_params.get('search_sort')
70 search_sort = search_params.get('search_sort')
71 search_max_lines = search_params.get('search_max_lines')
66 if search_params.get('search_query'):
72 if search_params.get('search_query'):
67 page_limit = search_params['page_limit']
73 page_limit = search_params['page_limit']
68 requested_page = search_params['requested_page']
74 requested_page = search_params['requested_page']
69
75
70 try:
76 try:
71 search_result = searcher.search(
77 search_result = searcher.search(
72 search_query, search_type, c.auth_user, repo_name,
78 search_query, search_type, c.auth_user, repo_name, repo_group_name,
73 requested_page, page_limit, search_sort)
79 requested_page=requested_page, page_limit=page_limit, sort=search_sort)
74
80
75 formatted_results = Page(
81 formatted_results = Page(
76 search_result['results'], page=requested_page,
82 search_result['results'], page=requested_page,
@@ -79,6 +85,8 b' def search(request, tmpl_context, repo_n'
79 finally:
85 finally:
80 searcher.cleanup()
86 searcher.cleanup()
81
87
88 search_tags = searcher.extract_search_tags(search_query)
89
82 if not search_result['error']:
90 if not search_result['error']:
83 execution_time = '%s results (%.3f seconds)' % (
91 execution_time = '%s results (%.3f seconds)' % (
84 search_result['count'],
92 search_result['count'],
@@ -90,6 +98,7 b' def search(request, tmpl_context, repo_n'
90
98
91 c.perm_user = c.auth_user
99 c.perm_user = c.auth_user
92 c.repo_name = repo_name
100 c.repo_name = repo_name
101 c.repo_group_name = repo_group_name
93 c.sort = search_sort
102 c.sort = search_sort
94 c.url_generator = url_generator
103 c.url_generator = url_generator
95 c.errors = errors
104 c.errors = errors
@@ -98,12 +107,12 b' def search(request, tmpl_context, repo_n'
98 c.cur_query = search_query
107 c.cur_query = search_query
99 c.search_type = search_type
108 c.search_type = search_type
100 c.searcher = searcher
109 c.searcher = searcher
110 c.search_tags = search_tags
101
111
102
112
103 class SearchView(BaseAppView):
113 class SearchView(BaseAppView):
104 def load_default_context(self):
114 def load_default_context(self):
105 c = self._get_local_tmpl_context()
115 c = self._get_local_tmpl_context()
106
107 return c
116 return c
108
117
109 @LoginRequired()
118 @LoginRequired()
@@ -112,14 +121,14 b' class SearchView(BaseAppView):'
112 renderer='rhodecode:templates/search/search.mako')
121 renderer='rhodecode:templates/search/search.mako')
113 def search(self):
122 def search(self):
114 c = self.load_default_context()
123 c = self.load_default_context()
115 search(self.request, c, repo_name=None)
124 perform_search(self.request, c)
116 return self._get_template_context(c)
125 return self._get_template_context(c)
117
126
118
127
119 class SearchRepoView(RepoAppView):
128 class SearchRepoView(RepoAppView):
120 def load_default_context(self):
129 def load_default_context(self):
121 c = self._get_local_tmpl_context()
130 c = self._get_local_tmpl_context()
122
131 c.active = 'search'
123 return c
132 return c
124
133
125 @LoginRequired()
134 @LoginRequired()
@@ -128,7 +137,28 b' class SearchRepoView(RepoAppView):'
128 @view_config(
137 @view_config(
129 route_name='search_repo', request_method='GET',
138 route_name='search_repo', request_method='GET',
130 renderer='rhodecode:templates/search/search.mako')
139 renderer='rhodecode:templates/search/search.mako')
140 @view_config(
141 route_name='search_repo_alt', request_method='GET',
142 renderer='rhodecode:templates/search/search.mako')
131 def search_repo(self):
143 def search_repo(self):
132 c = self.load_default_context()
144 c = self.load_default_context()
133 search(self.request, c, repo_name=self.db_repo_name)
145 perform_search(self.request, c, repo_name=self.db_repo_name)
134 return self._get_template_context(c)
146 return self._get_template_context(c)
147
148
149 class SearchRepoGroupView(RepoGroupAppView):
150 def load_default_context(self):
151 c = self._get_local_tmpl_context()
152 c.active = 'search'
153 return c
154
155 @LoginRequired()
156 @HasRepoGroupPermissionAnyDecorator(
157 'group.read', 'group.write', 'group.admin')
158 @view_config(
159 route_name='search_repo_group', request_method='GET',
160 renderer='rhodecode:templates/search/search.mako')
161 def search_repo_group(self):
162 c = self.load_default_context()
163 perform_search(self.request, c, repo_group_name=self.db_repo_group_name)
164 return self._get_template_context(c)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -36,6 +36,7 b' def _sanitize_settings_and_apply_default'
36 _bool_setting(settings, config_keys.generate_authorized_keyfile, 'false')
36 _bool_setting(settings, config_keys.generate_authorized_keyfile, 'false')
37 _bool_setting(settings, config_keys.wrapper_allow_shell, 'false')
37 _bool_setting(settings, config_keys.wrapper_allow_shell, 'false')
38 _bool_setting(settings, config_keys.enable_debug_logging, 'false')
38 _bool_setting(settings, config_keys.enable_debug_logging, 'false')
39 _bool_setting(settings, config_keys.ssh_key_generator_enabled, 'true')
39
40
40 _string_setting(settings, config_keys.authorized_keys_file_path,
41 _string_setting(settings, config_keys.authorized_keys_file_path,
41 '~/.ssh/authorized_keys_rhodecode',
42 '~/.ssh/authorized_keys_rhodecode',
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -24,6 +24,7 b''
24 generate_authorized_keyfile = 'ssh.generate_authorized_keyfile'
24 generate_authorized_keyfile = 'ssh.generate_authorized_keyfile'
25 authorized_keys_file_path = 'ssh.authorized_keys_file_path'
25 authorized_keys_file_path = 'ssh.authorized_keys_file_path'
26 authorized_keys_line_ssh_opts = 'ssh.authorized_keys_ssh_opts'
26 authorized_keys_line_ssh_opts = 'ssh.authorized_keys_ssh_opts'
27 ssh_key_generator_enabled = 'ssh.enable_ui_key_generator'
27 wrapper_cmd = 'ssh.wrapper_cmd'
28 wrapper_cmd = 'ssh.wrapper_cmd'
28 wrapper_allow_shell = 'ssh.wrapper_cmd_allow_shell'
29 wrapper_allow_shell = 'ssh.wrapper_cmd_allow_shell'
29 enable_debug_logging = 'ssh.enable_debug_logging'
30 enable_debug_logging = 'ssh.enable_debug_logging'
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -17,10 +17,10 b''
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
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 import os
21 import logging
21 import logging
22 import os
23 import shlex
22 import shlex
23 from pyramid import compat
24
24
25 # Do not use `from rhodecode import events` here, it will be overridden by the
25 # Do not use `from rhodecode import events` here, it will be overridden by the
26 # events module in this package due to pythons import mechanism.
26 # events module in this package due to pythons import mechanism.
@@ -85,6 +85,6 b' def _append_path_sep(path):'
85 """
85 """
86 Append the path separator if missing.
86 Append the path separator if missing.
87 """
87 """
88 if isinstance(path, basestring) and not path.endswith(os.path.sep):
88 if isinstance(path, compat.string_types) and not path.endswith(os.path.sep):
89 path += os.path.sep
89 path += os.path.sep
90 return path
90 return path
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -24,12 +24,15 b' RhodeCode authentication plugin for buil'
24
24
25 import logging
25 import logging
26
26
27 from rhodecode.translation import _
27 import colander
28
28
29 from rhodecode.authentication.base import RhodeCodeAuthPluginBase, hybrid_property
29 from rhodecode.translation import _
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
31 from rhodecode.lib.utils2 import safe_str
30 from rhodecode.lib.utils2 import safe_str
32 from rhodecode.model.db import User
31 from rhodecode.model.db import User
32 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
33 from rhodecode.authentication.base import (
34 RhodeCodeAuthPluginBase, hybrid_property, HTTP_TYPE, VCS_TYPE)
35 from rhodecode.authentication.routes import AuthnPluginResourceBase
33
36
34 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
35
38
@@ -45,6 +48,11 b' class RhodecodeAuthnResource(AuthnPlugin'
45
48
46 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
49 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
47 uid = 'rhodecode'
50 uid = 'rhodecode'
51 AUTH_RESTRICTION_NONE = 'user_all'
52 AUTH_RESTRICTION_SUPER_ADMIN = 'user_super_admin'
53 AUTH_RESTRICTION_SCOPE_ALL = 'scope_all'
54 AUTH_RESTRICTION_SCOPE_HTTP = 'scope_http'
55 AUTH_RESTRICTION_SCOPE_VCS = 'scope_vcs'
48
56
49 def includeme(self, config):
57 def includeme(self, config):
50 config.add_authn_plugin(self)
58 config.add_authn_plugin(self)
@@ -64,6 +72,9 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
64 route_name='auth_home',
72 route_name='auth_home',
65 context=RhodecodeAuthnResource)
73 context=RhodecodeAuthnResource)
66
74
75 def get_settings_schema(self):
76 return RhodeCodeSettingsSchema()
77
67 def get_display_name(self):
78 def get_display_name(self):
68 return _('RhodeCode Internal')
79 return _('RhodeCode Internal')
69
80
@@ -94,12 +105,36 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
94 if not userobj:
105 if not userobj:
95 log.debug('userobj was:%s skipping', userobj)
106 log.debug('userobj was:%s skipping', userobj)
96 return None
107 return None
108
97 if userobj.extern_type != self.name:
109 if userobj.extern_type != self.name:
98 log.warning(
110 log.warning("userobj:%s extern_type mismatch got:`%s` expected:`%s`",
99 "userobj:%s extern_type mismatch got:`%s` expected:`%s`",
100 userobj, userobj.extern_type, self.name)
111 userobj, userobj.extern_type, self.name)
101 return None
112 return None
102
113
114 # check scope of auth
115 scope_restriction = settings.get('scope_restriction', '')
116
117 if scope_restriction == self.AUTH_RESTRICTION_SCOPE_HTTP \
118 and self.auth_type != HTTP_TYPE:
119 log.warning("userobj:%s tried scope type %s and scope restriction is set to %s",
120 userobj, self.auth_type, scope_restriction)
121 return None
122
123 if scope_restriction == self.AUTH_RESTRICTION_SCOPE_VCS \
124 and self.auth_type != VCS_TYPE:
125 log.warning("userobj:%s tried scope type %s and scope restriction is set to %s",
126 userobj, self.auth_type, scope_restriction)
127 return None
128
129 # check super-admin restriction
130 auth_restriction = settings.get('auth_restriction', '')
131
132 if auth_restriction == self.AUTH_RESTRICTION_SUPER_ADMIN \
133 and userobj.admin is False:
134 log.warning("userobj:%s is not super-admin and auth restriction is set to %s",
135 userobj, auth_restriction)
136 return None
137
103 user_attrs = {
138 user_attrs = {
104 "username": userobj.username,
139 "username": userobj.username,
105 "firstname": userobj.firstname,
140 "firstname": userobj.firstname,
@@ -131,23 +166,55 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
131 user_attrs['_hash_migrate'] = new_hash
166 user_attrs['_hash_migrate'] = new_hash
132
167
133 if userobj.username == User.DEFAULT_USER and userobj.active:
168 if userobj.username == User.DEFAULT_USER and userobj.active:
134 log.info(
169 log.info('user `%s` authenticated correctly as anonymous user',
135 'user `%s` authenticated correctly as anonymous user', userobj.username)
170 userobj.username)
136 return user_attrs
171 return user_attrs
137
172
138 elif userobj.username == username and password_match:
173 elif userobj.username == username and password_match:
139 log.info('user `%s` authenticated correctly', userobj.username)
174 log.info('user `%s` authenticated correctly', userobj.username)
140 return user_attrs
175 return user_attrs
141 log.warn("user `%s` used a wrong password when "
176 log.warning("user `%s` used a wrong password when "
142 "authenticating on this plugin", userobj.username)
177 "authenticating on this plugin", userobj.username)
143 return None
178 return None
144 else:
179 else:
145 log.warning(
180 log.warning('user `%s` failed to authenticate via %s, reason: account not '
146 'user `%s` failed to authenticate via %s, reason: account not '
147 'active.', username, self.name)
181 'active.', username, self.name)
148 return None
182 return None
149
183
150
184
185 class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase):
186
187 auth_restriction_choices = [
188 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE, 'All users'),
189 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN, 'Super admins only'),
190 ]
191
192 auth_scope_choices = [
193 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL, 'HTTP and VCS'),
194 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_HTTP, 'HTTP only'),
195 ]
196
197 auth_restriction = colander.SchemaNode(
198 colander.String(),
199 default=auth_restriction_choices[0],
200 description=_('Allowed user types for authentication using this plugin.'),
201 title=_('User restriction'),
202 validator=colander.OneOf([x[0] for x in auth_restriction_choices]),
203 widget='select_with_labels',
204 choices=auth_restriction_choices
205 )
206 scope_restriction = colander.SchemaNode(
207 colander.String(),
208 default=auth_scope_choices[0],
209 description=_('Allowed protocols for authentication using this plugin. '
210 'VCS means GIT/HG/SVN. HTTP is web based login.'),
211 title=_('Scope restriction'),
212 validator=colander.OneOf([x[0] for x in auth_scope_choices]),
213 widget='select_with_labels',
214 choices=auth_scope_choices
215 )
216
217
151 def includeme(config):
218 def includeme(config):
152 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
219 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
153 plugin_factory(plugin_id).includeme(config)
220 plugin_factory(plugin_id).includeme(config)
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -23,7 +23,9 b' RhodeCode authentication token plugin fo'
23 """
23 """
24
24
25 import logging
25 import logging
26 import colander
26
27
28 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
27 from rhodecode.translation import _
29 from rhodecode.translation import _
28 from rhodecode.authentication.base import (
30 from rhodecode.authentication.base import (
29 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
31 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
@@ -48,6 +50,7 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
48 Enables usage of authentication tokens for vcs operations.
50 Enables usage of authentication tokens for vcs operations.
49 """
51 """
50 uid = 'token'
52 uid = 'token'
53 AUTH_RESTRICTION_SCOPE_VCS = 'scope_vcs'
51
54
52 def includeme(self, config):
55 def includeme(self, config):
53 config.add_authn_plugin(self)
56 config.add_authn_plugin(self)
@@ -67,6 +70,9 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
67 route_name='auth_home',
70 route_name='auth_home',
68 context=RhodecodeAuthnResource)
71 context=RhodecodeAuthnResource)
69
72
73 def get_settings_schema(self):
74 return RhodeCodeSettingsSchema()
75
70 def get_display_name(self):
76 def get_display_name(self):
71 return _('Rhodecode Token')
77 return _('Rhodecode Token')
72
78
@@ -142,12 +148,10 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
142 'user `%s` successfully authenticated via %s',
148 'user `%s` successfully authenticated via %s',
143 user_attrs['username'], self.name)
149 user_attrs['username'], self.name)
144 return user_attrs
150 return user_attrs
145 log.warn(
151 log.warning('user `%s` failed to authenticate via %s, reason: bad or '
146 'user `%s` failed to authenticate via %s, reason: bad or '
147 'inactive token.', username, self.name)
152 'inactive token.', username, self.name)
148 else:
153 else:
149 log.warning(
154 log.warning('user `%s` failed to authenticate via %s, reason: account not '
150 'user `%s` failed to authenticate via %s, reason: account not '
151 'active.', username, self.name)
155 'active.', username, self.name)
152 return None
156 return None
153
157
@@ -155,3 +159,19 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
155 def includeme(config):
159 def includeme(config):
156 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
160 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
157 plugin_factory(plugin_id).includeme(config)
161 plugin_factory(plugin_id).includeme(config)
162
163
164 class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase):
165 auth_scope_choices = [
166 (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS, 'VCS only'),
167 ]
168
169 scope_restriction = colander.SchemaNode(
170 colander.String(),
171 default=auth_scope_choices[0],
172 description=_('Choose operation scope restriction when authenticating.'),
173 title=_('Scope restriction'),
174 validator=colander.OneOf([x[0] for x in auth_scope_choices]),
175 widget='select_with_labels',
176 choices=auth_scope_choices
177 )
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2013-2018 RhodeCode GmbH
3 # Copyright (C) 2013-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -98,7 +98,7 b' def make_pyramid_app(global_config, **se'
98 global_config = _substitute_values(global_config, environ)
98 global_config = _substitute_values(global_config, environ)
99 settings = _substitute_values(settings, environ)
99 settings = _substitute_values(settings, environ)
100
100
101 sanitize_settings_and_apply_defaults(settings)
101 sanitize_settings_and_apply_defaults(global_config, settings)
102
102
103 config = Configurator(settings=settings)
103 config = Configurator(settings=settings)
104
104
@@ -165,7 +165,7 b' def error_handler(exception, request):'
165
165
166 error_explanation = base_response.explanation or str(base_response)
166 error_explanation = base_response.explanation or str(base_response)
167 if base_response.status_code == 404:
167 if base_response.status_code == 404:
168 error_explanation += " Or you don't have permission to access it."
168 error_explanation += " Optionally you don't have permission to access this page."
169 c = AttributeDict()
169 c = AttributeDict()
170 c.error_message = base_response.status
170 c.error_message = base_response.status
171 c.error_explanation = error_explanation
171 c.error_explanation = error_explanation
@@ -281,6 +281,7 b' def includeme(config):'
281 config.include('rhodecode.apps.ops')
281 config.include('rhodecode.apps.ops')
282 config.include('rhodecode.apps.admin')
282 config.include('rhodecode.apps.admin')
283 config.include('rhodecode.apps.channelstream')
283 config.include('rhodecode.apps.channelstream')
284 config.include('rhodecode.apps.file_store')
284 config.include('rhodecode.apps.login')
285 config.include('rhodecode.apps.login')
285 config.include('rhodecode.apps.home')
286 config.include('rhodecode.apps.home')
286 config.include('rhodecode.apps.journal')
287 config.include('rhodecode.apps.journal')
@@ -381,7 +382,7 b' def wrap_app_in_wsgi_middlewares(pyramid'
381 return pyramid_app_with_cleanup
382 return pyramid_app_with_cleanup
382
383
383
384
384 def sanitize_settings_and_apply_defaults(settings):
385 def sanitize_settings_and_apply_defaults(global_config, settings):
385 """
386 """
386 Applies settings defaults and does all type conversion.
387 Applies settings defaults and does all type conversion.
387
388
@@ -420,6 +421,7 b' def sanitize_settings_and_apply_defaults'
420 # TODO: johbo: Re-think this, usually the call to config.include
421 # TODO: johbo: Re-think this, usually the call to config.include
421 # should allow to pass in a prefix.
422 # should allow to pass in a prefix.
422 settings.setdefault('rhodecode.api.url', '/_admin/api')
423 settings.setdefault('rhodecode.api.url', '/_admin/api')
424 settings.setdefault('__file__', global_config.get('__file__'))
423
425
424 # Sanitize generic settings.
426 # Sanitize generic settings.
425 _list_setting(settings, 'default_encoding', 'UTF-8')
427 _list_setting(settings, 'default_encoding', 'UTF-8')
@@ -708,18 +710,29 b' def _string_setting(settings, name, defa'
708
710
709
711
710 def _substitute_values(mapping, substitutions):
712 def _substitute_values(mapping, substitutions):
713 result = {}
711
714
712 try:
715 try:
713 result = {
716 for key, value in mapping.items():
717 # initialize without substitution first
718 result[key] = value
719
714 # Note: Cannot use regular replacements, since they would clash
720 # Note: Cannot use regular replacements, since they would clash
715 # with the implementation of ConfigParser. Using "format" instead.
721 # with the implementation of ConfigParser. Using "format" instead.
716 key: value.format(**substitutions)
722 try:
717 for key, value in mapping.items()
723 result[key] = value.format(**substitutions)
718 }
719 except KeyError as e:
724 except KeyError as e:
720 raise ValueError(
725 env_var = '{}'.format(e.args[0])
721 'Failed to substitute env variable: {}. '
726
722 'Make sure you have specified this env variable without ENV_ prefix'.format(e))
727 msg = 'Failed to substitute: `{key}={{{var}}}` with environment entry. ' \
728 'Make sure your environment has {var} set, or remove this ' \
729 'variable from config file'.format(key=key, var=env_var)
730
731 if env_var.startswith('ENV_'):
732 raise ValueError(msg)
733 else:
734 log.warning(msg)
735
723 except ValueError as e:
736 except ValueError as e:
724 log.warning('Failed to substitute ENV variable: %s', e)
737 log.warning('Failed to substitute ENV variable: %s', e)
725 result = mapping
738 result = mapping
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -14,19 +14,6 b''
14 'hook_type': '',
14 'hook_type': '',
15 'user_agent': 'Client user agent, e.g git or mercurial CLI version',
15 'user_agent': 'Client user agent, e.g git or mercurial CLI version',
16 })
16 })
17 @has_kwargs({
18 'server_url': 'url of instance that triggered this hook',
19 'config': 'path to .ini config used',
20 'scm': 'type of version control "git", "hg", "svn"',
21 'username': 'username of actor who triggered this event',
22 'ip': 'ip address of actor who triggered this hook',
23 'action': '',
24 'repository': 'repository name',
25 'repo_store_path': 'full path to where repositories are stored',
26 'commit_ids': 'pre transaction metadata for commit ids',
27 'hook_type': '',
28 'user_agent': 'Client user agent, e.g git or mercurial CLI version',
29 })
30 def _pre_push_hook(*args, **kwargs):
17 def _pre_push_hook(*args, **kwargs):
31 """
18 """
32 Post push hook
19 Post push hook
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2018 RhodeCode GmbH
2 # Copyright (C) 2016-2019 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,4 +1,4 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2019 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -7457,7 +7457,7 b' msgid ""'
7457 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7457 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7458 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7458 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7459 " {user} current user username,\n"
7459 " {user} current user username,\n"
7460 " {sys_user} current system user running this process, usefull for ssh,\n"
7460 " {sys_user} current system user running this process, Useful for ssh,\n"
7461 " {hostname} hostname of this server running RhodeCode,\n"
7461 " {hostname} hostname of this server running RhodeCode,\n"
7462 " {netloc} network location/server host of running RhodeCode server,\n"
7462 " {netloc} network location/server host of running RhodeCode server,\n"
7463 " {repo} full repository name,\n"
7463 " {repo} full repository name,\n"
@@ -7455,7 +7455,7 b' msgid ""'
7455 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7455 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7456 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7456 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7457 " {user} current user username,\n"
7457 " {user} current user username,\n"
7458 " {sys_user} current system user running this process, usefull for ssh,\n"
7458 " {sys_user} current system user running this process, Useful for ssh,\n"
7459 " {hostname} hostname of this server running RhodeCode,\n"
7459 " {hostname} hostname of this server running RhodeCode,\n"
7460 " {netloc} network location/server host of running RhodeCode server,\n"
7460 " {netloc} network location/server host of running RhodeCode server,\n"
7461 " {repo} full repository name,\n"
7461 " {repo} full repository name,\n"
@@ -7456,7 +7456,7 b' msgid ""'
7456 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7456 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7457 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7457 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7458 " {user} current user username,\n"
7458 " {user} current user username,\n"
7459 " {sys_user} current system user running this process, usefull for ssh,\n"
7459 " {sys_user} current system user running this process, Useful for ssh,\n"
7460 " {hostname} hostname of this server running RhodeCode,\n"
7460 " {hostname} hostname of this server running RhodeCode,\n"
7461 " {netloc} network location/server host of running RhodeCode server,\n"
7461 " {netloc} network location/server host of running RhodeCode server,\n"
7462 " {repo} full repository name,\n"
7462 " {repo} full repository name,\n"
@@ -7456,7 +7456,7 b' msgid ""'
7456 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7456 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7457 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7457 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7458 " {user} current user username,\n"
7458 " {user} current user username,\n"
7459 " {sys_user} current system user running this process, usefull for ssh,\n"
7459 " {sys_user} current system user running this process, Useful for ssh,\n"
7460 " {hostname} hostname of this server running RhodeCode,\n"
7460 " {hostname} hostname of this server running RhodeCode,\n"
7461 " {netloc} network location/server host of running RhodeCode server,\n"
7461 " {netloc} network location/server host of running RhodeCode server,\n"
7462 " {repo} full repository name,\n"
7462 " {repo} full repository name,\n"
@@ -7463,7 +7463,7 b' msgid ""'
7463 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7463 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7464 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7464 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7465 " {user} current user username,\n"
7465 " {user} current user username,\n"
7466 " {sys_user} current system user running this process, usefull for ssh,\n"
7466 " {sys_user} current system user running this process, Useful for ssh,\n"
7467 " {hostname} hostname of this server running RhodeCode,\n"
7467 " {hostname} hostname of this server running RhodeCode,\n"
7468 " {netloc} network location/server host of running RhodeCode server,\n"
7468 " {netloc} network location/server host of running RhodeCode server,\n"
7469 " {repo} full repository name,\n"
7469 " {repo} full repository name,\n"
@@ -7461,7 +7461,7 b' msgid ""'
7461 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7461 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7462 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7462 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7463 " {user} current user username,\n"
7463 " {user} current user username,\n"
7464 " {sys_user} current system user running this process, usefull for ssh,\n"
7464 " {sys_user} current system user running this process, Useful for ssh,\n"
7465 " {hostname} hostname of this server running RhodeCode,\n"
7465 " {hostname} hostname of this server running RhodeCode,\n"
7466 " {netloc} network location/server host of running RhodeCode server,\n"
7466 " {netloc} network location/server host of running RhodeCode server,\n"
7467 " {repo} full repository name,\n"
7467 " {repo} full repository name,\n"
@@ -7457,7 +7457,7 b' msgid ""'
7457 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7457 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7458 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7458 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7459 " {user} current user username,\n"
7459 " {user} current user username,\n"
7460 " {sys_user} current system user running this process, usefull for ssh,\n"
7460 " {sys_user} current system user running this process, Useful for ssh,\n"
7461 " {hostname} hostname of this server running RhodeCode,\n"
7461 " {hostname} hostname of this server running RhodeCode,\n"
7462 " {netloc} network location/server host of running RhodeCode server,\n"
7462 " {netloc} network location/server host of running RhodeCode server,\n"
7463 " {repo} full repository name,\n"
7463 " {repo} full repository name,\n"
@@ -7497,7 +7497,7 b' msgid ""'
7497 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7497 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7498 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7498 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7499 " {user} current user username,\n"
7499 " {user} current user username,\n"
7500 " {sys_user} current system user running this process, usefull for ssh,\n"
7500 " {sys_user} current system user running this process, Useful for ssh,\n"
7501 " {hostname} hostname of this server running RhodeCode,\n"
7501 " {hostname} hostname of this server running RhodeCode,\n"
7502 " {netloc} network location/server host of running RhodeCode server,\n"
7502 " {netloc} network location/server host of running RhodeCode server,\n"
7503 " {repo} full repository name,\n"
7503 " {repo} full repository name,\n"
@@ -7474,7 +7474,7 b' msgid ""'
7474 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7474 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7475 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7475 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7476 " {user} current user username,\n"
7476 " {user} current user username,\n"
7477 " {sys_user} current system user running this process, usefull for ssh,\n"
7477 " {sys_user} current system user running this process, Useful for ssh,\n"
7478 " {hostname} hostname of this server running RhodeCode,\n"
7478 " {hostname} hostname of this server running RhodeCode,\n"
7479 " {netloc} network location/server host of running RhodeCode server,\n"
7479 " {netloc} network location/server host of running RhodeCode server,\n"
7480 " {repo} full repository name,\n"
7480 " {repo} full repository name,\n"
@@ -7458,7 +7458,7 b' msgid ""'
7458 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7458 "Schema of clone url construction eg. '{scheme}://{user}@{netloc}/{repo}', available vars:\n"
7459 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7459 " {scheme} 'http' or 'https' sent from running RhodeCode server,\n"
7460 " {user} current user username,\n"
7460 " {user} current user username,\n"
7461 " {sys_user} current system user running this process, usefull for ssh,\n"
7461 " {sys_user} current system user running this process, Useful for ssh,\n"
7462 " {hostname} hostname of this server running RhodeCode,\n"
7462 " {hostname} hostname of this server running RhodeCode,\n"
7463 " {netloc} network location/server host of running RhodeCode server,\n"
7463 " {netloc} network location/server host of running RhodeCode server,\n"
7464 " {repo} full repository name,\n"
7464 " {repo} full repository name,\n"
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,5 +1,5 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2012-2018 RhodeCode GmbH
2 # Copyright (C) 2012-2019 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -23,17 +23,27 b' import string'
23 import collections
23 import collections
24 import logging
24 import logging
25 import requests
25 import requests
26 import urllib
26 from requests.adapters import HTTPAdapter
27 from requests.adapters import HTTPAdapter
27 from requests.packages.urllib3.util.retry import Retry
28 from requests.packages.urllib3.util.retry import Retry
28
29
29 from mako import exceptions
30 from mako import exceptions
30
31
32 from rhodecode.lib.utils2 import safe_str
31 from rhodecode.translation import _
33 from rhodecode.translation import _
32
34
33
35
34 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
35
37
36
38
39 class UrlTmpl(string.Template):
40
41 def safe_substitute(self, **kws):
42 # url encode the kw for usage in url
43 kws = {k: urllib.quote(safe_str(v)) for k, v in kws.items()}
44 return super(UrlTmpl, self).safe_substitute(**kws)
45
46
37 class IntegrationTypeBase(object):
47 class IntegrationTypeBase(object):
38 """ Base class for IntegrationType plugins """
48 """ Base class for IntegrationType plugins """
39 is_dummy = False
49 is_dummy = False
@@ -217,7 +227,9 b' class WebhookDataHandler(CommitParsingDa'
217 common_vars.update(extra_vars)
227 common_vars.update(extra_vars)
218
228
219 template_url = self.template_url.replace('${extra:', '${extra__')
229 template_url = self.template_url.replace('${extra:', '${extra__')
220 return string.Template(template_url).safe_substitute(**common_vars)
230 for k, v in common_vars.items():
231 template_url = UrlTmpl(template_url).safe_substitute(**{k: v})
232 return template_url
221
233
222 def repo_push_event_handler(self, event, data):
234 def repo_push_event_handler(self, event, data):
223 url = self.get_base_parsed_template(data)
235 url = self.get_base_parsed_template(data)
@@ -228,20 +240,18 b' class WebhookDataHandler(CommitParsingDa'
228 if '${branch}' in url or '${branch_head}' in url or '${commit_id}' in url:
240 if '${branch}' in url or '${branch_head}' in url or '${commit_id}' in url:
229 # call it multiple times, for each branch if used in variables
241 # call it multiple times, for each branch if used in variables
230 for branch, commit_ids in branches_commits.items():
242 for branch, commit_ids in branches_commits.items():
231 branch_url = string.Template(url).safe_substitute(branch=branch)
243 branch_url = UrlTmpl(url).safe_substitute(branch=branch)
232
244
233 if '${branch_head}' in branch_url:
245 if '${branch_head}' in branch_url:
234 # last commit in the aggregate is the head of the branch
246 # last commit in the aggregate is the head of the branch
235 branch_head = commit_ids['branch_head']
247 branch_head = commit_ids['branch_head']
236 branch_url = string.Template(branch_url).safe_substitute(
248 branch_url = UrlTmpl(branch_url).safe_substitute(branch_head=branch_head)
237 branch_head=branch_head)
238
249
239 # call further down for each commit if used
250 # call further down for each commit if used
240 if '${commit_id}' in branch_url:
251 if '${commit_id}' in branch_url:
241 for commit_data in commit_ids['commits']:
252 for commit_data in commit_ids['commits']:
242 commit_id = commit_data['raw_id']
253 commit_id = commit_data['raw_id']
243 commit_url = string.Template(branch_url).safe_substitute(
254 commit_url = UrlTmpl(branch_url).safe_substitute(commit_id=commit_id)
244 commit_id=commit_id)
245 # register per-commit call
255 # register per-commit call
246 log.debug(
256 log.debug(
247 'register %s call(%s) to url %s',
257 'register %s call(%s) to url %s',
@@ -251,36 +261,34 b' class WebhookDataHandler(CommitParsingDa'
251
261
252 else:
262 else:
253 # register per-branch call
263 # register per-branch call
254 log.debug(
264 log.debug('register %s call(%s) to url %s',
255 'register %s call(%s) to url %s',
256 self.name, event, branch_url)
265 self.name, event, branch_url)
257 url_calls.append(
266 url_calls.append((branch_url, self.headers, data))
258 (branch_url, self.headers, data))
259
267
260 else:
268 else:
261 log.debug(
269 log.debug('register %s call(%s) to url %s', self.name, event, url)
262 'register %s call(%s) to url %s', self.name, event, url)
263 url_calls.append((url, self.headers, data))
270 url_calls.append((url, self.headers, data))
264
271
265 return url_calls
272 return url_calls
266
273
267 def repo_create_event_handler(self, event, data):
274 def repo_create_event_handler(self, event, data):
268 url = self.get_base_parsed_template(data)
275 url = self.get_base_parsed_template(data)
269 log.debug(
276 log.debug('register %s call(%s) to url %s', self.name, event, url)
270 'register %s call(%s) to url %s', self.name, event, url)
271 return [(url, self.headers, data)]
277 return [(url, self.headers, data)]
272
278
273 def pull_request_event_handler(self, event, data):
279 def pull_request_event_handler(self, event, data):
274 url = self.get_base_parsed_template(data)
280 url = self.get_base_parsed_template(data)
275 log.debug(
281 log.debug('register %s call(%s) to url %s', self.name, event, url)
276 'register %s call(%s) to url %s', self.name, event, url)
282 pr_vars = [
277 url = string.Template(url).safe_substitute(
283 ('pull_request_id', data['pullrequest']['pull_request_id']),
278 pull_request_id=data['pullrequest']['pull_request_id'],
284 ('pull_request_title', data['pullrequest']['title']),
279 pull_request_title=data['pullrequest']['title'],
285 ('pull_request_url', data['pullrequest']['url']),
280 pull_request_url=data['pullrequest']['url'],
286 ('pull_request_shadow_url', data['pullrequest']['shadow_url']),
281 pull_request_shadow_url=data['pullrequest']['shadow_url'],
287 ('pull_request_commits_uid', data['pullrequest']['commits_uid']),
282 pull_request_commits_uid=data['pullrequest']['commits_uid'],
288 ]
283 )
289 for k, v in pr_vars:
290 url = UrlTmpl(url).safe_substitute(**{k: v})
291
284 return [(url, self.headers, data)]
292 return [(url, self.headers, data)]
285
293
286 def __call__(self, event, data):
294 def __call__(self, event, data):
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -122,8 +122,10 b' class HipchatIntegrationType(Integration'
122 log.debug('event not valid: %r', event)
122 log.debug('event not valid: %r', event)
123 return
123 return
124
124
125 if event.name not in self.settings['events']:
125 allowed_events = self.settings['events']
126 log.debug('event ignored: %r', event)
126 if event.name not in allowed_events:
127 log.debug('event ignored: %r event %s not in allowed events %s',
128 event, event.name, allowed_events)
127 return
129 return
128
130
129 data = event.as_dict()
131 data = event.as_dict()
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -138,8 +138,10 b' class SlackIntegrationType(IntegrationTy'
138 log.debug('event not valid: %r', event)
138 log.debug('event not valid: %r', event)
139 return
139 return
140
140
141 if event.name not in self.settings['events']:
141 allowed_events = self.settings['events']
142 log.debug('event ignored: %r', event)
142 if event.name not in allowed_events:
143 log.debug('event ignored: %r event %s not in allowed events %s',
144 event, event.name, allowed_events)
143 return
145 return
144
146
145 data = event.as_dict()
147 data = event.as_dict()
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -118,12 +118,11 b' class WebhookSettingsSchema(colander.Sch'
118 method_type = colander.SchemaNode(
118 method_type = colander.SchemaNode(
119 colander.String(),
119 colander.String(),
120 title=_('Call Method'),
120 title=_('Call Method'),
121 description=_('Select if the Webhook call should be made '
121 description=_('Select a HTTP method to use when calling the Webhook.'),
122 'with POST or GET.'),
123 default='post',
122 default='post',
124 missing='',
123 missing='',
125 widget=deform.widget.RadioChoiceWidget(
124 widget=deform.widget.RadioChoiceWidget(
126 values=[('get', 'GET'), ('post', 'POST')],
125 values=[('get', 'GET'), ('post', 'POST'), ('put', 'PUT')],
127 inline=True
126 inline=True
128 ),
127 ),
129 )
128 )
@@ -171,8 +170,10 b' class WebhookIntegrationType(Integration'
171 log.debug('event not valid: %r', event)
170 log.debug('event not valid: %r', event)
172 return
171 return
173
172
174 if event.name not in self.settings['events']:
173 allowed_events = self.settings['events']
175 log.debug('event ignored: %r', event)
174 if event.name not in allowed_events:
175 log.debug('event ignored: %r event %s not in allowed events %s',
176 event, event.name, allowed_events)
176 return
177 return
177
178
178 data = event.as_dict()
179 data = event.as_dict()
@@ -187,8 +188,7 b' class WebhookIntegrationType(Integration'
187 handler = WebhookDataHandler(template_url, headers)
188 handler = WebhookDataHandler(template_url, headers)
188
189
189 url_calls = handler(event, data)
190 url_calls = handler(event, data)
190 log.debug('webhook: calling following urls: %s',
191 log.debug('Webhook: calling following urls: %s', [x[0] for x in url_calls])
191 [x[0] for x in url_calls])
192
192
193 run_task(post_to_webhook, url_calls, self.settings)
193 run_task(post_to_webhook, url_calls, self.settings)
194
194
@@ -214,7 +214,9 b' def post_to_webhook(url_calls, settings)'
214 'parents': [{'raw_id': '431b772a5353dad9974b810dd3707d79e3a7f6e0'}],
214 'parents': [{'raw_id': '431b772a5353dad9974b810dd3707d79e3a7f6e0'}],
215 'permalink_url': u'http://rc.local:8080/_7/changeset/a815cc738b9651eb5ffbcfb1ce6ccd7c701a5ddf',
215 'permalink_url': u'http://rc.local:8080/_7/changeset/a815cc738b9651eb5ffbcfb1ce6ccd7c701a5ddf',
216 'raw_id': 'a815cc738b9651eb5ffbcfb1ce6ccd7c701a5ddf',
216 'raw_id': 'a815cc738b9651eb5ffbcfb1ce6ccd7c701a5ddf',
217 'refs': {'bookmarks': [], 'branches': [u'default'], 'tags': [u'tip']},
217 'refs': {'bookmarks': [],
218 'branches': [u'default'],
219 'tags': [u'tip']},
218 'reviewers': [],
220 'reviewers': [],
219 'revision': 9L,
221 'revision': 9L,
220 'short_id': 'a815cc738b96',
222 'short_id': 'a815cc738b96',
@@ -228,11 +230,11 b' def post_to_webhook(url_calls, settings)'
228 'url': u'http://rc.local:8080/hg-repo'},
230 'url': u'http://rc.local:8080/hg-repo'},
229 'server_url': u'http://rc.local:8080',
231 'server_url': u'http://rc.local:8080',
230 'utc_timestamp': datetime.datetime(2017, 11, 30, 13, 0, 1, 569276)
232 'utc_timestamp': datetime.datetime(2017, 11, 30, 13, 0, 1, 569276)
233 }
234 """
231
235
232 """
233 call_headers = {
236 call_headers = {
234 'User-Agent': 'RhodeCode-webhook-caller/{}'.format(
237 'User-Agent': 'RhodeCode-webhook-caller/{}'.format(rhodecode.__version__)
235 rhodecode.__version__)
236 } # updated below with custom ones, allows override
238 } # updated below with custom ones, allows override
237
239
238 auth = get_auth(settings)
240 auth = get_auth(settings)
@@ -247,8 +249,7 b' def post_to_webhook(url_calls, settings)'
247 headers = headers or {}
249 headers = headers or {}
248 call_headers.update(headers)
250 call_headers.update(headers)
249
251
250 log.debug('calling Webhook with method: %s, and auth:%s',
252 log.debug('calling Webhook with method: %s, and auth:%s', call_method, auth)
251 call_method, auth)
252 if settings.get('log_data'):
253 if settings.get('log_data'):
253 log.debug('calling webhook with data: %s', data)
254 log.debug('calling webhook with data: %s', data)
254 resp = call_method(url, json={
255 resp = call_method(url, json={
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -35,6 +35,7 b' from paste.httpexceptions import HTTPUna'
35 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION
35 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION
36
36
37 import rhodecode
37 import rhodecode
38 from rhodecode.apps._base import TemplateArgs
38 from rhodecode.authentication.base import VCS_TYPE
39 from rhodecode.authentication.base import VCS_TYPE
39 from rhodecode.lib import auth, utils2
40 from rhodecode.lib import auth, utils2
40 from rhodecode.lib import helpers as h
41 from rhodecode.lib import helpers as h
@@ -43,7 +44,7 b' from rhodecode.lib.exceptions import Use'
43 from rhodecode.lib.utils import (password_changed, get_enabled_hook_classes)
44 from rhodecode.lib.utils import (password_changed, get_enabled_hook_classes)
44 from rhodecode.lib.utils2 import (
45 from rhodecode.lib.utils2 import (
45 str2bool, safe_unicode, AttributeDict, safe_int, sha1, aslist, safe_str)
46 str2bool, safe_unicode, AttributeDict, safe_int, sha1, aslist, safe_str)
46 from rhodecode.model.db import Repository, User, ChangesetComment
47 from rhodecode.model.db import Repository, User, ChangesetComment, UserBookmark
47 from rhodecode.model.notification import NotificationModel
48 from rhodecode.model.notification import NotificationModel
48 from rhodecode.model.settings import VcsSettingsModel, SettingsModel
49 from rhodecode.model.settings import VcsSettingsModel, SettingsModel
49
50
@@ -281,7 +282,7 b' def get_current_lang(request):'
281 return getattr(request, '_LOCALE_', request.locale_name)
282 return getattr(request, '_LOCALE_', request.locale_name)
282
283
283
284
284 def attach_context_attributes(context, request, user_id):
285 def attach_context_attributes(context, request, user_id=None):
285 """
286 """
286 Attach variables into template context called `c`.
287 Attach variables into template context called `c`.
287 """
288 """
@@ -312,6 +313,10 b' def attach_context_attributes(context, r'
312 rc_config.get('rhodecode_dashboard_items', 100))
313 rc_config.get('rhodecode_dashboard_items', 100))
313 context.visual.admin_grid_items = safe_int(
314 context.visual.admin_grid_items = safe_int(
314 rc_config.get('rhodecode_admin_grid_items', 100))
315 rc_config.get('rhodecode_admin_grid_items', 100))
316 context.visual.show_revision_number = str2bool(
317 rc_config.get('rhodecode_show_revision_number', True))
318 context.visual.show_sha_length = safe_int(
319 rc_config.get('rhodecode_show_sha_length', 100))
315 context.visual.repository_fields = str2bool(
320 context.visual.repository_fields = str2bool(
316 rc_config.get('rhodecode_repository_fields'))
321 rc_config.get('rhodecode_repository_fields'))
317 context.visual.show_version = str2bool(
322 context.visual.show_version = str2bool(
@@ -343,6 +348,8 b' def attach_context_attributes(context, r'
343 config.get('labs_settings_active', 'false'))
348 config.get('labs_settings_active', 'false'))
344 context.ssh_enabled = str2bool(
349 context.ssh_enabled = str2bool(
345 config.get('ssh.generate_authorized_keyfile', 'false'))
350 config.get('ssh.generate_authorized_keyfile', 'false'))
351 context.ssh_key_generator_enabled = str2bool(
352 config.get('ssh.enable_ui_key_generator', 'true'))
346
353
347 context.visual.allow_repo_location_change = str2bool(
354 context.visual.allow_repo_location_change = str2bool(
348 config.get('allow_repo_location_change', True))
355 config.get('allow_repo_location_change', True))
@@ -417,7 +424,13 b' def attach_context_attributes(context, r'
417 context.csrf_token = auth.get_csrf_token(session=request.session)
424 context.csrf_token = auth.get_csrf_token(session=request.session)
418 context.backends = rhodecode.BACKENDS.keys()
425 context.backends = rhodecode.BACKENDS.keys()
419 context.backends.sort()
426 context.backends.sort()
420 context.unread_notifications = NotificationModel().get_unread_cnt_for_user(user_id)
427 unread_count = 0
428 user_bookmark_list = []
429 if user_id:
430 unread_count = NotificationModel().get_unread_cnt_for_user(user_id)
431 user_bookmark_list = UserBookmark.get_bookmarks_for_user(user_id)
432 context.unread_notifications = unread_count
433 context.bookmark_items = user_bookmark_list
421
434
422 # web case
435 # web case
423 if hasattr(request, 'user'):
436 if hasattr(request, 'user'):
@@ -551,7 +564,11 b' def bootstrap_request(**kwargs):'
551 from rhodecode.lib.partial_renderer import get_partial_renderer
564 from rhodecode.lib.partial_renderer import get_partial_renderer
552 return get_partial_renderer(request=self, tmpl_name=tmpl_name)
565 return get_partial_renderer(request=self, tmpl_name=tmpl_name)
553
566
554 _call_context = {}
567 _call_context = TemplateArgs()
568 _call_context.visual = TemplateArgs()
569 _call_context.visual.show_sha_length = 12
570 _call_context.visual.show_revision_number = True
571
555 @property
572 @property
556 def call_context(self):
573 def call_context(self):
557 return self._call_context
574 return self._call_context
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
@@ -1,6 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/controllers/utils.py to rhodecode/lib/view_utils.py
NO CONTENT: file renamed from rhodecode/controllers/utils.py to rhodecode/lib/view_utils.py
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now